Example #1
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()
Example #2
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)