def binop(blk, result, n): if result is None: result = self.new_register(n.type) a, blk = self.expr(blk, None, n.children[0]) b, blk = self.expr(blk, None, n.children[1]) blk.append(il.Instruction(op, a, b, result)) return result, blk
def not_op(self, blk, result, n): if result is None: result = self.new_register(n.type) a, a_out_blk = self.expr(blk, result, n.children[0]) #aoutblk has EQ a_out_blk.append(il.Instruction(il.OPS['NOT'], a, None, result)) return result, a_out_blk
def rewrite(self, fn_ref, rewrites): ## Implements function rewriting for closure creation old = self.module.lookup(fn_ref) new = self.push_function(old.name + '-closure', old.type(), old.params, list()) new.locals = old.locals def replace(operand): if isinstance(operand, il.FunctionRef) and operand in rewrites: return rewrites[operand] elif isinstance(operand, il.Register) and operand in rewrites: return rewrites[operand] elif isinstance(operand, il.Register) and operand.fn == old.ref(): return il.Register(operand.id, new.ref(), operand.type()) elif isinstance(operand, list): return [replace(inner) for inner in operand] return operand for old_blk in old.blocks: new_blk = new.new_block() for inst in old_blk.code: new_blk.append( il.Instruction(inst.op, replace(inst.a), replace(inst.b), replace(inst.result))) for idx, old_blk in enumerate(old.blocks): new_blk = new.blocks[idx] for link in old_blk.next: new_blk.link_to(new.blocks[link.target], link.link_type) self.pop_function() return new
def negate(self, blk, result, n): if result is None: result = self.new_register(n.type) a, blk = self.expr(blk, None, n.children[0]) blk.append( il.Instruction(il.OPS['SUB'], il.Constant(0, n.type), a, result)) return result, blk
def call(self, blk, result, n): if result is None: result = self.new_register(n.type) #fn, blk = ## TODO: populate these variables param_operands = list() ## TODO: POPULATE PARAMS blk.append(il.Instruction(il.OPS['CALL'], fn, param_operands, result)) return result, blk
def return_action(self, blk, n): a, blk = self.expr(blk, None, n.children[0]) if isinstance(a, il.FunctionRef): closure = self.module.lookup(a).closure(self.module, self.symbols) if len(closure.captured) > 0: a, blk = self.create_closures(blk, closure) blk.append(il.Instruction(il.OPS['RTRN'], a, None, None)) return blk
def function_action(self, blk, n): function_type = n.children[2].value name = n.children[0].value body = n.children[3] params = [ il.Param(id=idx, name=param.children[0].value, type=param.type) for idx, param in enumerate(n.children[1].children) ] free = freevars(n) # Push the function into the function list. # self.function() returns this function now. fn = self.push_function(name, function_type, params, free) # Add function reference to the symbol table of the calling function. self.symbols[fn.name] = fn.ref() # Push a new symbol table for the function. self.symbols = self.symbols.push() # Create a new block for the function. function_block = fn.new_block() for i, param in enumerate(params): # Create a local register for each parameter. param_register = fn.new_register(param.type) # Add the parameter to symbol_table. self.symbols[param.name] = param_register # Append PRM instructions to the function_block. # This instruction gives the id of each parameter which can be # referenced by the called function to lookup the parameter value # in the params of the function frame. function_block.append( il.Instruction(il.OPS['PRM'], il.Constant(param.id, param.type), None, param_register)) # Fill out instructions in the function_block. self.stmts(function_block, body) # Remove the function from the function list. # After this call, self.function() should not return this function. self.pop_function() return blk
def call(self, blk, result, n): function_name = n.children[0].value exprs = n.children[1] parameters = [] # Resolve each parameter for expr in exprs.children: r, _ = self.expr(blk, None, expr) parameters.append(r) if result is None: result = self.function().new_register(n.type) # SymbolTable returns the function reference. blk.append( il.Instruction(il.OPS['CALL'], self.symbols.get(function_name), parameters, result)) return result, blk
def create_closures(self, blk, closure): ## Implements function closure creation registers = list() rewrite = dict() for name, operand in closure.captured.iteritems(): if isinstance(operand, il.Closure): fn_ref = operand.fn operand, blk = self.create_closures(blk, operand) rewrite[fn_ref] = il.ClosureRegister(len(registers), fn_ref.type()) registers.append(operand) result = self.new_register(closure.fn.type()) rewrite[closure.fn] = il.ClosureRegister(len(registers), closure.fn.type()) for idx, reg in enumerate(registers): rewrite[reg] = il.ClosureRegister(idx, reg.type()) closure_code = self.rewrite(closure.fn, rewrite) blk.append( il.Instruction(il.OPS['CLOSURE'], closure_code.ref(), registers, result)) return result, blk
def function_action(self, blk, n): type = n.children[0].type name = n.children[0].value params = [ il.Param(id=idx, name=param.children[0].value, type=param.type) for idx, param in enumerate(n.children[1].children) ] body = n.children[3] free = freevars(n) fn = self.push_function(name, type, params, free) self.symbols[name] = fn.ref() self.symbols = self.symbols.push() entry_blk = fn.new_block() for idx, param in enumerate(fn.params): r = self.new_register(param.type) self.symbols[param.name] = r entry_blk.append(il.Instruction(il.OPS['PRM'], param, 0, r)) self.stmts(entry_blk, body) self.symbols = self.symbols.pop() self.pop_function() self.symbols[name] = fn.ref() return blk
def number(self, blk, result, n): const = il.Constant(n.value, n.type) if result is None: return const, blk blk.append(il.Instruction(il.OPS['IMM'], const, None, result)) return result, blk
def name(self, blk, result, n): if result is None: return self.symbols[n.value], blk blk.append( il.Instruction(il.OPS['MV'], self.symbols[n.value], None, result)) return result, blk
def print_action(self, blk, n): a, blk = self.expr(blk, None, n.children[0]) blk.append(il.Instruction(il.OPS['PRINT'], a, None, None)) return blk
def not_op(self, blk, result, n): if not result: result = self.new_register(n.type) a, blk = self.expr(blk, result, n.children[0]) blk.append(il.Instruction(il.OPS['NOT'], a, None, result)) return result, blk