// setGlobal sets the value of a system-initialized global variable. func setGlobal(i *interpreter, pkg *ssa.Package, name string, v value) { if g, ok := i.globals[pkg.Var(name)]; ok { *g = v return } panic("no global variable: " + pkg.Object.Path() + "." + name) }
func (c *compiler) buildPackageInitData(mainPkg *ssa.Package, initmap map[*types.Package]gccgoimporter.InitData) gccgoimporter.InitData { var inits []gccgoimporter.PackageInit for _, imp := range mainPkg.Object.Imports() { inits = append(inits, initmap[imp].Inits...) } sort.Sort(byPriorityThenFunc(inits)) // Deduplicate init entries. We want to preserve the entry with the highest priority. // Normally a package's priorities will be consistent among its dependencies, but it is // possible for them to be different. For example, if a standard library test augments a // package which is a dependency of 'regexp' (which is imported by every test main package) // with additional dependencies, those dependencies may cause the package under test to // receive a higher priority than indicated by its init clause in 'regexp'. uniqinits := make([]gccgoimporter.PackageInit, len(inits)) uniqinitpos := len(inits) uniqinitnames := make(map[string]struct{}) for i, _ := range inits { init := inits[len(inits)-1-i] if _, ok := uniqinitnames[init.InitFunc]; !ok { uniqinitnames[init.InitFunc] = struct{}{} uniqinitpos-- uniqinits[uniqinitpos] = init } } uniqinits = uniqinits[uniqinitpos:] ourprio := 1 if len(uniqinits) != 0 { ourprio = uniqinits[len(uniqinits)-1].Priority + 1 } if imp := mainPkg.Func("init"); imp != nil { impname := c.types.mc.mangleFunctionName(imp) uniqinits = append(uniqinits, gccgoimporter.PackageInit{mainPkg.Object.Name(), impname, ourprio}) } return gccgoimporter.InitData{ourprio, uniqinits} }
// Interpret interprets the Go program whose main package is mainpkg. // mode specifies various interpreter options. filename and args are // the initial values of os.Args for the target program. sizes is the // effective type-sizing function for this program. // // Interpret returns the exit code of the program: 2 for panic (like // gc does), or the argument to os.Exit for normal termination. // // The SSA program must include the "runtime" package. // func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) { i := &interpreter{ prog: mainpkg.Prog, globals: make(map[ssa.Value]*value), mode: mode, sizes: sizes, } runtimePkg := i.prog.ImportedPackage("runtime") if runtimePkg == nil { panic("ssa.Program doesn't include runtime package") } i.runtimeErrorString = runtimePkg.Type("errorString").Object().Type() initReflect(i) i.osArgs = append(i.osArgs, filename) for _, arg := range args { i.osArgs = append(i.osArgs, arg) } for _, pkg := range i.prog.AllPackages() { // Initialize global storage. for _, m := range pkg.Members { switch v := m.(type) { case *ssa.Global: cell := zero(deref(v.Type())) i.globals[v] = &cell } } // Ad-hoc initialization for magic system variables. switch pkg.Object.Path() { case "syscall": setGlobal(i, pkg, "envs", environ) case "runtime": sz := sizes.Sizeof(pkg.Object.Scope().Lookup("MemStats").Type()) setGlobal(i, pkg, "sizeof_C_MStats", uintptr(sz)) // Delete the bodies of almost all "runtime" functions since they're magic. // A missing intrinsic leads to a very clear error. for _, mem := range pkg.Members { if fn, ok := mem.(*ssa.Function); ok { switch fn.Name() { case "GOROOT", "gogetenv": // keep default: fn.Blocks = nil } } } } } // Top-level error handler. exitCode = 2 defer func() { if exitCode != 2 || i.mode&DisableRecover != 0 { return } switch p := recover().(type) { case exitPanic: exitCode = int(p) return case targetPanic: fmt.Fprintln(os.Stderr, "panic:", toString(p.v)) case runtime.Error: fmt.Fprintln(os.Stderr, "panic:", p.Error()) case string: fmt.Fprintln(os.Stderr, "panic:", p) default: fmt.Fprintf(os.Stderr, "panic: unexpected type: %T\n", p) } // TODO(adonovan): dump panicking interpreter goroutine? // buf := make([]byte, 0x10000) // runtime.Stack(buf, false) // fmt.Fprintln(os.Stderr, string(buf)) // (Or dump panicking target goroutine?) }() // Run! call(i, nil, token.NoPos, mainpkg.Func("init"), nil) if mainFn := mainpkg.Func("main"); mainFn != nil { call(i, nil, token.NoPos, mainFn, nil) exitCode = 0 } else { fmt.Fprintln(os.Stderr, "No main function.") exitCode = 1 } return }
func doMain() error { flag.Parse() args := flag.Args() conf := loader.Config{Build: &build.Default} // Choose types.Sizes from conf.Build. var wordSize int64 = 8 switch conf.Build.GOARCH { case "386", "arm": wordSize = 4 } conf.TypeChecker.Sizes = &types.StdSizes{ MaxAlign: 8, WordSize: wordSize, } var interpMode interp.Mode for _, c := range *interpFlag { switch c { case 'T': interpMode |= interp.EnableTracing case 'R': interpMode |= interp.DisableRecover default: return fmt.Errorf("unknown -interp option: '%c'", c) } } if len(args) == 0 { fmt.Fprint(os.Stderr, usage) os.Exit(1) } // Profiling support. if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } // Use the initial packages from the command line. args, err := conf.FromArgs(args, *testFlag) if err != nil { return err } // The interpreter needs the runtime package. if *runFlag { conf.Import("runtime") } // Load, parse and type-check the whole program. iprog, err := conf.Load() if err != nil { return err } // Create and build SSA-form program representation. prog := ssautil.CreateProgram(iprog, *modeFlag) // Build and display only the initial packages // (and synthetic wrappers), unless -run is specified. for _, info := range iprog.InitialPackages() { prog.Package(info.Pkg).Build() } // Run the interpreter. if *runFlag { prog.Build() var main *ssa.Package pkgs := prog.AllPackages() if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Pkg.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } if runtime.GOARCH != build.Default.GOARCH { return fmt.Errorf("cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)", build.Default.GOARCH, runtime.GOARCH) } interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Pkg.Path(), args) } return nil }
func doMain() error { flag.Parse() args := flag.Args() conf := loader.Config{ Build: &build.Default, SourceImports: true, } // TODO(adonovan): make go/types choose its default Sizes from // build.Default or a specified *build.Context. var wordSize int64 = 8 switch conf.Build.GOARCH { case "386", "arm": wordSize = 4 } conf.TypeChecker.Sizes = &types.StdSizes{ MaxAlign: 8, WordSize: wordSize, } var mode ssa.BuilderMode for _, c := range *buildFlag { switch c { case 'D': mode |= ssa.GlobalDebug case 'P': mode |= ssa.PrintPackages case 'F': mode |= ssa.PrintFunctions case 'S': mode |= ssa.LogSource | ssa.BuildSerially case 'C': mode |= ssa.SanityCheckFunctions case 'N': mode |= ssa.NaiveForm case 'G': conf.SourceImports = false case 'L': mode |= ssa.BuildSerially case 'I': mode |= ssa.BareInits default: return fmt.Errorf("unknown -build option: '%c'", c) } } var interpMode interp.Mode for _, c := range *interpFlag { switch c { case 'T': interpMode |= interp.EnableTracing case 'R': interpMode |= interp.DisableRecover default: return fmt.Errorf("unknown -interp option: '%c'", c) } } if len(args) == 0 { fmt.Fprint(os.Stderr, usage) os.Exit(1) } // Profiling support. if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } pprof.StartCPUProfile(f) defer pprof.StopCPUProfile() } // Use the initial packages from the command line. args, err := conf.FromArgs(args, *testFlag) if err != nil { return err } // The interpreter needs the runtime package. if *runFlag { conf.Import("runtime") } // Load, parse and type-check the whole program. iprog, err := conf.Load() if err != nil { return err } // Create and build SSA-form program representation. prog := ssa.Create(iprog, mode) prog.BuildAll() // Run the interpreter. if *runFlag { var main *ssa.Package pkgs := prog.AllPackages() if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Object.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } if runtime.GOARCH != build.Default.GOARCH { return fmt.Errorf("cross-interpretation is not supported (target has GOARCH %s, interpreter has %s)", build.Default.GOARCH, runtime.GOARCH) } interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args) } return nil }
func doCallgraph(ctxt *build.Context, algo, format string, tests bool, args []string) error { conf := loader.Config{ Build: ctxt, SourceImports: true, } if len(args) == 0 { fmt.Fprintln(os.Stderr, Usage) return nil } // Use the initial packages from the command line. args, err := conf.FromArgs(args, tests) if err != nil { return err } // Load, parse and type-check the whole program. iprog, err := conf.Load() if err != nil { return err } // Create and build SSA-form program representation. prog := ssa.Create(iprog, 0) prog.BuildAll() // Determine the main package. // TODO(adonovan): allow independent control over tests, mains // and libraries. // TODO(adonovan): put this logic in a library; we keep reinventing it. var main *ssa.Package pkgs := prog.AllPackages() if tests { // If -test, use all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } } else { // Otherwise, use main.main. for _, pkg := range pkgs { if pkg.Object.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } // Invariant: main package has a main() function. // -- call graph construction ------------------------------------------ var cg *callgraph.Graph switch algo { case "pta": config := &pointer.Config{ Mains: []*ssa.Package{main}, BuildCallGraph: true, } ptares, err := pointer.Analyze(config) if err != nil { return err // internal error in pointer analysis } cg = ptares.CallGraph case "rta": roots := []*ssa.Function{ main.Func("init"), main.Func("main"), } rtares := rta.Analyze(roots, true) cg = rtares.CallGraph // NB: RTA gives us Reachable and RuntimeTypes too. default: return fmt.Errorf("unknown algorithm: %s", algo) } cg.DeleteSyntheticNodes() // -- output------------------------------------------------------------ var before, after string // Pre-canned formats. switch format { case "digraph": format = `{{printf "%q %q" .Caller .Callee}}` case "graphviz": before = "digraph callgraph {\n" after = "}\n" format = ` {{printf "%q" .Caller}} -> {{printf "%q" .Callee}}"` } tmpl, err := template.New("-format").Parse(format) if err != nil { return fmt.Errorf("invalid -format template: %v", err) } // Allocate these once, outside the traversal. var buf bytes.Buffer data := Edge{fset: prog.Fset} fmt.Fprint(stdout, before) if err := callgraph.GraphVisitEdges(cg, func(edge *callgraph.Edge) error { data.position.Offset = -1 data.edge = edge data.Caller = edge.Caller.Func data.Callee = edge.Callee.Func buf.Reset() if err := tmpl.Execute(&buf, &data); err != nil { return err } stdout.Write(buf.Bytes()) if len := buf.Len(); len == 0 || buf.Bytes()[len-1] != '\n' { fmt.Fprintln(stdout) } return nil }); err != nil { return err } fmt.Fprint(stdout, after) return nil }
func doTestable(args []string) error { conf := loader.Config{ Build: &build.Default, } // TODO(adonovan): make go/types choose its default Sizes from // build.Default or a specified *build.Context. var wordSize int64 = 8 switch conf.Build.GOARCH { case "386", "arm": wordSize = 4 } //if !(*runFlag) { wordSize = 4 // TARDIS Go addition to force default int size to 32 bits conf.Build.GOARCH = "haxe" // TARDIS Go addition - 32-bit int conf.Build.GOOS = "nacl" // or haxe? TARDIS Go addition - simplest OS-specific code to emulate? //} conf.Build.BuildTags = strings.Split(*buidTags, " ") conf.TypeChecker.Sizes = &types.StdSizes{ // must equal haxe.haxeStdSizes when (!*runFlag) MaxAlign: 8, WordSize: wordSize, } var mode ssa.BuilderMode /* for _, c := range *buildFlag { switch c { case 'D': mode |= ssa.GlobalDebug case 'P': mode |= ssa.PrintPackages case 'F': mode |= ssa.PrintFunctions case 'S': mode |= ssa.LogSource | ssa.BuildSerially case 'C': mode |= ssa.SanityCheckFunctions case 'N': mode |= ssa.NaiveForm case 'L': mode |= ssa.BuildSerially case 'I': mode |= ssa.BareInits default: return fmt.Errorf("unknown -build option: '%c'", c) } } */ // TARDIS go addition if *debugFlag { mode |= ssa.GlobalDebug } var interpMode interp.Mode for _, c := range *interpFlag { switch c { case 'T': interpMode |= interp.EnableTracing case 'R': interpMode |= interp.DisableRecover default: log.Fatalf("Unknown -interp option: '%c'.", c) } } if len(args) == 0 { //fmt.Fprint(os.Stderr, usage) return fmt.Errorf("%v", usage) } // Profiling support. if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { return err } err = pprof.StartCPUProfile(f) if err != nil { return err } defer pprof.StopCPUProfile() } // TODO Eventually this might be better as an environment variable //if !(*runFlag) { if *tgoroot == "" { if conf.Build.GOPATH == "" { return fmt.Errorf("GOPATH must be set") } conf.Build.GOROOT = strings.Split(conf.Build.GOPATH, ":")[0] + "/src/github.com/tardisgo/tardisgo/goroot/haxe/go1.4" } else { conf.Build.GOROOT = *tgoroot } //} //fmt.Println("DEBUG GOPATH", conf.Build.GOPATH) //fmt.Println("DEBUG GOROOT", conf.Build.GOROOT) if *testFlag { conf.ImportWithTests(args[0]) // assumes you give the full cannonical name of the package to test args = args[1:] } // Use the initial packages from the command line. _, err := conf.FromArgs(args, *testFlag) if err != nil { return err } // The interpreter needs the runtime package. //if *runFlag { conf.Import("runtime") //} else { // TARDIS GO additional line to add the language specific go runtime code conf.Import(pogo.LanguageList[pogo.TargetLang].Goruntime) // TODO add code to set pogo.TargetLang when more than one of them //} // Load, parse and type-check the whole program, including the type definitions. iprog, err := conf.Load() if err != nil { return err } // Create and build SSA-form program representation. *modeFlag |= mode | ssa.SanityCheckFunctions prog := ssautil.CreateProgram(iprog, *modeFlag) prog.BuildAll() // Run the interpreter. if *runFlag { var main *ssa.Package pkgs := prog.AllPackages() if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Object.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } // NOTE TARDIS Go removal of this test required if we alter the GOARCH to stop architecture-specific code //if runtime.GOARCH != build.Default.GOARCH { // return fmt.Errorf("cross-interpretation is not yet supported (target has GOARCH %s, interpreter has %s)", // build.Default.GOARCH, runtime.GOARCH) //} interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args) } else { // if not interpreting... // TARDIS Go additions: copy run interpreter code above, but call pogo class var main *ssa.Package pkgs := prog.AllPackages() //fmt.Println("DEBUG pkgs:", pkgs) if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } fd, err := os.Open(TestFS) fd.Close() if err == nil { LoadTestZipFS = true for l := range pogo.LanguageList { pogo.LanguageList[l].TestFS = TestFS } } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Object.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } /* if runtime.GOARCH != build.Default.GOARCH { return fmt.Errorf("cross-interpretation is not yet supported (target has GOARCH %s, interpreter has %s)", build.Default.GOARCH, runtime.GOARCH) } interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Object.Path(), args) */ pogo.DebugFlag = *debugFlag pogo.TraceFlag = *traceFlag err = pogo.EntryPoint(main) // TARDIS Go entry point, returns an error if err != nil { return err } results := make(chan resChan) switch *allFlag { case "": // NoOp case "all", "bench": //for _, dir := range dirs { // err := os.RemoveAll(dir) // if err != nil { // fmt.Println("Error deleting existing '" + dir + "' directory: " + err.Error()) // } //} var targets [][][]string if *allFlag == "bench" { targets = allBenchmark // fast execution time } else { targets = allCompile // fast compile time } for _, cmd := range targets { go doTarget(cmd, results) } for _ = range targets { r := <-results fmt.Println(r.output) if (r.err != nil || len(strings.TrimSpace(r.output)) == 0) && *allFlag != "bench" { os.Exit(1) // exit with an error if the test fails, but not for benchmarking } r.backChan <- true } case "math": // which is faster for the test with correct math processing, cpp or js? //err := os.RemoveAll("tardis/cpp") //if err != nil { // fmt.Println("Error deleting existing '" + "tardis/cpp" + "' directory: " + err.Error()) //} mathCmds := [][][]string{ [][]string{ []string{"haxe", "-main", "tardis.Go", "-cp", "tardis", "-dce", "full", "-D", "inlinepointers", "-cpp", "tardis/cpp"}, []string{"echo", `"CPP:"`}, []string{"time", "./tardis/cpp/Go"}, }, [][]string{ []string{"haxe", "-main", "tardis.Go", "-cp", "tardis", "-dce", "full", "-D", "inlinepointers", "-D", "fullunsafe", "-js", "tardis/go-fu.js"}, []string{"echo", `"Node/JS using fullunsafe memory mode (js dataview):"`}, []string{"time", "node", "tardis/go-fu.js"}, }, } for _, cmd := range mathCmds { go doTarget(cmd, results) } for _ = range mathCmds { r := <-results fmt.Println(r.output) if r.err != nil { os.Exit(1) // exit with an error if the test fails } r.backChan <- true } case "interp", "cpp", "cs", "js", "jsfu", "java": // for running tests switch *allFlag { case "interp": go doTarget([][]string{ []string{"echo", ``}, // Output from this line is ignored []string{"echo", `"Neko (haxe --interp):"`}, []string{"time", "haxe", "-main", "tardis.Go", "-cp", "tardis", "--interp"}, }, results) case "cpp": go doTarget([][]string{ []string{"haxe", "-main", "tardis.Go", "-cp", "tardis", "-dce", "full", "-D", "inlinepointers", "-cpp", "tardis/cpp"}, []string{"echo", `"CPP:"`}, []string{"time", "./tardis/cpp/Go"}, }, results) case "cs": go doTarget([][]string{ []string{"haxe", "-main", "tardis.Go", "-cp", "tardis", "-dce", "full", "-D", "inlinepointers", "-cs", "tardis/cs"}, []string{"echo", `"CS:"`}, []string{"time", "mono", "./tardis/cs/bin/Go.exe"}, }, results) case "js": go doTarget([][]string{ []string{"haxe", "-main", "tardis.Go", "-cp", "tardis", "-dce", "full", "-D", "inlinepointers", "-D", "uselocalfunctions", "-js", "tardis/go.js"}, []string{"echo", `"Node/JS:"`}, []string{"time", "node", "tardis/go.js"}, }, results) case "jsfu": go doTarget([][]string{ []string{"haxe", "-main", "tardis.Go", "-cp", "tardis", "-dce", "full", "-D", "inlinepointers", "-D", "uselocalfunctions", "-D", "fullunsafe", "-js", "tardis/go-fu.js"}, []string{"echo", `"Node/JS using fullunsafe memory mode (js dataview):"`}, []string{"time", "node", "tardis/go-fu.js"}, }, results) case "java": go doTarget([][]string{ []string{"haxe", "-main", "tardis.Go", "-cp", "tardis", "-dce", "full", "-D", "inlinepointers", "-java", "tardis/java"}, []string{"echo", `"Java:"`}, []string{"time", "java", "-jar", "tardis/java/Go.jar"}, }, results) } r := <-results fmt.Println(r.output) if r.err != nil { os.Exit(1) // exit with an error if the test fails } r.backChan <- true default: panic("invalid value for -haxe flag: " + *allFlag) } } return nil }
func doTestable(args []string) error { conf := loader.Config{ Build: &build.Default, } // TARDISgo addition langName := *targetFlag langEntry, e := pogo.FindTargetLang(langName) if e != nil { return e } // TODO(adonovan): make go/types choose its default Sizes from // build.Default or a specified *build.Context. var wordSize int64 = 8 switch conf.Build.GOARCH { case "386", "arm": wordSize = 4 } if *runFlag { // nothing here at the moment } else { wordSize = 4 // TARDIS Go addition to force default int size to 32 bits conf.Build.GOOS = "nacl" // TARDIS Go addition - simplest OS-specific code to emulate? conf.Build.GOARCH = langName // TARDIS Go addition } conf.Build.BuildTags = strings.Split(*buidTags, " ") conf.TypeChecker.Sizes = &types.StdSizes{ // must equal haxe.haxeStdSizes when (!*runFlag) MaxAlign: 8, WordSize: wordSize, } var mode ssa.BuilderMode /* for _, c := range *buildFlag { switch c { case 'D': mode |= ssa.GlobalDebug case 'P': mode |= ssa.PrintPackages case 'F': mode |= ssa.PrintFunctions case 'S': mode |= ssa.LogSource | ssa.BuildSerially case 'C': mode |= ssa.SanityCheckFunctions case 'N': mode |= ssa.NaiveForm case 'L': mode |= ssa.BuildSerially case 'I': mode |= ssa.BareInits default: return fmt.Errorf("unknown -build option: '%c'", c) } } */ // TARDIS go addition if *debugFlag { mode |= ssa.GlobalDebug } var interpMode interp.Mode for _, c := range *interpFlag { switch c { case 'T': interpMode |= interp.EnableTracing case 'R': interpMode |= interp.DisableRecover default: log.Fatalf("Unknown -interp option: '%c'.", c) } } if len(args) == 0 { //fmt.Fprint(os.Stderr, usage) return fmt.Errorf("%v", usage) } // Profiling support. if *cpuprofile != "" { f, err := os.Create(*cpuprofile) if err != nil { return err } err = pprof.StartCPUProfile(f) if err != nil { return err } defer pprof.StopCPUProfile() } if !(*runFlag) { if *tgoroot == "" { if conf.Build.GOPATH == "" { return fmt.Errorf("GOPATH must be set") } langGOROOT := pogo.LanguageList[langEntry].GOROOT if langGOROOT != "" { conf.Build.GOROOT = strings.Split(conf.Build.GOPATH, ":")[0] + langGOROOT } else { if conf.Build.GOROOT == "" { return fmt.Errorf("GOROOT must be set (hint: use -tgoroot flag)") } } } else { conf.Build.GOROOT = *tgoroot } } //fmt.Println("DEBUG GOPATH", conf.Build.GOPATH) //fmt.Println("DEBUG GOROOT", conf.Build.GOROOT) if *testFlag { conf.ImportWithTests(args[0]) // assumes you give the full cannonical name of the package to test args = args[1:] } // Use the initial packages from the command line. _, err := conf.FromArgs(args, *testFlag) if err != nil { return err } // The interpreter needs the runtime package. if *runFlag { conf.Import("runtime") } else { // TARDIS GO additional line to add the language specific go runtime code rt := pogo.LanguageList[langEntry].Goruntime if rt != "" { conf.Import(rt) } } // Load, parse and type-check the whole program. iprog, err := conf.Load() if err != nil { return err } // Create and build SSA-form program representation. *modeFlag |= mode | ssa.SanityCheckFunctions prog := ssautil.CreateProgram(iprog, *modeFlag) prog.Build() var main *ssa.Package pkgs := prog.AllPackages() //fmt.Println("DEBUG pkgs:", pkgs) testFSname := "" if *testFlag { // If -test, run all packages' tests. if len(pkgs) > 0 { main = prog.CreateTestMainPackage(pkgs...) } if main == nil { return fmt.Errorf("no tests") } fd, openErr := os.Open(testFS) closeErr := fd.Close() if openErr == nil && closeErr == nil { loadTestZipFS = true testFSname = testFS } } else { // Otherwise, run main.main. for _, pkg := range pkgs { if pkg.Pkg.Name() == "main" { main = pkg if main.Func("main") == nil { return fmt.Errorf("no func main() in main package") } break } } if main == nil { return fmt.Errorf("no main package") } } if *runFlag { // Run the golang.org/x/tools/go/ssa/interp interpreter. interp.Interpret(main, interpMode, conf.TypeChecker.Sizes, main.Pkg.Path(), args) } else { comp, err := pogo.Compile(main, *debugFlag, *traceFlag, langName, testFSname) // TARDIS Go entry point, returns an error if err != nil { return err } comp.Recycle() switch langName { case "haxe": haxe.RunHaxe(allFlag, loadTestZipFS, testFSname) } } return nil }