func TestMultiplePrefixMethodCallWithOne(t *testing.T) { tests := []struct { input string expected int }{ {"1+1", 2}, {"1-1", 0}, {"1+0", 1}, {"1-0", 1}, {"1+-0", 1}, {"1++0", 1}, {"1-+0", 1}, {"1--0", 1}, {"1+-1", 0}, {"1++1", 2}, {"1-+1", 0}, {"1--1", 2}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithPlusOne(t *testing.T) { tests := []struct { input string expected int }{ {"+1+1", 2}, {"+1-1", 0}, {"+1+0", 1}, {"+1-0", 1}, {"+1+-0", 1}, {"+1++0", 1}, {"+1-+0", 1}, {"+1--0", 1}, {"+1+-1", 0}, {"+1++1", 2}, {"+1-+1", 0}, {"+1--1", 2}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithMinusOne(t *testing.T) { tests := []struct { input string expected int }{ {"-1+1", 0}, {"-1-1", -2}, {"-1+0", -1}, {"-1-0", -1}, {"-1+-0", -1}, {"-1++0", -1}, {"-1-+0", -1}, {"-1--0", -1}, {"-1+-1", -2}, {"-1++1", 0}, {"-1-+1", -2}, {"-1--1", 0}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithZero(t *testing.T) { tests := []struct { input string expected int }{ {"0+1", 1}, {"0-1", -1}, {"0+0", 0}, {"0-0", -0}, {"0+-1", -1}, {"0++1", 1}, {"0-+1", -1}, {"0--1", 1}, {"0+-1", -1}, {"0++1", 1}, {"0-+1", -1}, {"0--1", 1}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithPlusZero(t *testing.T) { tests := []struct { input string expected int }{ {"+0+1", 1}, {"+0-1", -1}, {"+0+0", 0}, {"+0-0", -0}, {"+0+-1", -1}, {"+0++1", 1}, {"+0-+1", -1}, {"+0--1", 1}, {"+0+-1", -1}, {"+0++1", 1}, {"+0-+1", -1}, {"+0--1", 1}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithMinusZero(t *testing.T) { tests := []struct { input string expected int }{ {"-0+1", 1}, {"-0-1", -1}, {"-0+0", 0}, {"-0-0", -0}, {"-0+-1", -1}, {"-0++1", 1}, {"-0-+1", -1}, {"-0--1", 1}, {"-0+-1", -1}, {"-0++1", 1}, {"-0-+1", -1}, {"-0--1", 1}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithPlusPlusZero(t *testing.T) { tests := []struct { input string expected int }{ {"++1+1", 2}, {"++1-1", 0}, {"++1+0", 1}, {"++1-0", 1}, {"++1+-0", 1}, {"++1++0", 1}, {"++1-+0", 1}, {"++1--0", 1}, {"++1+-1", 0}, {"++1++1", 2}, {"++1-+1", 0}, {"++1--1", 2}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithMinusMinusZero(t *testing.T) { tests := []struct { input string expected int }{ {"--0+-1", -1}, {"--0++1", 1}, {"--0-+1", -1}, {"--0--1", 1}, {"--0+-1", -1}, {"--0++1", 1}, {"--0-+1", -1}, {"--0--1", 1}, {"--0+-0", 0}, {"--0++0", 0}, {"--0-+0", 0}, {"--0--0", 0}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithPlusMinusOne(t *testing.T) { tests := []struct { input string expected int }{ {"+-1+1", 0}, {"+-1-1", -2}, {"+-1+0", -1}, {"+-1-0", -1}, {"+-1+-0", -1}, {"+-1++0", -1}, {"+-1-+0", -1}, {"+-1--0", -1}, {"+-1+-1", -2}, {"+-1++1", 0}, {"+-1-+1", -2}, {"+-1--1", 0}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithMinusPlusOne(t *testing.T) { tests := []struct { input string expected int }{ {"-+1+1", 0}, {"-+1-1", -2}, {"-+1+0", -1}, {"-+1-0", -1}, {"-+1+-0", -1}, {"-+1++0", -1}, {"-+1-+0", -1}, {"-+1--0", -1}, {"-+1+-1", -2}, {"-+1++1", 0}, {"-+1-+1", -2}, {"-+1--1", 0}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallWithMinusMinusOne(t *testing.T) { tests := []struct { input string expected int }{ {"--1+-1", 0}, {"--1++1", 2}, {"--1-+1", 0}, {"--1--1", 2}, {"--1+-1", 0}, {"--1++1", 2}, {"--1-+1", 0}, {"--1--1", 2}, {"--1+-0", 1}, {"--1++0", 1}, {"--1-+0", 1}, {"--1--0", 1}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallUnary(t *testing.T) { tests := []struct { input string expected int }{ // 52-94 {"+1", 1}, {"++1", 1}, {"+-1", -1}, {"-+1", -1}, {"-1", -1}, {"--1", 1}, {"+0", 0}, {"++0", 0}, {"+-0", 0}, {"-+0", 0}, {"-0", 0}, {"--0", 0}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodCallUnaryParentheses(t *testing.T) { tests := []struct { input string expected int }{ {"(+1)", 1}, {"+(1)", 1}, {"+(+1)", 1}, {"+(-1)", -1}, {"(-1)", -1}, {"-(1)", -1}, {"-(-1)", 1}, {"(+0)", 0}, {"+(+0)", 0}, {"+(0)", 0}, {"+(-0)", 0}, {"(-0)", 0}, {"-(0)", 0}, {"-(-0)", 0}, {"(+0+1)", 1}, {"-(+0+1)", -1}, {"(1+1)", 2}, {"-(1+1)", -2}, {"(+1+1)", 2}, {"-(+1+1)", -2}, {"(-1+1)", 0}, {"-(-1+1)", 0}, {"(-1-1)", -2}, {"-(-1-1)", 2}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodSparseExpressionWithMultipleSigns(t *testing.T) { tests := []struct { input string expected int }{ {"1 -1", 0}, {"1 - 1", 0}, {"1---1", 0}, {"1----1", 2}, {"-1 -1", -2}, {"-1 - 1", -2}, {"-1---1", -2}, {"-1----1", 0}, {"-1 +1", 0}, {"-1 + 1", 0}, {"-1+--1", 0}, {"-1+---1", -2}, {"1+--1", 2}, {"1+---1", 0}, {"+++1", 1}, {"++++1", 1}, {"---1", -1}, {"----1", 1}, {"1-+-1", 2}, {"--+- -++-- -1", -1}, {"--+ -++-- - 1", 1}, {"(--+- -++-- - 1)", -1}, {"(--+ -++-- -1)", 1}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodVariableWithSigns(t *testing.T) { tests := []struct { input string expected int }{ { `a=1 +a`, 1, }, { `a=1 -a`, -1, }, { `a=0 +a`, 0, }, { `a=0 -a`, 0, }, { `a=-1 +a`, -1, }, { `a=-1 -a`, 1, }, { "a=1; +a", // TODO: needs fix: Some panic happen token: (. Line: 0 1, }, { "a=1;(+a)", // TODO: needs fix: Some panic happen token: (. Line: 0 1, }, { "a=1;(++a)", // TODO: needs fix: Some panic happen token: (. Line: 0 1, }, { "a=1;++a", // TODO: needs fix: Some panic happen token: (. Line: 0 1, }, { "a=1;+++a", // TODO: needs fix: Some panic happen token: (. Line: 0 1, }, { "a=1;-a", // TODO: needs fix: Some panic happen token: (. Line: 0 -1, }, { "a=1;(--a)", // TODO: needs fix: Some panic happen token: (. Line: 0 1, }, { "a=1;--a", // TODO: needs fix: Some panic happen token: (. Line: 0 1, }, { "a=1;---a", // TODO: needs fix: Some panic happen token: (. Line: 0 -1, }, { "a=1;(+a+1)", // TODO: needs fix: Some panic happen token: (. Line: 0 2, }, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodInstanceVariableWithSigns(t *testing.T) { tests := []struct { input string expected int }{ { ` class Foo def initialize @a = 1 end def bar +@a end end Foo.new.bar`, 1, }, { ` class Foo def initialize @a = 1 end def bar -@a end end Foo.new.bar`, -1, }, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodArrayWithSigns(t *testing.T) { tests := []struct { input string expected int }{ { "+[1, 2][0]", // TypeError: Expect argument to be Numeric. got: Array 1, }, { "-[1, 2][0]", // TypeError: Expect argument to be Numeric. got: Array -1, }, { "[1, 2][+0]", 1, }, { "+[1, 2][-0]", // TypeError: Expect argument to be Numeric. got: Array 1, }, { "[1, 2][+1]", 2, }, { "[1, 2][-1]", 2, }, { "[+1][0]", 1, }, { "[+1, +2][0]", 1, }, { "[-1, -2][0]", -1, }, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestMultiplePrefixMethodHashWithSigns(t *testing.T) { tests := []struct { input string expected int }{ { "{ a: 1 }[:a]", 1, }, { "{ a: +1 }[:a]", 1, }, { "-{ a: 1 }[:a]", // TypeError: Expect argument to be Numeric. got: Array -1, }, { "+{ a: +1 }[:a]", // TypeError: Expect argument to be Numeric. got: Array 1, }, { "+{ a: +0 }[:a]", // TypeError: Expect argument to be Numeric. got: Array 0, }, { "{ a: -0 }[:a]", 0, }, { "{ a: -1 }[:a]", -1, }, { "{ x: -1, y: -0 }[:x]", -1, }, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } //---------------------------------------------------------------------------------- func TestPostfixMethodCall(t *testing.T) { tests := []struct { input string expected int }{ {` a = 1 a += 1 a `, 2}, {` a = 10 a -= 1 a `, 9}, {` a = 0 a -= 1 a `, -1}, {` a = -5 a += 1 a `, -4}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestRemoveUnusedExpression(t *testing.T) { tests := []struct { input string expected interface{} }{ {` 1 100 10 `, 10}, {` [1, 2] "123" 10 `, 10}, {` @foo 10 `, 10}, {` class Bar; end Bar 10 `, 10}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestSelfExpressionEvaluation(t *testing.T) { tests := []struct { input string expected string }{ {`self.class.name`, "Object"}, { ` class Bar def whoami "Instance of " + self.class.name end end Bar.new.whoami `, "Instance of Bar"}, { ` class Foo Self = self def get_self Self end end Foo.new.get_self.name `, "Foo"}, { ` class Foo def class Foo end end Foo.new.class.name `, "Foo"}, { ` class Foo def class_name self.class.name end end Foo.new.class_name `, "Foo"}, } for i, tt := range tests { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) if isError(evaluated) { t.Fatalf("got Error: %s", evaluated.(*Error).message) } VerifyExpected(t, i, evaluated, tt.expected) v.checkCFP(t, i, 0) v.checkSP(t, i, 1) } } func TestUnusedVariableFail(t *testing.T) { testsFail := []errorTestCase{ {` _ = 1 _ `, "NoMethodError: Undefined Method '_' for ", 1}, {` _, b = [1, 2] _ `, "NoMethodError: Undefined Method '_' for ", 1}, } for i, tt := range testsFail { v := initTestVM() evaluated := v.testEval(t, tt.input, getFilename()) checkErrorMsg(t, i, evaluated, tt.expected) v.checkCFP(t, i, 1) v.checkSP(t, i, 1) }