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_to_expression_should_return_correct_value(self): expression = Expression(Type.vector(), [1.0, 2.0, 3.0], "a") expected = Expression(Type.decimal(), 1.0) self.assertEqual(expected, VectorElem("a", expression, 0).to_expression()) expression = Expression(Type.vector(), [1.0, 2.0, 3.0], "b[1]") expected = Expression(Type.decimal(), 3.0) self.assertEqual(expected, VectorElem("b[1]", expression, 2).to_expression())
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_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 list(self, children) -> Expression: exprs = children if len(exprs) == 0: return Expression(Type.empty_list(), []) if not all(e.type == exprs[0].type for e in exprs): raise CompileError( "Elements in list {} should have the same type".format(exprs)) return Expression(Type.list_of(exprs[0].type), [e.value for e in exprs])
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_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 declare(self, children) -> List[Command]: type, identifier = children ident = identifier.ident if ident in self.symbol_table: raise CompileError("Identifier {} already declared".format(ident)) self.symbol_table.store( ident, Expression(type, type.default_value, ident=ident)) return []
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_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 update(self, ident: str, value: Union[int, float, str, bool, list]) -> None: assert self.__contains__( ident ), "Expression not in symbol table, please use store() to store it first" old_expression = self._symbol_table[ident] self._symbol_table[ident] = Expression(old_expression.type, value, ident=ident)
def test_declare_and_assign_decimal_should_change_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { decimal a <- 1.0; } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.decimal(), 1.0, ident="a")) self.assertEqual(expected, actual)
def vector(self, children) -> Expression: expr1, expr2, expr3 = children for expr in [expr1, expr2, expr3]: if expr.type != Type.decimal(): raise CompileError( "Expression {} should have type decimal, but is {}".format( expr, expr.type)) return Expression(Type.vector(), [expr1.value, expr2.value, expr3.value])
def test_declare_and_assign_vector_should_change_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { vector a <- (1.0, 2.0, -3.0); } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.vector(), [1, 2, -3], ident="a")) self.assertEqual(expected, actual)
def test_declare_and_assign_boolean_should_change_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { boolean a <- true; } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.boolean(), True, ident="a")) self.assertEqual(expected, actual)
def test_declare_and_assign_string_should_change_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { string a <- "\0a"; } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.string(), "\0a", ident="a")) self.assertEqual(expected, actual)
def test_eq(self): vector_elems1 = [None, VectorElem("a", Expression(Type.vector(), [1.0, 2.0, 3.0], "a"), 0), VectorElem("b", Expression(Type.vector(), [1.0, 2.0, 3.0], "b"), 0), VectorElem("a", Expression(Type.vector(), [2.0, 2.0, 3.0], "a"), 0), VectorElem("a", Expression(Type.vector(), [1.0, 2.0, 3.0], "a"), 1), VectorElem("b[1]", Expression(Type.vector(), [1.0, 2.0, 3.0], "a"), 0)] vector_elems2 = [None, VectorElem("a", Expression(Type.vector(), [1.0, 2.0, 3.0], "a"), 0), VectorElem("b", Expression(Type.vector(), [1.0, 2.0, 3.0], "b"), 0), VectorElem("a", Expression(Type.vector(), [2.0, 2.0, 3.0], "a"), 0), VectorElem("a", Expression(Type.vector(), [1.0, 2.0, 3.0], "a"), 1), VectorElem("b[1]", Expression(Type.vector(), [1.0, 2.0, 3.0], "a"), 0)] for i in range(len(vector_elems1)): for j in range(len(vector_elems2)): if i == j: self.assertEqual(vector_elems1[i], vector_elems2[j]) else: self.assertNotEqual(vector_elems1[i], vector_elems2[j])
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_assign_ident_vector_should_update_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { vector a; a <- (1.0, -1.0, +1.0); } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.vector(), [1, -1, 1], ident="a")) self.assertEqual(expected, actual)
def test_assign_ident_string_should_update_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { string a; a <- "1"; } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.string(), "1", ident="a")) self.assertEqual(expected, actual)
def declare_assign(self, children) -> List[Command]: type, identifier, expr = children ident = identifier.ident if ident in self.symbol_table: raise CompileError("Identifier {} already declared".format(ident)) if expr.type != type: raise CompileError( "Identifier {} has been declared as {}, but assigned as {}". format(ident, type, expr.type)) expr_with_ident = Expression(expr.type, expr.value, ident) self.symbol_table.store(ident, expr_with_ident) return []
def test_assign_ident_decimal_should_update_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { decimal a; a <- -1.5e10; } """, actual) expected = SymbolTable() expected.store("a", Expression(Type.decimal(), -1.5e10, 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_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_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_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 test_assign_vector_elem_to_variable_should_update_symbol_table(self): for index, vector in zip(["x", "y", "z"], [[-1.0, 0, 0], [0, -2.0, 0], [0, 0, -3.0]]): actual = SymbolTable() generate_commands( """ main () {{ vector a; a.{} <- (-1.0, -2.0, -3.0).{}; }} """.format(index, index), actual) expected = SymbolTable() expected.store("a", Expression(Type.vector(), vector, ident="a")) self.assertEqual(expected, actual)
def test_to_expression_should_return_correct_value(self): expression = Expression(Type.list_of(Type.decimal()), [1.0, 2.0, 3.0, 4.0], "a") expected = Expression(Type.decimal(), 1.0, "a[0]") self.assertEqual(expected, ListElem("a", expression, 0).to_expression()) expression = Expression(Type.list_of(Type.list_of(Type.vector())), [[[1.1, 2.2, -1.1], [1, 2, -1]]], "a") expected = Expression(Type.list_of(Type.vector()), [[1.1, 2.2, -1.1], [1, 2, -1]], "a[0]") self.assertEqual(expected, ListElem("a", expression, 0).to_expression()) expression = Expression(Type.list_of(Type.boolean()), [True, False], "b[1]") expected = Expression(Type.boolean(), False, "b[1][1]") self.assertEqual(expected, ListElem("b[1]", expression, 1).to_expression())
def test_assign_list_elem_with_vector_should_update_symbol_table(self): actual = SymbolTable() generate_commands( """ main () { list[vector] a <- [(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)]; a[0] <- (7.0, 8.0, 9.0); a[1].x <- 10.0; a[1].y <- 11.0; a[1].z <- 12.0; } """, actual) expected = SymbolTable() expected.store( "a", Expression(Type.list_of(Type.vector()), [[7, 8, 9], [10, 11, 12]], ident="a")) self.assertEqual(expected, actual)
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)