def cgen_new_array(node): emit_comment('cgen_new_array') stack_handler.add_checkpoint() len_expr = cgen_expr(node.ref_child[1]) (member_type, dimension) = expr_type(node.ref_child[2]) if len_expr.get_type() != Type.int: raise TypeError("in node: \n" + node.__repr__() + "\n length of new_array isn't int.") len_expr_address = len_expr.get_address() len_expr_address.load() emit_li('$t0', '4') emit_addi('$s0', '$s0', '1') emit('mult $s0, $t0') emit('mflo $a0') emit_li('$v0', 9) emit_syscall() # Set length emit_addi('$s0', '$s0', '-1') emit('sw $s0, 0($v0)') emit_addi('$s0', '$s0', '1') emit_move('$s0', '$v0') stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, Type.array) node.get_address().store() node.set_array_dim(dimension + 1) node.set_array_member_type(member_type) return node
def expr_add_sub(node, operation): # operation = 'add' or 'sub' stack_handler.add_checkpoint() left_child = cgen_expr(node.ref_child[0]) right_child = cgen_expr(node.ref_child[2]) left_child_type = left_child.get_type() left_child_address = left_child.get_address() right_child_address = right_child.get_address() if left_child_type != right_child.get_type() or left_child_type not in ( Type.double, Type.int): raise TypeError("in node: \n" + node.__repr__() + "\n exprs' types are not good for " + operation + " operation.") elif left_child_type == Type.int: left_child_address.load() emit("move $s1, $s0") right_child_address.load() emit(operation + " $s0, $s1, $s0") elif left_child_type == Type.double: left_child_address.load() emit("mov.s $f2, $f0") right_child_address.load() emit(operation + ".s $f0, $f2, $f0") stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, left_child_type) node.get_address().store() return node
def cgen_expr_le(node): emit_comment('cgen_expr_le') stack_handler.add_checkpoint() left_child = cgen_expr(node.ref_child[0]) right_child = cgen_expr(node.ref_child[2]) left_child_address = left_child.get_address() right_child_address = right_child.get_address() if left_child.get_type() != right_child.get_type(): raise TypeError("in node: \n" + node.__repr__() + "\nTwo exprs must have same type.") elif left_child.get_type() == Type.double: expr_float_cmp(left_child_address, right_child_address, 'lt') elif left_child.get_type() == Type.int: left_child_address.load() emit_move("$s1", "$s0") right_child_address.load() emit("slt $s0, $s1, $s0") else: raise TypeError("in node: \n" + node.__repr__() + "\nExprs' type isn't comparable.") stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, Type.bool) node.get_address().store() return node
def expr_or_and(node, operation): # operation = 'and' or 'or' stack_handler.add_checkpoint() left_child = cgen_expr(node.ref_child[0]) right_child = cgen_expr(node.ref_child[2]) if left_child.get_type() != Type.bool or right_child.get_type( ) != Type.bool: raise TypeError("in node: \n" + node.__repr__() + "\n one of exprs' type is not bool.") left_child_address = left_child.get_address() right_child_address = right_child.get_address() left_child_address.load() emit("move $s1, $s0") right_child_address.load() emit(operation + " $s0, $s0, $s1") stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, Type.bool) node.get_address().store() return node
def cgen_expr_equal(node): emit_comment('cgen_expr_equal') stack_handler.add_checkpoint() left_child = cgen_expr(node.ref_child[0]) right_child = cgen_expr(node.ref_child[2]) left_child_address = left_child.get_address() right_child_address = right_child.get_address() if not expr_convertable(left_child.get_type(), right_child.get_type()) and not expr_convertable( right_child.get_type(), left_child.get_type()): emit_li("$s0", 0) elif left_child.get_type() == Type.double: expr_float_cmp(left_child_address, right_child_address, 'eq') elif left_child.get_type() == Type.string: left_child_address.load() emit_move('$s1', '$s0') right_child_address.load() emit_move('$s2', '$s0') emit_li('$s0', 1) first_label = create_label() second_label = create_label() out_label = create_label() emit_label(first_label) emit_load_byte('$t0', '$s1') emit_load_byte('$t1', '$s2') emit_addi('$s1', '$s1', '1') emit_addi('$s2', '$s2', '1') emit('beq $t0, $t1, ' + second_label) emit_li('$s0', 0) emit_label(second_label) emit('beqz $t0, ' + out_label) emit('beqz $t1, ' + out_label) emit_jump(first_label) emit_label(out_label) else: left_child_address.load() emit_move('$s1', '$s0') right_child_address.load() emit("xor $t0, $s0, $s1") emit("slt $t1, $t0, $zero") emit("slt $t0, $zero, $t0") emit("or $t0, $t0, $t1") emit("li $t1, 1") emit("sub $s0, $t1, $t0") emit("") stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, Type.bool) node.get_address().store() return node
def cgen_expr_leq(node): emit_comment('cgen_expr_leq') stack_handler.add_checkpoint() node = cgen_expr_le(node) node.get_address().load() emit_move("$s2", "$s0") stack_handler.back_to_last_checkpoint() node = cgen_expr_equal(node) node.get_address().load() emit("or $s0, $s0, $s2") node.get_address().store() return node
def cgen_expr_not(node): emit_comment('cgen_expr_not') stack_handler.add_checkpoint() child = cgen_expr(node.ref_child[1]) if child.get_type() != Type.bool: raise TypeError("in node: \n" + node.__repr__() + "\n expr's type is not bool.") child_address = child.get_address() child_address.load() emit("li $t0, 1") emit("sub $s0, $t0, $s0") stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, Type.bool) node.get_address().store() return node
def cgen_expr_assign(node): emit_comment('cgen_expr_assign') stack_handler.add_checkpoint() lvalue = cgen_lvalue(node.ref_child[0]) rvalue_expr = cgen_expr(node.ref_child[2]) rvalue_expr_type = rvalue_expr.get_type() lvalue_type = lvalue.get_type() if not expr_convertable(lvalue_type, rvalue_expr_type): raise TypeError("in node: \n" + lvalue.__repr__() + rvalue_expr.__repr__() + "\nrvalue and lvalue type must be equal.") if rvalue_expr_type == Type.array: if (not expr_convertable(lvalue.get_array_member_type(), rvalue_expr.get_array_member_type())) or \ rvalue_expr.get_array_dim() != lvalue.get_array_dim(): raise TypeError("in node: \n" + lvalue.__repr__() + rvalue_expr.__repr__() + "\nrvalue and lvalue member-type and " "arr-dimension must be equal.") lvalue_address = lvalue.get_address() rvalue_address = rvalue_expr.get_address() rvalue_address.load() emit_move('$t0', '$s0') lvalue_address.store() emit_move('$s0', '$t0') stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, lvalue_type) node.get_address().store() if rvalue_expr_type == Type.array: node.set_array_dim(lvalue.get_array_dim()) node.set_array_member_type(lvalue.get_array_member_type()) return node
def cgen_expr_neg(node): emit_comment('cgen_expr_neg') stack_handler.add_checkpoint() child = cgen_expr(node.ref_child[1]) child_type = child.get_type() child_address = child.get_address() child_address.load() if child_type == Type.int: emit("sub $s0, $zero, $s0") elif child_type == Type.double: emit("neg.s $f0, $f0") else: raise TypeError("in node: \n" + node.__repr__() + "\n expr's type is not int or double.") stack_handler.back_to_last_checkpoint() expr_set_node_attributes(node, child_type) node.get_address().store() return node
def cgen_lvalue(node): emit_comment('cgen_lvalue') left_child = node.ref_child[0] right_child = None if len(node.ref_child) >= 3: right_child = node.ref_child[2] if left_child.data == 'ident': ident_name = expr_ident(left_child) variable = ut.symbolTable.get_variable_by_name(ident_name) if variable.is_array: node.set_type(Type.array) node.set_array_member_type(variable.type[0]) node.set_array_dim(variable.type[1]) else: node.set_type(variable.type) node.set_address(variable.address) elif right_child.data == 'ident': stack_handler.add_checkpoint() expr = cgen_expr(left_child) ident_name = expr_ident(right_child) variable = ut.class_handler.get_variable(expr.get_type(), ident_name) expr.get_address().load() stack_handler.back_to_last_checkpoint() new_address = new_address_on_top_of_stack(False) new_address.store() if variable.is_array: node.set_type(Type.array) node.set_array_member_type(variable.type[0]) node.set_array_dim(variable.type[1]) else: node.set_type(variable.type) node.set_address( Address((new_address, variable.address), 2, node.get_type() == Type.double)) else: left_expr = cgen_expr(left_child) stack_handler.add_checkpoint() right_expr = cgen_expr(right_child) if left_expr.get_type() != Type.array: raise TypeError("in node: \n" + node.__repr__() + "\nleft-expr isn't an array.") if right_expr.get_type() != Type.int: raise TypeError("in node: \n" + node.__repr__() + "\nright-expr isn't an integer.") node.set_type(Type.array) array_member_type = left_expr.get_array_member_type() dimension = left_expr.get_array_dim() - 1 if dimension > 0: node.set_array_dim(dimension) node.set_array_member_type(array_member_type) else: node.set_type(array_member_type) right_expr.get_address().load() stack_handler.back_to_last_checkpoint() new_address = new_address_on_top_of_stack(False) new_address.store() node.set_address( Address((left_expr.get_address(), new_address), 3, array_member_type == Type.double and dimension == 0)) return node
def cgen_call(node): emit_comment('cgen_call()') left_child = node.ref_child[0] stack_handler.add_checkpoint() if left_child.data == 'expr': expr = cgen_expr(node.ref_child[0]) function_name = expr_ident(node.ref_child[2]) actual_node = node.ref_child[3] if not is_class_type( expr.get_type()) and expr.get_type() != Type.array: raise TypeError("in node: \n" + node.__repr__() + "\nexpr's type isn't class or array type.") if expr.get_type == Type.array and function_name != 'length': raise TypeError( "in node: \n" + node.__repr__() + "\nwhen expr is array function_name must be length") argument_list = expr_atual_get_args_list(actual_node, [expr]) argument_type_list = get_args_type_list(argument_list) push_arguments_to_stack(argument_list) ra_address = push_ra_to_stack() if expr.get_type() == Type.array: emit_load_address('$s0', '___array_length') return_type = Type.int else: function, function_address = get_class_function_and_its_address( expr.get_address(), function_name, expr.get_type(), argument_type_list[1:]) function_address.load() return_type = function.return_type else: function_name = expr_ident(left_child) actual_node = node.ref_child[1] argument_list = expr_atual_get_args_list(actual_node, []) argument_type_list = get_args_type_list(argument_list) if ut.this_type is None: function = function_handler.get_function(function_name, argument_type_list) function_address = None push_arguments_to_stack(argument_list) else: try: function, function_address = get_class_function_and_its_address( get_this_address(), function_name, ut.this_type, argument_type_list) push_arguments_to_stack(argument_list) get_this_address().load() new_address_on_top_of_stack( ut.this_type == Type.double).store() except FunctionError: function = function_handler.get_function( function_name, argument_type_list) function_address = None push_arguments_to_stack(argument_list) return_type = function.return_type ra_address = push_ra_to_stack() if function_address is None: emit_load_address('$s0', function.label) else: function_address.load() stack_handler.set_fp_equal_sp() emit_jalr('$s0') stack_handler.back_to_last_fp() ra_address.load() emit_move('$ra', '$s0') emit_move('$s0', '$v0') stack_handler.back_to_last_checkpoint() if isinstance(return_type, str): expr_set_node_attributes(node, return_type) else: expr_set_node_attributes(node, Type.array) node.set_array_member_type(return_type[0]) node.set_array_dim(return_type[1]) node.get_address().store() return node