func TestParseVar(t *testing.T) { types := []Type{FILE, DECL, IDENT, IDENT, VAR, IDENT, IDENT} src := "(decl main int (var a int))" file := token.NewFile("var.calc", 1, len(src)) f := parse.ParseFile(file, "var.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) types = []Type{FILE, DECL, IDENT, IDENT, VAR, IDENT, IDENT, ASSIGN, IDENT, BASIC} src = "(decl main int (var (= a 5) int))" file = token.NewFile("var2.calc", 1, len(src)) f = parse.ParseFile(file, "var2.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) types = []Type{FILE, DECL, IDENT, IDENT, VAR, IDENT, ASSIGN, IDENT, BASIC} src = "(decl main int (var (= a 5)))" file = token.NewFile("var3.calc", 1, len(src)) f = parse.ParseFile(file, "var3.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) }
func TestParseIf(t *testing.T) { types := []Type{FILE, DECL, IDENT, IDENT, IF, IDENT, IDENT, BASIC} src := "(decl main int (if true int 3))" file := token.NewFile("if.calc", 1, len(src)) f := parse.ParseFile(file, "if.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) types = []Type{FILE, DECL, IDENT, IDENT, IF, BINARY, IDENT, IDENT, IDENT, IDENT, LIST, BINARY, IDENT, BASIC, IDENT} src = "(decl main int (if (< a b) int a ((+ b 1) b)))" file = token.NewFile("if2.calc", 1, len(src)) f = parse.ParseFile(file, "if2.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) types = []Type{FILE, DECL, IDENT, IDENT, IF, BINARY, IDENT, IDENT, LIST, ASSIGN, IDENT, IDENT} src = "(decl main int (if (< a b) ((= a b))))" file = token.NewFile("if3.calc", 1, len(src)) f = parse.ParseFile(file, "if3.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) }
func TestParseDecl(t *testing.T) { types := []Type{FILE, DECL, IDENT, IDENT, IDENT} src := "(decl func int a)" file := token.NewFile("decl1.calc", 1, len(src)) f := parse.ParseFile(file, "decl1.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) types = []Type{FILE, DECL, IDENT, IDENT, BINARY, BASIC, BASIC} src = "(decl five int (+ 2 3))" file = token.NewFile("decl2.calc", 1, len(src)) f = parse.ParseFile(file, "decl1.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) types = []Type{FILE, DECL, IDENT, IDENT, IDENT, IDENT, BINARY, IDENT, IDENT} src = "(decl add(a b int) int (+ a b))" file = token.NewFile("decl3.calc", 1, len(src)) f = parse.ParseFile(file, "decl2.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) }
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 TestExpectFail(t *testing.T) { var tests = []string{ "+ 3 5)", "(- 5)", "(3 5 +)", "(3 + 4)", "(+ 6 2", "(- 4 5)2", "(d", "(% / d)", "(& 3 5)", "((+ 3 5) 5)", "(* (- 2 6) (+ 4 2)())", ";comment", "(var a)", "(decl main () int a)", "(decl main int ())", "(decl main int a)(decl main in b)", "(var a)", "(var (+ a b))", "(var 23)", "(var a int)(var a int)", } for _, src := range tests { file := token.NewFile("expectfail", 1, len(src)) if f := parse.ParseFile(file, "expectfail", src); f != nil { t.Log(src, "- not nil") t.Fail() } } }
func CompileFile(path string) { var c compiler c.fset = token.NewFileSet() f := parse.ParseFile(c.fset, path) if f == nil { os.Exit(1) } path = path[:len(path)-len(filepath.Ext(path))] fp, err := os.Create(path + ".c") if err != nil { fmt.Println(err) os.Exit(1) } defer fp.Close() c.fp = fp c.compFile(f) if c.errors.Count() != 0 { c.errors.Print() os.Exit(1) } }
func test_file(t *testing.T, name string, test Test) { f, err := parse.ParseFile(token.NewFileSet(), name, test.src) if err != nil { t.Fatal(err) } test_handler(t, test, name, &ast.Package{Files: []*ast.File{f}}) }
func TestParseFileBasic(t *testing.T) { types := []Type{FILE, DECL, IDENT, IDENT, BINARY, BASIC, BASIC} src := "(decl main int (+ 1 2))" file := token.NewFile("basicdec", 1, len(src)) f := parse.ParseFile(file, "basicdec", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) }
func TestParseNested(t *testing.T) { var types = []Type{FILE, DECL, IDENT, IDENT, BINARY, BINARY, BASIC, BASIC, BASIC, BINARY, BASIC, BASIC} src := ";comment\n(decl main int (+ (/ 9 3) 5 (- 3 1)))" file := token.NewFile("nested.calc", 1, len(src)) f := parse.ParseFile(file, "nested.calc", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) }
func TestParseCall(t *testing.T) { types := []Type{FILE, DECL, IDENT, IDENT, CALL, IDENT, BASIC, BASIC, BASIC, BASIC} src := "(decl main int (add 1 2 3 4))" file := token.NewFile("call1", 1, len(src)) f := parse.ParseFile(file, "call1", "(decl main int (add 1 2 3 4))") if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) types = []Type{FILE, DECL, IDENT, IDENT, CALL, IDENT} src = "(decl main int (nothing))" file = token.NewFile("call1", 1, len(src)) f = parse.ParseFile(file, "call1", src) if f == nil { t.Fatal("Failed to parse") } ast.Walk(f, nodeTest(types, t)) }
func TestParseFile(t *testing.T) { test := Test{"bad-ext", "", []Type{}, false} // test for file with bad extension f, err := ioutil.TempFile("", "") if err != nil { t.Log(err) } defer func() { f.Close() err := os.Remove(f.Name()) t.Log(err) }() n, err := parse.ParseFile(token.NewFileSet(), f.Name(), "") checkTest(t, test, n, err) test = Test{"simple.calc", "(define main (func:int 0))", []Type{FILE, DEFINE, FUNC, BASIC}, true} f, err = os.Create(test.name) if err != nil { t.Log(err) } defer func() { f.Close() if err := os.Remove(f.Name()); err != nil { t.Log(err) } }() _, err = f.WriteString(test.src) if err != nil { t.Fatal(err) } n, err = parse.ParseFile(token.NewFileSet(), f.Name(), "") }
// 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 }
// 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) error { var c compiler c.fset = token.NewFileSet() f, err := parse.ParseFile(c.fset, path, nil) if err != nil { return err } path = path[:len(path)-len(filepath.Ext(path))] fp, err := os.Create(path + ".c") if err != nil { return err } defer fp.Close() c.fp = fp c.compFile(f) if c.errors.Count() != 0 { return c.errors } return nil }
func handleFileTests(t *testing.T, tests []Test) { for _, test := range tests { f, err := parse.ParseFile(token.NewFileSet(), test.name, test.src) checkTest(t, test, f, err) } }