def arr_brace(sym: SyntaxTree, context: SemanticContext): size = sym.childs[1].sym.val dims = [size] ll_dims = sym.childs[3].get_attr('dims') if ll_dims: dims.extend(ll_dims) sym.set_attr('dims', dims)
def expr_idn(sym: SyntaxTree, context: SemanticContext): var = sym.childs[0].sym.val symbol = context.lookup_sym(var) if not symbol: return -1, "{} is not defined".format(var) operand = Operand(var, symbol.type) sym.set_attr("res", operand)
def stmt_s(sym: SyntaxTree, context: SemanticContext): saddr = sym.childs[1].get_attr('quad') s1nl = sym.childs[0].get_attr('nl') s2nl = sym.childs[2].get_attr('nl') if s1nl: context.back_patch(s1nl, saddr) sym.set_attr('nl', s2nl)
def struct_type(sym: SyntaxTree, context: SemanticContext): vardl = sym.childs[2] eles = vardl.get_attr('eles') sym_width = vardl.get_attr('width') sym_type = STypeRecord(eles) sym.set_attr('type', sym_type) sym.set_attr('width', sym_width)
def arr_ref(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) operand = sym.childs[0].get_attr('res') last_res = operand.val last_type = operand.type arr_type = last_type.get_ref_type() if not isinstance(arr_type, STypeArray): return -1, "Too many array brackets" ele_type = arr_type.get_ele_type() index_operand = sym.childs[2].get_attr('res') index_res = index_operand.val index_type = index_operand.type if index_type != TokenType.INT: return -1, "Array index must be int" if index_res != 0: res1 = context.gen_tmp() ele_type_width = get_type_width(ele_type) context.gen_ins("*", index_res, ele_type_width, res1) res = context.gen_tmp() context.gen_ins('+', last_res, res1, res) else: res = last_res res_type = STypePtr(ele_type) sym.set_attr('res', Operand(res, res_type))
def arr_ref_one(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) var = sym.childs[0].sym.val symbol = context.lookup_sym(var) if not symbol: return -1, "{} is not defined".format(var) elif not isinstance(symbol.type, STypeArray): return -1, "{} is not a valid array".format(var) index_res = sym.childs[2].get_attr('res') # get offset ele_type = symbol.type.get_ele_type() if index_res != 0: res1 = context.gen_tmp() ele_type_width = get_type_width(ele_type) context.gen_ins("*", index_res, ele_type_width, res1) res2 = context.gen_tmp() context.gen_ins('&', var, None, res2) res = context.gen_tmp() context.gen_ins('+', res2, res1, res) else: res = context.gen_tmp() context.gen_ins('&', var, None, res) res_type = STypePtr(ele_type) sym.set_attr('res', Operand(res, res_type))
def sub_val(sym: SyntaxTree, context: SemanticContext): tok = sym.childs[1].sym if tok.type == TokenType.CINT: res_type = TokenType.INT elif tok.type == TokenType.CFLOAT: res_type = TokenType.FLOAT else: assert False, "Invalid Type {}".format(tok.type) sym.set_attr("res", Operand(-tok.val, res_type))
def stmt_if(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[1] sym_s = sym.childs[4] sstart = sym.childs[3].get_attr('quad') btl = sym_b.get_attr('tl') bfl = sym_b.get_attr('fl') context.back_patch(btl, sstart) snl = bfl + sym_s.get_attr('nl') sym.set_attr('nl', snl)
def bool_expr2(sym: SyntaxTree, context: SemanticContext): sym_g = sym.childs[0] sym_h = sym.childs[3] quad = sym.childs[2].get_attr('quad') gtl = sym_g.get_attr('tl') htl = sym_h.get_attr('tl') gfl = sym_g.get_attr('fl') hfl = sym_h.get_attr('fl') context.back_patch(gtl, quad) sym.set_attr('tl', htl) sym.set_attr('fl', gfl + hfl)
def bool_expr1(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[0] sym_g = sym.childs[3] quad = sym.childs[2].get_attr('quad') btl = sym_b.get_attr('tl') gtl = sym_g.get_attr('tl') bfl = sym_b.get_attr('fl') gfl = sym_g.get_attr('fl') context.back_patch(bfl, quad) sym.set_attr('tl', btl + gtl) sym.set_attr('fl', gfl)
def param_list_one(sym: SyntaxTree, context: SemanticContext): child_type = sym.childs[0].get_attr('type') child_width = sym.childs[0].get_attr('width') child_name = sym.childs[1].sym.val context.add_sym(child_name, child_type) params = [{ 'name': child_name, 'type': child_type, 'width': child_width }] sym.set_attr('params', params)
def stmt_while(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[2] sym_s = sym.childs[6] bstart = sym.childs[1].get_attr('quad') sstart = sym.childs[5].get_attr('quad') snl = sym_s.get_attr('nl') btl = sym_b.get_attr('tl') bfl = sym_b.get_attr('fl') context.back_patch(snl, bstart) context.back_patch(btl, sstart) context.gen_ins('goto', None, None, bstart) sym.set_attr('nl', bfl)
def array_type(sym: SyntaxTree, context: SemanticContext): dims = sym.childs[1].get_attr('dims') prim_type = sym.childs[0].get_attr('type') prim_width = sym.childs[0].get_attr('width') if dims: sym_type = STypeArray(prim_type, dims) ele_num = reduce(lambda total, x: total * x, dims) else: sym_type = prim_type ele_num = 1 sym.set_attr('type', sym_type) sym.set_attr('width', prim_width * ele_num)
def var_decl_list_begin(sym: SyntaxTree, context: SemanticContext): child_type = sym.childs[0].get_attr('type') child_width = sym.childs[0].get_attr('width') child_name = sym.childs[0].get_attr('name') eles = { child_name: { "type": child_type, "width": child_width, "offset": 0 } } sym.set_attr('eles', eles) sym.set_attr('offset', child_width)
def bool_expr5(sym: SyntaxTree, context: SemanticContext): toktype = sym.childs[0].childs[0].sym.type start = context.addr sym.set_attr('start', start) if toktype == TokenType.TRUE: ins = context.gen_ins('goto', None, None, None) stl = [ins] sfl = [] else: ins = context.gen_ins('goto', None, None, None) stl = [] sfl = [ins] sym.set_attr('tl', stl) sym.set_attr('fl', sfl)
def prim_type(sym: SyntaxTree, context: SemanticContext): sym_type = sym.childs[0].sym.type sym.set_attr("type", sym_type) if sym_type == TokenType.CHAR: width = 1 elif sym_type == TokenType.SHORT: width = 2 elif sym_type == TokenType.INT or sym_type == TokenType.FLOAT: width = 4 elif sym_type == TokenType.DOUBLE: width = 8 else: assert False, "Unknown Type {}".format(str(sym_type)) sym.set_attr("width", width)
def wrapper(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) op = func(sym, context) ysym = sym.childs[0] fsym = sym.childs[2] yres = ysym.get_attr('res') fres = fsym.get_attr('res') res = context.gen_tmp() res_type = deduce_type(yres.type, fres.type) context.gen_ins(op, yres.val, fres.val, res) sym.set_attr('res', Operand(res, res_type)) if res_type is None: return -1, "Can't do {} on {} and {}".format( op, str(yres.type), str(fres.type))
def stmt_if_else(sym: SyntaxTree, context: SemanticContext): sym_b = sym.childs[1] sym_s1 = sym.childs[4] sym_s2 = sym.childs[10] else_gate = sym.childs[6] s1start = sym.childs[3].get_attr('quad') s2start = sym.childs[9].get_attr('quad') s1nl = sym_s1.get_attr('nl') s2nl = sym_s2.get_attr('nl') btl = sym_b.get_attr('tl') bfl = sym_b.get_attr('fl') context.back_patch(btl, s1start) context.back_patch(bfl, s2start) snl = s1nl + s2nl + else_gate.get_attr('nl') sym.set_attr('nl', snl)
def param_list(sym: SyntaxTree, context: SemanticContext): has_err = False err_strs = [] child_type = sym.childs[2].get_attr('type') child_width = sym.childs[2].get_attr('width') child_name = sym.childs[3].sym.val sym_param = sym.childs[0] params = list(sym_param.get_attr('params')) for param in params: if child_name == param['name']: has_err = True err_strs.append("Duplicate parameter {}".format(child_name)) context.add_sym(child_name, child_type) params.append({ 'name': child_name, 'type': child_type, 'width': child_width }) sym.set_attr('params', params) if has_err: return -1, '\n'.join(err_strs)
def var_decl(sym: SyntaxTree, context: SemanticContext): child_type = sym.childs[0].get_attr('type') child_width = sym.childs[0].get_attr('width') child_name = sym.childs[1].sym.val sym.set_attr('type', child_type) sym.set_attr('width', child_width) sym.set_attr('name', child_name)
def var_decl_list(sym: SyntaxTree, context: SemanticContext): has_err = False vard = sym.childs[1] child_type = vard.get_attr('type') child_width = vard.get_attr('width') child_name = vard.get_attr('name') vardl = sym.childs[0] eles = dict(vardl.get_attr('eles')) offset = vardl.get_attr('offset') if child_name in eles: has_err = True else: eles[child_name] = { "type": child_type, "width": child_width, "offset": offset } offset += child_width sym.set_attr('eles', eles) sym.set_attr('offset', offset) if has_err: return -1, "Duplicate record attribute {}".format(child_name)
def record_ref(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) var = sym.childs[0].sym.val attr = sym.childs[2].sym.val symbol = context.lookup_sym(var) if not symbol: return -1, "{} is not defined".format(var) elif not isinstance(symbol.type, STypeRecord): return -1, "{} is not a valid structure".format(var) offset = symbol.type.get_ele_offset(attr) if offset is None: return -1, "{} has no attribute {}".format(var, attr) if offset != 0: res1 = context.gen_tmp() context.gen_ins("&", var, None, res1) res = context.gen_tmp() context.gen_ins('+', res1, offset, res) else: res = context.gen_tmp() context.gen_ins("&", var, None, res) res_type = STypePtr(symbol.type.get_ele_type(attr)) sym.set_attr('res', Operand(res, res_type))
def stmt_call(sym: SyntaxTree, context: SemanticContext): fname = sym.childs[1].sym.val symbol = context.lookup_sym(fname) if not symbol: return -1, "Function {} is not defined".format(fname) args = sym.childs[3].get_attr('args') res = Operand(context.gen_tmp(), symbol.type.ret_type) context.gen_ins('call', symbol, len(args), res) sym.set_attr('res', res) args_len = len(args) params_len = len(symbol.type.param_types) if args_len < params_len: return -1, "Too few arguments was given" if args_len > params_len: return -1, "Too many arguments was given" for i in range(args_len): if args[i].type != symbol.type.param_types[i] and\ deduce_type(args[i].type, symbol.type.param_types[i]) is None: args_str = ', '.join(map(lambda arg: str(arg.type), args)) params_str = ', '.join(map(str, symbol.type.param_types)) return -1, "Incompatible parameter types {}({}). expected {}({})".format( fname, args_str, fname, params_str)
def bool_expr4(sym: SyntaxTree, context: SemanticContext): start = context.addr sym.set_attr('start', start) res1 = sym.childs[0].get_attr('res') res2 = sym.childs[2].get_attr('res') relop = RELOPS[sym.childs[1].childs[0].sym.type] ins1 = context.gen_ins(relop, res1, res2, None) sym.set_attr('tl', [ins1]) ins2 = context.gen_ins('goto', None, None, None) sym.set_attr('fl', [ins2])
def arg_list_one(sym: SyntaxTree, context: SemanticContext): res = sym.childs[0].get_attr('res') sym.set_attr('args', [res])
def arg_list_empty(sym: SyntaxTree, context: SemanticContext): sym.set_attr('args', [])
def quad(sym: SyntaxTree, context: SemanticContext): sym.set_attr('quad', context.addr)
def bool_expr3(sym: SyntaxTree, context: SemanticContext): sym_h = sym.childs[1] htl = sym_h.get_attr('tl') hfl = sym_h.get_attr('fl') sym.set_attr('tl', hfl) sym.set_attr('fl', htl)
def arg_list(sym: SyntaxTree, context: SemanticContext): left = sym.childs[0] arg = sym.childs[2] args = left.get_attr('args') args += [arg.get_attr('res')] sym.set_attr('args', args)
def param_list_empty(sym: SyntaxTree, context: SemanticContext): sym.set_attr('params', [])