def cgen_for(node): emit_comment('cgen_for') expr1 = node.ref_child[0] expr2 = node.ref_child[1] expr3 = node.ref_child[2] stmt = node.ref_child[3] top = ut.disFp l1 = create_label() l2 = create_label() node.attribute[AttName.exit_label] = l2 if expr1.data != "nothing": cgen_expr(expr1) align_stack(top) emit_label(l1) t = cgen_expr(expr2) if t.attribute[AttName.type] != Type.bool: raise TypeError("error in node " + str(node) + "\n type of the decision statement must be bool!") t.attribute[AttName.address].load_address() emit_load("$t0", "$s0") align_stack(top) emit("beqz $t0, " + l2) cgen_stmt(stmt) align_stack(top) if expr3.data != "nothing": cgen_expr(expr3) align_stack(top) emit_jump(l1) emit_label(l2) emit_li("$t6", top) ut.emit_add("$t6", "$t6", "$fp") emit_move("$sp", "$t6") return
def cgen_if1(expr, stmt1, stmt2): emit_comment('cgen_if1') l1 = create_label() l2 = create_label() top = ut.disFp t1 = cgen_expr(expr) if t1.attribute[AttName.type] != Type.bool: raise TypeError("error in node " + str(expr) + "\n type of the decision statement must be bool!") t1.attribute[AttName.address].load_address() emit_load("$t0", "$s0") align_stack(top) emit("beqz $t0, " + l1) st1 = cgen_stmt(stmt1) ret = 0 if st1.attribute[AttName.has_return]: ret += 1 align_stack(top) emit_jump(l2) emit_label(l1) st2 = cgen_stmt(stmt2) if st2.attribute[AttName.has_return]: ret += 1 align_stack(top) emit_label(l2) return ret
def cgen_return_stmt(node): # checking validity of statement func = node.ref_parent while func is not None and func.data != "functiondecl": func = func.ref_parent # return isn't in any function! if func is None: raise FunctionError("Error in return node " + str(node) + ", return node must be use in a funcion!") # return for void functions if node.ref_child[0].data == "nothing": if func.ref_child[0].data == "void": emit_move("$sp", "$fp") emit("jr $ra") return else: raise TypeError("Error in return statement for function in node" + str(func) + ", function type must be void") # return for non void functions type = get_type(func.ref_child[0]) # type of parent function expr = cgen_expr(node.ref_child[0]) # expr node of return # checking equality of types # if not type[0]: # type isn't array # if type[1] != expr.attribute[AttName.type]: # raise TypeError( # "Error in return statement in node" + str(node) + ", type of function and return isn't match!" # ) # else: # type is array # if type[1] != expr.attribute[AttName.array_member_type]: # checking type of members # raise TypeError( # "Error in return statement in node" + str(node) + ", type of function and returned array isn't match!" # ) # if type[2] != expr.attribute[AttName.array_dim]: # checking dimension # raise TypeError( # "Error in return statement in node" + str(node) + # ", dimension of returned array isn't match to function array dimension!" # ) # load return statement to $v0 and jump to callee expr.attribute[AttName.address].load() emit_move("$v0", "$s0") emit_move("$sp", "$fp") emit("jr $ra") return node.ref_child[0].data != "nothing"
def cgen_stmt(node): emit_comment('cgen_stmt') child = node.ref_child[0] top = ut.disFp if child.data == "stmt": ret = cgen_stmt(child) node.attribute[AttName.has_return] = ret.attribute[AttName.has_return] elif child.data == "forstmt": cgen_for(child) node.attribute[AttName.has_return] = False elif child.data == "whilestmt": cgen_while(child) node.attribute[AttName.has_return] = False elif child.data == "ifstmt": ret = cgen_if(child) node.attribute[AttName.has_return] = ret.attribute[AttName.has_return] elif child.data == "stmtblock": ret = cgen_stmt_block(child) node.attribute[AttName.has_return] = ret.attribute[AttName.has_return] elif child.data == "expr": cgen_expr(child) align_stack(top) node.attribute[AttName.has_return] = False elif child.data == "breakstmt": cgen_break(child) node.attribute[AttName.has_return] = False elif child.data == "printstmt": cgen_print_stmt(child) node.attribute[AttName.has_return] = False elif child.data == "returnstmt": ret = cgen_return_stmt(child) node.attribute[AttName.has_return] = ret return node
def cgen_if2(expr, stmt): emit_comment('cgen_if2') l1 = create_label() top = ut.disFp t1 = cgen_expr(expr) if t1.attribute[AttName.type] != Type.bool: raise TypeError("error in node " + str(expr) + "\n type of the decision statement must be bool!") t1.attribute[AttName.address].load_address() emit_load("$t0", "$s0") align_stack(top) emit("beqz $t0, " + l1) cgen_stmt(stmt) align_stack(top) emit_label(l1) return
def cgen_print_stmt(node): emit_comment('cgen_print_stmt') top = ut.disFp for child in node.ref_child: expr = cgen_expr(child) address = expr.attribute[AttName.address] type = expr.attribute[AttName.type] address.load_address() if type == Type.double: emit_load_double("$f12", "$s0") emit_li("$v0", 2) emit_syscall() #print_double() elif type == "string": emit_load("$a0", "$s0") emit_li("$v0", 4) emit_syscall() elif type == Type.bool: l1 = create_label() l2 = create_label() emit_load('$s0', '$s0') emit('beqz $s0, ' + l1) emit('la $a0, __true') emit_jump(l2) emit_label(l1) emit('la $a0, __false') emit_label(l2) emit_li("$v0", 4) emit_syscall() else: emit_load("$a0", "$s0") emit_li("$v0", 1) emit_syscall() align_stack(top) emit('la $a0, __newLine') emit_li("$v0", 4) emit_syscall()