Exemple #1
0
func runImage(bs []byte, dasm bool, n int) {
	if dasm {
		err := dasm8.DumpImage(bytes.NewReader(bs), os.Stdout)
		if err != nil {
			fmt.Println(err)
		}
	}
	if len(bs) == 0 {
		fmt.Println("(the image is empty)")
		return
	}

	m := arch8.NewMachine(new(arch8.Config))
	if err := m.LoadImageBytes(bs); err != nil {
		fmt.Println(err)
		return
	}

	ncycle, exp := m.Run(n)
	fmt.Printf("(%d cycles)\n", ncycle)
	if exp != nil {
		if !arch8.IsHalt(exp) {
			fmt.Println(exp)
			err := arch8.FprintStack(os.Stdout, m, exp)
			if err != nil {
				fmt.Println(err)
			}
		}
	} else {
		fmt.Println("(end of time)")
	}
}
Exemple #2
0
func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) != 1 {
		log.Fatal("need exactly one input file\n")
	}

	fname := args[0]

	if *doDasm {
		f, err := os.Open(fname)
		defer f.Close()

		err = dasm8.DumpImage(f, os.Stdout)
		if err != nil {
			log.Fatal(err)
		}
	} else if *printDebug {
		f, err := os.Open(fname)
		defer f.Close()

		secs, err := e8.Read(f)
		if err != nil {
			log.Fatal(err)
		}

		for _, sec := range secs {
			if sec.Type != e8.Debug {
				continue
			}

			tab, err := debug8.UnmarshalTable(sec.Bytes)
			if err != nil {
				log.Fatal(err)
			}

			tab.PrintTo(os.Stdout)
		}
	} else {
		bs, err := ioutil.ReadFile(fname)
		if err != nil {
			log.Fatal(err)
		}
		n, e := run(bs)
		fmt.Printf("(%d cycles)\n", n)
		if e != nil {
			if !arch8.IsHalt(e) {
				fmt.Println(e)
			}
		} else {
			fmt.Println("(end of time)")
		}
	}
}
Exemple #3
0
func main() {
	flag.Parse()

	args := flag.Args()
	if len(args) != 1 {
		log.Fatal("need exactly one input file\n")
	}

	fname := args[0]
	var bs []byte
	f, e := os.Open(fname)
	if e != nil {
		log.Fatalf("open: %s", e)
	}

	var es []*lex8.Error
	if strings.HasSuffix(fname, "_bare.s") {
		bs, es = asm8.BuildBareFunc(fname, f)
	} else {
		bs, es = asm8.BuildSingleFile(fname, f)
	}

	if len(es) > 0 {
		for _, e := range es {
			fmt.Println(e)
		}
		os.Exit(-1)
		return
	}

	if *doDasm {
		lines := dasm8.Dasm(bs, arch8.InitPC)
		for _, line := range lines {
			fmt.Println(line)
		}
	} else {
		n, e := run(bs)
		fmt.Printf("(%d cycles)\n", n)
		if e != nil {
			if !arch8.IsHalt(e) {
				fmt.Println(e)
			}
		} else {
			fmt.Println("(end of time)")
		}
	}
}
Exemple #4
0
func run(bs []byte) (int, error) {
	// create a single core machine
	m := arch8.NewMachine(uint32(*memSize), 1)
	secs, err := e8.Read(bytes.NewReader(bs))
	if err != nil {
		return 0, err
	}

	if err := m.LoadSections(secs); err != nil {
		return 0, err
	}

	if *bootArg > math.MaxUint32 {
		log.Fatalf("boot arg(%d) is too large", *bootArg)
	}
	if err := m.WriteWord(arch8.AddrBootArg, uint32(*bootArg)); err != nil {
		return 0, err
	}

	if *romRoot != "" {
		m.MountROM(*romRoot)
	}
	if *randSeed != 0 {
		m.RandSeed(*randSeed)
	}

	ret, exp := m.Run(*ncycle)
	if *printStatus {
		m.PrintCoreStatus()
	}

	if !arch8.IsHalt(exp) {
		fmt.Println(exp)
		err := arch8.FprintStack(os.Stdout, m, exp)
		if err != nil {
			log.Fatal(err)
		}
	}

	if exp == nil {
		return ret, nil
	}
	return ret, exp
}
Exemple #5
0
func run(bs []byte) (int, error) {
	if *bootArg > math.MaxUint32 {
		log.Fatalf("boot arg(%d) is too large", *bootArg)
	}

	// create a single core machine
	m := arch8.NewMachine(&arch8.Config{
		MemSize:  uint32(*memSize),
		ROM:      *romRoot,
		RandSeed: *randSeed,
		BootArg:  uint32(*bootArg),
	})

	secs, err := e8.Read(bytes.NewReader(bs))
	if err != nil {
		return 0, err
	}

	if err := m.LoadSections(secs); err != nil {
		return 0, err
	}

	ret, exp := m.Run(*ncycle)
	if *printStatus {
		m.PrintCoreStatus()
	}

	if !arch8.IsHalt(exp) {
		fmt.Println(exp)
		err := arch8.FprintStack(os.Stdout, m, exp)
		if err != nil {
			log.Fatal(err)
		}
	}

	if exp == nil {
		return ret, nil
	}
	return ret, exp
}
Exemple #6
0
func runImage(bs []byte, dasm bool, n int) {
	if dasm {
		err := dasm8.DumpImage(bytes.NewReader(bs), os.Stdout)
		if err != nil {
			fmt.Println(err)
		}
	}
	if len(bs) == 0 {
		fmt.Println("(the image is empty)")
		return
	}

	ncycle, e := arch8.RunImage(bs, n)
	fmt.Printf("(%d cycles)\n", ncycle)
	if e != nil {
		if !arch8.IsHalt(e) {
			fmt.Println(e)
		}
	} else {
		fmt.Println("(end of time)")
	}
}
Exemple #7
0
func runTests(
	log lex8.Logger, tests map[string]uint32, img []byte, verbose bool,
) {
	report := func(name string, pass bool, err error) {
		if !pass {
			lex8.LogError(log, fmt.Errorf("%s failed: got %s", name, err))
			if verbose {
				fmt.Println("FAILED")
			}
			return
		}

		if verbose {
			fmt.Println("pass")
		}
	}

	var testNames []string
	for name := range tests {
		testNames = append(testNames, name)
	}
	sort.Strings(testNames)

	for _, test := range testNames {
		if verbose {
			fmt.Printf("  - %s: ", test)
		}

		arg := tests[test]
		_, err := arch8.RunImageArg(img, arg)
		if strings.HasPrefix(test, "TestBad") {
			report(test, arch8.IsPanic(err), err)
		} else {
			report(test, arch8.IsHalt(err), err)
		}
	}
}
Exemple #8
0
func TestMultiFile(t *testing.T) {
	const N = 100000

	o := func(fs map[string]string, output string) {
		out, err := multiTestRun(t, fs, N)
		if err == errRunFailed {
			t.Error(err)
			return
		}

		if !arch8.IsHalt(err) {
			t.Log(fs)
			t.Log(err)
			t.Error("did not halt gracefully")
			return
		}

		got := strings.TrimSpace(out)
		expect := strings.TrimSpace(output)
		if got != expect {
			t.Log(fs)
			t.Logf("expect: %s", expect)
			t.Errorf("got: %s", got)
		}
	}
	type files map[string]string

	o(files{
		"main/m.g": "func main() { }",
	}, "")

	o(files{
		"a/a.g": "func P() { printInt(33) }",
		"main/m.g": `
			import ( "a" )
			func main() { a.P() }`,
	}, "33")

	o(files{
		"a/a.g":    "struct A { func P() { printInt(33) } }",
		"b/b.g":    `import ("a"); var A a.A`,
		"main/m.g": `import ("b"); func main() { b.A.P() }`,
	}, "33")

	o(files{
		"a/a.g":    "func init() { printInt(33) }",
		"b/b.g":    `import (_ "a"); func init() { printInt(44) }`,
		"main/m.g": `import (_ "b"); func main() { printInt(55) }`,
	}, "33\n44\n55")

	o(files{
		"a/a.g": "const A=33",
		"main/m.g": `
			import ("a")
			var array [a.A]int
			func main() { printInt(len(array)) }`,
	}, "33")
	o(files{
		"a/a.g": "const A=33+5-2",
		"main/m.g": `
			import ("a")
			var array [a.A-3]int
			func main() { printInt(len(array)) }`,
	}, "33")

	o(files{
		"asm/a/a.g": `
			func F {
				mov pc ret
			}`,
		"main/m.g": `
			import ("asm/a")
			func main() { a.F(); printInt(33) }`,
	}, "33")

	o(files{
		"asm/a/a.g": `
			func F {
				addi r1 r0 33
				mov pc ret
			}`,
		"main/m.g": `
			import ("asm/a")
			func f() int = a.F
			func main() { printInt(f()) }`,
	}, "33")
}
Exemple #9
0
func TestBareFunc_good(t *testing.T) {
	const N = 100000
	o := func(input, output string) {
		out, e := bareTestRun(t, input, N)
		if e == errRunFailed {
			t.Error(e)
			return
		}
		if !arch8.IsHalt(e) {
			t.Log(input)
			t.Log(e)
			t.Error("did not halt gracefully")
			return
		}
		out = strings.TrimSpace(out)
		output = strings.TrimSpace(output)
		if out != output {
			t.Log(input)
			t.Logf("expect: %s", output)
			t.Errorf("got: %s", out)
		}
	}

	o(";;;;", "")
	o("printInt(0)", "0")
	o("printInt(3)", "3")
	o("printInt(-444)", "-444")
	o("printInt(2147483647)", "2147483647")
	o("printInt(-2147483647-1)", "-2147483648")
	o("printInt(-2147483648)", "-2147483648")
	o("printInt(300000000)", "300000000")
	o("printInt(4*5+3)", "23")
	o("printInt(3+4*5)", "23")
	o("printInt((3+4)*5)", "35")
	o("printInt((5*(3+4)))", "35")
	o("printInt(3^1)", "2")
	o("printInt(0xf)", "15")
	o("printInt(0xA)", "10")
	o("a:=3; if a==3 { printInt(5) }", "5")
	o("a:=5; if a==3 { printInt(5) }", "")
	o("a:=5; if a==3 { printInt(5) } else { printInt(10) }", "10")
	o("a:=3; for a>0 { printInt(a); a-- }", "3\n2\n1")
	o("a:=0; for a<4 { printInt(a); a++ }", "0\n1\n2\n3")
	o("for i:=0;i<3;i++ { printInt(i); }", "0\n1\n2")
	o("for i:=0;i<10;i+=3 { printInt(i); }", "0\n3\n6\n9")
	o("i:=3; for i:=0;i<3;i++ { printInt(i); }", "0\n1\n2")
	o("i:=0; for ;i<3;i++ { printInt(i); }", "0\n1\n2")
	o("a:=1; { a:=3; printInt(a) }", "3")
	o("true:=3; printInt(true)", "3")
	o("a,b:=3,4; printInt(a); printInt(b)", "3\n4")
	o("a,b:=3,4; { a,b:=b,a; printInt(a); printInt(b) }", "4\n3")
	o("a,b:=3,4; a,b=b,a; printInt(a); printInt(b)", "4\n3")
	o("var a int; printInt(a)", "0")
	o("var a (int); printInt(a)", "0")
	o("var a,b = 3,4; printInt(a); printInt(b)", "3\n4")
	o("var a,b = 3,4; printInt(a); printInt(b)", "3\n4")
	o("var a,b int = 3,4; printInt(a); printInt(b)", "3\n4")
	o("var a,b uint = 3,4; printUint(a); printUint(b)", "3\n4")
	o(` a,b:=3,4; { var a,b=b,a; printInt(a); printInt(b) }
	   	printInt(a); printInt(b)
	`, "4\n3\n3\n4")
	o("var i int; for i < 3 { printInt(i); i=i+1 }", "0\n1\n2")
	o("for true { break }; printInt(3)", "3")
	o("for true { if true break }; printInt(3)", "3")
	o("for { break }; printInt(33)", "33")
	o("i:=0; for i<3 { printInt(i); i=i+1; continue; break }", "0\n1\n2")
	o("printChar('x')", "x")
	o("var a=32; var b=*&a; printInt(b)", "32")
	o("var a=32; var b=&a; var c=*b; printInt(c)", "32")
	o("var a=32; var b int = *&*&a; printInt(b)", "32")
	o("var a='x'; var b = *&*&a; printChar(b)", "x")
	o("if nil==nil { printInt(3) }", "3")
	o("if nil!=nil { printInt(3) }", "")
	o("var a*int; if a==nil { printInt(3) }", "3")
	o("var a*int; if nil==a { printInt(3) }", "3")
	o("b:=3; a:=&b; if *a==3 { printInt(*a) }", "3")
	o("b:=3; a:=&b; a=nil; if a==nil { printInt(b) }", "3")
	o("b:=3; a:=&b; *a=4; printInt(b)", "4")
	o("if true==true { printChar('y') }", "y")
	o("if true!=true { printChar('y') }", "")
	o("if true==false { printChar('y') }", "")
	o("if true!=false { printChar('y') }", "y")
	o("if false==false { printChar('y') }", "y")
	o("if false!=false { printChar('y') }", "")
	o("var a [4]int; a[3] = 3; printInt(a[3]); printInt(a[2])", "3\n0")
	o("var a [7]int; a[3]=33; pt:=&a[3]; printInt(*pt)", "33")
	o("var a [7]int; printInt(len(a))", "7")
	o("var a [7]int; s:=a[:]; printInt(len(s))", "7")
	o("var a [7]int; s:=a[:3]; printInt(len(s))", "3")
	o("var a [7]int; s:=a[1:]; printInt(len(s))", "6")
	o("var a [7]int; s:=a[1:3]; printInt(len(s))", "2")
	o("var a [7]int; s:=a[0:0]; printInt(len(s))", "0")
	o("var a [7]int; s:=a[:]; a[3]=33; printInt(s[3])", "33")
	o("var a [7]int; s:=a[1:]; a[3]=33; printInt(s[2])", "33")
	o("var a [7]int; s:=a[1:4]; a[3]=33; printInt(s[2])", "33")
	o("var a [7]int; s:=a[:]; a[3]=33; pt:=&s[3]; printInt(*pt)", "33")
	o("a:=3; a++; printInt(a)", "4")
	o("a:=3; pt := &a; *pt++; printInt(a)", "4")

	o("printInt(int(byte(int(-1))))", "255")
	o("printInt(int(byte(3)))", "3")
	o("printInt(int(byte(int(256))))", "0")
	o("printInt(int(char(int(-1))))", "-1")
	o("printInt(int(char(int(255))))", "-1")
	o("printInt(int(char(int(256))))", "0")
	o("printInt(int(byte(char(int(255)))))", "255")
	o("printInt(int(byte(char(int(-1)))))", "255")

	o("printInt(33 << uint(1))", "66")
	o("printInt(33 << 1)", "66")
	o("printInt(33 >> uint(1))", "16")
	o("printInt(33 >> 1)", "16")
	o("printInt(-33 >> uint(1))", "-17")
	o("printInt(-1 >> uint(1))", "-1")
	o("printInt(int(byte(255) << uint(1)))", "254")
	o("printInt(int(byte(255) << 1))", "254")
	o("printInt(int(uint(33) >> uint(1)))", "16")
	o("printInt(int(uint(33) >> 1))", "16")

	o("a:=3; a+=4; printInt(a)", "7")
	o("a:=3; a-=4; printInt(a)", "-1")
	o("a:=3; a*=4; printInt(a)", "12")
	o("a:=3; a/=2; printInt(a)", "1")
	o("a:=uint(3); a/=2; printUint(a)", "1")
	o("a:=33; a<<=uint(1); printInt(a)", "66")
	o("a:=33; a<<=1; printInt(a)", "66")
	o("a:=33; a>>=uint(1); printInt(a)", "16")
	o("a:=33; a>>=1; printInt(a)", "16")

	o("a:=33; b:=(*uint)(&a); printUint(*b)", "33")

	o("if 0x33 == 51 { printInt(33) }", "33")

	o("const a = 33; printInt(a)", "33")
	o("const a = 33; printUint(a)", "33")
	o("const ( a,b=3,4; c=a+b ); printInt(a+b+c)", "14")
	o("const a,b=3,4; var v [a+b]int; printInt(len(v))", "7")
}
Exemple #10
0
func runTests(
	log lex8.Logger, tests map[string]uint32, img []byte, opt *Options,
) {
	logln := func(s string) {
		if opt.LogLine == nil {
			fmt.Println(s)
		} else {
			opt.LogLine(s)
		}
	}

	// TODO(h8liu): this reporting should go with JSON for better formatting.
	report := func(
		name string, ncycle int, pass bool,
		m *arch8.Machine, err error,
	) {
		if pass {
			if opt.Verbose {
				logln(fmt.Sprintf(
					"  - %s: passed (%s)", name, cycleStr(ncycle),
				))
			}
			return
		}

		if err == nil {
			err = errTimeOut
		}
		lex8.LogError(log, fmt.Errorf("%s failed: got %s", name, err))
		if opt.Verbose {
			logln(fmt.Sprintf(
				"  - %s: FAILED (%s, got %s)",
				name, cycleStr(ncycle), err,
			))
			// TODO(h8liu): this is too ugly here...
			excep, ok := err.(*arch8.CoreExcep)
			if !arch8.IsHalt(err) && ok {
				stackTrace := new(bytes.Buffer)
				arch8.FprintStack(stackTrace, m, excep)
				logln(stackTrace.String())
			}
		}
	}

	var testNames []string
	for name := range tests {
		testNames = append(testNames, name)
	}
	sort.Strings(testNames)

	for _, test := range testNames {
		arg := tests[test]
		m := arch8.NewMachine(&arch8.Config{
			BootArg: arg,
		})
		if err := m.LoadImageBytes(img); err != nil {
			report(test, 0, false, m, err)
			continue
		}

		var err error
		n, excep := m.Run(opt.TestCycles)
		if excep == nil {
			err = errTimeOut
		} else {
			err = excep
		}
		if strings.HasPrefix(test, "TestBad") {
			report(test, n, arch8.IsPanic(err), m, err)
		} else {
			report(test, n, arch8.IsHalt(err), m, err)
		}
	}
}
Exemple #11
0
func TestSingleFile(t *testing.T) {
	const N = 100000

	o := func(input, output string) {
		out, err := singleTestRun(t, input, N)
		if err == errRunFailed {
			t.Error(err)
			return
		}
		if !arch8.IsHalt(err) {
			t.Log(input)
			t.Log(err)
			t.Error("did not halt gracefully")
			return
		}

		got := strings.TrimSpace(out)
		expect := strings.TrimSpace(output)
		if got != expect {
			t.Log(input)
			t.Logf("expect: %s", expect)
			t.Errorf("got: %s", got)
		}
	}

	o("func main() { }", "")
	o("func main() { return }", "")
	o("func main() { printInt(3) }", "3")

	o(` func r() int { return 7 }
		func main() { printInt(r()) }`,
		"7")
	o(`	func p(i int) { printInt(i) }
		func main() { p(33); p(44) }`,
		"33\n44")
	o(`	func r() (int, int) { return 3, 4 }
		func main() { a, b := r(); printInt(a); printInt(b) }`,
		"3\n4")
	o(` func r() (int, int) { return 3, 4 }
		func p(a, b int) { printInt(a); printInt(b) }
		func main() { p(r()) }`,
		"3\n4")
	o(` func r() (int) { return 3 }
		func p(a, b int) { printInt(a); printInt(b) }
		func main() { p(r(), 4) }`,
		"3\n4")
	o(`	func fabo(n int) int {
			if n == 0 return 0
			if n == 1 return 1
			return fabo(n-1) + fabo(n-2)
		}
		func main() { printInt(fabo(10)) }`,
		"55")

	o(`	func b() bool { printInt(4); return true }
		func main() { if false || b() { printInt(3) } }`,
		"4\n3")
	o(`	func b() bool { printInt(4); return true }
		func main() { if true || b() { printInt(3) } }`,
		"3")
	o(`	func b() bool { printInt(4); return false }
		func main() { if true && b() { printInt(3) } }`,
		"4")
	o(`	func b() bool { printInt(4); return true }
		func main() { if false && b() { printInt(3) } }`,
		"")
	o(`	func b() bool { printInt(4); return true }
		func main() { if true && b() { printInt(3) } }`,
		"4\n3")
	o(`func f(i int) { i=33; printInt(i) }; func main() { f(44) }`, "33")
	o(`	func f(a []int) { printInt(a[3]) }
		func main() { var a [8]int; a[4]=33; f(a[1:5]) }`,
		"33")
	o(`func main() { for true { printInt(33); break } }`, "33")
	o(`func main() { for 0==0 { printInt(33); break } }`, "33")
	o(`func main() { for true && true { printInt(33); break } }`, "33")
	o(`func main() { for true && false { printInt(33); break } }`, "")
	o(`func main() { for 0==0 && 0==1 { printInt(33); break } }`, "")
	o(`func main() { for true || false { printInt(33); break } }`, "33")
	o(`func main() { for false || true { printInt(33); break } }`, "33")
	o(`func main() { for false { printInt(33); break } }`, "")

	o(`	func printStr(s string) {
			n:=len(s); for i:=0;i<n;i++ { printChar(s[i]) }
		}
		func main() { printStr("hello") }`, "hello")
	o(`	func printStr(s string) {
			n:=len(s); for i:=0;i<n;i++ { printChar(s[i]) }
		}
		func main() { var a []int8; b:="hello"; a=b; printStr(a) }`, "hello")
	o(`	func printStr(s string) {
			n:=len(s); for i:=0;i<n;i++ { printChar(s[i]) }
		}
		func main() { b:="hello"; var a []int8; a=b; printStr(b); _ := a }`,
		"hello")

	o(` struct A {}; func main() { var a A; pa := &a; _ := pa }`, "")
	o(` struct A { a int }
		func main() { var a A; printInt(a.a) }`, "0")
	o(` struct A { a int }
		func main() { var a A; a.a = 33; printInt(a.a) }`, "33")
	o(` struct A { a int }
		func main() { var a A; pi:=&a.a; *pi=33; printInt(a.a) }`, "33")
	o(` struct A { a int }
		func main() { var a A; (&a).a = 33; printInt(a.a) }`, "33")
	o(` struct A { a int }
		func main() { var a A; var pa=&a; pa.a = 33; printInt(pa.a) }`, "33")
	o(` struct A { b byte; a int }
		func main() { var a A; var pa=&a; 
			pa.a = 33; pa.b = byte(7);
			printInt(pa.a); printInt(int(pa.b))
		}`, "33\n7")

	o(` func p(i int) { printInt(i) }
		func main() { f:=p; f(33) }`, "33")
	o(` func p(i int) { printInt(i+2) }
		func c(x func(i int)) { x(33) }
		func main() { c(p) }`, "35")

	o("struct A { a *A }; func main() {}", "")
	o(`struct A { b B }; struct B { a *A }; func main() {}`, "")

	o(` struct A {}; func (p *A) p(a int) { printInt(a) }
		func main() { var a A; a.p(33) }`, "33")
	o(` struct A { a int }
		func (p *A) s(a int) { p.a = a }
		func (a *A) p() { printInt(a.a) }
		func main() { var a A; a.s(33); a.p() }`, "33")
	o(` struct A { a int }
		func (p *A) s(a int) { (*p).a = a }
		func (a *A) p() { printInt(a.a) }
		func main() { var a A; a.s(33); a.p() }`, "33")
	o(` struct A { a int }
		func (a *A) p() { printInt(a.a) }
		func (p *A) q(a int) { printInt(a) }
		func main() { var a A; a.p(); a.a=33; a.p(); a.q(78) }`, "0\n33\n78")
	o(` struct A { }
		func (a *A) p() { printInt(33) }
		func (a *A) q() { a.p() }
		func main() { var a A; a.q() }`, "33")

	o("var a int; func main() { a := 33; printInt(a) }", "33")
	o(`	struct A { }
		func (a *A) p() { printInt(33) }
		var a A
		func main() { a.p() }`, "33")
	o(` struct A { a int }
		func (a *A) p() { printInt(a.a) }
		var a A
		func main() { a.a=33; a.p() }`, "33")
	o(` struct A { a, b int }
		func (a *A) p() { printInt(a.a+a.b) }
		var a A
		func main() { a.a=30; a.b=3; a.p() }`, "33")
	o(` var ( a []int; s [2]int )
		func main() { a=s[:]; s[1]=33; printInt(a[1]) }`, "33")
	o(` var ( a []int )
		func main() { if a == nil { printInt(33) } }`, "33")
	o(` var ( a []int; v [0]int )
		func main() { a=v[:]; if a != nil { printInt(33) } }`, "33")
	o(` var ( a, b []int; v [3]int )
		func main() { a=v[:2]; b = v[:3]; if a != b { printInt(33) } }`, "33")
	o(` var ( a, b []int; v [3]int )
		func main() { a=v[:]; b = v[:]; if a == b { printInt(33) } }`, "33")

	o("func init() { printInt(33) }; func main() { printInt(44) }", "33\n44")

	o(`	struct a { a int; b byte }
		func main() { 
			var x,y a; x.a=33; y.a=44; 
			printInt(x.a); printInt(y.a) 
		}`, "33\n44")
	o(` struct a { a int; b,c byte }
		func main() { 
			var as [4]a
			printUint(uint(&as[1])-uint(&as[0]))
			printUint(uint(&as[0].c)-uint(&as[0].a))
		}`, "8\n5")
	o(` struct a { a [4]byte; b byte }
		func main() { 
			var as [4]a
			printUint(uint(&as[1])-uint(&as[0]))
		}`, "5")

	o("import(); func main() {}", "")
	o("import(); func main() { printInt(33) }", "33")

	o("const a=33; func main() { printInt(a) }", "33")
	o("const a=33; func main() { const a=34; printInt(a) }", "34")
	o(`	const a, b = 1, a; const c, d = d, 3
		func main() { printInt(a); printInt(b); printInt(c); printInt(d) }`,
		"1\n1\n3\n3\n")
	o(`const a, b = b + 3, 30; func main() { printInt(a) }`, "33")

	o(`	var a [4]int
		func main() {
			s := make([]int, 2, &a[1])
			s[0] = 33; s[1] = 47
			printInt(a[1]); printInt(a[2])
		}`, "33\n47")

	o(`func f() int { for {} }; func main() { }`, "")
	o(`	func f() int { if true { return 1 } else { return 0 } }
		func main() { }`, "")
	o(`func f() int { for { if true { return 0 } } }; func main() { }`, "")

	// Bugs found by the fuzzer in the past
	o("func main() { a := 0==0; if a { printInt(33) } }", "33")
	o(`	func n()[(4-3)*1]string { var a [1]string; return a }
		func main() { printInt(len(n())) }`, "1")
	o(`	func n()[1<<1]string { var a [2]string; return a }
		func main() { printInt(len(n())) }`, "2")
	o(` func n()[1>>1]string { var a [0]string; return a }
		func main() { printInt(len(n())) }`, "0")
	o("func main() { r:=+'0'; printChar(r) }", "0")
	o("func n(b**bool) { **b=**b }; func main() {}", "")
	o("func n(b****bool) { ****b=****b }; func main() {}", "")
	o(` struct A { }
		func (p *A) n() (a int) { return 33 }
		func main() { var a A; printInt(a.n()) }`, "33")
	o(`	func main() {printInt(33)}
		func _(){}
		func _(){}
		var _, _ int`, "33")

	// Bugs found when writing OS8
	o(` func main() { a, b := f(); printInt(a); printInt(len(b)) }
		var dat [5]int
		func f() (int, []int) { return 33, dat[:] }`, "33\n5")
	o(` func p(a []uint) {}
		func main() {
			var t [10]uint; t2:=t[:];
			before := uint(&t2[0]); p(t2[2:5]); after := uint(&t2[0])
			if before != after { panic() }
		}`, "")
}