Procedural macro toolbox for Golang.
go get github.com/tdakkota/gomacro
package main
import (
"go/ast"
"io/ioutil"
"os"
builders "github.com/tdakkota/astbuilders"
macro "github.com/tdakkota/gomacro"
"github.com/tdakkota/gomacro/runner"
)
// hello() -> println("Hello, ", "World")
// hello(arg) -> println("Hello, ", arg)
// hello(args...) -> println("Hello, ", args...)
func Macro() macro.Handler {
return macro.OnlyFunction("hello", func(ctx macro.Context, call *ast.CallExpr) error {
args := append([]ast.Expr{builders.StringLit("hello, ")}, call.Args...)
if len(call.Args) == 0 {
args = append(args, builders.StringLit("world"))
}
toReplace := builders.CallName("println", args...)
ctx.Replace(toReplace)
return nil
})
}
const src = `
package main
//procm:use=runme
func main() {
hello()
}
`
func writeTempFile(src string) (string, error) {
f, err := ioutil.TempFile("", "src.*.go")
if err != nil {
return "", err
}
defer f.Close()
_, err = f.WriteString(src)
if err != nil {
return "", err
}
return f.Name(), nil
}
func main() {
srcPath, err := writeTempFile(src)
if err != nil {
panic(err)
}
err = runner.Print(srcPath, os.Stdout, macro.Macros{
"runme": Macro(),
})
if err != nil {
panic(err)
}
}
Output:
package main
//procm:use=runme
func main() {
println("hello, ", "world")
}