// CompileDir generates C source code for the Calc sources found in the // directory specified by path. The C source file uses the same name as // directory rather than any individual file. func CompileDir(path string, opt bool) error { fset := token.NewFileSet() p, err := parse.ParseDir(fset, path) if err != nil { return err } pkg := ir.MakePackage(p, filepath.Base(path)) if err := ir.TypeCheck(pkg, fset); err != nil { return err } if opt { pkg = ir.FoldConstants(pkg).(*ir.Package) } //ir.Tag(pkg) fp, err := os.Create(filepath.Join(path, filepath.Base(path)) + ".c") if err != nil { return err } defer fp.Close() c := &compiler{fp: fp, fset: fset} c.emitHeaders() c.compPackage(pkg) c.emitMain() if c.errors.Count() != 0 { return c.errors } return nil }
func TestAssignmentFolding(t *testing.T) { test := FoldTest{src: "(= a (* 1 1))", expect: "1"} name := "assign" expr, _ := parse.ParseExpression(name, test.src) o := ir.FoldConstants(ir.MakeExpr(ir.MakePackage(&ast.Package{}, name), expr)) validate_constant(t, name, o.(*ir.Assignment).Rhs, test) }
func TestCallFolding(t *testing.T) { src := "(fn (== 3 2) (+ 2 2))" name := "call" expr, _ := parse.ParseExpression(name, src) o := ir.FoldConstants(ir.MakeExpr(ir.MakePackage(&ast.Package{}, name), expr)) validate_constant(t, name, o.(*ir.Call).Args[0], FoldTest{src, "false"}) validate_constant(t, name, o.(*ir.Call).Args[1], FoldTest{src, "4"}) }
func TestVarFolding(t *testing.T) { test := FoldTest{src: "(var (a:int):int (= a (/ 24 3)))", expect: "8"} name := "var" expr, _ := parse.ParseExpression(name, test.src) o := ir.FoldConstants(ir.MakeExpr(ir.MakePackage(&ast.Package{}, name), expr)) o = o.(*ir.Variable).Body[0].(*ir.Assignment).Rhs validate_constant(t, name, o, test) }
func TestIfFolding(t *testing.T) { src := "(if (== false (!= 3 3)):int (/ 9 3) (* 1 2 3))" name := "if" expr, _ := parse.ParseExpression(name, src) o := ir.FoldConstants(ir.MakeExpr(ir.MakePackage(&ast.Package{}, name), expr)) validate_constant(t, name, o.(*ir.If).Cond, FoldTest{src, "true"}) validate_constant(t, name, o.(*ir.If).Then, FoldTest{src, "3"}) validate_constant(t, name, o.(*ir.If).Else, FoldTest{src, "6"}) }
func TestPackageFolding(t *testing.T) { fs := token.NewFileSet() f1, _ := parse.ParseFile(fs, "package", "(define f1 (func:int (+ 1 2)))") f2, _ := parse.ParseFile(fs, "package", "(define f2 (func:int (* 8 2)))") pkg := &ast.Package{Files: []*ast.File{f1, f2}} o := ir.FoldConstants(ir.MakePackage(pkg, "package")) o1 := o.(*ir.Package).Scope().Lookup("f1") o2 := o.(*ir.Package).Scope().Lookup("f2") validate_constant(t, "package", o1.(*ir.Define).Body.(*ir.Function).Body[0], FoldTest{"", "3"}) validate_constant(t, "package", o2.(*ir.Define).Body.(*ir.Function).Body[0], FoldTest{"", "16"}) }
func test_handler(t *testing.T, test Test, name string, n ast.Node) { var o ir.Object pkg := ir.MakePackage(&ast.Package{}, name) switch x := n.(type) { case *ast.DefineStmt: o = ir.MakeDefine(pkg, x) case *ast.Package: o = ir.MakePackage(x, name) case ast.Expr: o = ir.MakeExpr(pkg, x) t.Log("makexpr, test:", test.src) } t.Log(o) fset := token.NewFileSet() fset.Add(name, len(test.src)) if err := ir.TypeCheck(o, fset); (err == nil) != test.pass { t.Logf("expected %v got %v", test.pass, err == nil) if err != nil { t.Log(err) } t.Fail() } /* ir.Tag(o)*/ }
// CompileFile generates a C source file for the corresponding file // specified by path. The .calc extension for the filename in path is // replaced with .c for the C source output. func CompileFile(path string, opt bool) error { fset := token.NewFileSet() f, err := parse.ParseFile(fset, path, "") if err != nil { return err } pkg := ir.MakePackage(&ast.Package{ Files: []*ast.File{f}, }, filepath.Base(path)) if err := ir.TypeCheck(pkg, fset); err != nil { return err } if opt { pkg = ir.FoldConstants(pkg).(*ir.Package) } //ir.Tag(pkg) path = path[:len(path)-len(filepath.Ext(path))] fp, err := os.Create(path + ".c") if err != nil { return err } defer fp.Close() c := &compiler{fp: fp} c.emitHeaders() c.compPackage(pkg) c.emitMain() if c.errors.Count() != 0 { return c.errors } return nil }
func test_folding(t *testing.T, name string, test FoldTest) { expr, _ := parse.ParseExpression(name, test.src) o := ir.FoldConstants(ir.MakeExpr(ir.MakePackage(&ast.Package{}, name), expr)) validate_constant(t, name, o, test) }