예제 #1
0
 def visit_Script(self, node):
     return_value = []
     for stmt in node.statements:
         if not isinstance(stmt, structural_nodes.Push) and SInstructions.is_push_operation(stmt):
             msg = 'Implicit push of %s %s' % (stmt.__class__.__name__, SInstructions.format_op(stmt))
             if not self.options.implicit_pushes:
                 self.error(msg, stmt.lineno)
                 raise IRImplicitPushError(msg, stmt.lineno)
             else:
                 self.warning(msg, stmt.lineno)
         return_value.extend(self.visit(stmt))
     return return_value
예제 #2
0
 def test_conditional(self):
     for node, expected in [
         (sir.If(test=sir.Int(1), truebranch=[sir.Int(5)], falsebranch=[]), 'if 1 {5;}'),
         (sir.If(test=sir.Int(1), truebranch=[sir.Int(5)], falsebranch=[sir.Int(6)]), 'if 1 {5;} else {6;}'),
         (sir.If(test=sir.Int(1), truebranch=[sir.Int(5)], falsebranch=[sir.Int(6), sir.Int(7)]), 'if 1 {5;} else {6; 7;}'),
     ]:
         self.assertEqual(expected, SInstructions.format_op(node))
예제 #3
0
 def test_assignments(self):
     for node, expected in [
         (sir.Declaration(name='foo', value=sir.Int(5), type_=SymbolType.Integer, mutable=True), 'let mutable foo = 5'),
         (sir.Declaration(name='foo', value=sir.Int(5), type_=SymbolType.Integer, mutable=False), 'let foo = 5'),
         (sir.Assignment(name='foo', value=sir.Int(5), type_=SymbolType.Integer), 'foo = 5'),
         (sir.Assignment(name='foo', value=sir.Bytes('05'), type_=SymbolType.Integer), 'foo = 05'),
     ]:
         self.assertEqual(expected, SInstructions.format_op(node))
예제 #4
0
 def test_function_call(self):
     for node, expected in [
         (sir.FunctionCall(name='foo', args=[]), 'foo()'),
         (sir.FunctionCall(name='foo', args=[sir.Int(5)]), 'foo(5)'),
         (sir.FunctionCall(name='foo', args=[sir.Int(5), sir.Int(6)]), 'foo(5, 6)'),
         (sir.FunctionCall(name='foo', args=[sir.Int(5), sir.Bytes('06')]), 'foo(5, 06)'),
     ]:
         self.assertEqual(expected, SInstructions.format_op(node))
예제 #5
0
 def test_function(self):
     for node, expected in [
         (sir.Function(name='foo', args=[sir.Symbol('a')],
                 body=[sir.BinOpCode(name='OP_ADD', left=sir.Symbol('a'), right=sir.Int(2))]), 'func foo(a) {a + 2;}'),
         (sir.Function(name='foo', args=[sir.Symbol('a')],
                 body=[sir.BinOpCode(name='OP_ADD', left=sir.Symbol('a'), right=sir.Int(2)), sir.Int(5)]), 'func foo(a) {a + 2; 5;}'),
         (sir.Function(name='foo', args=[sir.Symbol('a'), sir.Symbol('b')],
                 body=[sir.BinOpCode(name='OP_ADD', left=sir.Symbol('a'), right=sir.Symbol('b')), sir.Int(5)]), 'func foo(a, b) {a + b; 5;}'),
     ]:
         self.assertEqual(expected, SInstructions.format_op(node))
예제 #6
0
 def test_unary_op(self):
     for name, expected in [
         ('OP_1ADD', '05++'),
         ('OP_1SUB', '05--'),
         ('OP_2MUL', '05 * 2'),
         ('OP_2DIV', '05 / 2'),
         ('OP_NEGATE', '-05'),
         ('OP_ABS', '|05|'),
     ]:
         op = sir.UnaryOpCode(name = name, operand = sir.Bytes('05'))
         self.assertEqual(expected, SInstructions.format_op(op))
예제 #7
0
 def visit_UnaryOpCode(self, node):
     if SInstructions.is_arithmetic_op(node) and isinstance(node.operand, (structural_nodes.Int, structural_nodes.Bytes)):
         if not formats.is_strict_num(int(node.operand)):
             msg = 'Input value to %s is longer than 4 bytes: 0x%x' % (node.name, node.operand)
             if self.options.strict_num:
                 self.error(msg, node.lineno)
                 raise IRStrictNumError(msg)
             else:
                 self.warning(msg, node.lineno)
     return_value = self.visit(node.operand)
     op = types.opcode_by_name(node.name)()
     return return_value + [op]
예제 #8
0
    def check_types(self, node):
        """Check the operand types of node."""
        if not isinstance(node, structural_nodes.OpCode):
            return
        args = node.get_args()
        if any(isinstance(arg, structural_nodes.Symbol) for arg in args):
            self.require_symbol_table('process operands')
        for i, arg in enumerate(args):
            if isinstance(arg, structural_nodes.Symbol):
                args[i] = self.symbol_table.lookup(arg.name).value

        if SInstructions.is_arithmetic_op(node):
            for arg in args:
                if isinstance(arg, structural_nodes.Bytes):
                    msg = 'Byte array %s used in arithmetic operation' % (arg)
                    self.warning(msg, node.lineno)
        elif SInstructions.is_byte_string_op(node):
            for arg in args:
                if isinstance(arg, structural_nodes.Int):
                    msg = 'Integer %s used in byte string operation' % (arg)
                    self.error(msg, node.lineno)
                    raise IRTypeError(msg, node.lineno)
예제 #9
0
    def cast_return_type(self, node, as_type):
        """Return node implicitly casted as as_type.

        This does not perform casting of types that have equal
        specificity (e.g. integers are not implicitly casted to byte arrays).
        """
        value_type = SInstructions.get_symbol_type_for_node(node)
        line_number = node.lineno
        return_value = None
        if value_type == as_type:
            return_value = node
        if as_type == SymbolType.Expr:
            return_value = node

        if return_value:
            return_value.lineno = line_number
            return return_value
        raise IRTypeError('Function returned type %s (expected %s)' % (value_type, as_type))
예제 #10
0
    def visit_BinOpCode(self, node):
        # Check for values longer than 4 bytes.
        if SInstructions.is_arithmetic_op(node):
            operands = [node.left, node.right]
            if all(isinstance(i, (structural_nodes.Int, structural_nodes.Bytes)) for i in operands):
                valid = [formats.is_strict_num(int(i)) for i in operands]
                if False in valid:
                    msg = 'Input value to %s is longer than 4 bytes: 0x%x' % (node.name, operands[valid.index(False)])
                    if self.options.strict_num:
                        self.error(msg, node.lineno)
                        raise IRStrictNumError(msg)
                    else:
                        self.warning(msg, node.lineno)

        return_value = self.visit(node.left)
        return_value.extend(self.visit(node.right))
        op = types.opcode_by_name(node.name)()
        return return_value + [op]
예제 #11
0
    def visit_Symbol(self, node):
        """Attempt to simplify the value of a symbol."""
        symbol = self.symbol_table.lookup(node.name)
        if not symbol:
            raise IRError('Symbol "%s" was not declared.' % node.name)
        value = symbol.value

        # Constant value.
        if get_const(value):
            return value
        # Try to evaluate and/or optimize the expression.
        if symbol.type_ == SymbolType.Expr:
            expr = self.visit(value)
            if get_const(expr):
                symbol.value = expr
                symbol.type_ = SInstructions.get_symbol_type_for_node(expr)
                return expr

        return node
예제 #12
0
    def test_binary_op(self):
        for name, expected in [
            ('OP_ADD', '05 + 06'),
            ('OP_SUB', '05 - 06'),
            ('OP_MUL', '05 * 06'),
            ('OP_DIV', '05 / 06'),
            ('OP_MOD', '05 % 06'),
            ('OP_LSHIFT', '05 << 06'),
            ('OP_RSHIFT', '05 >> 06'),

            ('OP_BOOLAND', '05 and 06'),
            ('OP_BOOLOR', '05 or 06'),

            ('OP_NUMEQUAL', '05 == 06'),
            ('OP_NUMNOTEQUAL', '05 != 06'),
            ('OP_LESSTHAN', '05 < 06'),
            ('OP_GREATERTHAN', '05 > 06'),
            ('OP_LESSTHANOREQUAL', '05 <= 06'),
            ('OP_GREATERTHANOREQUAL', '05 >= 06'),
        ]:
            op = sir.BinOpCode(name = name, left = sir.Bytes('05'), right = sir.Bytes('06'))
            self.assertEqual(expected, SInstructions.format_op(op))
예제 #13
0
 def visit_Function(self, node):
     for stmt in node.body:
         if SInstructions.is_push_operation(stmt):
             msg = 'Functions cannot push values to the stack'
             self.error(msg, stmt.lineno)
             raise IRImplicitPushError(msg, stmt.lineno)
예제 #14
0
 def _linearize(self, structural):
     return StructuralVisitor().transform(SInstructions(structural))
예제 #15
0
 def test_innerscript(self):
     for node, expected in [
         (sir.InnerScript(statements=[sir.Int(5)]), '5;'),
         (sir.InnerScript(statements=[sir.Int(5), sir.Int(6)]), '5; 6;'),
     ]:
         self.assertEqual(expected, SInstructions.format_op(node))
예제 #16
0
 def _test(self, type_test):
     type_name = SInstructions.get_symbol_type_for_node(type_test.node)
     msg = '%s != %s (node: %s)' % (type_test.expected_type, type_name, type_test.node)
     self.assertEqual(type_test.expected_type, type_name, msg)