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()
def _exp_eq(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_eq() else: cmp_pos = code.pos() code.if_cmp_int_eq() 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) else: raise NotImplementedError()
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)
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)
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)
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()
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()
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()
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)