package vm import ( "fmt" "testing" "gitea.paas.celticinfo.fr/oabrivard/monkeylang/monkey5/ast" "gitea.paas.celticinfo.fr/oabrivard/monkeylang/monkey5/compiler" "gitea.paas.celticinfo.fr/oabrivard/monkeylang/monkey5/lexer" "gitea.paas.celticinfo.fr/oabrivard/monkeylang/monkey5/object" "gitea.paas.celticinfo.fr/oabrivard/monkeylang/monkey5/parser" ) func TestIntegerArithmetic(t *testing.T) { tests := []vmTestCase{ {"1", 1}, {"2", 2}, {"1 + 2", 3}, } runVmTests(t, tests) } type vmTestCase struct { input string expected interface{} } func runVmTests(t *testing.T, tests []vmTestCase) { t.Helper() for _, tt := range tests { program := parse(tt.input) comp := compiler.New() err := comp.Compile(program) if err != nil { t.Fatalf("compiler error: %s", err) } vm := New(comp.Bytecode()) err = vm.Run() if err != nil { t.Fatalf("vm error: %s", err) } stackElem := vm.StackTop() testExpectedObject(t, tt.expected, stackElem) } } func parse(input string) *ast.Program { l := lexer.New(input) p := parser.New(l) return p.ParseProgram() } func testExpectedObject( t *testing.T, expected interface{}, actual object.Object, ) { t.Helper() switch expected := expected.(type) { case int: err := testIntegerObject(int64(expected), actual) if err != nil { t.Errorf("testIntegerObject failed: %s", err) } } } func testIntegerObject(expected int64, actual object.Object) error { result, ok := actual.(*object.Integer) if !ok { return fmt.Errorf("object is not Integer. got=%T (%+v)", actual, actual) } if result.Value != expected { return fmt.Errorf("object has wrong value. got=%d, want=%d", result.Value, expected) } return nil }