// 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 /src/intrinsics.def file, then scans the // project directory for '.tmpl' files, to produce '' 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" ) const defProjectRelPath = "src/intrinsics.def" 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 /src/intrinsics.def file, then scans the project directory for '.tmpl' files, to produce '' 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, defProjectRelPath) defSource, err := ioutil.ReadFile(defPath) if err != nil { return err } // Parse the definition file to produce an AST ast, err := parser.Parse(string(defSource), defProjectRelPath) 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 /src directory files, err := glob.Scan(projectRoot, glob.MustParseConfig(`{ "paths": [{"include": [ "src/**.tmpl", "test/**.tmpl" ]}] }`)) if err != nil { return err } // For each template file... for _, relTmplPath := range files { // Make tmplPath absolute tmplPath := filepath.Join(projectRoot, relTmplPath) // Read the template file tmpl, err := ioutil.ReadFile(tmplPath) if err != nil { return fmt.Errorf("failed to open '%v': %w", tmplPath, err) } // Create or update the file at relpath if the file content has changed // relpath is a path relative to the template writeFile := func(relpath, body string) error { // Write the common file header sb := strings.Builder{} sb.WriteString(fmt.Sprintf(header, filepath.ToSlash(relTmplPath), filepath.ToSlash(defProjectRelPath))) sb.WriteString(body) content := sb.String() abspath := filepath.Join(filepath.Dir(tmplPath), relpath) return writeFileIfChanged(abspath, content) } // Write the content generated using the template and semantic info sb := strings.Builder{} if err := gen.Generate(sem, string(tmpl), &sb, writeFile); err != nil { return fmt.Errorf("while processing '%v': %w", tmplPath, err) } if body := sb.String(); body != "" { _, tmplFileName := filepath.Split(tmplPath) outFileName := strings.TrimSuffix(tmplFileName, ".tmpl") if err := writeFile(outFileName, body); err != nil { return err } } } return nil } // writes content to path if the file has changed func writeFileIfChanged(path, content string) error { existing, err := ioutil.ReadFile(path) if err == nil && string(existing) == content { return nil // Not changed } if err := os.MkdirAll(filepath.Dir(path), 0777); err != nil { return fmt.Errorf("failed to create directory for '%v': %w", path, err) } if err := ioutil.WriteFile(path, []byte(content), 0666); err != nil { return fmt.Errorf("failed to write file '%v': %w", path, err) } return nil } 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 // using the template: // %v // and the intrinsic defintion file: // %v // // Do not modify this file directly //////////////////////////////////////////////////////////////////////////////// `