Пример #1
0
def _exp_uminus(code: Code, exp):
    expression = exp['expression']
    exp_type = exp['expression']['type']
    _expression(code, expression)

    if isinstance(exp_type, TypeInt):
        code.neg_int()
    elif isinstance(exp_type, TypeReal):
        code.neg_double()
    else:
        raise NotImplementedError()
Пример #2
0
def _statement_function_call(code: Code, exp):
    ret = exp['type']
    _exp_function_call(code, exp)

    if isinstance(ret, TypeInt) \
            or isinstance(ret, TypeBool) \
            or isinstance(ret, TypeStr) \
            or isinstance(ret, TypeArray):
        code.pop()
    elif isinstance(ret, TypeReal):
        code.pop2()
Пример #3
0
def _exp_sub(code: Code, exp):
    left = exp['left']
    right = exp['right']
    left_type = exp['left']['type']
    _expression(code, left)
    _expression(code, right)

    if isinstance(left_type, TypeInt):
        code.add_int()
    elif isinstance(left_type, TypeReal):
        code.add_double()
    else:
        raise NotImplementedError()
Пример #4
0
def _statement(code: Code,
               statement,
               loop_start: Optional[int] = None,
               breaks: Optional[List[int]] = None):
    node_type = statement['node']

    if node_type == Node.VARIABLE_DEFINITION:
        _statement_var_def(code, statement)
    elif node_type == Node.CONSTANT_DEFINITION:
        _statement_var_def(code, statement)
    elif node_type == Node.VARIABLE_STORE:
        _statement_var_store(code, statement)
    elif node_type == Node.ARRAY_STORE:
        _statement_array_store(code, statement)
    elif node_type == Node.FUNCTION_CALL:
        _statement_function_call(code, statement)
    elif node_type == Node.RETURN:
        _statement_return(code, statement)
    elif node_type == Node.RETURN_VOID:
        code.return_void()
    elif node_type == Node.IF:
        _statement_if(code, statement, loop_start, breaks)
    elif node_type == Node.IF_ELSE:
        _statement_if_else(code, statement, loop_start, breaks)
    elif node_type == Node.WHILE:
        _statement_while(code, statement)
    elif node_type == Node.BREAK:
        break_pos = code.pos()
        code.goto()
        breaks.append(break_pos)
    elif node_type == Node.CONTINUE:
        code.goto(loop_start)
    else:
        raise NotImplementedError(node_type)
Пример #5
0
def _expression(code: Code, expression):
    node_type = expression['node']

    if node_type == Node.UMINUS:
        _exp_uminus(code, expression)
    elif node_type == Node.UPLUS:
        _exp_uplus(code, expression)
    elif node_type == Node.MUL:
        _exp_mul(code, expression)
    elif node_type == Node.DIV:
        _exp_div(code, expression)
    elif node_type == Node.PLUS:
        _exp_plus(code, expression)
    elif node_type == Node.MINUS:
        _exp_minus(code, expression)
    elif node_type == Node.EQ:
        _exp_eq(code, expression)
    elif node_type == Node.NE:
        _exp_ne(code, expression)
    elif node_type == Node.LT:
        _exp_lt(code, expression)
    elif node_type == Node.GT:
        _exp_gt(code, expression)
    elif node_type == Node.LE:
        _exp_le(code, expression)
    elif node_type == Node.GE:
        _exp_ge(code, expression)
    elif node_type == Node.NOT:
        _exp_not(code, expression)
    elif node_type == Node.AND:
        _exp_and(code, expression)
    elif node_type == Node.OR:
        _exp_or(code, expression)
    elif node_type == Node.VARIABLE_LOAD:
        _exp_var_load(code, expression)
    elif node_type == Node.ARRAY_LOAD:
        _exp_array_load(code, expression)
    elif node_type == Node.VARIABLE_ASSIGNMENT:
        _exp_var_assign(code, expression)
    elif node_type == Node.ARRAY_ASSIGNMENT:
        _exp_array_assign(code, expression)
    elif node_type == Node.VALUE_INT:
        code.const_int(expression['value'])
    elif node_type == Node.VALUE_REAL:
        code.const_double(expression['value'])
    elif node_type == Node.VALUE_BOOL:
        code.const_int(int(expression['value']))
    elif node_type == Node.VALUE_STR:
        code.const_string(expression['value'])
    elif node_type == Node.VALUE_ARRAY:
        _exp_value_array(code, expression)
    elif node_type == Node.FUNCTION_CALL_VALUE:
        _exp_function_call(code, expression)
    else:
        raise NotImplementedError()
Пример #6
0
def _statement_var_store(code: Code, exp):
    name = exp['name']
    expression = exp['expression']
    t = exp['type']

    index = _locals[name]

    _expression(code, expression)

    if isinstance(t, TypeInt):
        code.store_int(index)
    elif isinstance(t, TypeReal):
        code.store_double(index)
    elif isinstance(t, TypeBool):
        code.store_int(index)
    elif isinstance(t, TypeStr):
        code.store_reference(index)
    elif isinstance(t, TypeArray):
        code.store_reference(index)
    else:
        raise NotImplementedError()
Пример #7
0
def _write_code(code: Code, output: BinaryIO):

    # calculate absolute positions of instructions, max_stack and max locals
    code_size = 0
    inst_positions = []
    stack = 0
    max_stack = 0

    for (index, instruction) in enumerate(code.instructions):
        inst_positions.append(code_size)
        code_size += code.instruction_length(index)
        stack += code.instruction_stack_diff(index)

        if max_stack < stack:
            max_stack = stack

    max_locals = 0

    for local in code.locals:
        max_locals += local.size()

    size = CODE_ATTRIBUTE_DEFAULT_SIZE + code_size

    output.write(struct.pack(BE + U2, _code_attribute_name_index))
    output.write(struct.pack(BE + U4, size))
    output.write(struct.pack(BE + U2, max_stack))
    output.write(struct.pack(BE + U2, max_locals))
    output.write(struct.pack(BE + U4, code_size))

    # write instructions
    for (i, instruction) in enumerate(code.instructions):
        _write_instruction(i, instruction, inst_positions, output)

    # exception table length
    output.write(struct.pack(BE + U2, 0))
    # attributes count
    output.write(struct.pack(BE + U2, 0))
Пример #8
0
    def __init__(self, name: str, descriptor: MethodDescriptor,
                 constant_pool: ConstantPool):
        self._constant_pool = constant_pool
        self._name_index: int = constant_pool.method_name(name)
        self._descriptor_index: int = constant_pool.method_descriptor(
            descriptor)
        self._code: Code = Code(constant_pool)

        # setup local variables
        for p in descriptor.params_descriptors:
            if isinstance(p, IntDesc):
                self._code.variable_int()
            elif isinstance(p, LongDesc):
                self._code.variable_long()
            elif isinstance(p, FloatDesc):
                self._code.variable_float()
            elif isinstance(p, DoubleDesc):
                self._code.variable_double()
            elif isinstance(p, ClassDesc) or isinstance(p, ArrayDesc):
                self._code.variable_reference()
Пример #9
0
def _exp_plus(code: Code, exp):
    left = exp['left']
    right = exp['right']
    left_type = exp['left']['type']
    _expression(code, left)
    _expression(code, right)

    if isinstance(left_type, TypeInt):
        code.add_int()
    elif isinstance(left_type, TypeReal):
        code.add_double()
    elif isinstance(left_type, TypeStr):
        code.invoke_virtual(*JM_STRING_CONCAT)
    else:
        raise NotImplementedError()
Пример #10
0
def _statement_if(code: Code,
                  statement,
                  loop_start: Optional[int] = None,
                  breaks: Optional[List[int]] = None):
    condition = statement['condition']
    statements = statement['statements']

    _expression(code, condition)
    cond_pos = code.pos()
    code.if_eq()

    for s in statements:
        _statement(code, s, loop_start, breaks)

    end_pos = code.pos()
    code.update_jump(cond_pos, end_pos)
Пример #11
0
def _exp_ge(code: Code, exp):
    left = exp['left']
    right = exp['right']
    left_type = exp['left']['type']
    _expression(code, left)
    _expression(code, right)

    if isinstance(left_type, TypeInt) or isinstance(left_type, TypeReal):
        if isinstance(left_type, TypeReal):
            code.cmp_double_g()
            cmp_pos = code.pos()
            code.if_ge()
        else:
            cmp_pos = code.pos()
            code.if_cmp_int_ge()
        code.const_int(0)
        goto_pos = code.pos()
        code.goto()
        true_pos = code.pos()
        code.const_int(1)
        end_pos = code.pos()

        code.update_jump(cmp_pos, true_pos)
        code.update_jump(goto_pos, end_pos)
    else:
        raise NotImplementedError()
Пример #12
0
def _exp_function_call(code: Code, exp):
    name = exp['name']
    args_exps = exp['arguments']
    params = exp['parameters']
    ret = exp['type']

    for e in args_exps:
        _expression(code, e)

    # check for predefined functions
    if name == FN_LEN and len(params) == 1:
        if isinstance(params[0], TypeStr):
            code.invoke_virtual(*JM_STRING_LENGTH)
            return
        elif isinstance(params[0], TypeArray):
            code.array_length()
            return

    if name == FN_INT and len(params) == 1:
        if isinstance(params[0], TypeInt):
            # nothing to do
            return
        elif isinstance(params[0], TypeReal):
            code.double_to_int()
            return
        elif isinstance(params[0], TypeBool):
            # nothing to do
            return
        elif isinstance(params[0], TypeStr):
            code.invoke_static(*JSM_INT_PARSE)
            return

    if name == FN_REAL and len(params) == 1:
        if isinstance(params[0], TypeInt):
            code.int_to_double()
            return
        elif isinstance(params[0], TypeReal):
            # nothing to do
            return
        elif isinstance(params[0], TypeBool):
            code.int_to_double()
            return
        elif isinstance(params[0], TypeStr):
            code.invoke_static(*JSM_DOUBLE_PARSE)
            return

    if name == FN_BOOL and len(params) == 1:
        if isinstance(params[0], TypeInt):
            code.const_int(1)
            code.and_int()
            return
        elif isinstance(params[0], TypeReal):
            code.const_double(0.0)
            code.cmp_double_l()
            cmp_pos = code.pos()
            code.if_eq()
            code.const_int(1)
            goto_pos = code.pos()
            code.goto()
            false_pos = code.pos()
            code.const_int(0)
            end_pos = code.pos()

            code.update_jump(cmp_pos, false_pos)
            code.update_jump(goto_pos, end_pos)
            return
        elif isinstance(params[0], TypeBool):
            # nothing to do
            return
        elif isinstance(params[0], TypeStr):
            code.invoke_static(*JSM_BOOLEAN_PARSE)
            return

    if name == FN_STR and len(params) == 1:
        if isinstance(params[0], TypeInt):
            code.invoke_static(*JSM_INT_TO_STRING)
            return
        elif isinstance(params[0], TypeReal):
            code.invoke_static(*JSM_DOUBLE_TO_STRING)
            return
        elif isinstance(params[0], TypeBool):
            code.invoke_static(*JSM_BOOLEAN_TO_STRING)
            return

    if name == FN_SUBSTRING and len(params) == 3:
        if isinstance(params[0], TypeStr) and isinstance(
                params[1], TypeInt) and isinstance(params[2], TypeInt):
            code.invoke_static(*JM_STRING_SUBSTRING)
            return

    if name == FN_WRITE and len(params) == 1:
        if isinstance(params[0], TypeStr):
            code.load_static_field(*JSF_STDOUT)
            code.swap()
            code.invoke_virtual(*JM_PRINT)
            return

    if name == FN_READ_LINE and len(params) == 0:
        code.load_static_field(_class_name, BUFF_READER_FIELD,
                               ClassDesc(JC_BUFF_READER))
        code.invoke_virtual(*JM_READLINE)

        # if result null, set the eof field to true and load empty string
        code.dup()
        cmp_pos = code.pos()
        code.if_non_null()
        code.const_int(1)
        code.store_static_field(_class_name, EOF_FIELD, BooleanDesc())
        code.const_string('')
        end_pos = code.pos()
        code.update_jump(cmp_pos, end_pos)
        return

    if name == FN_EOF and len(params) == 0:
        code.load_static_field(_class_name, EOF_FIELD, BooleanDesc())
        return

    # custom function
    name = PREFIX + name
    desc = _create_method_descriptor(params, ret)
    code.invoke_static(_class_name, name, desc)
Пример #13
0
def _exp_array_assign(code: Code, exp):
    name = exp['name']
    index_exps = exp['indexes']
    expression = exp['expression']
    t = exp['type']

    # top array load
    index = _locals[name]
    code.load_reference(index)

    # subarrays load if multidim
    for e in index_exps[:-1]:
        _expression(code, e)
        code.array_load_reference()

    # item store
    _expression(code, index_exps[-1])
    _expression(code, expression)
    if isinstance(t.inner, TypeInt):
        code.dup_x1()
        code.array_store_int()
    elif isinstance(t.inner, TypeReal):
        code.dup2_x1()
        code.array_store_double()
    elif isinstance(t.inner, TypeBool):
        code.dup_x1()
        code.array_store_boolean()
    elif isinstance(t.inner, TypeStr):
        code.dup_x1()
        code.array_store_reference()
    elif isinstance(t.inner, TypeArray):
        code.dup_x1()
        code.array_store_reference()
    else:
        raise NotImplementedError()
Пример #14
0
def _exp_value_array(code: Code, exp):
    items = exp['items']
    t = exp['type']

    if t.dim > 1:
        desc = _create_field_descriptor(TypeArray(t.dim - 1, t.inner))
    else:
        desc = _create_field_descriptor(t.inner)

    code.const_int(len(items))
    code.new_array(desc)

    for (i, item) in enumerate(items):
        code.dup()
        code.const_int(i)
        item_type = item['type']
        _expression(code, item)
        if isinstance(item_type, TypeInt):
            code.array_store_int()
        elif isinstance(item_type, TypeReal):
            code.array_store_double()
        elif isinstance(item_type, TypeBool):
            code.array_store_boolean()
        elif isinstance(item_type, TypeStr):
            code.array_store_reference()
        elif isinstance(item_type, TypeArray):
            code.array_store_reference()
        else:
            raise NotImplementedError()
Пример #15
0
def _exp_array_load(code: Code, exp):
    name = exp['name']
    index_exps = exp['indexes']
    t = exp['type']

    index = _locals.get(name)
    if index is not None:
        code.load_reference(index)
    else:
        name = PREFIX + name
        field = _fields.get(name)
        code.load_static_field(field[0], field[1], field[2])

    # subarrays load if multidim
    for e in index_exps[:-1]:
        _expression(code, e)
        code.array_load_reference()

    # item load
    _expression(code, index_exps[-1])
    if isinstance(t, TypeInt):
        code.array_load_int()
    elif isinstance(t, TypeReal):
        code.array_load_double()
    elif isinstance(t, TypeBool):
        code.array_load_boolean()
    elif isinstance(t, TypeStr):
        code.array_load_reference()
    elif isinstance(t, TypeArray):
        code.array_load_reference()
    else:
        raise NotImplementedError()
Пример #16
0
def _exp_var_load(code: Code, exp):
    name = exp['name']
    t = exp['type']

    index = _locals.get(name)
    if index is not None:
        if isinstance(t, TypeInt):
            code.load_int(index)
        elif isinstance(t, TypeReal):
            code.load_double(index)
        elif isinstance(t, TypeBool):
            code.load_int(index)
        elif isinstance(t, TypeStr):
            code.load_reference(index)
        elif isinstance(t, TypeArray):
            code.load_reference(index)
        else:
            raise NotImplementedError()
    else:
        name = PREFIX + name
        field = _fields.get(name)
        code.load_static_field(field[0], field[1], field[2])
Пример #17
0
def _exp_or(code: Code, exp):
    left = exp['left']
    right = exp['right']
    t = exp['type']
    _expression(code, left)
    _expression(code, right)

    if isinstance(t, TypeBool):
        cmp1_pos = code.pos()
        code.if_ne()
        cmp2_pos = code.pos()
        code.if_ne()
        code.const_int(0)
        goto_pos = code.pos()
        code.goto()
        true_pos = code.pos()
        code.const_int(1)
        end_pos = code.pos()

        code.update_jump(cmp1_pos, true_pos)
        code.update_jump(cmp2_pos, true_pos)
        code.update_jump(goto_pos, end_pos)
    else:
        raise NotImplementedError()
Пример #18
0
def _statement_while(code: Code, statement):
    condition = statement['condition']
    statements = statement['statements']

    start = code.pos()
    _expression(code, condition)
    cond_pos = code.pos()
    code.if_eq()

    breaks = []
    for s in statements:
        _statement(code, s, start, breaks)

    code.goto(start)
    end_pos = code.pos()
    code.update_jump(cond_pos, end_pos)
    for b in breaks:
        code.update_jump(b, end_pos)
Пример #19
0
def _exp_and(code: Code, exp):
    left = exp['left']
    right = exp['right']
    left_type = exp['left']['type']
    _expression(code, left)
    _expression(code, right)

    if isinstance(left_type, TypeBool):
        cmp1_pos = code.pos()
        code.if_eq()
        cmp2_pos = code.pos()
        code.if_eq()
        code.const_int(1)
        goto_pos = code.pos()
        code.goto()
        false_pos = code.pos()
        code.const_int(0)
        end_pos = code.pos()

        code.update_jump(cmp1_pos, false_pos)
        code.update_jump(cmp2_pos, false_pos)
        code.update_jump(goto_pos, end_pos)
    else:
        raise NotImplementedError()
Пример #20
0
def _exp_not(code: Code, exp):
    expression = exp['expression']
    exp_type = exp['expression']['type']
    _expression(code, expression)

    if isinstance(exp_type, TypeBool):
        cmp_pos = code.pos()
        code.if_eq()
        code.const_int(0)
        goto_pos = code.pos()
        code.goto()
        false_pos = code.pos()
        code.const_int(1)
        end_pos = code.pos()

        code.update_jump(cmp_pos, false_pos)
        code.update_jump(goto_pos, end_pos)
    else:
        raise NotImplementedError()
Пример #21
0
def _statement_if_else(code: Code,
                       statement,
                       loop_start: Optional[int] = None,
                       breaks: Optional[List[int]] = None):
    condition = statement['condition']
    if_statements = statement['if_statements']
    else_statements = statement['else_statements']

    _expression(code, condition)
    cond_pos = code.pos()
    code.if_eq()

    for s in if_statements:
        _statement(code, s, loop_start, breaks)

    goto_pos = code.pos()
    code.goto()

    else_pos = code.pos()
    for s in else_statements:
        _statement(code, s, loop_start, breaks)

    end_pos = code.pos()

    code.update_jump(cond_pos, else_pos)
    code.update_jump(goto_pos, end_pos)
Пример #22
0
def _exp_ne(code: Code, exp):
    left = exp['left']
    right = exp['right']
    left_type = exp['left']['type']
    _expression(code, left)
    _expression(code, right)

    if isinstance(left_type, TypeInt) or isinstance(
            left_type, TypeBool) or isinstance(left_type, TypeReal):
        if isinstance(left_type, TypeReal):
            code.cmp_double_l()
            cmp_pos = code.pos()
            code.if_ne()
        else:
            cmp_pos = code.pos()
            code.if_cmp_int_ne()
        code.const_int(0)
        goto_pos = code.pos()
        code.goto()
        true_pos = code.pos()
        code.const_int(1)
        end_pos = code.pos()

        code.update_jump(cmp_pos, true_pos)
        code.update_jump(goto_pos, end_pos)
    elif isinstance(left_type, TypeStr):
        code.invoke_virtual(*JM_STRING_EQUALS)
        cmp_pos = code.pos()
        code.if_eq()
        code.const_int(0)
        goto_pos = code.pos()
        code.goto()
        false_pos = code.pos()
        code.const_int(1)
        end_pos = code.pos()

        code.update_jump(cmp_pos, false_pos)
        code.update_jump(goto_pos, end_pos)
    else:
        raise NotImplementedError()
Пример #23
0
def _statement_return(code: Code, statement):
    expression = statement['expression']
    t = statement['type']

    if expression:
        _expression(code, expression)

    if isinstance(t, TypeVoid):
        code.return_void()
    elif isinstance(t, TypeInt):
        code.return_int()
    elif isinstance(t, TypeReal):
        code.return_double()
    elif isinstance(t, TypeBool):
        code.return_int()
    elif isinstance(t, TypeStr):
        code.return_reference()
    elif isinstance(t, TypeArray):
        code.return_reference()
    else:
        raise NotImplementedError()
Пример #24
0
def _statement_var_def(code: Code, statement):
    name = statement['name']
    t = statement['type']
    expression = statement['expression']

    _expression(code, expression)

    if isinstance(t, TypeInt):
        index = code.variable_int()
        code.store_int(index)
    elif isinstance(t, TypeReal):
        index = code.variable_double()
        code.store_double(index)
    elif isinstance(t, TypeBool):
        index = code.variable_int()
        code.store_int(index)
    elif isinstance(t, TypeStr):
        index = code.variable_reference()
        code.store_reference(index)
    elif isinstance(t, TypeArray):
        index = code.variable_reference()
        code.store_reference(index)
    else:
        raise NotImplementedError()

    _locals[name] = index