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_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_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 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_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_vector_elem_to_temp_vector_should_not_change_symbol_table(
         self):
     actual = SymbolTable()
     generate_commands(
         """
         main () {
          (0.0, 0.0, 0.0).x <- 1.0;
         }
         """, actual)
     expected = SymbolTable()
     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 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_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_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)
예제 #13
0
    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_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_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)
예제 #16
0
 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_to_temp_vector_should_not_change_symbol_table(
         self):
     for code in [
             "[0.0][0] <- 1.0", "[0][0] <- 1", "[[\"a\"]][0] <- [\"b\"]",
             "[0.0, 1.0][0] <- 1.0"
     ]:
         actual = SymbolTable()
         generate_commands(
             """
             main () {{
              {};
             }}
             """.format(code), actual)
         expected = SymbolTable()
         self.assertEqual(expected, actual)
 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)
 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)
예제 #21
0
 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))
예제 #22
0
 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))
예제 #23
0
 def test_contains(self):
     st = SymbolTable()
     self.assertFalse("a" in st)
     st.store("a", Expression(Type.int(), 0))
     self.assertTrue("a" in st)
예제 #24
0
 def test_get_expression(self):
     st = SymbolTable()
     st.store("a", Expression(Type.list_of(Type.int()), [1]))
     self.assertEqual([1], st.get_expression("a").value)
     self.assertEqual(1, st.get_expression("a").value[0])
     self.assertEqual(Type.list_of(Type.int()), st.get_expression("a").type)
예제 #25
0
 def __init__(self, symbol_table):
     super().__init__()
     self.symbol_table = SymbolTable(
     ) if symbol_table is None else symbol_table
예제 #26
0
class Interpreter(Transformer):
    def __init__(self, symbol_table):
        super().__init__()
        self.symbol_table = SymbolTable(
        ) if symbol_table is None else symbol_table

    # def __default__(self, command, children, meta):
    #     logging.error("Ignoring unsupported command %s with children %s" % (command, children))
    #     raise Discard()

    ######## prog ########

    def prog(self, children):
        return children

    ######## commands ########

    def commands(self, children):
        return children

    ######## command ########

    def takeoff(self, children) -> List[Command]:
        return [Command.takeoff()]

    def land(self, children) -> List[Command]:
        return [Command.land()]

    def up(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.up(expr.value)]

    def down(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.down(expr.value)]

    def left(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.left(expr.value)]

    def 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.right(expr.value)]

    def forward(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.forward(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 rotate_left(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_left(radians(expr.value))]

    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 wait(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.wait(expr.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 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 assign_ident(self, children) -> List[Command]:
        identifier, expr = children
        ident = identifier.ident
        if ident not in self.symbol_table:
            raise CompileError(
                "Identifier {} has not been declared".format(ident))
        assigned_type = expr.type
        declared_type = self.symbol_table.get_expression(ident).type
        if assigned_type != declared_type:
            raise CompileError(
                "Identifier {} has been declared as {}, but assigned as {}".
                format(ident, declared_type, assigned_type))
        self.symbol_table.update(ident, expr.value)
        return []

    def _update_nested_ident(self, ident, expr, index) -> None:
        if ident is not None:
            if "[" in ident:
                tokens = ident.split("[")
                ident = tokens[0]
                indices = [int(token.replace("]", "")) for token in tokens[1:]]
            else:
                indices = []
            assert ident in self.symbol_table
            new_list = self.symbol_table.get_expression(ident).value
            curr = new_list
            for i in indices:
                curr = curr[i]
            curr[index] = expr.value
            self.symbol_table.update(ident, new_list)

    def assign_list_elem(self, children) -> List[Command]:
        list_elem, expr = children
        ident = list_elem.ident
        list = list_elem.container
        index = list_elem.index
        assigned_type = expr.type
        declared_type = list.type.elem_type
        if assigned_type != declared_type:
            raise CompileError(
                "Assigned value {} should have type {}, but is {}".format(
                    expr.value, declared_type, assigned_type))
        self._update_nested_ident(ident, expr, index)
        return []

    def assign_vector_elem(self, children) -> List[Command]:
        vector_elem, expr = children
        ident = vector_elem.ident
        vector = vector_elem.container
        index = vector_elem.index
        if expr.type != Type.decimal():
            raise CompileError(
                "Assigned value {} should have type decimal, but is {}".format(
                    expr.value, expr.type))
        self._update_nested_ident(ident, expr, index)
        return []

    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

    ######## func ########
    # TODO

    ######## func_command ########
    # TODO

    ######## param_list ########
    # TODO

    ######## func_call ########
    # TODO

    ######## arg_list ########
    # TODO

    ######## ident ########

    def ident(self, children) -> Identifier:
        ident = "".join([str(child) for child in children])
        if ident in self.symbol_table:
            return Identifier(str(ident),
                              self.symbol_table.get_expression(ident))
        return Identifier(str(ident), None)

    ######## list_elem ########

    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)

    ######## vector_elem ########

    def vector_x(self, children) -> VectorElem:
        expr, = children
        if expr.type != Type.vector():
            raise CompileError(
                "Expression {} should have type vector, but is {}".format(
                    expr, expr.type))
        return VectorElem(expr.ident, expr, 0)

    def vector_y(self, children) -> VectorElem:
        expr, = children
        if expr.type != Type.vector():
            raise CompileError(
                "Expression {} should have type vector, but is {}".format(
                    expr, expr.type))
        return VectorElem(expr.ident, expr, 1)

    def vector_z(self, children) -> VectorElem:
        expr, = children
        if expr.type != Type.vector():
            raise CompileError(
                "Expression {} should have type vector, but is {}".format(
                    expr, expr.type))
        return VectorElem(expr.ident, expr, 2)

    ######## type ########

    def int_type(self, children) -> Type:
        return Type.int()

    def decimal_type(self, children) -> Type:
        return Type.decimal()

    def string_type(self, children) -> Type:
        return Type.string()

    def boolean_type(self, children) -> Type:
        return Type.boolean()

    def vector_type(self, children) -> Type:
        return Type.vector()

    def list_type(self, children) -> Type:
        elem_type, = children
        return Type.list_of(elem_type)

    ######## expr ########

    def expr(self, children) -> Expression:
        child, = children
        assert isinstance(child, AbstractExpression)
        if isinstance(child,
                      Identifier) and child.ident not in self.symbol_table:
            # child.expression is None iff child.ident not in self.symbol_table
            raise CompileError("Identifier {} has not been declared".format(
                child.ident))
        expr = child.to_expression()
        assert expr is not None and isinstance(expr, Expression)
        return expr

    def int_expr(self, children) -> Expression:
        signed_int, = children
        return Expression(Type.int(), int(signed_int))

    def decimal_expr(self, children) -> Expression:
        signed_float, = children
        return Expression(Type.decimal(), float(signed_float))

    def string_expr(self, children) -> Expression:
        escaped_string, = children
        quotation_removed = str(escaped_string)[1:-1]
        return Expression(Type.string(), quotation_removed)

    def true_expr(self, children) -> Expression:
        return Expression(Type.boolean(), True)

    def false_expr(self, children) -> Expression:
        return Expression(Type.boolean(), False)

    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 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])