def _parse_source_file(self, source_file_path): parser = LingoParser() try: with open(source_file_path, "r") as source_file: self.program_source = source_file.read() self.program_component = parser.parse(self.program_source) except IOError as e: raise CannotOpenSourceFile(source_file_path).from_exception(e) except LingoException as e: raise CannotParseSource(source_file_path).from_exception(e) self.program_block = ProgramBlock(self.program_component)
def _parse_source_file(self, source_file_path): parser = LingoParser() try: with open(source_file_path, 'r') as source_file: self.program_source = source_file.read() self.program_component = parser.parse(self.program_source) except IOError as e: raise CannotOpenSourceFile(source_file_path).from_exception(e) except LingoException as e: raise CannotParseSource(source_file_path).from_exception(e) self.program_block = ProgramBlock(self.program_component)
class TestTypeCheck(unittest.TestCase): def setUp(self): self.parser = LingoParser() self.typecheck = TypeCheck(False) def get_type(self, var): return self.typecheck.rename.get_type( self.typecheck.rename.find(self.typecheck.variables[var])) def testSkip1(self): program_text = ''' skip; a := 1; skip '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(self.get_type('a').value == "INTEGER") self.typecheck.visit_program(program) def testWhile1(self): program_text = ''' while(a) do{ b := 1 }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('b'), Primitive)) self.assertTrue(self.get_type('a').value == "BOOLEAN") self.assertTrue(self.get_type('b').value == "INTEGER") def testWhile2(self): program_text = ''' while(a < b) do{ b := 1 }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('b'), Primitive)) self.assertTrue(self.get_type('a').value == "INTEGER") self.assertTrue(self.get_type('b').value == "INTEGER") def testWhile3(self): program_text = ''' while(a < b) do{ b := true }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testWhile4(self): program_text = ''' a := 1; while(a) do{ b := true }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testIf1(self): program_text = ''' if(a) then{ b := 1 }else { b:=2 }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('b'), Primitive)) self.assertTrue(self.get_type('a').value == "BOOLEAN") self.assertTrue(self.get_type('b').value == "INTEGER") def testIf2(self): program_text = ''' if(a < b) then{ b := 1 }else { b:=2 }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('b'), Primitive)) self.assertTrue(self.get_type('a').value == "INTEGER") self.assertTrue(self.get_type('b').value == "INTEGER") def testIf3(self): program_text = ''' if(a < b) then{ b := true }else { b:=false }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testIf4(self): program_text = ''' a := 1; if(a) then{ b := true }else { b:=false }; c := 1; c:= 2 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCannotDetermine1(self): program_text = ''' def foo = fun(a,b){ return a } a := 1; b := 1 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCannotDetermine2(self): program_text = ''' input x; a := 1; b := 1 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCannotDetermine3(self): program_text = ''' a := d; b := 1 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testFunctionUnification1(self): program_text = ''' def foo = fun(a,b){ return a } def bar = fun(a,b){ return b } a := 1; b := 2; a := foo(a,b); c := ref foo; c := ref bar '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('foo_a'), Primitive)) self.assertTrue(isinstance(self.get_type('foo_b'), Primitive)) self.assertTrue(isinstance(self.get_type('bar_a'), Primitive)) self.assertTrue(isinstance(self.get_type('bar_b'), Primitive)) self.assertTrue(self.get_type('foo_a').value == "INTEGER") self.assertTrue(self.get_type('foo_b').value == "INTEGER") self.assertTrue(self.get_type('bar_a').value == "INTEGER") self.assertTrue(self.get_type('bar_b').value == "INTEGER") def testFunctionUnification2(self): program_text = ''' def foo = fun(a,b){ c := a + b; return c } def bar = fun(a,b){ c := a || b; return c } a := 1; b := 2; a := foo(a,b); c := ref foo; c := ref bar '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefUnification1(self): program_text = ''' a := 1; b := ref a; b := ref c '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('c'), Primitive)) self.assertTrue(isinstance(self.get_type('b'), Reference)) self.assertTrue(isinstance(self.get_type('b').value, Primitive)) self.assertTrue(self.get_type('a').value == "INTEGER") self.assertTrue(self.get_type('c').value == "INTEGER") self.assertTrue(self.get_type('b').value.value == "INTEGER") def testRefUnification2(self): program_text = ''' b := 1; c := true; a := ref b; a := ref c '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCyclicTypes1(self): program_text = ''' a := ref b; b := ref a '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCyclicTypes2(self): program_text = ''' a := ref b; b := 1; c := 1; a := ref d; a := ref c; d := ref a '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCyclicTypes3(self): program_text = ''' def foo = fun(foo1){ a := ref foo1; b := !foo1(a); return a } a := ref foo; b := 1 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefFunction1(self): program_text = ''' def foo = fun(a,b,c){ d := !c(a,b); a := a + b; return a } def help = fun(a,b){ c := a < b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('foo_a'), Primitive)) self.assertTrue(isinstance(self.get_type('foo_b'), Primitive)) self.assertTrue(isinstance(self.get_type('foo_d'), Primitive)) self.assertTrue(isinstance(self.get_type('help_a'), Primitive)) self.assertTrue(isinstance(self.get_type('help_b'), Primitive)) self.assertTrue(isinstance(self.get_type('help_c'), Primitive)) self.assertTrue(isinstance(self.get_type('foo'), Function)) self.assertTrue(isinstance(self.get_type('help'), Function)) self.assertTrue(isinstance(self.get_type('foo_c'), Reference)) self.assertTrue(isinstance(self.get_type('foo_c').value, Function)) self.assertTrue(self.get_type('foo_a').value == "INTEGER") self.assertTrue(self.get_type('foo_b').value == "INTEGER") def testRefFunction2(self): program_text = ''' def foo = fun(a,b,c){ d := !c(a,b); a := a + b; return a } def help = fun(a,b){ c := a || b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefFunction3(self): program_text = ''' def foo = fun(a,b,c){ d := !c(a); a := a + b; return a } def help = fun(a,b){ c := a < b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefFunction4(self): program_text = ''' def foo = fun(a,b,c){ d:= 1; d := !c(a,b); a := a + b; return a } def help = fun(a,b){ c := a < b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testFunctionSignature1(self): program_text = ''' def foo = fun(a,b){ a := a + b; return a } a := 1; b := 2; a := foo(a,b) '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('foo_a'), Primitive)) self.assertTrue(isinstance(self.get_type('foo_b'), Primitive)) self.assertTrue(isinstance(self.get_type('foo'), Function)) self.assertTrue(self.get_type('foo_a').value == "INTEGER") self.assertTrue(self.get_type('foo_b').value == "INTEGER") for sig in self.get_type('foo').signature: self.assertTrue(sig.value == "INTEGER") def testFunctionSignature2(self): program_text = ''' def foo = fun(a,b){ a := a + b; return a } a := 1; b := true; a := foo(a,b) '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testFunctionSignature3(self): program_text = ''' def foo = fun(a,b){ a := a + b; return a } a := 1; b := ref foo; a := foo(a,b) '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testDereference1(self): program_text = ''' a := 1; x := ref a; a := !x '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('x'), Reference)) self.assertTrue(self.get_type('a').value == "INTEGER") self.assertTrue(self.get_type('x').value.value == "INTEGER") def testDereference2(self): program_text = ''' a := 1; x := ref a; y := ref x; x := !y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('x'), Reference)) self.assertTrue(isinstance(self.get_type('y'), Reference)) self.assertTrue(isinstance(self.get_type('x').value, Primitive)) self.assertTrue(isinstance(self.get_type('y').value, Reference)) self.assertTrue(isinstance(self.get_type('y').value.value, Primitive)) self.assertTrue(self.get_type('a').value == "INTEGER") self.assertTrue(self.get_type('x').value.value == "INTEGER") self.assertTrue(self.get_type('y').value.value.value == "INTEGER") def testDereference3(self): program_text = ''' a := 1; x := ref a; y := ref x; y := !x '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testDereference4(self): program_text = ''' a := 1; b := !a '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testReference1(self): program_text = ''' a := 1; b := 2; x := ref a; y := ref b; z := !x / !y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('b'), Primitive)) self.assertTrue(isinstance(self.get_type('x'), Reference)) self.assertTrue(isinstance(self.get_type('y'), Reference)) self.assertTrue(isinstance(self.get_type('x').value, Primitive)) self.assertTrue(isinstance(self.get_type('y').value, Primitive)) self.assertTrue(self.get_type('a').value == "INTEGER") self.assertTrue(self.get_type('b').value == "INTEGER") self.assertTrue(self.get_type('y').value.value == "INTEGER") self.assertTrue(self.get_type('x').value.value == "INTEGER") self.assertTrue(isinstance(self.get_type('z'), Primitive)) self.assertTrue(self.get_type('z').value == "INTEGER") def testReference2(self): program_text = ''' a := 1; x := ref a; y := ref x '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('a'), Primitive)) self.assertTrue(isinstance(self.get_type('x'), Reference)) self.assertTrue(isinstance(self.get_type('y'), Reference)) self.assertTrue(isinstance(self.get_type('x').value, Primitive)) self.assertTrue(isinstance(self.get_type('y').value, Reference)) self.assertTrue(isinstance(self.get_type('y').value.value, Primitive)) self.assertTrue(self.get_type('a').value == "INTEGER") self.assertTrue(self.get_type('x').value.value == "INTEGER") self.assertTrue(self.get_type('y').value.value.value == "INTEGER") def testReference3(self): program_text = ''' a := 1; x := ref a; y := ref x; a := !y '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testReference4(self): program_text = ''' a := 1; b := true; x := ref a; b := !x '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testNew1(self): program_text = ''' x := new integer; y := new integer; z := !x * !y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Reference)) self.assertTrue(isinstance(self.get_type('y'), Reference)) self.assertTrue(isinstance(self.get_type('x').value, Primitive)) self.assertTrue(isinstance(self.get_type('y').value, Primitive)) self.assertTrue(self.get_type('y').value.value == "INTEGER") self.assertTrue(self.get_type('x').value.value == "INTEGER") self.assertTrue(isinstance(self.get_type('z'), Primitive)) self.assertTrue(self.get_type('z').value == "INTEGER") def testNew2(self): program_text = ''' x := new boolean; y := new boolean; z := !x || !y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Reference)) self.assertTrue(isinstance(self.get_type('y'), Reference)) self.assertTrue(isinstance(self.get_type('x').value, Primitive)) self.assertTrue(isinstance(self.get_type('y').value, Primitive)) self.assertTrue(self.get_type('y').value.value == "BOOLEAN") self.assertTrue(self.get_type('x').value.value == "BOOLEAN") self.assertTrue(isinstance(self.get_type('z'), Primitive)) self.assertTrue(self.get_type('z').value == "BOOLEAN") def testNew3(self): program_text = ''' x := new ref boolean; y := !x; z := !y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Reference)) self.assertTrue(isinstance(self.get_type('y'), Reference)) self.assertTrue(isinstance(self.get_type('z'), Primitive)) self.assertTrue(isinstance(self.get_type('x').value, Reference)) self.assertTrue(isinstance(self.get_type('x').value.value, Primitive)) self.assertTrue(isinstance(self.get_type('y').value, Primitive)) self.assertTrue(self.get_type('y').value.value == "BOOLEAN") self.assertTrue(self.get_type('x').value.value.value == "BOOLEAN") self.assertTrue(self.get_type('z').value == "BOOLEAN") def testNew4(self): program_text = ''' x := new ref integer; z := !x + 1 '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorLessEqual1(self): program_text = ''' x := 1; y := 2; z := x <= y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Primitive)) self.assertTrue(isinstance(self.get_type('y'), Primitive)) self.assertTrue(self.get_type('y').value == "INTEGER") self.assertTrue(self.get_type('x').value == "INTEGER") self.assertTrue(isinstance(self.get_type('z'), Primitive)) self.assertTrue(self.get_type('z').value == "BOOLEAN") def testOperatorLessEqual2(self): program_text = ''' x := 1; y := true; z := x <= y '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorLess1(self): program_text = ''' x := 1; y := 2; z := x < y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Primitive)) self.assertTrue(isinstance(self.get_type('y'), Primitive)) self.assertTrue(self.get_type('y').value == "INTEGER") self.assertTrue(self.get_type('x').value == "INTEGER") self.assertTrue(isinstance(self.get_type('z'), Primitive)) self.assertTrue(self.get_type('z').value == "BOOLEAN") def testOperatorLess2(self): program_text = ''' x := false; y := 2; z := x < y '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorDivide1(self): program_text = ''' x := 1; y := 2; x := x / y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Primitive)) self.assertTrue(isinstance(self.get_type('y'), Primitive)) self.assertTrue(self.get_type('y').value == "INTEGER") self.assertTrue(self.get_type('x').value == "INTEGER") def testOperatorDivide2(self): program_text = ''' x := false; y := true; z := x / y '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorTimes1(self): program_text = ''' x := 1; y := 2; x := x * y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Primitive)) self.assertTrue(isinstance(self.get_type('y'), Primitive)) self.assertTrue(self.get_type('y').value == "INTEGER") self.assertTrue(self.get_type('x').value == "INTEGER") def testOperatorTimes2(self): program_text = ''' x := 3; y := 1; z := x * y; z := false '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorMinus1(self): program_text = ''' x := 1; y := 2; x := x - y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Primitive)) self.assertTrue(isinstance(self.get_type('y'), Primitive)) self.assertTrue(self.get_type('y').value == "INTEGER") self.assertTrue(self.get_type('x').value == "INTEGER") def testOperatorMinus2(self): program_text = ''' x := true; y := 3; z := x - y '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorPlus1(self): program_text = ''' x := 1; y := 2; x := x + y '''.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type('x'), Primitive)) self.assertTrue(isinstance(self.get_type('y'), Primitive)) self.assertTrue(self.get_type('y').value == "INTEGER") self.assertTrue(self.get_type('x').value == "INTEGER") def testOperatorPlus2(self): program_text = ''' x := false; y := true; z := x + y '''.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program)
class TestTypeCheck(unittest.TestCase): def setUp(self): self.parser = LingoParser() self.typecheck = TypeCheck(False) def get_type(self, var): return self.typecheck.rename.get_type(self.typecheck.rename.find(self.typecheck.variables[var])) def testSkip1(self): program_text = """ skip; a := 1; skip """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(self.get_type("a").value == "INTEGER") self.typecheck.visit_program(program) def testWhile1(self): program_text = """ while(a) do{ b := 1 }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("b"), Primitive)) self.assertTrue(self.get_type("a").value == "BOOLEAN") self.assertTrue(self.get_type("b").value == "INTEGER") def testWhile2(self): program_text = """ while(a < b) do{ b := 1 }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("b"), Primitive)) self.assertTrue(self.get_type("a").value == "INTEGER") self.assertTrue(self.get_type("b").value == "INTEGER") def testWhile3(self): program_text = """ while(a < b) do{ b := true }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testWhile4(self): program_text = """ a := 1; while(a) do{ b := true }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testIf1(self): program_text = """ if(a) then{ b := 1 }else { b:=2 }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("b"), Primitive)) self.assertTrue(self.get_type("a").value == "BOOLEAN") self.assertTrue(self.get_type("b").value == "INTEGER") def testIf2(self): program_text = """ if(a < b) then{ b := 1 }else { b:=2 }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("b"), Primitive)) self.assertTrue(self.get_type("a").value == "INTEGER") self.assertTrue(self.get_type("b").value == "INTEGER") def testIf3(self): program_text = """ if(a < b) then{ b := true }else { b:=false }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testIf4(self): program_text = """ a := 1; if(a) then{ b := true }else { b:=false }; c := 1; c:= 2 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCannotDetermine1(self): program_text = """ def foo = fun(a,b){ return a } a := 1; b := 1 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCannotDetermine2(self): program_text = """ input x; a := 1; b := 1 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCannotDetermine3(self): program_text = """ a := d; b := 1 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testFunctionUnification1(self): program_text = """ def foo = fun(a,b){ return a } def bar = fun(a,b){ return b } a := 1; b := 2; a := foo(a,b); c := ref foo; c := ref bar """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("foo_a"), Primitive)) self.assertTrue(isinstance(self.get_type("foo_b"), Primitive)) self.assertTrue(isinstance(self.get_type("bar_a"), Primitive)) self.assertTrue(isinstance(self.get_type("bar_b"), Primitive)) self.assertTrue(self.get_type("foo_a").value == "INTEGER") self.assertTrue(self.get_type("foo_b").value == "INTEGER") self.assertTrue(self.get_type("bar_a").value == "INTEGER") self.assertTrue(self.get_type("bar_b").value == "INTEGER") def testFunctionUnification2(self): program_text = """ def foo = fun(a,b){ c := a + b; return c } def bar = fun(a,b){ c := a || b; return c } a := 1; b := 2; a := foo(a,b); c := ref foo; c := ref bar """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefUnification1(self): program_text = """ a := 1; b := ref a; b := ref c """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("c"), Primitive)) self.assertTrue(isinstance(self.get_type("b"), Reference)) self.assertTrue(isinstance(self.get_type("b").value, Primitive)) self.assertTrue(self.get_type("a").value == "INTEGER") self.assertTrue(self.get_type("c").value == "INTEGER") self.assertTrue(self.get_type("b").value.value == "INTEGER") def testRefUnification2(self): program_text = """ b := 1; c := true; a := ref b; a := ref c """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCyclicTypes1(self): program_text = """ a := ref b; b := ref a """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCyclicTypes2(self): program_text = """ a := ref b; b := 1; c := 1; a := ref d; a := ref c; d := ref a """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testCyclicTypes3(self): program_text = """ def foo = fun(foo1){ a := ref foo1; b := !foo1(a); return a } a := ref foo; b := 1 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefFunction1(self): program_text = """ def foo = fun(a,b,c){ d := !c(a,b); a := a + b; return a } def help = fun(a,b){ c := a < b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("foo_a"), Primitive)) self.assertTrue(isinstance(self.get_type("foo_b"), Primitive)) self.assertTrue(isinstance(self.get_type("foo_d"), Primitive)) self.assertTrue(isinstance(self.get_type("help_a"), Primitive)) self.assertTrue(isinstance(self.get_type("help_b"), Primitive)) self.assertTrue(isinstance(self.get_type("help_c"), Primitive)) self.assertTrue(isinstance(self.get_type("foo"), Function)) self.assertTrue(isinstance(self.get_type("help"), Function)) self.assertTrue(isinstance(self.get_type("foo_c"), Reference)) self.assertTrue(isinstance(self.get_type("foo_c").value, Function)) self.assertTrue(self.get_type("foo_a").value == "INTEGER") self.assertTrue(self.get_type("foo_b").value == "INTEGER") def testRefFunction2(self): program_text = """ def foo = fun(a,b,c){ d := !c(a,b); a := a + b; return a } def help = fun(a,b){ c := a || b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefFunction3(self): program_text = """ def foo = fun(a,b,c){ d := !c(a); a := a + b; return a } def help = fun(a,b){ c := a < b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testRefFunction4(self): program_text = """ def foo = fun(a,b,c){ d:= 1; d := !c(a,b); a := a + b; return a } def help = fun(a,b){ c := a < b; return c } a := 1; b := 2; c := ref help; a := foo(a, b, c) """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testFunctionSignature1(self): program_text = """ def foo = fun(a,b){ a := a + b; return a } a := 1; b := 2; a := foo(a,b) """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("foo_a"), Primitive)) self.assertTrue(isinstance(self.get_type("foo_b"), Primitive)) self.assertTrue(isinstance(self.get_type("foo"), Function)) self.assertTrue(self.get_type("foo_a").value == "INTEGER") self.assertTrue(self.get_type("foo_b").value == "INTEGER") for sig in self.get_type("foo").signature: self.assertTrue(sig.value == "INTEGER") def testFunctionSignature2(self): program_text = """ def foo = fun(a,b){ a := a + b; return a } a := 1; b := true; a := foo(a,b) """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testFunctionSignature3(self): program_text = """ def foo = fun(a,b){ a := a + b; return a } a := 1; b := ref foo; a := foo(a,b) """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testDereference1(self): program_text = """ a := 1; x := ref a; a := !x """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("x"), Reference)) self.assertTrue(self.get_type("a").value == "INTEGER") self.assertTrue(self.get_type("x").value.value == "INTEGER") def testDereference2(self): program_text = """ a := 1; x := ref a; y := ref x; x := !y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("x"), Reference)) self.assertTrue(isinstance(self.get_type("y"), Reference)) self.assertTrue(isinstance(self.get_type("x").value, Primitive)) self.assertTrue(isinstance(self.get_type("y").value, Reference)) self.assertTrue(isinstance(self.get_type("y").value.value, Primitive)) self.assertTrue(self.get_type("a").value == "INTEGER") self.assertTrue(self.get_type("x").value.value == "INTEGER") self.assertTrue(self.get_type("y").value.value.value == "INTEGER") def testDereference3(self): program_text = """ a := 1; x := ref a; y := ref x; y := !x """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testDereference4(self): program_text = """ a := 1; b := !a """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testReference1(self): program_text = """ a := 1; b := 2; x := ref a; y := ref b; z := !x / !y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("b"), Primitive)) self.assertTrue(isinstance(self.get_type("x"), Reference)) self.assertTrue(isinstance(self.get_type("y"), Reference)) self.assertTrue(isinstance(self.get_type("x").value, Primitive)) self.assertTrue(isinstance(self.get_type("y").value, Primitive)) self.assertTrue(self.get_type("a").value == "INTEGER") self.assertTrue(self.get_type("b").value == "INTEGER") self.assertTrue(self.get_type("y").value.value == "INTEGER") self.assertTrue(self.get_type("x").value.value == "INTEGER") self.assertTrue(isinstance(self.get_type("z"), Primitive)) self.assertTrue(self.get_type("z").value == "INTEGER") def testReference2(self): program_text = """ a := 1; x := ref a; y := ref x """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("a"), Primitive)) self.assertTrue(isinstance(self.get_type("x"), Reference)) self.assertTrue(isinstance(self.get_type("y"), Reference)) self.assertTrue(isinstance(self.get_type("x").value, Primitive)) self.assertTrue(isinstance(self.get_type("y").value, Reference)) self.assertTrue(isinstance(self.get_type("y").value.value, Primitive)) self.assertTrue(self.get_type("a").value == "INTEGER") self.assertTrue(self.get_type("x").value.value == "INTEGER") self.assertTrue(self.get_type("y").value.value.value == "INTEGER") def testReference3(self): program_text = """ a := 1; x := ref a; y := ref x; a := !y """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testReference4(self): program_text = """ a := 1; b := true; x := ref a; b := !x """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testNew1(self): program_text = """ x := new integer; y := new integer; z := !x * !y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Reference)) self.assertTrue(isinstance(self.get_type("y"), Reference)) self.assertTrue(isinstance(self.get_type("x").value, Primitive)) self.assertTrue(isinstance(self.get_type("y").value, Primitive)) self.assertTrue(self.get_type("y").value.value == "INTEGER") self.assertTrue(self.get_type("x").value.value == "INTEGER") self.assertTrue(isinstance(self.get_type("z"), Primitive)) self.assertTrue(self.get_type("z").value == "INTEGER") def testNew2(self): program_text = """ x := new boolean; y := new boolean; z := !x || !y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Reference)) self.assertTrue(isinstance(self.get_type("y"), Reference)) self.assertTrue(isinstance(self.get_type("x").value, Primitive)) self.assertTrue(isinstance(self.get_type("y").value, Primitive)) self.assertTrue(self.get_type("y").value.value == "BOOLEAN") self.assertTrue(self.get_type("x").value.value == "BOOLEAN") self.assertTrue(isinstance(self.get_type("z"), Primitive)) self.assertTrue(self.get_type("z").value == "BOOLEAN") def testNew3(self): program_text = """ x := new ref boolean; y := !x; z := !y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Reference)) self.assertTrue(isinstance(self.get_type("y"), Reference)) self.assertTrue(isinstance(self.get_type("z"), Primitive)) self.assertTrue(isinstance(self.get_type("x").value, Reference)) self.assertTrue(isinstance(self.get_type("x").value.value, Primitive)) self.assertTrue(isinstance(self.get_type("y").value, Primitive)) self.assertTrue(self.get_type("y").value.value == "BOOLEAN") self.assertTrue(self.get_type("x").value.value.value == "BOOLEAN") self.assertTrue(self.get_type("z").value == "BOOLEAN") def testNew4(self): program_text = """ x := new ref integer; z := !x + 1 """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorLessEqual1(self): program_text = """ x := 1; y := 2; z := x <= y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Primitive)) self.assertTrue(isinstance(self.get_type("y"), Primitive)) self.assertTrue(self.get_type("y").value == "INTEGER") self.assertTrue(self.get_type("x").value == "INTEGER") self.assertTrue(isinstance(self.get_type("z"), Primitive)) self.assertTrue(self.get_type("z").value == "BOOLEAN") def testOperatorLessEqual2(self): program_text = """ x := 1; y := true; z := x <= y """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorLess1(self): program_text = """ x := 1; y := 2; z := x < y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Primitive)) self.assertTrue(isinstance(self.get_type("y"), Primitive)) self.assertTrue(self.get_type("y").value == "INTEGER") self.assertTrue(self.get_type("x").value == "INTEGER") self.assertTrue(isinstance(self.get_type("z"), Primitive)) self.assertTrue(self.get_type("z").value == "BOOLEAN") def testOperatorLess2(self): program_text = """ x := false; y := 2; z := x < y """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorDivide1(self): program_text = """ x := 1; y := 2; x := x / y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Primitive)) self.assertTrue(isinstance(self.get_type("y"), Primitive)) self.assertTrue(self.get_type("y").value == "INTEGER") self.assertTrue(self.get_type("x").value == "INTEGER") def testOperatorDivide2(self): program_text = """ x := false; y := true; z := x / y """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorTimes1(self): program_text = """ x := 1; y := 2; x := x * y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Primitive)) self.assertTrue(isinstance(self.get_type("y"), Primitive)) self.assertTrue(self.get_type("y").value == "INTEGER") self.assertTrue(self.get_type("x").value == "INTEGER") def testOperatorTimes2(self): program_text = """ x := 3; y := 1; z := x * y; z := false """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorMinus1(self): program_text = """ x := 1; y := 2; x := x - y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Primitive)) self.assertTrue(isinstance(self.get_type("y"), Primitive)) self.assertTrue(self.get_type("y").value == "INTEGER") self.assertTrue(self.get_type("x").value == "INTEGER") def testOperatorMinus2(self): program_text = """ x := true; y := 3; z := x - y """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program) def testOperatorPlus1(self): program_text = """ x := 1; y := 2; x := x + y """.strip() program = self.parser.parse(program_text) self.typecheck.visit_program(program) self.assertTrue(isinstance(self.get_type("x"), Primitive)) self.assertTrue(isinstance(self.get_type("y"), Primitive)) self.assertTrue(self.get_type("y").value == "INTEGER") self.assertTrue(self.get_type("x").value == "INTEGER") def testOperatorPlus2(self): program_text = """ x := false; y := true; z := x + y """.strip() program = self.parser.parse(program_text) self.assertRaises(TypeException, self.typecheck.visit_program, program)
class LanguageTest(TestCase): def setUp(self): super(LanguageTest, self).setUp() # For these tests, restrict logging to ERROR only and # print to stderr. This allows the lexer/parser to inform # us of real problems, without complaining in tests that # don't use all the tokens and/or productions. self.withLogging(stream=sys.stderr, level=logging.ERROR) self.parser = LingoParser() def run_token_match(self, parser, token_data): from ply.lex import runmain #@UnresolvedImport original_stdout = sys.stdout stdout_stringio = StringIO() sys.stdout = stdout_stringio try: runmain(lexer=parser.lexer, data=token_data) captured_io = stdout_stringio.getvalue() return captured_io finally: sys.stdout = original_stdout def assert_token_matches(self, parser, token_data, expected_type, expected_value): captured_io = self.run_token_match(parser, token_data) self.assertEqual( captured_io, '({0},{1},1,0)\n'.format(expected_type, repr(expected_value))) def test_recognizes_token_IDENTIFIER(self): self.assert_token_matches(self.parser, 'foo', 'IDENTIFIER', 'foo') def test_recognizes_token_NUMBER(self): self.assert_token_matches(self.parser, '100', 'NUMBER', 100) def test_recognizes_token_OP_PLUS(self): self.assert_token_matches(self.parser, '+', 'OP_PLUS', '+') def test_recognizes_token_OP_MINUS(self): self.assert_token_matches(self.parser, '-', 'OP_MINUS', '-') def test_recognizes_token_OP_TIMES(self): self.assert_token_matches(self.parser, '*', 'OP_TIMES', '*') def test_recognizes_token_OP_DIVIDE(self): self.assert_token_matches(self.parser, '/', 'OP_DIVIDE', '/') def test_recognizes_token_OP_CMP_LT(self): self.assert_token_matches(self.parser, '<', 'OP_CMP_LT', '<') def test_recognizes_token_OP_CMP_EQ(self): self.assert_token_matches(self.parser, '=', 'OP_CMP_EQ', '=') def test_recognizes_token_OP_CMP_NE(self): self.assert_token_matches(self.parser, '!=', 'OP_CMP_NE', '!=') def test_recognizes_token_OP_CMP_LTE(self): self.assert_token_matches(self.parser, '<=', 'OP_CMP_LTE', '<=') def test_recognizes_token_OP_BOOL_AND(self): self.assert_token_matches(self.parser, '&&', 'OP_BOOL_AND', '&&') def test_recognizes_token_OP_BOOL_OR(self): self.assert_token_matches(self.parser, '||', 'OP_BOOL_OR', '||') def test_recognizes_token_OP_DEREF(self): self.assert_token_matches(self.parser, '!', 'OP_DEREF', '!') def test_recognizes_token_OP_ASSIGNMENT(self): self.assert_token_matches(self.parser, ':=', 'OP_ASSIGNMENT', ':=') def test_recognizes_token_LPAREN(self): self.assert_token_matches(self.parser, '(', 'LPAREN', '(') def test_recognizes_token_RPAREN(self): self.assert_token_matches(self.parser, ')', 'RPAREN', ')') def test_recognizes_token_LBRACE(self): self.assert_token_matches(self.parser, '{', 'LBRACE', '{') def test_recognizes_token_RBRACE(self): self.assert_token_matches(self.parser, '}', 'RBRACE', '}') def test_recognizes_token_SEMI(self): self.assert_token_matches(self.parser, ';', 'SEMI', ';') def test_recognizes_token_KEYWORD_REF(self): self.assert_token_matches(self.parser, 'ref', 'KEYWORD_REF', 'ref') def test_recognizes_token_KEYWORD_DEF(self): self.assert_token_matches(self.parser, 'def', 'KEYWORD_DEF', 'def') def test_recognizes_token_KEYWORD_FUN(self): self.assert_token_matches(self.parser, 'fun', 'KEYWORD_FUN', 'fun') def test_recognizes_token_KEYWORD_RETURN(self): self.assert_token_matches(self.parser, 'return', 'KEYWORD_RETURN', 'return') def test_recognizes_token_KEYWORD_WHILE(self): self.assert_token_matches(self.parser, 'while', 'KEYWORD_WHILE', 'while') def test_recognizes_token_KEYWORD_DO(self): self.assert_token_matches(self.parser, 'do', 'KEYWORD_DO', 'do') def test_recognizes_token_KEYWORD_IF(self): self.assert_token_matches(self.parser, 'if', 'KEYWORD_IF', 'if') def test_recognizes_token_KEYWORD_THEN(self): self.assert_token_matches(self.parser, 'then', 'KEYWORD_THEN', 'then') def test_recognizes_token_KEYWORD_ELSE(self): self.assert_token_matches(self.parser, 'else', 'KEYWORD_ELSE', 'else') def test_recognizes_token_KEYWORD_SKIP(self): self.assert_token_matches(self.parser, 'skip', 'KEYWORD_SKIP', 'skip') def test_token_newline(self): captured_io = self.run_token_match(self.parser, '\n\n') self.assertEqual(captured_io, '') self.assertEqual(self.parser.lexer.lineno, 3) def test_token_ignore(self): captured_io = self.run_token_match(self.parser, ' \t') self.assertEqual(captured_io, '') def test_token_error(self): token = Mock() token.value = 'unknown' token.lexer = Mock() token.lexer.lineno = 10 self.assertRaises(LingoLexingException, self.parser.t_error, token) # # Error Production Tests # def test_production_error(self): production = Mock() production.lexer = Mock() production.lexer.lexdata = 'hello\nworld' production.lexpos = 0 production.lineno = 1 self.assertRaises(LingoParsingException, self.parser.p_error, production) # # Program Production Tests # def test_production_program(self): self.parser.start = 'program' result = self.parser.parse(''' def square = fun (x) { a := x * x; return a } square_argument := 11; square_result := square( square_argument ) ''') self.assertIsInstance(result, Program) self.assertEqual(len(result.functions), 1) self.assertIsInstance(result.command, AssignmentCommand) # # Function Production Tests # def test_production_function(self): self.parser.start = 'function_definition' result = self.parser.parse('fun (foo) { a := 1; return a }') self.assertIsInstance(result, FunctionDefinition) self.assertEqual(result.parameter.name, 'foo') self.assertIsInstance(result.body, AssignmentCommand) # # Command Production Tests # def test_production_command_sequence(self): self.parser.start = 'command' result = self.parser.parse('a := 1 ; b := 2') self.assertIsInstance(result, AssignmentCommand) self.assertEqual(result.assigned_variable.name, 'a') self.assertEqual(result.get_next_command().assigned_variable.name, 'b') def test_production_command_assignment(self): self.parser.start = 'command' result = self.parser.parse('a := 1') self.assertIsInstance(result, AssignmentCommand) self.assertEqual(result.assigned_variable.name, 'a') self.assertIsInstance(result.expression, Number) def test_production_command_dereferenced_assignment(self): self.parser.start = 'command' result = self.parser.parse('!a := 1') self.assertIsInstance(result, AssignmentCommand) self.assertEqual(result.assigned_variable.name, 'a') self.assertIsInstance(result.expression, Number) def test_production_command_if(self): self.parser.start = 'command' result = self.parser.parse( 'if ( a < b ) then { a := 1 } else { a := 2 }') self.assertIsInstance(result, IfCommand) self.assertIsInstance(result.expression, Expression) self.assertIsInstance(result.true_block, AssignmentCommand) self.assertIsInstance(result.false_block, AssignmentCommand) def test_production_command_while(self): self.parser.start = 'command' result = self.parser.parse('while ( 1 < 2 ) do { a := 1 }') self.assertIsInstance(result, WhileCommand) self.assertIsInstance(result.expression, Expression) self.assertIsInstance(result.loop_block, AssignmentCommand) def test_production_command_skip(self): self.parser.start = 'command' result = self.parser.parse('skip') self.assertIsInstance(result, SkipCommand) # # Assignment RHS Production Rule Tests # def test_production_assignment_rhs_expression(self): self.parser.start = 'assignment_rhs' result = self.parser.parse('1 + 2') self.assertIsInstance(result, BinaryExpression) def test_production_assignment_rhs_referenced_variable(self): self.parser.start = 'assignment_rhs' result = self.parser.parse('ref foo') self.assertIsInstance(result, ReferencedVariable) self.assertEqual(result.name, 'foo') def test_production_assignment_rhs_function_application(self): self.parser.start = 'assignment_rhs' result = self.parser.parse('foo(bar)') self.assertIsInstance(result, FunctionCall) self.assertEqual(result.function_variable.name, 'foo') self.assertEqual(result.parameter_variable.name, 'bar') # # Expression Production Rule Tests # def test_production_expression_binary_operation(self): self.parser.start = 'expression' result = self.parser.parse('a + 2') self.assertIsInstance(result, BinaryExpression) self.assertIsInstance(result.left_term, Variable) self.assertIsInstance(result.operator, Operator) self.assertIsInstance(result.right_term, Number) def test_production_expression_binary_operation_nested(self): self.parser.start = 'expression' result = self.parser.parse('(a + 2) <= b') self.assertIsInstance(result, BinaryExpression) self.assertIsInstance(result.left_term, BinaryExpression) self.assertIsInstance(result.operator, Operator) self.assertIsInstance(result.right_term, Variable) def test_production_expression_atom_number(self): self.parser.start = 'expression' result = self.parser.parse('1234') self.assertIsInstance(result, Number) self.assertEqual(result.value, 1234) def test_production_expression_atom_boolean(self): self.parser.start = 'expression' result = self.parser.parse('true') self.assertIsInstance(result, Boolean) self.assertEqual(result.value, True) def test_production_expression_atom_variable(self): self.parser.start = 'expression' result = self.parser.parse('abcd') self.assertIsInstance(result, Variable) self.assertEqual(result.name, 'abcd') def test_production_expression_atom_dereferenced_variable(self): self.parser.start = 'expression' result = self.parser.parse('!abcd') self.assertIsInstance(result, DereferencedVariable) self.assertEqual(result.name, 'abcd') # # Atom Production Rule Tests # def test_production_variable(self): self.parser.start = 'variable' result = self.parser.parse('foo') self.assertIsInstance(result, Variable) self.assertEqual(result.name, 'foo') def test_production_referenced_variable(self): self.parser.start = 'referenced_variable' result = self.parser.parse('ref foo') self.assertIsInstance(result, ReferencedVariable) self.assertEqual(result.name, 'foo') def test_production_dereferenced_variable(self): self.parser.start = 'dereferenced_variable' result = self.parser.parse('!foo') self.assertIsInstance(result, DereferencedVariable) self.assertEqual(result.name, 'foo') def test_production_bool_true(self): self.parser.start = 'bool' result = self.parser.parse('true') self.assertIsInstance(result, Boolean) self.assertEqual(result.value, True) def test_production_bool_false(self): self.parser.start = 'bool' result = self.parser.parse('false') self.assertIsInstance(result, Boolean) self.assertEqual(result.value, False) def test_production_number(self): self.parser.start = 'number' result = self.parser.parse('1234') self.assertIsInstance(result, Number) self.assertEqual(result.value, 1234) def test_production_arithmetic_operator_plus(self): self.parser.start = 'operator' result = self.parser.parse('+') self.assertIsInstance(result, OperatorPlus) def test_production_arithmetic_operator_minus(self): self.parser.start = 'operator' result = self.parser.parse('-') self.assertIsInstance(result, OperatorMinus) def test_production_arithmetic_operator_times(self): self.parser.start = 'operator' result = self.parser.parse('*') self.assertIsInstance(result, OperatorTimes) def test_production_arithmetic_operator_divide(self): self.parser.start = 'operator' result = self.parser.parse('/') self.assertIsInstance(result, OperatorDivide) def test_production_comparison_operator_lt(self): self.parser.start = 'operator' result = self.parser.parse('<') self.assertIsInstance(result, OperatorLessThan) def test_production_comparison_operator_eq(self): self.parser.start = 'operator' result = self.parser.parse('=') self.assertIsInstance(result, OperatorEqualTo) def test_production_comparison_operator_ne(self): self.parser.start = 'operator' result = self.parser.parse('!=') self.assertIsInstance(result, OperatorNotEqualTo) def test_production_comparison_operator_lte(self): self.parser.start = 'operator' result = self.parser.parse('<=') self.assertIsInstance(result, OperatorLessThanOrEqualTo) def test_production_operator_and(self): self.parser.start = 'operator' result = self.parser.parse('&&') self.assertIsInstance(result, OperatorAnd) def test_production_operator_or(self): self.parser.start = 'operator' result = self.parser.parse('||') self.assertIsInstance(result, OperatorOr) # # Tests for complete programs # These aren't really "unit" tests, so much as tests # that check some of the more involved features of the # LingoComponent stack. # def test_program_simple(self): program_text = ''' a := 1; b := 2; c := a + b '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 0) cmd_assign_a = program.command cmd_assign_b = cmd_assign_a.get_next_command() cmd_assign_c = cmd_assign_b.get_next_command() self.assertEqual(cmd_assign_c.assigned_variable.name, 'c') def test_program_conditional(self): program_text = ''' a := 1; b := 2; while ( a + b < 10 ) do { a := a + 1; b := b * 2 }; c := a + b '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 0) cmd_assign_a = program.command cmd_assign_b = cmd_assign_a.get_next_command() cmd_while = cmd_assign_b.get_next_command() cmd_assign_c = cmd_while.get_next_command() self.assertEqual(cmd_assign_c.assigned_variable.name, 'c') def test_program_functions(self): program_text = ''' def square = fun( x ) { result := x * x; return result } def cube = fun( x ) { result := x * x * x; return result } value := 4; squared := square(value); cubed := square(value) '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 2) def test_program_all_parse_symbols(self): # Lengthy test demonstrating all Lingo syntax features program_text = ''' def foo = fun(x) { skip; return x } a := 1 + 1; b := 2 - 2; c := 3 * 3; d := 4 / 4; e := true; f := false; g := a; h := 0; i := ref a; !i := 32; j := !i; k := ref foo; l := foo(a); m := !l(a); if (true) then { n := a } else { n := b }; o := true; while ( o ) do { o := false }; skip; if ( 1 < 2 ) then { skip } else { skip }; if ( 2 <= 2 ) then { skip } else { skip }; if ( 1 = 1 ) then { skip } else { skip }; if ( 1 != 2 ) then { skip } else { skip }; if ( true && true ) then { skip } else { skip }; if ( true || false ) then { skip } else { skip } '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 1) a_cmd = program.command self.assertIsInstance(a_cmd, AssignmentCommand) self.assertIsInstance(a_cmd.assigned_variable, Variable) self.assertEqual(a_cmd.assigned_variable.name, 'a') self.assertIsInstance(a_cmd.expression, BinaryExpression) self.assertIsInstance(a_cmd.expression.left_term, Number) self.assertEqual(a_cmd.expression.left_term.value, 1) self.assertIsInstance(a_cmd.expression.operator, OperatorPlus) self.assertIsInstance(a_cmd.expression.right_term, Number) self.assertEqual(a_cmd.expression.right_term.value, 1) b_cmd = a_cmd.get_next_command() self.assertIsInstance(b_cmd, AssignmentCommand) self.assertIsInstance(b_cmd.expression, BinaryExpression) self.assertIsInstance(b_cmd.expression.left_term, Number) self.assertEqual(b_cmd.expression.left_term.value, 2) self.assertIsInstance(b_cmd.expression.operator, OperatorMinus) self.assertIsInstance(b_cmd.expression.right_term, Number) self.assertEqual(b_cmd.expression.right_term.value, 2) c_cmd = b_cmd.get_next_command() self.assertIsInstance(c_cmd, AssignmentCommand) self.assertIsInstance(c_cmd.expression, BinaryExpression) self.assertIsInstance(c_cmd.expression.left_term, Number) self.assertEqual(c_cmd.expression.left_term.value, 3) self.assertIsInstance(c_cmd.expression.operator, OperatorTimes) self.assertIsInstance(c_cmd.expression.right_term, Number) self.assertEqual(c_cmd.expression.right_term.value, 3) d_cmd = c_cmd.get_next_command() self.assertIsInstance(d_cmd, AssignmentCommand) self.assertIsInstance(d_cmd.expression, BinaryExpression) self.assertIsInstance(d_cmd.expression.left_term, Number) self.assertEqual(d_cmd.expression.left_term.value, 4) self.assertIsInstance(d_cmd.expression.operator, OperatorDivide) self.assertIsInstance(d_cmd.expression.right_term, Number) self.assertEqual(d_cmd.expression.right_term.value, 4) e_cmd = d_cmd.get_next_command() self.assertIsInstance(e_cmd, AssignmentCommand) self.assertIsInstance(e_cmd.expression, Boolean) self.assertTrue(e_cmd.expression.value) f_cmd = e_cmd.get_next_command() self.assertIsInstance(f_cmd, AssignmentCommand) self.assertIsInstance(f_cmd.expression, Boolean) self.assertFalse(f_cmd.expression.value) g_cmd = f_cmd.get_next_command() self.assertIsInstance(g_cmd, AssignmentCommand) self.assertIsInstance(g_cmd.expression, Variable) self.assertEqual(g_cmd.expression.name, 'a') h_cmd = g_cmd.get_next_command() self.assertIsInstance(h_cmd, AssignmentCommand) self.assertIsInstance(h_cmd.expression, Number) self.assertEqual(h_cmd.expression.value, 0) i_cmd = h_cmd.get_next_command() self.assertIsInstance(i_cmd, AssignmentCommand) self.assertIsInstance(i_cmd.expression, ReferencedVariable) self.assertEqual(i_cmd.expression.name, 'a') i_deref_cmd = i_cmd.get_next_command() self.assertIsInstance(i_deref_cmd, AssignmentCommand) self.assertIsInstance(i_deref_cmd.assigned_variable, DereferencedVariable) self.assertEqual(i_deref_cmd.assigned_variable.name, 'i') j_cmd = i_deref_cmd.get_next_command() self.assertIsInstance(j_cmd, AssignmentCommand) self.assertIsInstance(j_cmd.expression, DereferencedVariable) self.assertEqual(j_cmd.expression.name, 'i') k_cmd = j_cmd.get_next_command() self.assertIsInstance(k_cmd, AssignmentCommand) self.assertIsInstance(k_cmd.expression, ReferencedVariable) self.assertEqual(k_cmd.expression.name, 'foo') l_call_cmd = k_cmd.get_next_command() self.assertIsInstance(l_call_cmd, AssignmentCommand) self.assertIsInstance(l_call_cmd.expression, FunctionCall) self.assertIsInstance(l_call_cmd.expression.function_variable, Variable) self.assertEqual(l_call_cmd.expression.function_variable.name, 'foo') self.assertIsInstance(l_call_cmd.expression.parameter_variable, Variable) self.assertEqual(l_call_cmd.expression.parameter_variable.name, 'a') l_ret_cmd = l_call_cmd.get_next_command() self.assertIsInstance(l_ret_cmd, AssignmentCommand) self.assertIsInstance(l_ret_cmd.expression, FunctionReturn) self.assertIsInstance(l_ret_cmd.expression.function_variable, Variable) self.assertEqual(l_ret_cmd.expression.function_variable.name, 'foo') self.assertIsInstance(l_ret_cmd.expression.parameter_variable, Variable) self.assertEqual(l_ret_cmd.expression.parameter_variable.name, 'a') m_call_cmd = l_ret_cmd.get_next_command() self.assertIsInstance(m_call_cmd, AssignmentCommand) self.assertIsInstance(m_call_cmd.expression, FunctionCall) self.assertIsInstance(m_call_cmd.expression.function_variable, DereferencedVariable) self.assertEqual(m_call_cmd.expression.function_variable.name, 'l') self.assertIsInstance(m_call_cmd.expression.parameter_variable, Variable) self.assertEqual(m_call_cmd.expression.parameter_variable.name, 'a') m_ret_cmd = m_call_cmd.get_next_command() self.assertIsInstance(m_ret_cmd, AssignmentCommand) self.assertIsInstance(m_ret_cmd.expression, FunctionReturn) self.assertIsInstance(m_ret_cmd.expression.function_variable, DereferencedVariable) self.assertEqual(m_ret_cmd.expression.function_variable.name, 'l') self.assertIsInstance(m_ret_cmd.expression.parameter_variable, Variable) self.assertEqual(m_ret_cmd.expression.parameter_variable.name, 'a') n_cmd = m_ret_cmd.get_next_command() self.assertIsInstance(n_cmd, IfCommand) self.assertIsInstance(n_cmd.expression, Boolean) self.assertEqual(n_cmd.expression.value, True) self.assertIsInstance(n_cmd.true_block, AssignmentCommand) self.assertIsInstance(n_cmd.true_block.assigned_variable, Variable) self.assertEqual(n_cmd.true_block.assigned_variable.name, 'n') self.assertIsInstance(n_cmd.false_block, AssignmentCommand) self.assertIsInstance(n_cmd.false_block.assigned_variable, Variable) self.assertEqual(n_cmd.false_block.assigned_variable.name, 'n') o_cmd = n_cmd.get_next_command() o_while_cmd = o_cmd.get_next_command() self.assertIsInstance(o_while_cmd, WhileCommand) self.assertIsInstance(o_while_cmd.expression, Variable) self.assertEqual(o_while_cmd.expression.name, 'o') self.assertIsInstance(o_while_cmd.loop_block, AssignmentCommand) self.assertIsInstance(o_while_cmd.loop_block.assigned_variable, Variable) self.assertEqual(o_while_cmd.loop_block.assigned_variable.name, 'o') skip_cmd = o_while_cmd.get_next_command() self.assertIsInstance(skip_cmd, SkipCommand) lt_if_cmd = skip_cmd.get_next_command() self.assertIsInstance(lt_if_cmd, IfCommand) self.assertIsInstance(lt_if_cmd.expression, BinaryExpression) self.assertIsInstance(lt_if_cmd.expression.operator, OperatorLessThan) le_if_cmd = lt_if_cmd.get_next_command() self.assertIsInstance(le_if_cmd, IfCommand) self.assertIsInstance(le_if_cmd.expression, BinaryExpression) self.assertIsInstance(le_if_cmd.expression.operator, OperatorLessThanOrEqualTo) eq_if_cmd = le_if_cmd.get_next_command() self.assertIsInstance(eq_if_cmd, IfCommand) self.assertIsInstance(eq_if_cmd.expression, BinaryExpression) self.assertIsInstance(eq_if_cmd.expression.operator, OperatorEqualTo) ne_if_cmd = eq_if_cmd.get_next_command() self.assertIsInstance(ne_if_cmd, IfCommand) self.assertIsInstance(ne_if_cmd.expression, BinaryExpression) self.assertIsInstance(ne_if_cmd.expression.operator, OperatorNotEqualTo) and_if_cmd = ne_if_cmd.get_next_command() self.assertIsInstance(and_if_cmd, IfCommand) self.assertIsInstance(and_if_cmd.expression, BinaryExpression) self.assertIsInstance(and_if_cmd.expression.operator, OperatorAnd) or_if_cmd = and_if_cmd.get_next_command() self.assertIsInstance(or_if_cmd, IfCommand) self.assertIsInstance(or_if_cmd.expression, BinaryExpression) self.assertIsInstance(or_if_cmd.expression.operator, OperatorOr)
class LanguageTest(TestCase): def setUp(self): super(LanguageTest, self).setUp() # For these tests, restrict logging to ERROR only and # print to stderr. This allows the lexer/parser to inform # us of real problems, without complaining in tests that # don't use all the tokens and/or productions. self.withLogging(stream = sys.stderr, level = logging.ERROR) self.parser = LingoParser() def run_token_match(self, parser, token_data): from ply.lex import runmain #@UnresolvedImport original_stdout = sys.stdout stdout_stringio = StringIO() sys.stdout = stdout_stringio try: runmain(lexer = parser.lexer, data = token_data) captured_io = stdout_stringio.getvalue() return captured_io finally: sys.stdout = original_stdout def assert_token_matches(self, parser, token_data, expected_type, expected_value): captured_io = self.run_token_match(parser, token_data) self.assertEqual(captured_io, '({0},{1},1,0)\n'.format(expected_type, repr(expected_value))) def test_recognizes_token_IDENTIFIER(self): self.assert_token_matches(self.parser, 'foo', 'IDENTIFIER', 'foo') def test_recognizes_token_NUMBER(self): self.assert_token_matches(self.parser, '100', 'NUMBER', 100) def test_recognizes_token_OP_PLUS(self): self.assert_token_matches(self.parser, '+', 'OP_PLUS', '+') def test_recognizes_token_OP_MINUS(self): self.assert_token_matches(self.parser, '-', 'OP_MINUS', '-') def test_recognizes_token_OP_TIMES(self): self.assert_token_matches(self.parser, '*', 'OP_TIMES', '*') def test_recognizes_token_OP_DIVIDE(self): self.assert_token_matches(self.parser, '/', 'OP_DIVIDE', '/') def test_recognizes_token_OP_CMP_LT(self): self.assert_token_matches(self.parser, '<', 'OP_CMP_LT', '<') def test_recognizes_token_OP_CMP_EQ(self): self.assert_token_matches(self.parser, '=', 'OP_CMP_EQ', '=') def test_recognizes_token_OP_CMP_NE(self): self.assert_token_matches(self.parser, '!=', 'OP_CMP_NE', '!=') def test_recognizes_token_OP_CMP_LTE(self): self.assert_token_matches(self.parser, '<=', 'OP_CMP_LTE', '<=') def test_recognizes_token_OP_BOOL_AND(self): self.assert_token_matches(self.parser, '&&', 'OP_BOOL_AND', '&&') def test_recognizes_token_OP_BOOL_OR(self): self.assert_token_matches(self.parser, '||', 'OP_BOOL_OR', '||') def test_recognizes_token_OP_DEREF(self): self.assert_token_matches(self.parser, '!', 'OP_DEREF', '!') def test_recognizes_token_OP_ASSIGNMENT(self): self.assert_token_matches(self.parser, ':=', 'OP_ASSIGNMENT', ':=') def test_recognizes_token_LPAREN(self): self.assert_token_matches(self.parser, '(', 'LPAREN', '(') def test_recognizes_token_RPAREN(self): self.assert_token_matches(self.parser, ')', 'RPAREN', ')') def test_recognizes_token_LBRACE(self): self.assert_token_matches(self.parser, '{', 'LBRACE', '{') def test_recognizes_token_RBRACE(self): self.assert_token_matches(self.parser, '}', 'RBRACE', '}') def test_recognizes_token_SEMI(self): self.assert_token_matches(self.parser, ';', 'SEMI', ';') def test_recognizes_token_KEYWORD_REF(self): self.assert_token_matches(self.parser, 'ref', 'KEYWORD_REF', 'ref') def test_recognizes_token_KEYWORD_DEF(self): self.assert_token_matches(self.parser, 'def', 'KEYWORD_DEF', 'def') def test_recognizes_token_KEYWORD_FUN(self): self.assert_token_matches(self.parser, 'fun', 'KEYWORD_FUN', 'fun') def test_recognizes_token_KEYWORD_RETURN(self): self.assert_token_matches(self.parser, 'return', 'KEYWORD_RETURN', 'return') def test_recognizes_token_KEYWORD_WHILE(self): self.assert_token_matches(self.parser, 'while', 'KEYWORD_WHILE', 'while') def test_recognizes_token_KEYWORD_DO(self): self.assert_token_matches(self.parser, 'do', 'KEYWORD_DO', 'do') def test_recognizes_token_KEYWORD_IF(self): self.assert_token_matches(self.parser, 'if', 'KEYWORD_IF', 'if') def test_recognizes_token_KEYWORD_THEN(self): self.assert_token_matches(self.parser, 'then', 'KEYWORD_THEN', 'then') def test_recognizes_token_KEYWORD_ELSE(self): self.assert_token_matches(self.parser, 'else', 'KEYWORD_ELSE', 'else') def test_recognizes_token_KEYWORD_SKIP(self): self.assert_token_matches(self.parser, 'skip', 'KEYWORD_SKIP', 'skip') def test_token_newline(self): captured_io = self.run_token_match(self.parser, '\n\n') self.assertEqual(captured_io, '') self.assertEqual(self.parser.lexer.lineno, 3) def test_token_ignore(self): captured_io = self.run_token_match(self.parser, ' \t') self.assertEqual(captured_io, '') def test_token_error(self): token = Mock() token.value = 'unknown' token.lexer = Mock() token.lexer.lineno = 10 self.assertRaises(LingoLexingException, self.parser.t_error, token) # # Error Production Tests # def test_production_error(self): production = Mock() production.lexer = Mock() production.lexer.lexdata = 'hello\nworld' production.lexpos = 0 production.lineno = 1 self.assertRaises(LingoParsingException, self.parser.p_error, production) # # Program Production Tests # def test_production_program(self): self.parser.start = 'program' result = self.parser.parse(''' def square = fun (x) { a := x * x; return a } square_argument := 11; square_result := square( square_argument ) ''') self.assertIsInstance(result, Program) self.assertEqual(len(result.functions), 1) self.assertIsInstance(result.command, AssignmentCommand) # # Function Production Tests # def test_production_function(self): self.parser.start = 'function_definition' result = self.parser.parse('fun (foo) { a := 1; return a }') self.assertIsInstance(result, FunctionDefinition) self.assertEqual(result.parameter.name, 'foo') self.assertIsInstance(result.body, AssignmentCommand) # # Command Production Tests # def test_production_command_sequence(self): self.parser.start = 'command' result = self.parser.parse('a := 1 ; b := 2') self.assertIsInstance(result, AssignmentCommand) self.assertEqual(result.assigned_variable.name, 'a') self.assertEqual(result.get_next_command().assigned_variable.name, 'b') def test_production_command_assignment(self): self.parser.start = 'command' result = self.parser.parse('a := 1') self.assertIsInstance(result, AssignmentCommand) self.assertEqual(result.assigned_variable.name, 'a') self.assertIsInstance(result.expression, Number) def test_production_command_dereferenced_assignment(self): self.parser.start = 'command' result = self.parser.parse('!a := 1') self.assertIsInstance(result, AssignmentCommand) self.assertEqual(result.assigned_variable.name, 'a') self.assertIsInstance(result.expression, Number) def test_production_command_if(self): self.parser.start = 'command' result = self.parser.parse('if ( a < b ) then { a := 1 } else { a := 2 }') self.assertIsInstance(result, IfCommand) self.assertIsInstance(result.expression, Expression) self.assertIsInstance(result.true_block, AssignmentCommand) self.assertIsInstance(result.false_block, AssignmentCommand) def test_production_command_while(self): self.parser.start = 'command' result = self.parser.parse('while ( 1 < 2 ) do { a := 1 }') self.assertIsInstance(result, WhileCommand) self.assertIsInstance(result.expression, Expression) self.assertIsInstance(result.loop_block, AssignmentCommand) def test_production_command_skip(self): self.parser.start = 'command' result = self.parser.parse('skip') self.assertIsInstance(result, SkipCommand) # # Assignment RHS Production Rule Tests # def test_production_assignment_rhs_expression(self): self.parser.start = 'assignment_rhs' result = self.parser.parse('1 + 2') self.assertIsInstance(result, BinaryExpression) def test_production_assignment_rhs_referenced_variable(self): self.parser.start = 'assignment_rhs' result = self.parser.parse('ref foo') self.assertIsInstance(result, ReferencedVariable) self.assertEqual(result.name, 'foo') def test_production_assignment_rhs_function_application(self): self.parser.start = 'assignment_rhs' result = self.parser.parse('foo(bar)') self.assertIsInstance(result, FunctionCall) self.assertEqual(result.function_variable.name, 'foo') self.assertEqual(result.parameter_variable.name, 'bar') # # Expression Production Rule Tests # def test_production_expression_binary_operation(self): self.parser.start = 'expression' result = self.parser.parse('a + 2') self.assertIsInstance(result, BinaryExpression) self.assertIsInstance(result.left_term, Variable) self.assertIsInstance(result.operator, Operator) self.assertIsInstance(result.right_term, Number) def test_production_expression_binary_operation_nested(self): self.parser.start = 'expression' result = self.parser.parse('(a + 2) <= b') self.assertIsInstance(result, BinaryExpression) self.assertIsInstance(result.left_term, BinaryExpression) self.assertIsInstance(result.operator, Operator) self.assertIsInstance(result.right_term, Variable) def test_production_expression_atom_number(self): self.parser.start = 'expression' result = self.parser.parse('1234') self.assertIsInstance(result, Number) self.assertEqual(result.value, 1234) def test_production_expression_atom_boolean(self): self.parser.start = 'expression' result = self.parser.parse('true') self.assertIsInstance(result, Boolean) self.assertEqual(result.value, True) def test_production_expression_atom_variable(self): self.parser.start = 'expression' result = self.parser.parse('abcd') self.assertIsInstance(result, Variable) self.assertEqual(result.name, 'abcd') def test_production_expression_atom_dereferenced_variable(self): self.parser.start = 'expression' result = self.parser.parse('!abcd') self.assertIsInstance(result, DereferencedVariable) self.assertEqual(result.name, 'abcd') # # Atom Production Rule Tests # def test_production_variable(self): self.parser.start = 'variable' result = self.parser.parse('foo') self.assertIsInstance(result, Variable) self.assertEqual(result.name, 'foo') def test_production_referenced_variable(self): self.parser.start = 'referenced_variable' result = self.parser.parse('ref foo') self.assertIsInstance(result, ReferencedVariable) self.assertEqual(result.name, 'foo') def test_production_dereferenced_variable(self): self.parser.start = 'dereferenced_variable' result = self.parser.parse('!foo') self.assertIsInstance(result, DereferencedVariable) self.assertEqual(result.name, 'foo') def test_production_bool_true(self): self.parser.start = 'bool' result = self.parser.parse('true') self.assertIsInstance(result, Boolean) self.assertEqual(result.value, True) def test_production_bool_false(self): self.parser.start = 'bool' result = self.parser.parse('false') self.assertIsInstance(result, Boolean) self.assertEqual(result.value, False) def test_production_number(self): self.parser.start = 'number' result = self.parser.parse('1234') self.assertIsInstance(result, Number) self.assertEqual(result.value, 1234) def test_production_arithmetic_operator_plus(self): self.parser.start = 'operator' result = self.parser.parse('+') self.assertIsInstance(result, OperatorPlus) def test_production_arithmetic_operator_minus(self): self.parser.start = 'operator' result = self.parser.parse('-') self.assertIsInstance(result, OperatorMinus) def test_production_arithmetic_operator_times(self): self.parser.start = 'operator' result = self.parser.parse('*') self.assertIsInstance(result, OperatorTimes) def test_production_arithmetic_operator_divide(self): self.parser.start = 'operator' result = self.parser.parse('/') self.assertIsInstance(result, OperatorDivide) def test_production_comparison_operator_lt(self): self.parser.start = 'operator' result = self.parser.parse('<') self.assertIsInstance(result, OperatorLessThan) def test_production_comparison_operator_eq(self): self.parser.start = 'operator' result = self.parser.parse('=') self.assertIsInstance(result, OperatorEqualTo) def test_production_comparison_operator_ne(self): self.parser.start = 'operator' result = self.parser.parse('!=') self.assertIsInstance(result, OperatorNotEqualTo) def test_production_comparison_operator_lte(self): self.parser.start = 'operator' result = self.parser.parse('<=') self.assertIsInstance(result, OperatorLessThanOrEqualTo) def test_production_operator_and(self): self.parser.start = 'operator' result = self.parser.parse('&&') self.assertIsInstance(result, OperatorAnd) def test_production_operator_or(self): self.parser.start = 'operator' result = self.parser.parse('||') self.assertIsInstance(result, OperatorOr) # # Tests for complete programs # These aren't really "unit" tests, so much as tests # that check some of the more involved features of the # LingoComponent stack. # def test_program_simple(self): program_text = ''' a := 1; b := 2; c := a + b '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 0) cmd_assign_a = program.command cmd_assign_b = cmd_assign_a.get_next_command() cmd_assign_c = cmd_assign_b.get_next_command() self.assertEqual(cmd_assign_c.assigned_variable.name, 'c') def test_program_conditional(self): program_text = ''' a := 1; b := 2; while ( a + b < 10 ) do { a := a + 1; b := b * 2 }; c := a + b '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 0) cmd_assign_a = program.command cmd_assign_b = cmd_assign_a.get_next_command() cmd_while = cmd_assign_b.get_next_command() cmd_assign_c = cmd_while.get_next_command() self.assertEqual(cmd_assign_c.assigned_variable.name, 'c') def test_program_functions(self): program_text = ''' def square = fun( x ) { result := x * x; return result } def cube = fun( x ) { result := x * x * x; return result } value := 4; squared := square(value); cubed := square(value) '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 2) def test_program_all_parse_symbols(self): # Lengthy test demonstrating all Lingo syntax features program_text = ''' def foo = fun(x) { skip; return x } a := 1 + 1; b := 2 - 2; c := 3 * 3; d := 4 / 4; e := true; f := false; g := a; h := 0; i := ref a; !i := 32; j := !i; k := ref foo; l := foo(a); m := !l(a); if (true) then { n := a } else { n := b }; o := true; while ( o ) do { o := false }; skip; if ( 1 < 2 ) then { skip } else { skip }; if ( 2 <= 2 ) then { skip } else { skip }; if ( 1 = 1 ) then { skip } else { skip }; if ( 1 != 2 ) then { skip } else { skip }; if ( true && true ) then { skip } else { skip }; if ( true || false ) then { skip } else { skip } '''.strip() program = self.parser.parse(program_text) self.assertIsInstance(program, Program) self.assertEqual(len(program.functions), 1) a_cmd = program.command self.assertIsInstance(a_cmd, AssignmentCommand) self.assertIsInstance(a_cmd.assigned_variable, Variable) self.assertEqual(a_cmd.assigned_variable.name, 'a') self.assertIsInstance(a_cmd.expression, BinaryExpression) self.assertIsInstance(a_cmd.expression.left_term, Number) self.assertEqual(a_cmd.expression.left_term.value, 1) self.assertIsInstance(a_cmd.expression.operator, OperatorPlus) self.assertIsInstance(a_cmd.expression.right_term, Number) self.assertEqual(a_cmd.expression.right_term.value, 1) b_cmd = a_cmd.get_next_command() self.assertIsInstance(b_cmd, AssignmentCommand) self.assertIsInstance(b_cmd.expression, BinaryExpression) self.assertIsInstance(b_cmd.expression.left_term, Number) self.assertEqual(b_cmd.expression.left_term.value, 2) self.assertIsInstance(b_cmd.expression.operator, OperatorMinus) self.assertIsInstance(b_cmd.expression.right_term, Number) self.assertEqual(b_cmd.expression.right_term.value, 2) c_cmd = b_cmd.get_next_command() self.assertIsInstance(c_cmd, AssignmentCommand) self.assertIsInstance(c_cmd.expression, BinaryExpression) self.assertIsInstance(c_cmd.expression.left_term, Number) self.assertEqual(c_cmd.expression.left_term.value, 3) self.assertIsInstance(c_cmd.expression.operator, OperatorTimes) self.assertIsInstance(c_cmd.expression.right_term, Number) self.assertEqual(c_cmd.expression.right_term.value, 3) d_cmd = c_cmd.get_next_command() self.assertIsInstance(d_cmd, AssignmentCommand) self.assertIsInstance(d_cmd.expression, BinaryExpression) self.assertIsInstance(d_cmd.expression.left_term, Number) self.assertEqual(d_cmd.expression.left_term.value, 4) self.assertIsInstance(d_cmd.expression.operator, OperatorDivide) self.assertIsInstance(d_cmd.expression.right_term, Number) self.assertEqual(d_cmd.expression.right_term.value, 4) e_cmd = d_cmd.get_next_command() self.assertIsInstance(e_cmd, AssignmentCommand) self.assertIsInstance(e_cmd.expression, Boolean) self.assertTrue(e_cmd.expression.value) f_cmd = e_cmd.get_next_command() self.assertIsInstance(f_cmd, AssignmentCommand) self.assertIsInstance(f_cmd.expression, Boolean) self.assertFalse(f_cmd.expression.value) g_cmd = f_cmd.get_next_command() self.assertIsInstance(g_cmd, AssignmentCommand) self.assertIsInstance(g_cmd.expression, Variable) self.assertEqual(g_cmd.expression.name, 'a') h_cmd = g_cmd.get_next_command() self.assertIsInstance(h_cmd, AssignmentCommand) self.assertIsInstance(h_cmd.expression, Number) self.assertEqual(h_cmd.expression.value, 0) i_cmd = h_cmd.get_next_command() self.assertIsInstance(i_cmd, AssignmentCommand) self.assertIsInstance(i_cmd.expression, ReferencedVariable) self.assertEqual(i_cmd.expression.name, 'a') i_deref_cmd = i_cmd.get_next_command() self.assertIsInstance(i_deref_cmd, AssignmentCommand) self.assertIsInstance(i_deref_cmd.assigned_variable, DereferencedVariable) self.assertEqual(i_deref_cmd.assigned_variable.name, 'i') j_cmd = i_deref_cmd.get_next_command() self.assertIsInstance(j_cmd, AssignmentCommand) self.assertIsInstance(j_cmd.expression, DereferencedVariable) self.assertEqual(j_cmd.expression.name, 'i') k_cmd = j_cmd.get_next_command() self.assertIsInstance(k_cmd, AssignmentCommand) self.assertIsInstance(k_cmd.expression, ReferencedVariable) self.assertEqual(k_cmd.expression.name, 'foo') l_call_cmd = k_cmd.get_next_command() self.assertIsInstance(l_call_cmd, AssignmentCommand) self.assertIsInstance(l_call_cmd.expression, FunctionCall) self.assertIsInstance(l_call_cmd.expression.function_variable, Variable) self.assertEqual(l_call_cmd.expression.function_variable.name, 'foo') self.assertIsInstance(l_call_cmd.expression.parameter_variable, Variable) self.assertEqual(l_call_cmd.expression.parameter_variable.name, 'a') l_ret_cmd = l_call_cmd.get_next_command() self.assertIsInstance(l_ret_cmd, AssignmentCommand) self.assertIsInstance(l_ret_cmd.expression, FunctionReturn) self.assertIsInstance(l_ret_cmd.expression.function_variable, Variable) self.assertEqual(l_ret_cmd.expression.function_variable.name, 'foo') self.assertIsInstance(l_ret_cmd.expression.parameter_variable, Variable) self.assertEqual(l_ret_cmd.expression.parameter_variable.name, 'a') m_call_cmd = l_ret_cmd.get_next_command() self.assertIsInstance(m_call_cmd, AssignmentCommand) self.assertIsInstance(m_call_cmd.expression, FunctionCall) self.assertIsInstance(m_call_cmd.expression.function_variable, DereferencedVariable) self.assertEqual(m_call_cmd.expression.function_variable.name, 'l') self.assertIsInstance(m_call_cmd.expression.parameter_variable, Variable) self.assertEqual(m_call_cmd.expression.parameter_variable.name, 'a') m_ret_cmd = m_call_cmd.get_next_command() self.assertIsInstance(m_ret_cmd, AssignmentCommand) self.assertIsInstance(m_ret_cmd.expression, FunctionReturn) self.assertIsInstance(m_ret_cmd.expression.function_variable, DereferencedVariable) self.assertEqual(m_ret_cmd.expression.function_variable.name, 'l') self.assertIsInstance(m_ret_cmd.expression.parameter_variable, Variable) self.assertEqual(m_ret_cmd.expression.parameter_variable.name, 'a') n_cmd = m_ret_cmd.get_next_command() self.assertIsInstance(n_cmd, IfCommand) self.assertIsInstance(n_cmd.expression, Boolean) self.assertEqual(n_cmd.expression.value, True) self.assertIsInstance(n_cmd.true_block, AssignmentCommand) self.assertIsInstance(n_cmd.true_block.assigned_variable, Variable) self.assertEqual(n_cmd.true_block.assigned_variable.name, 'n') self.assertIsInstance(n_cmd.false_block, AssignmentCommand) self.assertIsInstance(n_cmd.false_block.assigned_variable, Variable) self.assertEqual(n_cmd.false_block.assigned_variable.name, 'n') o_cmd = n_cmd.get_next_command() o_while_cmd = o_cmd.get_next_command() self.assertIsInstance(o_while_cmd, WhileCommand) self.assertIsInstance(o_while_cmd.expression, Variable) self.assertEqual(o_while_cmd.expression.name, 'o') self.assertIsInstance(o_while_cmd.loop_block, AssignmentCommand) self.assertIsInstance(o_while_cmd.loop_block.assigned_variable, Variable) self.assertEqual(o_while_cmd.loop_block.assigned_variable.name, 'o') skip_cmd = o_while_cmd.get_next_command() self.assertIsInstance(skip_cmd, SkipCommand) lt_if_cmd = skip_cmd.get_next_command() self.assertIsInstance(lt_if_cmd, IfCommand) self.assertIsInstance(lt_if_cmd.expression, BinaryExpression) self.assertIsInstance(lt_if_cmd.expression.operator, OperatorLessThan) le_if_cmd = lt_if_cmd.get_next_command() self.assertIsInstance(le_if_cmd, IfCommand) self.assertIsInstance(le_if_cmd.expression, BinaryExpression) self.assertIsInstance(le_if_cmd.expression.operator, OperatorLessThanOrEqualTo) eq_if_cmd = le_if_cmd.get_next_command() self.assertIsInstance(eq_if_cmd, IfCommand) self.assertIsInstance(eq_if_cmd.expression, BinaryExpression) self.assertIsInstance(eq_if_cmd.expression.operator, OperatorEqualTo) ne_if_cmd = eq_if_cmd.get_next_command() self.assertIsInstance(ne_if_cmd, IfCommand) self.assertIsInstance(ne_if_cmd.expression, BinaryExpression) self.assertIsInstance(ne_if_cmd.expression.operator, OperatorNotEqualTo) and_if_cmd = ne_if_cmd.get_next_command() self.assertIsInstance(and_if_cmd, IfCommand) self.assertIsInstance(and_if_cmd.expression, BinaryExpression) self.assertIsInstance(and_if_cmd.expression.operator, OperatorAnd) or_if_cmd = and_if_cmd.get_next_command() self.assertIsInstance(or_if_cmd, IfCommand) self.assertIsInstance(or_if_cmd.expression, BinaryExpression) self.assertIsInstance(or_if_cmd.expression.operator, OperatorOr)