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()
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)