Example #1
0
func run(t *testing.T, dir, input string) bool {
	fmt.Printf("Input: %s\n", input)

	var inputs []string
	for _, i := range strings.Split(input, " ") {
		inputs = append(inputs, dir+i)
	}

	b := ssa.NewBuilder(ssa.SanityCheckFunctions, ssa.GorootLoader, nil)
	files, err := ssa.ParseFiles(b.Prog.Files, ".", inputs...)
	if err != nil {
		t.Errorf("ssa.ParseFiles(%s) failed: %s", inputs, err.Error())
		return false
	}

	// Print a helpful hint if we don't make it to the end.
	var hint string
	defer func() {
		if hint != "" {
			fmt.Println(red("FAIL"))
			fmt.Println(hint)
		} else {
			fmt.Println(green("PASS"))
		}
	}()

	hint = fmt.Sprintf("To dump SSA representation, run:\n%% go run exp/ssa/ssadump.go -build=CFP %s\n", input)
	mainpkg, err := b.CreatePackage("main", files)
	if err != nil {
		t.Errorf("ssa.Builder.CreatePackage(%s) failed: %s", inputs, err.Error())

		return false
	}

	b.BuildPackage(mainpkg)
	b = nil // discard Builder

	hint = fmt.Sprintf("To trace execution, run:\n%% go run exp/ssa/ssadump.go -build=C -run --interp=T %s\n", input)
	if exitCode := interp.Interpret(mainpkg, 0, inputs[0], []string{}); exitCode != 0 {
		t.Errorf("interp.Interpret(%s) exited with code %d, want zero", inputs, exitCode)
		return false
	}

	hint = "" // call off the hounds
	return true
}
Example #2
0
func main() {
	flag.Parse()
	args := flag.Args()

	// TODO(adonovan): perhaps we need a more extensible option
	// API than a bitset, e.g. a struct with a sane zero value?
	var mode ssa.BuilderMode
	for _, c := range *buildFlag {
		switch c {
		case 'P':
			mode |= ssa.LogPackages
		case 'F':
			mode |= ssa.LogFunctions
		case 'S':
			mode |= ssa.LogSource
		case 'C':
			mode |= ssa.SanityCheckFunctions
		case 'N':
			mode |= ssa.NaiveForm
		case 'G':
			mode |= ssa.UseGCImporter
		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)
		os.Exit(1)
	}

	// Treat all leading consecutive "*.go" arguments as a single package.
	//
	// TODO(gri): make it a typechecker error for there to be
	// duplicate (e.g.) main functions in the same package.
	var gofiles []string
	for len(args) > 0 && strings.HasSuffix(args[0], ".go") {
		gofiles = append(gofiles, args[0])
		args = args[1:]
	}
	if gofiles == nil {
		log.Fatal("No *.go source files specified.")
	}

	// Profiling support.
	if *cpuprofile != "" {
		f, err := os.Create(*cpuprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}

	// TODO(adonovan): permit naming a package directly instead of
	// a list of .go files.

	// TODO(adonovan/gri): the cascade of errors is confusing due
	// to reentrant control flow.  Disable for now and re-think.
	var errh func(error)
	// errh = func(err error) { fmt.Println(err.Error()) }

	b := ssa.NewBuilder(mode, ssa.GorootLoader, errh)
	files, err := ssa.ParseFiles(b.Prog.Files, ".", gofiles...)
	if err != nil {
		log.Fatalf(err.Error())
	}
	mainpkg, err := b.CreatePackage("main", files)
	if err != nil {
		log.Fatalf(err.Error())
	}
	b.BuildPackage(mainpkg)
	b = nil // discard Builder

	if *runFlag {
		interp.Interpret(mainpkg, interpMode, gofiles[0], args)
	}
}