示例#1
0
 def test_get_expression(self):
     st = SymbolTable()
     self.assertRaises(AssertionError, st.get_expression, "a")
     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)
 def visitInsert(self, ctx: xDroneParser.InsertContext) -> None:
     list = self.visit(ctx.expr(0))
     if not isinstance(list.type, ListType):
         raise CompileError(
             "Expression {} should have type list, but is {}".format(
                 list, list.type))
     if ctx.AT():
         index = self.visit(ctx.expr(1))
         value = self.visit(ctx.expr(2))
     else:
         index = Expression(Type.int(), len(list.value))
         value = self.visit(ctx.expr(1))
     if index.type != Type.int():
         raise CompileError(
             "Expression {} should have type int, but is {}".format(
                 index, index.type))
     if index.value > len(list.value) or index.value < 0:
         raise CompileError(
             "List {} has length {}, but has been inserted at out-of-range index {}"
             .format(list, len(list.value), index.value))
     if not isinstance(list.type,
                       EmptyList) and value.type != list.type.elem_type:
         raise CompileError(
             "List {} has been declared as {}, but inserted with element type {}"
             .format(list, list.type, value.type))
     self._insert_nested_ident(list.ident, value, index.value)
示例#3
0
 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 visitNot(self, ctx: xDroneParser.NotContext) -> Expression:
     expr = self.visit(ctx.expr())
     if expr.type != Type.boolean():
         raise CompileError(
             "Expression {} should have type boolean, but is {}".format(
                 expr, expr.type))
     return Expression(Type.boolean(), not expr.value)
    def test_list_elem_expr_out_of_range_should_give_error(self):
        with self.assertRaises(CompileError) as context:
            generate_commands("""
                main () {{
                  list[int] a <- [1, 2];
                  int b <- a[2];
                }}
                """.format(type))

        self.assertTrue(
            "List {} has length {}, but has been assessed with out-of-range index {}"
            .format(Expression(Type.list_of(Type.int()), [1, 2], ident="a"), 2,
                    2) in str(context.exception))

        with self.assertRaises(CompileError) as context:
            generate_commands("""
                main () {{
                  list[int] a <- [1, 2];
                  int b <- a[-1];
                }}
                """.format(type))

        self.assertTrue(
            "List {} has length {}, but has been assessed with out-of-range index {}"
            .format(Expression(Type.list_of(Type.int()), [1, 2], ident="a"), 2,
                    -1) in str(context.exception))
    def test_assess_list_elem_nested_out_of_bound_should_give_error(self):
        with self.assertRaises(CompileError) as context:
            generate_commands("""
                main () {
                 list[list[list[int]]] a <- [[[1], [2]]];
                 a[0][2] <- [1];
                }
                """)
        self.assertTrue(
            "List {} has length 2, but has been assessed with out-of-range index 2"
            .format(
                Expression(Type.list_of(Type.list_of(Type.int())), [[1], [2]],
                           ident="a[0]")) in str(context.exception))

        with self.assertRaises(CompileError) as context:
            generate_commands("""
                main () {
                 list[list[list[int]]] a <- [[[1], [2]]];
                 a[0][1][1] <- 1;
                }
                """)
        self.assertTrue(
            "List {} has length 1, but has been assessed with out-of-range index 1"
            .format(Expression(Type.list_of(Type.int()), [2],
                               ident="a[0][1]")) in str(context.exception))
示例#7
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 visitPlusMinus(self, ctx: xDroneParser.PlusMinusContext) -> Expression:
     expr1, expr2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1))
     if self._is_int_or_decimal(expr1.type) and self._is_int_or_decimal(
             expr2.type):
         result_type, func = self._get_int_decimal_result_type(
             expr1.type, expr2.type)
         if ctx.PLUS():
             result_value = func(expr1.value + expr2.value)
         else:  # MINUS
             result_value = func(expr1.value - expr2.value)
     elif expr1.type == Type.vector() and expr2.type == Type.vector():
         result_type = Type.vector()
         if ctx.PLUS():
             result_value = [
                 e1 + e2 for e1, e2 in zip(expr1.value, expr2.value)
             ]
         else:  # MINUS
             result_value = [
                 e1 - e2 for e1, e2 in zip(expr1.value, expr2.value)
             ]
     else:
         raise CompileError(
             "Expression {} and {} have wrong types to perform addition or subtraction"
             .format(expr1, expr2))
     return Expression(result_type, result_value)
 def visitMultiDivide(self,
                      ctx: xDroneParser.MultiDivideContext) -> Expression:
     expr1, expr2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1))
     if self._is_int_or_decimal(expr1.type) and self._is_int_or_decimal(
             expr2.type):
         result_type, func = self._get_int_decimal_result_type(
             expr1.type, expr2.type)
         if ctx.MULTI():
             result_value = func(expr1.value * expr2.value)
         else:  # DIV
             if expr2.value == 0:
                 raise CompileError("Division by zero")
             result_value = func(expr1.value / expr2.value)
     elif self._is_int_or_decimal(
             expr1.type) and expr2.type == Type.vector():
         result_type = Type.vector()
         if ctx.MULTI():
             result_value = [expr1.value * e for e in expr2.value]
         else:  # DIV
             raise CompileError(
                 "Expression {} and {} have wrong types to perform multiplication or division"
                 .format(expr1, expr2))
     elif expr1.type == Type.vector() and self._is_int_or_decimal(
             expr2.type):
         result_type = Type.vector()
         if ctx.MULTI():
             result_value = [e * expr2.value for e in expr1.value]
         else:  # DIV
             result_value = [e / expr2.value for e in expr1.value]
     else:
         raise CompileError(
             "Expression {} and {} have wrong types to perform multiplication or division"
             .format(expr1, expr2))
     return Expression(result_type, result_value)
示例#10
0
 def test_empty_list(self):
     empty_list = Type.empty_list()
     self.assertEqual(Type.empty_list(), empty_list)
     self.assertEqual(EmptyList(), empty_list)
     self.assertEqual("list[]", empty_list.type_name)
     self.assertEqual([], empty_list.default_value)
     self.assertEqual(Type("all", 0), empty_list.elem_type)
     self.assertEqual("list[]", str(empty_list))
示例#11
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))
示例#12
0
 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)
示例#13
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))
示例#14
0
 def visitList(self, ctx: xDroneParser.ListContext) -> Expression:
     exprs = [self.visit(expr) for expr in ctx.expr()]
     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(
                 [str(e) for e in exprs]))
     return Expression(Type.list_of(exprs[0].type),
                       [e.value for e in exprs])
示例#15
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())
示例#16
0
 def test_str(self):
     self.assertEqual(
         "ListElem: { ident: a, " +
         "container: Expression: { type: list[int], value: [1, 2, 3, 4], ident: a }, "
         +
         "index: 0, expression: Expression: { type: int, value: 1, ident: a[0] } }",
         str(
             ListElem(
                 "a", Expression(Type.list_of(Type.int()), [1, 2, 3, 4],
                                 "a"), 0)))
示例#17
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_declare_list_should_change_symbol_table(self):
     actual = SymbolTable()
     generate_commands("""
         main () { list[int] a; }
         """,
                       symbol_table=actual)
     expected = SymbolTable()
     expected.store("a", Expression(Type.list_of(Type.int()), [],
                                    ident="a"))
     self.assertEqual(expected, actual)
示例#19
0
 def visitConcat(self, ctx: xDroneParser.ConcatContext) -> Expression:
     expr1, expr2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1))
     if expr1.type != Type.string():
         raise CompileError(
             "Expression {} should have type string, but is {}".format(
                 expr1, expr1.type))
     if expr2.type != Type.string():
         raise CompileError(
             "Expression {} should have type string, but is {}".format(
                 expr2, expr2.type))
     return Expression(Type.string(), expr1.value + expr2.value)
示例#20
0
 def visitOr(self, ctx: xDroneParser.OrContext) -> Expression:
     expr1, expr2 = self.visit(ctx.expr(0)), self.visit(ctx.expr(1))
     if expr1.type != Type.boolean():
         raise CompileError(
             "Expression {} should have type boolean, but is {}".format(
                 expr1, expr1.type))
     if expr2.type != Type.boolean():
         raise CompileError(
             "Expression {} should have type boolean, but is {}".format(
                 expr2, expr2.type))
     return Expression(Type.boolean(), expr1.value or expr2.value)
 def test_return_in_main_should_give_error(self):
     types = [Type.int(), Type.decimal(), Type.string(), Type.boolean(), Type.vector(), Type.drone(),
              Type.list_of(Type.int()), Type.list_of(Type.decimal()), Type.list_of(Type.list_of(Type.int()))]
     for type in types:
         with self.assertRaises(CompileError) as context:
             generate_commands("""
                 main () {{
                   {} a;
                   return a;
                 }}
                 """.format(type))
         self.assertTrue("Cannot return in the Main function" in str(context.exception))
 def test_list_with_inconsistent_type_should_give_error(self):
     with self.assertRaises(CompileError) as context:
         generate_commands("""
             main () {
               list[int] a <- [1, 1.0];
             }
             """)
     self.assertTrue(
         "Elements in list {} should have the same type".format([
             str(Expression(Type.int(), 1, None)),
             str(Expression(Type.decimal(), 1.0, None))
         ]) in str(context.exception))
 def test_list_remove_from_empty_list_should_give_error(self):
     with self.assertRaises(CompileError) as context:
         generate_commands("""
             main () {
               list[int] a <- [];
               a.remove();
             }
             """)
     self.assertTrue(
         "List {} has length {}, but has been removed at out-of-range index {}"
         .format(Expression(Type.list_of(Type.int()), [], ident="a"), 0,
                 -1) in str(context.exception))
示例#24
0
 def visitVector(self, ctx: xDroneParser.VectorContext) -> Expression:
     expr1, expr2, expr3 = self.visit(ctx.expr(0)), self.visit(
         ctx.expr(1)), self.visit(ctx.expr(2))
     for expr in [expr1, expr2, expr3]:
         if expr.type != Type.int() and expr.type != Type.decimal():
             raise CompileError(
                 "Expression {} should have type int or decimal, but is {}".
                 format(expr, expr.type))
     return Expression(
         Type.vector(),
         [float(expr1.value),
          float(expr2.value),
          float(expr3.value)])
示例#25
0
 def visitUp(self, ctx: xDroneParser.UpContext) -> None:
     exprs = [self.visit(expr) for expr in ctx.expr()]
     if ctx.DOT():
         drone_expr, expr = exprs
     else:
         drone_expr, expr = None, exprs[0]
     if expr.type != Type.int() and expr.type != Type.decimal():
         raise CompileError(
             "Expression {} should have type int or decimal, but is {}".
             format(expr, expr.type))
     drone_name = self._get_drone_name(drone_expr)
     self._get_latest_commands().append(
         SingleDroneCommand(drone_name, Command.up(expr.value)))
 def test_list_insert_to_empty_list_should_update_symbol_table(self):
     actual = SymbolTable()
     generate_commands("""
         main () {
           list[int] a <- [];
           a.insert(0);
         }
         """,
                       symbol_table=actual)
     expected = SymbolTable()
     expected.store("a", Expression(Type.list_of(Type.int()), [0],
                                    ident="a"))
     self.assertEqual(expected, actual)
    def test_assign_list_elem_to_variable_out_of_bound_should_give_error(self):
        with self.assertRaises(CompileError) as context:
            generate_commands("""
                main () {
                 list[int] a <- [];
                 a[0] <- 1;
                }
                """)

        self.assertTrue(
            "List {} has length 0, but has been assessed with out-of-range index 0"
            .format(Expression(Type.list_of(Type.int()), [],
                               ident="a")) in str(context.exception))
 def test_assign_ident_list_should_update_symbol_table(self):
     actual = SymbolTable()
     generate_commands("""
         main () {
          list[int] a;
          a <- [1, -1, +1];
         }
         """,
                       symbol_table=actual)
     expected = SymbolTable()
     expected.store(
         "a", Expression(Type.list_of(Type.int()), [1, -1, 1], ident="a"))
     self.assertEqual(expected, actual)
 def test_list_elem_assign_should_update_symbol_table_correctly(self):
     actual = SymbolTable()
     generate_commands("""
         main () {
           list[int] a <- [1, 2, 3];
           a[0] <- 4;
         }
         """,
                       symbol_table=actual)
     expected = SymbolTable()
     expected.store(
         "a", Expression(Type.list_of(Type.int()), [4, 2, 3], ident="a"))
     self.assertEqual(expected, actual)
 def test_list_remove_without_index_should_update_symbol_table(self):
     actual = SymbolTable()
     generate_commands("""
         main () {
           list[int] a <- [1, 2, 3];
           a.remove();
         }
         """,
                       symbol_table=actual)
     expected = SymbolTable()
     expected.store("a",
                    Expression(Type.list_of(Type.int()), [1, 2], ident="a"))
     self.assertEqual(expected, actual)