Example #1
0
func doTestable(args []string) error {

	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
	}

	wordSize = 4 // TARDIS Go addition to force default int size to 32 bits
	//conf.Build.GOARCH = "tardisgo" // TARDIS Go addition to ensure no architecure-specific code will compile
	//conf.Build.GOOS = "tardisgo"   // TARDIS Go addition to ensure no OS-specific code will compile

	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.LogPackages | ssa.BuildSerially
		case 'F':
			mode |= ssa.LogFunctions | ssa.BuildSerially
		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
		default:
			log.Fatalf("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:
			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
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	// TARDIS Go TEST
	// Really need to find a way to replace entire packages, this experiment did not work...
	/*
		conf.Fset = token.NewFileSet()
		f, err := parser.ParseFile(conf.Fset, conf.Build.GOPATH+"/src/github.com/tardisgo/tardisgo/golibruntime/runtime/runtime.go", nil, 0)
		if err != nil {
			fmt.Println(err)
			return err
		}
		conf.CreateFromFiles("", f)
		fmt.Printf("DEBUG %s %s\n", f.Name.Name, "") //, f.Name.Obj.Name)
	*/
	// end TARDIS Go TEST

	// 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")
		conf.Import("github.com/tardisgo/tardisgo/golibruntime/runtime") // This required for TARDIS go to run runtime
	}

	// 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.
	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")
			}
		}

		// 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)
	}

	// TARDIS Go additions: copy run interpreter code above, but call pogo class
	if true {
		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 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)
		*/
		err = pogo.EntryPoint(main) // TARDIS Go entry point, returns an error
		if err != nil {
			return err
		}
		if *allFlag {
			targets := [][][]string{
				[][]string{
					[]string{"haxe", "-main", "tardis.Go", "-dce", "full", "-cpp", "cpp"},
					[]string{"echo", `"CPP:"`},
					[]string{"./cpp/Go"},
				},
				[][]string{
					[]string{"haxe", "-main", "tardis.Go", "-dce", "full", "-java", "java"},
					[]string{"echo", `"Java:"`},
					[]string{"java", "-jar", "java/Go.jar"},
				},
				[][]string{
					[]string{"haxe", "-main", "tardis.Go", "-dce", "full", "-cs", "cs"},
					[]string{"echo", `"CS:"`},
					[]string{"mono", "./cs/bin/Go.exe"},
				},
				[][]string{
					[]string{"haxe", "-main", "tardis.Go", "-dce", "full", "-neko", "tardisgo.n"},
					[]string{"echo", `"Neko:"`},
					[]string{"neko", "tardisgo.n"},
				},
				[][]string{
					[]string{"haxe", "-main", "tardis.Go", "-dce", "full", "-js", "tardisgo.js"},
					[]string{"echo", `"Node/JS:"`},
					[]string{"node", "tardisgo.js"},
				},
				[][]string{
					[]string{"haxe", "-main", "tardis.Go", "-dce", "full", "-swf", "tardisgo.swf"},
					[]string{"echo", `"Opening swf file (Chrome as a file association for swf works to test on OSX):"` + "\n"},
					[]string{"open", "tardisgo.swf"},
				},
				[][]string{
					[]string{"haxe", "-main", "tardis.Go", "-dce", "full", "-php", "php", "--php-prefix", "tgo"},
					[]string{"echo", `"PHP:"`},
					[]string{"php", "php/index.php"},
				},
				[][]string{
					[]string{"echo", ``}, // Output from this line is ignored
					[]string{"echo", `"Neko (haxe --interp):"`},
					[]string{"haxe", "-main", "tardis.Go", "--interp"},
				},
			}
			results := make(chan string, len(targets))
			for id, cmd := range targets {
				go func(i int, cl [][]string) {
					res := ""
					for j, c := range cl {
						exe := c[0]
						if exe == "echo" {
							res += c[1]
						} else {
							_, err := exec.LookPath(exe)
							if err != nil {
								switch exe {
								case "node":
									exe = "nodejs" // for Ubuntu
								default:
									res += "TARDISgo error - executable not found: " + exe + "\n"
									exe = "" // nothing to execute
								}
							}
							if exe != "" {
								out, err := exec.Command(exe, c[1:]...).CombinedOutput()
								if err != nil {
									out = append(out, []byte(err.Error())...)
								}
								if j > 0 { // ignore the output from the compile phase
									res += string(out)
								}
							}
						}
					}
					results <- res
				}(id, cmd)
			}
			for t := 0; t < len(targets); t++ {
				fmt.Println(<-results)
			}
		}
	}
	return nil
}
Example #2
0
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
}