def VarCall(node, children_codes): # VarCall -> ident VarCallRight code = [] ident = node.children[0].token.string var_type = node.properties['var_type'] data_type = node.properties['data_type'] if var_type == 'var': arg = Argument('ident', data_type, ident) elif var_type == 'array': # todo: array pass elif var_type == 'call': arglist_code = children_codes[1] code = [*code, *arglist_code] code.append(new_inst('call', ident)) if data_type != 'void': getval = Argument('ident', data_type, GETVAL) arg = Argument('ident', data_type, get_ident()) code.append(new_inst('mov', arg, getval)) else: arg = None else: assert False node.properties['arg'] = arg return code
def Function(node, children_codes): # Fucntion -> def ident(ParaList) FunctionBody body_code = children_codes[-1] para_list = node.properties['para_list'] # ((type, ident),...) para_code = [] i = len(para_list) - 1 while i >= 0: para = para_list[i] para_code.append(new_inst('alloc', *para, DEFAULT_VAL[para[0]])) para_code.append( new_inst('mov', Argument('ident', *para), Argument('ident', para[0], ARG_PREFIX + str(i)))) i = i - 1 name = node.properties['name'] if name == MAIN: return_code = [new_inst('exit')] else: return_code = [new_inst('ret')] return_type = node.properties['return_type'] if return_type != 'void': retval_code = [ new_inst('alloc', return_type, RETVAL, DEFAULT_VAL[return_type]) ] else: retval_code = [] return [ new_inst('proc', name), *retval_code, *para_code, *body_code, *return_code, new_inst('end', name) ]
def HandleCalcItem(inst_of_op, left, right, node, children_codes): # Xxx -> Item XxxRight # XxxRight -> Op Item XxxRight code = [] if (right.children # and right.children[].syntax_item.startswith(node.syntax_item) ): op = right.properties['op'] right_arg = right.properties['arg'] left_arg = left.properties['arg'] data_type = node.properties['data_type'] temp = Argument('ident', data_type, get_ident()) code.append(new_inst(inst_of_op[op], temp, left_arg, right_arg)) node.properties['arg'] = temp if node.deriv_tuple[0] in inst_of_op: node.properties['op'] = node.children[0].token.string else: pass else: if node.deriv_tuple[0] in inst_of_op: node.properties['op'] = node.children[0].token.string else: pass node.properties['arg'] = left.properties['arg'] return expand_code_list(children_codes) + code
def Assign(node, children_codes): # Assign -> Var = Expr ident = node.children[0].properties['ident'] data_type = node.children[0].properties['data_type'] var_arg = Argument('ident', data_type, ident) expr_arg = node.children[2].properties['arg'] expr_code = children_codes[2] return [*expr_code, new_inst('mov', var_arg, expr_arg)]
def Oprand(node, children_codes): # Oprand -> Var | integer_value | double_value | bool_value data_type = node.properties['data_type'] child = node.children[0] if node.deriv_tuple[0] == 'VarCall': arg = node.children[0].properties['arg'] else: arg = Argument('data', data_type, child.token.string) node.properties['arg'] = arg return expand_code_list(children_codes)
def Unary(node, children_codes): # Unary -> {+, -, !} Unary | ParExpr | Oprand code = [] op = node.deriv_tuple[0] oprand = node.children[-1] oprand_arg = oprand.properties['arg'] data_type = node.properties['data_type'] if op in ['ParExpr', 'Oprand', '+']: node.properties['arg'] = oprand_arg elif op == '-': temp = Argument('ident', data_type, get_ident()) zero = Argument('data', data_type, 0) code.append(new_inst('minus', temp, zero, oprand_arg)) node.properties['arg'] = temp elif op == '!': temp = Argument('ident', data_type, get_ident()) code.append(new_inst('not', temp, oprand_arg)) node.properties['arg'] = temp else: assert False return expand_code_list(children_codes) + code
def ArgList(node, children_codes): # ArgList -> Expr ArgListRight if not node.children: return [] result_code = [] expr_node = node.children[0] right = node.children[-1] arg = expr_node.properties['arg'] code = children_codes[0] args = node.properties['args'] = [arg, *right.properties['args']] codes = [[*code], *children_codes[-1]] types = node.properties['arg_types'] for i in range(0, len(args)): result_code = [ *result_code, *codes[i], new_inst('override', Argument('ident', types[i], ARG_PREFIX + str(i)), args[i]) ] return result_code
def Stmt(node, children_codes): # Stmt -> Assign; | read Var; | print Expr; | eval Expr; # if(Expr) Stmt Else | while(Expr) Stmt | # do Stmt while(Expr); | for(Assign; Expr; Assign) Stmt | # break; | continue; | return ReturnValue | Block def enable_jump(code, continue_label, break_label): for i in range(0, len(code)): if code[i] == 'continue': code[i] = new_inst('goto', continue_label) elif code[i] == 'break': code[i] = new_inst('goto', break_label) rule = node.deriv_tuple[0] if rule == 'if': # if(Expr) Stmt Else expr_node = node.children[2] expr_code = children_codes[2] expr_arg = expr_node.properties['arg'] stmt_code = children_codes[4] else_code = children_codes[5] label_pre_else = get_label() label_post_else = get_label() return [ *expr_code, new_inst('goto_if_false', expr_arg, label_pre_else), *stmt_code, new_inst('goto', label_post_else), new_inst('label', label_pre_else), *else_code, new_inst('label', label_post_else) ] elif rule == 'while': # while(Expr) Stmt expr_node = node.children[2] expr_code = children_codes[2] expr_arg = expr_node.properties['arg'] stmt_code = children_codes[4] label_go_back = get_label() label_tail = get_label() enable_jump(stmt_code, label_go_back, label_tail) return [ new_inst('label', label_go_back), *expr_code, new_inst('goto_if_false', expr_arg, label_tail), *stmt_code, new_inst('goto', label_go_back), new_inst('label', label_tail) ] elif rule == 'do': # do Stmt while(Expr); expr_node = node.children[4] expr_code = children_codes[4] expr_arg = expr_node.properties['arg'] stmt_code = children_codes[1] label_go_back = get_label() label_tail = get_label() enable_jump(stmt_code, label_go_back, label_tail) return [ new_inst('label', label_go_back), *stmt_code, *expr_code, new_inst('goto_if', expr_arg, label_go_back), new_inst('label', label_tail) ] elif rule == 'for': # for(Assign; Expr; Assign) Stmt initial_code = children_codes[2] condition_node = node.children[4] condition_code = children_codes[4] condition_arg = condition_node.properties['arg'] increment_code = children_codes[6] stmt_code = children_codes[8] label_go_back = get_label() label_tail = get_label() enable_jump(stmt_code, label_go_back, label_tail) return [ *initial_code, new_inst('label', label_go_back), *condition_code, new_inst('goto_if_false', condition_arg, label_tail), *stmt_code, *increment_code, new_inst('goto', label_go_back), new_inst('label', label_tail) ] elif rule == 'break': # to be handled in enable_jump() return ['break'] elif rule == 'continue': # to be handled in enable_jump() return ['continue'] elif rule == 'return': code = [] data_type = node.children[1].properties['data_type'] if data_type != 'void': retval_arg = Argument('ident', data_type, RETVAL) expr_arg = node.children[1].properties['arg'] expr_code = children_codes[1] code = [*code, *expr_code] code.append(new_inst('mov', retval_arg, expr_arg)) assert node.function if node.function.properties['name'] == MAIN: code.append(new_inst('exit')) else: code.append(new_inst('ret')) return code elif rule == 'read': # read Var; ident = node.children[1].properties['ident'] data_type = node.children[1].properties['data_type'] ident_arg = Argument('ident', data_type, ident) return [new_inst('read', ident_arg)] elif rule == 'print': # print Expr; expr_code = children_codes[1] expr_arg = node.children[1].properties['arg'] return [*expr_code, new_inst('print', expr_arg)] else: return expand_code_list(children_codes)
#!/usr/bin/env python3 import sys from syntax import get_syntax_tree from machine import (Instruction, Argument, CALCULATION, RETVAL, GETVAL, ARG_PREFIX, TEMP_PREFIX) from common import DEBUG, e_print LABEL_PREFIX = 'L' MAIN = 'main' DEFAULT_VAL = { 'int': Argument('data', 'int', 0), 'double': Argument('data', 'double', 0.0), 'bool': Argument('data', 'bool', False) } def translate(syntax_tree_root): max_ident_index = -1 max_label_index = -1 released_idents_list = [] released_idents = {} def get_label(): nonlocal max_label_index max_label_index += 1 return LABEL_PREFIX + str(max_label_index) def get_ident(): nonlocal max_ident_index if released_idents_list: