def test_eq(self): expressions1 = [None, Expression(Type.int(), 1), Expression(Type.decimal(), 1.1), Expression(Type.boolean(), False), Expression(Type.vector(), [1.1, 2.2, -1.1]), Expression(Type.list_of(Type.int()), [1, 2, 3, 4]), Expression(Type.list_of(Type.int()), []), Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0]), Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]]), Expression(Type.int(), 1, "a"), Expression(Type.decimal(), 1.1, "a"), Expression(Type.boolean(), False, "a"), Expression(Type.vector(), [1.1, 2.2, -1.1], "a"), Expression(Type.list_of(Type.int()), [1, 2, 3, 4], "a"), Expression(Type.list_of(Type.int()), [], "a"), Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]], "a")] expressions2 = [None, Expression(Type.int(), 1), Expression(Type.decimal(), 1.1), Expression(Type.boolean(), False), Expression(Type.vector(), [1.1, 2.2, -1.1]), Expression(Type.list_of(Type.int()), [1, 2, 3, 4]), Expression(Type.list_of(Type.int()), []), Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0]), Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]]), Expression(Type.int(), 1, "a"), Expression(Type.decimal(), 1.1, "a"), Expression(Type.boolean(), False, "a"), Expression(Type.vector(), [1.1, 2.2, -1.1], "a"), Expression(Type.list_of(Type.int()), [1, 2, 3, 4], "a"), Expression(Type.list_of(Type.int()), [], "a"), Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]], "a")] for i in range(len(expressions1)): for j in range(len(expressions2)): if i == j: self.assertEqual(expressions1[i], expressions2[j]) else: self.assertNotEqual(expressions1[i], expressions2[j])
def test_declare_and_assign_with_different_type_should_give_error(self): types = [ Type.int(), Type.decimal(), Type.string(), Type.boolean(), Type.vector(), Type.list_of(Type.int()), Type.list_of(Type.list_of(Type.int())) ] for t1 in types: for t2 in types: if t1 == t2: continue with self.assertRaises(CompileError) as context: generate_commands(""" main () {{ {} a; {} b <- a; }} """.format(t1, t2)) self.assertTrue( "Identifier b has been declared as {}, but assigned as {}". format(t2.type_name, t1.type_name) in str( context.exception))
def test_str(self): self.assertEqual("Expression: { type: int, value: 1, ident: None }", str(Expression(Type.int(), 1))) self.assertEqual("Expression: { type: decimal, value: 1.1, ident: None }", str(Expression(Type.decimal(), 1.1))) self.assertEqual("Expression: { type: boolean, value: False, ident: None }", str(Expression(Type.boolean(), False))) self.assertEqual("Expression: { type: vector, value: [1.1, 2.2, -1.1], ident: None }", str(Expression(Type.vector(), [1.1, 2.2, -1.1]))) self.assertEqual("Expression: { type: list[int], value: [1, 2, 3, 4], ident: None }", str(Expression(Type.list_of(Type.int()), [1, 2, 3, 4]))) self.assertEqual("Expression: { type: list[int], value: [], ident: None }", str(Expression(Type.list_of(Type.int()), []))) self.assertEqual( "Expression: { type: list[list[vector]], value: [[[1.1, 2.2, -1.1], [1, 2, -1]]], ident: None }", str(Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]]))) self.assertEqual("Expression: { type: int, value: 1, ident: a }", str(Expression(Type.int(), 1, "a"))) self.assertEqual("Expression: { type: decimal, value: 1.1, ident: a }", str(Expression(Type.decimal(), 1.1, "a"))) self.assertEqual("Expression: { type: boolean, value: False, ident: a }", str(Expression(Type.boolean(), False, "a"))) self.assertEqual("Expression: { type: vector, value: [1.1, 2.2, -1.1], ident: a }", str(Expression(Type.vector(), [1.1, 2.2, -1.1], "a"))) self.assertEqual("Expression: { type: list[int], value: [1, 2, 3, 4], ident: a }", str(Expression(Type.list_of(Type.int()), [1, 2, 3, 4], "a"))) self.assertEqual("Expression: { type: list[int], value: [], ident: a }", str(Expression(Type.list_of(Type.int()), [], "a"))) self.assertEqual("Expression: { type: list[list[vector]], value: [[[1.1, 2.2, -1.1], [1, 2, -1]]], ident: a }", str(Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]], "a")))
def test_update(self): st = SymbolTable() self.assertRaises(AssertionError, st.update, "a", 1) st.store("a", Expression(Type.int(), 1)) st.update("a", 2) self.assertEqual(Type.int(), st.get_expression("a").type) self.assertEqual(2, st.get_expression("a").value)
def test_assign_list_elem_with_different_type_should_give_error(self): types = [ Type.int(), Type.decimal(), Type.string(), Type.boolean(), Type.vector(), Type.list_of(Type.int()), Type.list_of(Type.list_of(Type.int())) ] for t1 in types: for t2 in types: if t1 == t2: continue with self.assertRaises(CompileError) as context: generate_commands(""" main () {{ {} a; {} b; list[{}] c <- [a]; c[0] <- b; }} """.format(t1, t2, t1)) self.assertTrue( "Assigned value {} should have type {}, but is {}".format( t2.default_value, t1.type_name, t2.type_name) in str( context.exception))
def test_list(self): list_type = Type.list_of(Type.int()) self.assertEqual(Type.list_of(Type.int()), list_type) self.assertEqual(ListType(Type.int()), list_type) self.assertEqual("list[int]", list_type.type_name) self.assertEqual([], list_type.default_value) self.assertEqual(Type.int(), list_type.elem_type) self.assertEqual("list[int]", str(list_type))
def test_nested_list(self): inner = Type.list_of(Type.int()) outer = Type.list_of(inner) self.assertEqual(ListType(Type.list_of(Type.int())), outer) self.assertEqual("list[list[int]]", outer.type_name) self.assertEqual([], outer.default_value) self.assertEqual(Type.list_of(Type.int()), outer.elem_type) self.assertEqual("list[list[int]]", str(outer))
def test_store(self): st = SymbolTable() st.store("a", Expression(Type.int(), 1)) self.assertTrue("a" in st) self.assertEqual(Type.int(), st.get_expression("a").type) self.assertEqual(1, st.get_expression("a").value) self.assertRaises(AssertionError, st.store, "a", Expression(Type.int(), 1))
def test_corrupted_type_should_not_affect_correct_type(self): int_type = Type.int() corrupted_type = Type.int() corrupted_type._type_name = "corrupted" self.assertNotEqual(int_type, corrupted_type) self.assertEqual("int", str(Type.int())) self.assertEqual(0, Type.int().default_value) self.assertEqual("corrupted", str(corrupted_type)) self.assertEqual(0, corrupted_type.default_value)
def test_to_expression_should_return_correct_value(self): expressions = [None, Expression(Type.int(), 1, "a"), Expression(Type.decimal(), 1.1, "a"), Expression(Type.boolean(), False, "a"), Expression(Type.vector(), [1.1, 2.2, -1.1], "a"), Expression(Type.list_of(Type.int()), [1, 2, 3, 4], "a"), Expression(Type.list_of(Type.int()), [], "a"), Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]], "a")] for expression in expressions: self.assertEqual(expression, Identifier("a", expression).to_expression())
def test_eq(self): st1 = SymbolTable() st2 = SymbolTable() self.assertTrue(st1 == st2) st1.store("a", Expression(Type.int(), 0)) self.assertFalse(st1 == st2) st2.store("a", Expression(Type.int(), 0)) self.assertTrue(st1 == st2) self.assertNotEqual(SymbolTable(), None)
def test_to_expression_should_equal_self(self): expressions = [Expression(Type.int(), 1), Expression(Type.decimal(), 1.1), Expression(Type.boolean(), False), Expression(Type.vector(), [1.1, 2.2, -1.1]), Expression(Type.list_of(Type.int()), [1, 2, 3, 4]), Expression(Type.list_of(Type.int()), []), Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0]), Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]]), Expression(Type.int(), 1, "a"), Expression(Type.decimal(), 1.1, "a"), Expression(Type.boolean(), False, "a"), Expression(Type.vector(), [1.1, 2.2, -1.1], "a"), Expression(Type.list_of(Type.int()), [1, 2, 3, 4], "a"), Expression(Type.list_of(Type.int()), [], "a"), Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]], "a")] for expression in expressions: self.assertEqual(expression, expression.to_expression())
def rotate_right(self, children) -> List[Command]: expr, = children if expr.type != Type.int() and expr.type != Type.decimal(): raise CompileError( "Expression {} should have type int or decimal, but is {}". format(expr.value, expr.type)) return [Command.rotate_right(radians(expr.value))]
def backward(self, children) -> List[Command]: expr, = children if expr.type != Type.int() and expr.type != Type.decimal(): raise CompileError( "Expression {} should have type int or decimal, but is {}". format(expr.value, expr.type)) return [Command.backward(expr.value)]
def test_container_not_list_should_give_error(self): none_list_exprs = [Expression(Type.int(), 1, "a"), Expression(Type.decimal(), 1.0, "a"), Expression(Type.boolean(), True, "a"), Expression(Type.string(), "abc", "a"), Expression(Type.vector(), [1.0, 1.0, 1.0], "a")] for none_list_expr in none_list_exprs: with self.assertRaises(AssertionError) as context: ListElem("a", none_list_expr, 0)
def test_declare_int_should_change_symbol_table(self): actual = SymbolTable() generate_commands(""" main () { int a; } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.int(), 0, ident="a")) self.assertEqual(expected, actual)
def test_str(self): st = SymbolTable() st.store("a", Expression(Type.int(), 0)) st.store("b", Expression(Type.list_of(Type.boolean()), [True])) expected = "SymbolTable: {\n" + \ " a -> Expression: { type: int, value: 0, ident: None }\n" + \ " b -> Expression: { type: list[boolean], value: [True], ident: None }\n" + \ "}" self.assertEqual(expected, str(st))
def repeat(self, children) -> List[Command]: expr = children[0] commands = children[1:] if expr.type != Type.int(): raise CompileError( "Expression {} should have type int, but is {}".format( expr.value, expr.type)) times = expr.value return commands * times
def test_declare_and_assign_list_should_change_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { list[int] a <- [1, 2, -3]; } """, actual) expected = SymbolTable() expected.store( "a", Expression(Type.list_of(Type.int()), [1, 2, -3], ident="a")) self.assertEqual(expected, actual)
def test_eq(self): list_elems1 = [None, ListElem("a", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), 0), ListElem("b", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "b"), 0), ListElem("a", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0], "a"), 0), ListElem("a", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), 1), ListElem("a", Expression(Type.list_of(Type.list_of(Type.int())), [[[1], [1]]], "a"), 0), ListElem("b[1]", Expression(Type.list_of(Type.boolean()), [True, False], "b[1]"), 0)] list_elems2 = [None, ListElem("a", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), 0), ListElem("b", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "b"), 0), ListElem("a", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0], "a"), 0), ListElem("a", Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a"), 1), ListElem("a", Expression(Type.list_of(Type.list_of(Type.int())), [[[1], [1]]], "a"), 0), ListElem("b[1]", Expression(Type.list_of(Type.boolean()), [True, False], "b[1]"), 0)] for i in range(len(list_elems1)): for j in range(len(list_elems2)): if i == j: self.assertEqual(list_elems1[i], list_elems2[j]) else: self.assertNotEqual(list_elems1[i], list_elems2[j])
def test_assign_ident_int_should_update_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { int a; a <- -1; } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.int(), -1, ident="a")) self.assertEqual(expected, actual)
def test_assign_ident_list_should_update_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { list[int] a; a <- [1, -1, +1]; } """, actual) expected = SymbolTable() expected.store( "a", Expression(Type.list_of(Type.int()), [1, -1, 1], ident="a")) self.assertEqual(expected, actual)
def test_declare_and_assign_ident_empty_list_should_update_symbol_table( self): types = [ Type.int(), Type.decimal(), Type.string(), Type.boolean(), Type.vector(), Type.list_of(Type.int()), Type.list_of(Type.list_of(Type.int())) ] for type in types: actual = SymbolTable() generate_commands( """ main () {{ list[{}] a <- []; }} """.format(type.type_name), actual) expected = SymbolTable() expected.store("a", Expression(Type.list_of(type), [], ident="a")) self.assertEqual(expected, actual)
def test_declare_with_different_variable_name_should_change_symbol_table( self): for name in [ "a", "A", "_a", "_1", "_A", "abc", "Abc", "a12", "aA1", "_aA1" ]: actual = SymbolTable() generate_commands( """ main () {{ int {}; }} """.format(name), actual) expected = SymbolTable() expected.store(name, Expression(Type.int(), 0, ident=name)) self.assertEqual(expected, actual)
def test_declare_and_then_assign_vector_elem_with_different_type_should_give_error( self): for type in [ Type.int(), Type.string(), Type.boolean(), Type.vector(), Type.list_of(Type.int()), Type.list_of(Type.list_of(Type.int())) ]: with self.assertRaises(CompileError) as context: generate_commands(""" main () {{ vector a; {} b; a.x <- b; }} """.format(type.type_name)) self.assertTrue( "Assigned value {} should have type decimal, but is {}".format( type.default_value, type.type_name) in str( context.exception))
def test_assign_list_elem_to_variable_should_update_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { list[int] a <- [0, 1, 2]; a[0] <- 1; a[2] <- a[0]; } """, actual) expected = SymbolTable() expected.store( "a", Expression(Type.list_of(Type.int()), [1, 1, 1], ident="a")) self.assertEqual(expected, actual)
def list_elem(self, children) -> ListElem: expr1, expr2 = children if not isinstance(expr1.type, ListType): raise CompileError( "Expression {} has type {} is not a list".format( expr1, expr1.type)) if expr2.type != Type.int(): raise CompileError( "Expression {} should have type int, but is {}".format( expr2, expr2.type)) if expr2.value >= len(expr1.value): raise CompileError( "List {} has length {}, but has been assessed with out-of-range index {}" .format(expr1.ident, len(expr1.value), expr2.value)) return ListElem(expr1.ident, expr1, expr2.value)
def test_assign_list_elem_to_variable_nested_should_update_symbol_table( self): actual = SymbolTable() generate_commands( """ main () { list[list[int]] a <- [[0, 1], [2, 3]]; a[0] <- [4, 5]; a[1][0] <- 6; a[1][1] <- 7; } """, actual) expected = SymbolTable() expected.store( "a", Expression(Type.list_of(Type.list_of(Type.int())), [[4, 5], [6, 7]], ident="a")) self.assertEqual(expected, actual)
def test_eq(self): identifiers1 = [None, Identifier("a", None), Identifier("a", Expression(Type.int(), 1, "a")), Identifier("a", Expression(Type.decimal(), 1.1, "a")), Identifier("b", Expression(Type.int(), 1, "b")), Identifier("b", Expression(Type.list_of(Type.int()), [], "b"))] identifiers2 = [None, Identifier("a", None), Identifier("a", Expression(Type.int(), 1, "a")), Identifier("a", Expression(Type.decimal(), 1.1, "a")), Identifier("b", Expression(Type.int(), 1, "b")), Identifier("b", Expression(Type.list_of(Type.int()), [], "b"))] for i in range(len(identifiers1)): for j in range(len(identifiers2)): if i == j: self.assertEqual(identifiers1[i], identifiers2[j]) else: self.assertNotEqual(identifiers1[i], identifiers2[j])
def test_eq(self): types1 = [ None, Type.int(), Type.decimal(), Type.string(), Type.boolean(), Type.vector(), Type.list_of(Type.int()), Type.list_of(Type.decimal()), Type.list_of(Type.list_of(Type.int())), Type.list_of(Type.list_of(Type.decimal())) ] types2 = [ None, Type.int(), Type.decimal(), Type.string(), Type.boolean(), Type.vector(), Type.list_of(Type.int()), Type.list_of(Type.decimal()), Type.list_of(Type.list_of(Type.int())), Type.list_of(Type.list_of(Type.decimal())) ] for i in range(len(types1)): for j in range(len(types2)): if i == j: self.assertEqual(types1[i], types2[j]) else: self.assertNotEqual(types1[i], types2[j]) self.assertEqual(Type.empty_list(), Type.empty_list()) for type in types1: if isinstance(type, ListType): self.assertEqual(Type.empty_list(), type) self.assertEqual(type, Type.empty_list()) else: self.assertNotEqual(Type.empty_list(), type) self.assertNotEqual(type, Type.empty_list())