예제 #1
0
 def test_num_num(self):
     n0, n1, n2 = model.Number(4), model.Number(2), model.Number(3)
     mul = model.BinaryOperation(n0, "*",
                                 model.BinaryOperation(n1, "+", n2))
     folder = ConstantFolder()
     tree = folder.visit(mul)
     assert isinstance(tree, model.Number) and tree.value == 20
예제 #2
0
 def test_assign(self):
     n1, n2 = model.Number(2), model.Number(3)
     assign = model.Assign("x", model.BinaryOperation(n1, "+", n2))
     folder = ConstantFolder()
     tree = folder.visit(assign)
     assert isinstance(tree.value, model.Number)
     assert tree.value.value == 5
예제 #3
0
 def test_ref_num(self):
     scope = model.Scope()
     scope["a"] = model.Number(10)
     op = model.BinaryOperation(model.Reference("a"), "*", model.Number(0))
     folder = ConstantFolder()
     tree = folder.visit(op)
     assert isinstance(tree, model.Number) and tree.value == 0
예제 #4
0
 def test_mixed_arithmetic(self):
     n0, n1, n2 = model.Number(1), model.Number(2), model.Number(3)
     add = model.BinaryOperation(n1, "+", n2)
     mul = model.BinaryOperation(n0, "*", add)
     printer = PrettyPrinter()
     result = printer.visit(mul)
     assert result == "(1) * ((2) + (3));\n"
예제 #5
0
def test_binary_operation():
    a = model.Number(10)
    b = model.Number(20)
    for op in [
            "+", "-", "*", "/", "%", "==", "!=", "<", ">", "<=", ">=", "&&",
            "||"
    ]:
        model.BinaryOperation(a, op, b).evaluate(model.Scope())
예제 #6
0
 def test_function_call(self):
     reference = model.Reference("foo")
     call = model.FunctionCall(
         reference, [model.Number(1),
                     model.Number(2),
                     model.Number(3)])
     printer = PrettyPrinter()
     result = printer.visit(call)
     assert result == "foo(1, 2, 3);\n"
예제 #7
0
def test_bool_print():
    strio = io.StringIO()
    old_stdout = sys.stdout
    sys.stdout = strio
    try:
        a = model.Number(10)
        b = model.Number(20)
        for op in ["==", "!=", "<", ">", "<=", ">=", "&&", "||"]:
            model.Print(model.BinaryOperation(a, op, b)).evaluate(model.Scope())
    finally:
        sys.stdout = old_stdout
    map(int, strio.getvalue().split())
예제 #8
0
 def visitBinaryOperation(self, node):
     node.lhs = self.visit(node.lhs)
     node.rhs = self.visit(node.rhs)
     if node.op == "*" and isinstance(node.lhs, model.Number) and not node.lhs.value:
         return model.Number(0)
     if node.op == "*" and isinstance(node.rhs, model.Number) and not node.rhs.value:
         return model.Number(0)
     if isinstance(node.lhs, model.Number) and isinstance(node.rhs, model.Number):
         return node.evaluate(None)
     if isinstance(node.lhs, model.Reference) and isinstance(node.rhs, model.Reference) and node.lhs.name == node.rhs.name and node.op == "-":
         return model.Number(0)
     return node
예제 #9
0
def test_scope():
    f = model.Function([], [model.Number(0)])
    ft = model.Number(42)
    t = model.Number(10)
    parent = model.Scope()
    parent["foo"] = f
    parent["bar"] = t
    assert parent["bar"] is t
    assert parent["foo"] is f
    scope = model.Scope(parent)
    assert scope["bar"] is t
    scope["bar"] = ft
    assert scope["bar"] is ft
    assert parent["bar"] is t
예제 #10
0
 def test_conditional(self):
     scope = model.Scope()
     scope["a"] = model.Number(10)
     cond = model.Conditional(
         model.BinaryOperation(model.Number(4), ">", model.Number(3)), [
             model.Assign(
                 "x",
                 model.BinaryOperation(model.Number(3), "-",
                                       model.Number(5))),
             model.Assign(
                 "y",
                 model.BinaryOperation(model.Number(5), "*",
                                       model.Number(5)))
         ], [
             model.Assign(
                 "x",
                 model.BinaryOperation(model.Reference("a"), "*",
                                       model.Number(0)))
         ])
     folder = ConstantFolder()
     tree = folder.visit(cond)
     assert (isinstance(tree, model.Conditional)
             and tree.condition.value > 0
             and isinstance(tree.if_true[0], model.Assign)
             and tree.if_true[0].value.value == -2
             and isinstance(tree.if_true[1], model.Assign)
             and tree.if_true[1].value.value == 25
             and len(tree.if_true) == 2 and len(tree.if_false) == 1
             and isinstance(tree.if_false[0], model.Assign)
             and tree.if_false[0].value.value == 0)
예제 #11
0
    def visit_binary_operation(self, bin_op):
        lhs = self.visit(bin_op.lhs)
        rhs = self.visit(bin_op.rhs)

        if (bin_op.op == '*' and (isinstance(lhs, model.Number) and lhs.number == 0 and
                                  isinstance(rhs, model.Reference) or
                                  isinstance(rhs, model.Number) and rhs.number == 0 and
                                  isinstance(lhs, model.Reference))) or \
           (isinstance(lhs, model.Reference) and isinstance(rhs, model.Reference) and bin_op.op == '-' and
               lhs.name == rhs.name):
            return model.Number(0)
        if isinstance(lhs, model.Number) and isinstance(rhs, model.Number):
            return model.Number(bin_op.operations[bin_op.op](lhs.number,
                                                             rhs.number))
        return model.BinaryOperation(lhs, bin_op.op, rhs)
예제 #12
0
 def visit_binary_operation(self, binary_operation):
     lhs = binary_operation.lhs.accept(self)
     rhs = binary_operation.rhs.accept(self)
     if type(lhs) == m.Number and type(rhs) == m.Number:
         return m.BinaryOperation(lhs, binary_operation.op,
                                  rhs).evaluate(self.scope)
     if (type(rhs) == m.Number and rhs.value == 0
             and type(lhs) == m.Reference and binary_operation.op == "*"):
         return m.Number(0)
     if (type(lhs) == m.Number and lhs.value == 0
             and type(rhs) == m.Reference and binary_operation.op == "*"):
         return m.Number(0)
     if (type(lhs) == m.Reference and type(rhs) == m.Reference
             and lhs.name == rhs.name and binary_operation.op == '-'):
         return m.Number(0)
     return m.BinaryOperation(lhs, binary_operation.op, rhs)
예제 #13
0
def test_reference():
    name = "foo"
    value = model.Number(10)
    ref = model.Reference(name)
    scope = model.Scope()
    scope[name] = value
    assert ref.evaluate(scope) is value
예제 #14
0
 def test_ref_num_var(self):
     op = model.BinaryOperation(model.Reference("a"), "+", model.Number(0))
     folder = ConstantFolder()
     tree = folder.visit(op)
     assert (isinstance(tree, model.BinaryOperation) and tree.op == "+"
             and isinstance(tree.rhs, model.Number) and tree.rhs.value == 0
             and isinstance(tree.lhs, model.Reference)
             and tree.lhs.name == "a")
예제 #15
0
def test_function_definition():
    name = "foo"
    scope = model.Scope()
    n = model.Number(10)
    f = model.Function([], [n])
    d = model.FunctionDefinition(name, f)
    d.evaluate(scope)
    assert scope[name] is f
예제 #16
0
 def test_assign_var(self):
     scope = model.Scope()
     scope["a"] = model.Number(0)
     assign = model.Assign("x", model.Reference("a"))
     folder = ConstantFolder()
     tree = folder.visit(assign)
     assert (isinstance(tree, model.Assign) and tree.name == "x"
             and isinstance(tree.value, model.Reference)
             and tree.value.name == "a")
예제 #17
0
def test_function_call():
    arg_name = "arg"
    f = model.Function([arg_name], [model.Reference(arg_name)])
    scope = model.Scope()
    f_name = "foo"
    f_r = model.Reference(f_name)
    scope[f_name] = f
    n = model.Number(10)
    call = model.FunctionCall(f_r, [n])
    assert call.evaluate(scope) is n
예제 #18
0
 def test_mixed_conditional(self):
     scope = model.Scope()
     scope["a"] = model.Number(-10)
     scope["b"] = model.Number(5)
     scope["c"] = model.Number(10)
     """ if not (a == c) and b < c:
             print(a) """
     conditional = model.Conditional(
         model.BinaryOperation(
             model.UnaryOperation(
                 "!",
                 model.BinaryOperation(model.Reference("a"), "==",
                                       model.Reference("c"))), "&&",
             model.BinaryOperation(model.Reference("b"), "<",
                                   model.Number(42))),
         [model.Assign("res", model.Reference("a"))])
     printer = PrettyPrinter()
     result = printer.visit(conditional)
     assert (result == "if ((!((a) == (c))) && ((b) < (42))) {\n\tres =" +
             " a;\n};\n")
예제 #19
0
    def get_constant_value(self, tree):
        if isinstance(tree, model.BinaryOperation):
            if self.check_num_num(tree):
                return tree.evaluate(model.Scope())
            if self.check_num_ref(tree) or self.check_ref_num(tree) or \
               self.check_ref_ref(tree):
                return model.Number(0)

        if isinstance(tree, model.UnaryOperation):
            if isinstance(tree.expr, model.Number):
                return tree.evaluate(model.Scope())

        return tree
예제 #20
0
    def test_function_call(self):
        scope = model.Scope()
        scope["x"] = model.Number(10)
        function = model.Function(["a", "b", "c"], [])
        model.FunctionDefinition("f", function).evaluate(scope)

        call = model.FunctionCall(model.Reference("f"), [
            model.BinaryOperation(model.Number(2), "*", model.Number(3)),
            model.BinaryOperation(model.Number(0), "*", model.Reference("x")),
            model.Reference("x")
        ])
        folder = ConstantFolder()
        tree = folder.visit(call)
        assert (isinstance(tree, model.FunctionCall)
                and isinstance(tree.fun_expr, model.Reference)
                and tree.fun_expr.name == "f" and len(tree.args) == 3
                and isinstance(tree.args[0], model.Number)
                and tree.args[0].value == 6
                and isinstance(tree.args[1], model.Number)
                and tree.args[1].value == 0
                and isinstance(tree.args[2], model.Reference)
                and tree.args[2].name == "x")
예제 #21
0
def test_conditional():
    scope = model.Scope()
    true = model.Number(1)
    false = model.Number(0)
    f = model.FunctionCall(model.Function([], [true]), [])
    cond = model.Conditional(true, None, None)
    cond.evaluate(scope)
    cond = model.Conditional(false, None, None)
    cond.evaluate(scope)
    cond = model.Conditional(true, [], None)
    cond.evaluate(scope)
    cond = model.Conditional(true, None, [])
    cond.evaluate(scope)
    cond = model.Conditional(false, [], None)
    cond.evaluate(scope)
    cond = model.Conditional(false, None, [])
    cond.evaluate(scope)
    cond = model.Conditional(true, [], [])
    cond.evaluate(scope)
    cond = model.Conditional(true, [], [])
    cond.evaluate(scope)
    cond = model.Conditional(true, [true], None)
    assert cond.evaluate(scope) is true
    cond = model.Conditional(false, None, [false])
    assert cond.evaluate(scope) is false
    cond = model.Conditional(true, [f], None)
    assert cond.evaluate(scope) is true
    cond = model.Conditional(false, None, [f])
    assert cond.evaluate(scope) is true
    # If one of the following assertions fail, it means that Conditional has
    # evaluated wrong branch.
    cond = model.Conditional(false, [true], None)
    assert cond.evaluate(scope) is not true
    cond = model.Conditional(false, [true], [])
    assert cond.evaluate(scope) is not true
    cond = model.Conditional(true, None, [false])
    assert cond.evaluate(scope) is not false
    cond = model.Conditional(true, [], [false])
    assert cond.evaluate(scope) is not false
예제 #22
0
    def test_function_with_body_args(self):
        parent = model.Scope()
        parent["f"] = model.Function(("a", "b"), [
            model.Print(
                model.BinaryOperation(model.Reference("a"), "+",
                                      model.Reference("b")))
        ])
        parent["x"] = model.Number(10)
        scope = model.Scope(parent)
        scope["y"] = model.Number(20)
        definition = model.FunctionDefinition("f", parent["f"])
        printer = PrettyPrinter()
        result = printer.visit(definition)
        assert result == "def f(a, b) {\n\tprint (a) + (b);\n};\n"

        definition.evaluate(scope)
        call = model.FunctionCall(
            model.Reference("f"),
            [model.Number(5),
             model.UnaryOperation("-", model.Number(3))])
        result = printer.visit(call)
        assert result == "f(5, -(3));\n"
예제 #23
0
    def parse_primary(self):
        token = self.peek_token()
        if self.is_number(token.value):
            return model.Number(self.parse_number())
        if self.is_name(token.value):
            return model.Reference(self.parse_name())

        if token.value == '(':
            self.drop_tokens()
            expr = self.parse_expression()
            self.ensure_token(')')
            return expr
        raise Exception('Unexpected token "{}" at {}:{}'.format(
            token.value, token.line, token.offset))
예제 #24
0
def test_number():
    scope = model.Scope()
    n = model.Number(42)
    assert n.evaluate(scope) is n
    assert n == model.Number(42)
    assert n != model.Number(43)
    d = {n: 42, model.Number(10): 10}
    assert d[model.Number(42)] == 42
    assert d[model.Number(10)] == 10
예제 #25
0
def test():
    folder = ConstantFolder()
    prr = printer.PrettyPrinter()
    oper = model.BinaryOperation(
        model.BinaryOperation(
            model.BinaryOperation(
                model.BinaryOperation(model.Number(2), "+", model.Number(3)),
                "/",
                model.BinaryOperation(model.Number(
                    2), "+", model.Reference("x"))
            ),
            "/",
            model.BinaryOperation(
                model.BinaryOperation(model.Reference(
                    "x"), "-", model.Reference("x")),
                "/",
                model.BinaryOperation(model.Reference(
                    "x"), "-", model.Reference("y"))
            )
        ),
        "/",
        model.BinaryOperation(
            model.BinaryOperation(
                model.BinaryOperation(model.Number(
                    0), "*", model.Reference("x")),
                "/",
                model.UnaryOperation("!", model.Reference("x"))
            ),
            "/",
            model.UnaryOperation("-", model.Number(30))
        ),
    )
    opr = model.Conditional(model.UnaryOperation("!", model.Number(2)), [model.Print(model.Number(2))])
    prr.visit(oper)
    prr.visit(opr)
    noper = folder.visit(oper)
    nopr = folder.visit(opr)
    prr.visit(noper)
    prr.visit(nopr)
예제 #26
0
def main():
    v = PrettyPrinter()
    v.visit(m.Print(m.Number(10)))
    v.visit(m.UnaryOperation('-', m.Number(10)))
    v.visit(
        m.BinaryOperation(
            m.BinaryOperation(m.Reference('foo'), '+', m.Number(7)), '*',
            m.Number(2)))
    v.visit(m.Read("read"))
    v.visit(
        m.Conditional(
            m.Number(5),
            [m.BinaryOperation(m.Reference('var'), '-', m.Number(-5))]))
    v.visit(
        m.FunctionDefinition(
            'summer',
            m.Function(['a', 'b'], [
                m.Print(
                    m.BinaryOperation(m.Reference('a'), '+',
                                      m.Reference('b'))),
                m.BinaryOperation(m.Reference('a'), '+', m.Reference('b'))
            ])))
    v.visit(
        m.FunctionCall(
            m.Reference('summer'),
            [m.Number(1),
             m.BinaryOperation(m.Number(2), '+', m.Number(3))]))
    v.visit(
        m.Print(
            m.Conditional(m.BinaryOperation(m.Number(4), '-', m.Number(4)), [],
                          [
                              m.BinaryOperation(m.Number(9), '/', m.Number(3)),
                              m.Reference('var')
                          ])))
    v.visit(
        m.FunctionDefinition(
            'abs',
            m.Function(['a', 'b'], [
                m.Conditional(
                    m.BinaryOperation(
                        m.BinaryOperation(m.Reference('a'), '-',
                                          m.Reference('b')), '>', m.Number(0)),
                    [
                        m.Print(
                            m.BinaryOperation(m.Reference('a'), '-',
                                              m.Reference('b')))
                    ], [
                        m.Print(
                            m.BinaryOperation(m.Reference('b'), '-',
                                              m.Reference('a')))
                    ])
            ])))
    v.visit(
        m.FunctionCall(
            m.Reference('abs'),
            [m.Number(23), m.UnaryOperation('-', m.Number(-30))]))
    v.visit(m.FunctionDefinition('fu', m.Function([], [])))
    v.visit(m.FunctionCall(m.Reference('fu'), []))
    v.visit(m.Print(m.BinaryOperation(m.Number(5), '&&', m.Number(6))))
    v.visit(m.Print(m.BinaryOperation(m.Number(3), '<', m.Number(5))))
    v.visit(m.Print(m.Conditional(m.Number(3), None, None)))
    v.visit(m.Print(m.BinaryOperation(m.Number(1), '||', m.Number(4))))
예제 #27
0
 def test_print(self):
     number = model.Number(42)
     my_print = model.Print(number)
     printer = PrettyPrinter()
     result = printer.visit(my_print)
     assert result == "print 42;\n"
예제 #28
0
 def test_arithmetic_print(self):
     my_print = model.Print(
         model.BinaryOperation(model.Number(0), "+", model.Number(1)))
     printer = PrettyPrinter()
     result = printer.visit(my_print)
     assert result == "print (0) + (1);\n"
예제 #29
0
 def test_unary_operation(self):
     number = model.Number(42)
     unary = model.UnaryOperation("-", number)
     printer = PrettyPrinter()
     result = printer.visit(unary)
     assert result == "-(42);\n"
예제 #30
0
 def test_assign(self):
     assign = model.Assign("x", model.Number(2))
     printer = PrettyPrinter()
     result = printer.visit(assign)
     assert result == "x = 2;\n"