blob: 51dc79904134a508fd95ab7259b7013ae9faa580 [file] [log] [blame]
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// intrinsic-gen parses the <tint>/src/intrinsics.def file, then scans the
// project directory for '<file>.tmpl' files, to produce '<file>' source code
// files.
package main
import (
"flag"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/gen"
"dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/parser"
"dawn.googlesource.com/tint/tools/src/cmd/intrinsic-gen/resolver"
"dawn.googlesource.com/tint/tools/src/fileutils"
"dawn.googlesource.com/tint/tools/src/glob"
)
func main() {
if err := run(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func showUsage() {
fmt.Println(`
intrinsic-gen generates the intrinsic table for the Tint compiler
intrinsic-gen parses the <tint>/src/intrinsics.def file, then scans the project
directory for '<file>.tmpl' files, to produce '<file>' source code files.
usage:
intrinsic-gen
optional flags:`)
flag.PrintDefaults()
fmt.Println(``)
os.Exit(1)
}
func run() error {
// Load the intrinsics definition file
projectRoot := fileutils.ProjectRoot()
defPath := filepath.Join(projectRoot, "src/intrinsics.def")
defSource, err := ioutil.ReadFile(defPath)
if err != nil {
return err
}
// Parse the definition file to produce an AST
ast, err := parser.Parse(string(defSource), defPath)
if err != nil {
return err
}
// Resolve the AST to produce the semantic info
sem, err := resolver.Resolve(ast)
if err != nil {
return err
}
// Recursively find all the template files in the <tint>/src directory
srcDir := filepath.Join(projectRoot, "src")
files, err := glob.Scan(srcDir, glob.MustParseConfig(`{
"paths": [{"include": [ "**.tmpl" ]}]
}`))
if err != nil {
return err
}
// For each template file...
for _, tmplPath := range files {
// Make tmplPath absolute
tmplPath := filepath.Join(srcDir, tmplPath)
// Read the template file
tmpl, err := ioutil.ReadFile(tmplPath)
if err != nil {
return fmt.Errorf("failed to open '%v': %w", tmplPath, err)
}
// Write the common file header
sb := strings.Builder{}
sb.WriteString(header)
// Write the content generated using the template and semantic info
if err := gen.Generate(sem, string(tmpl), &sb); err != nil {
return fmt.Errorf("while processing '%v': %w", tmplPath, err)
}
// Create or update the output file if the content has not changed
filePath := strings.TrimSuffix(tmplPath, ".tmpl")
if err := writeFileIfChanged(filePath, sb.String()); err != nil {
return fmt.Errorf("failed to write '%v': %w", filePath, err)
}
}
return nil
}
func writeFileIfChanged(path, content string) error {
existing, err := ioutil.ReadFile(path)
if err == nil && string(existing) == content {
return nil // Not changed
}
return ioutil.WriteFile(path, []byte(content), 0666)
}
const header = `// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
////////////////////////////////////////////////////////////////////////////////
// File generated by tools/intrinsic-gen
// Do not modify this file directly
////////////////////////////////////////////////////////////////////////////////
`