mirror of https://github.com/liamg/aminal.git
277 lines
5.9 KiB
Go
277 lines
5.9 KiB
Go
// Copyright 2014 The go-gl/mathgl Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build ignore
|
|
|
|
// codegen generates go code from templates. Intended to be
|
|
// used with go generate; Also makes mgl64 from mgl32.
|
|
// See the invocation in mgl32/util.go for details.
|
|
// To use it, just run "go generate github.com/go-gl/mathgl/mgl32"
|
|
// (or "go generate" in mgl32 directory).
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
"text/template"
|
|
)
|
|
|
|
type Context struct {
|
|
Comment string
|
|
TemplateName string
|
|
}
|
|
|
|
type MatrixIter struct {
|
|
M int // row
|
|
N int // column
|
|
index int
|
|
}
|
|
|
|
var mgl64RewriteRules = []string{
|
|
"mgl32 -> mgl64",
|
|
"float32 -> float64",
|
|
"f32 -> f64",
|
|
"a.Float32 -> a.Float64",
|
|
"math.MaxFloat32 -> math.MaxFloat64",
|
|
"math.SmallestNonzeroFloat32 -> math.SmallestNonzeroFloat64",
|
|
}
|
|
|
|
func main() {
|
|
flag.Usage = func() {
|
|
fmt.Println("Usage: codegen -template file.tmpl -output file.go")
|
|
fmt.Println("Usage: codegen -mgl64 [-dir ../mgl64]")
|
|
flag.PrintDefaults()
|
|
}
|
|
|
|
tmplPath := flag.String("template", "file.tmpl", "template path")
|
|
oPath := flag.String("output", "file.go", "output path")
|
|
mgl64 := flag.Bool("mgl64", false, "make mgl64")
|
|
mgl64Path := flag.String("dir", "../mgl64", "path to mgl64 location")
|
|
|
|
flag.Parse()
|
|
if flag.NArg() > 0 || flag.NFlag() == 0 {
|
|
flag.Usage()
|
|
os.Exit(2)
|
|
}
|
|
|
|
if *mgl64 {
|
|
genMgl64(*mgl64Path)
|
|
return
|
|
}
|
|
|
|
tmpl := template.New("").Delims("<<", ">>").Funcs(template.FuncMap{
|
|
"typename": typenameHelper,
|
|
"elementname": elementNameHelper,
|
|
"iter": iterHelper,
|
|
"matiter": matrixIterHelper,
|
|
"enum": enumHelper,
|
|
"sep": separatorHelper,
|
|
"repeat": repeatHelper,
|
|
"add": addHelper,
|
|
"mul": mulHelper,
|
|
})
|
|
tmpl = template.Must(tmpl.ParseFiles(*tmplPath))
|
|
tmplName := filepath.Base(*tmplPath)
|
|
|
|
oFile, err := os.Create(*oPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
context := Context{
|
|
Comment: "This file is generated by codegen.go; DO NOT EDIT",
|
|
TemplateName: tmplName,
|
|
}
|
|
if err = tmpl.ExecuteTemplate(oFile, tmplName, context); err != nil {
|
|
panic(err)
|
|
}
|
|
oFile.Close()
|
|
|
|
if err = rungofmt(*oPath, false, nil); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func genMgl64(destPath string) {
|
|
HandleFile := func(source string, info os.FileInfo, err error) error {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
dest := filepath.Join(destPath, source)
|
|
|
|
if info.IsDir() {
|
|
return os.MkdirAll(dest, info.Mode())
|
|
}
|
|
if !strings.HasSuffix(source, ".go") || info.Name() == "codegen.go" {
|
|
return nil
|
|
}
|
|
if !info.Mode().IsRegular() {
|
|
fmt.Println("Ignored, not a regular file:", source)
|
|
return nil
|
|
}
|
|
|
|
in, err := ioutil.ReadFile(source)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
out, err := os.OpenFile(dest, os.O_RDWR|os.O_CREATE|os.O_TRUNC,
|
|
info.Mode())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer out.Close()
|
|
|
|
comment := fmt.Sprintf(
|
|
"// This file is generated from mgl32/%s; DO NOT EDIT\n\n",
|
|
source)
|
|
if _, err = out.WriteString(comment); err != nil {
|
|
return err
|
|
}
|
|
|
|
r := strings.NewReplacer("//go:generate ", "//#go:generate ") // We don't want go generate directives in mgl64 package.
|
|
|
|
if _, err = r.WriteString(out, string(in)); err != nil {
|
|
return err
|
|
}
|
|
|
|
return rungofmt(dest, true, mgl64RewriteRules)
|
|
}
|
|
|
|
if err := filepath.Walk(".", HandleFile); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
func rungofmt(path string, fiximports bool, rewriteRules []string) error {
|
|
args := []string{"-w", path}
|
|
output, err := exec.Command("gofmt", args...).CombinedOutput()
|
|
|
|
for i := 0; err == nil && i < len(rewriteRules); i++ {
|
|
args = []string{"-w", "-r", rewriteRules[i], path}
|
|
output, err = exec.Command("gofmt", args...).CombinedOutput()
|
|
}
|
|
|
|
if fiximports && err == nil {
|
|
args = []string{"-w", path}
|
|
output, err = exec.Command("goimports", args...).CombinedOutput()
|
|
}
|
|
|
|
if err != nil {
|
|
fmt.Println("Error executing gofmt", strings.Join(args, " "))
|
|
os.Stdout.Write(output)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
func typenameHelper(m, n int) string {
|
|
if m == 1 {
|
|
return fmt.Sprintf("Vec%d", n)
|
|
}
|
|
if n == 1 {
|
|
return fmt.Sprintf("Vec%d", m)
|
|
}
|
|
if m == n {
|
|
return fmt.Sprintf("Mat%d", m)
|
|
}
|
|
return fmt.Sprintf("Mat%dx%d", m, n)
|
|
}
|
|
|
|
func elementNameHelper(m int) string {
|
|
switch m {
|
|
case 0:
|
|
return "X"
|
|
case 1:
|
|
return "Y"
|
|
case 2:
|
|
return "Z"
|
|
case 3:
|
|
return "W"
|
|
default:
|
|
panic("Can't generate element name")
|
|
}
|
|
}
|
|
|
|
func iterHelper(start, end int) []int {
|
|
iter := make([]int, end-start)
|
|
for i := start; i < end; i++ {
|
|
iter[i] = i
|
|
}
|
|
return iter
|
|
}
|
|
|
|
func matrixIterHelper(rows, cols int) []MatrixIter {
|
|
res := make([]MatrixIter, 0, rows*cols)
|
|
|
|
for n := 0; n < cols; n++ {
|
|
for m := 0; m < rows; m++ {
|
|
res = append(res, MatrixIter{
|
|
M: m,
|
|
N: n,
|
|
index: n*rows + m,
|
|
})
|
|
}
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
// Template function that returns slice from its arguments. Indended to be used
|
|
// in range loops.
|
|
func enumHelper(args ...int) []int {
|
|
return args
|
|
}
|
|
|
|
// Template function to insert commas and '+' in range loops.
|
|
func separatorHelper(sep string, iterCond int) string {
|
|
if iterCond > 0 {
|
|
return sep
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// Template function to repeat string 'count' times. Inserting 'sep' between
|
|
// repetitions. Also changes all occurrences of '%d' to repetition number.
|
|
// For example, repeatHelper(3, "col%d", ",") will output "col0, col1, col2"
|
|
func repeatHelper(count int, text string, sep string) string {
|
|
var res bytes.Buffer
|
|
|
|
for i := 0; i < count; i++ {
|
|
if i > 0 {
|
|
res.WriteString(sep)
|
|
}
|
|
res.WriteString(strings.Replace(text, "%d", fmt.Sprintf("%d", i), -1))
|
|
}
|
|
|
|
return res.String()
|
|
}
|
|
|
|
func addHelper(args ...int) int {
|
|
res := 0
|
|
for _, a := range args {
|
|
res += a
|
|
}
|
|
return res
|
|
}
|
|
|
|
func mulHelper(args ...int) int {
|
|
res := 1
|
|
for _, a := range args {
|
|
res *= a
|
|
}
|
|
return res
|
|
}
|
|
|
|
func (i MatrixIter) String() string {
|
|
return fmt.Sprintf("%d", i.index)
|
|
}
|