def test_linkedlist(self): items = map(LinkableItem, range(5)) l = LinkedList(items) foo, bar, head, tail = map(LinkableItem, ["foo", "bar", "head", "tail"]) five = LinkableItem(5) l.insert_before(foo, items[2]) l.insert_after(bar, items[2]) l.insert_before(head, items[0]) l.append(five) l.insert_after(tail, five) l.remove(items[4]) expected = ["head", 0, 1, "foo", 2, "bar", 3, 5, "tail"] self.assertEqual(list(l), list(map(LinkableItem, expected)))
def test_linkedlist(self): items = [LinkableItem(i) for i in range(5)] l = LinkedList(items) foo, bar, head, tail = map(LinkableItem, ["foo", "bar", "head", "tail"]) five = LinkableItem(5) l.insert_before(foo, items[2]) l.insert_after(bar, items[2]) l.insert_before(head, items[0]) l.append(five) l.insert_after(tail, five) l.remove(items[4]) expected = ["head", 0, 1, "foo", 2, "bar", 3, 5, "tail"] expected = [LinkableItem(x) for x in expected] got = list(l) self.assertEqual(got, expected)
class Function(Value): """ Function consisting of basic blocks. Attributes ---------- module: Module Module owning the function name: name of the function args: [FuncArg] argnames: argument names ([str]) blocks: List of basic blocks in topological order startblock: Block The entry basic block exitblock: Block The last block in the list. This will only be the actual 'exit block' if the function is actually populated and has an exit block. values: { op_name: Operation } uses: { Operation : [Operation] } Operations that refer to this operation in their 'args' list temp: function, name -> tempname allocate a temporary name """ __slots__ = ('module', 'name', 'type', 'temp', 'blocks', 'blockmap', 'argnames', 'argdict', 'uses') def __init__(self, name, argnames, type, temper=None): self.module = None self.name = name self.type = type self.temp = temper or make_temper() self.blocks = LinkedList() self.blockmap = dict((block.name, block) for block in self.blocks) self.argnames = argnames self.argdict = {} self.uses = defaultdict(set) # reserve names for argname in argnames: self.temp(argname) @property def args(self): return [self.get_arg(argname) for argname in self.argnames] @property def startblock(self): return self.blocks.head @property def exitblock(self): return self.blocks.tail @property def ops(self): """Get a flat iterable of all Ops in this function""" return chain(*self.blocks) def new_block(self, label, ops=None, after=None): """Create a new block with name `label` and append it""" label = self.temp(label) return self.add_block(Block(label, self, ops), after) def add_arg(self, argname, argtype): self.argnames.append(argname) argtypes = tuple(self.type.argtypes) + (argtype,) self.type = types.Function(self.type.restype, argtypes, self.type.varargs) return self.get_arg(argname) def add_block(self, block, after=None): """Add a Block at the end, or after `after`""" assert block.name not in self.blockmap self.temp(block.name) # Make sure this name is taken if block.parent is None: block.parent = self else: assert block.parent is self self.blockmap[block.name] = block if after is None: self.blocks.append(block) else: self.blocks.insert_after(block, after) return block def get_block(self, label): return self.blockmap[label] def del_block(self, block): self.blocks.remove(block) del self.blockmap[block.name] def get_arg(self, argname): """Get argument as a Value""" if argname in self.argdict: return self.argdict[argname] idx = self.argnames.index(argname) type = self.type.argtypes[idx] arg = FuncArg(self, argname, type) self.argdict[argname] = arg return arg @property def result(self): """We are a first-class value...""" return self.name # ______________________________________________________________________ # uses def add_op(self, op): """ Register a new Op as part of the function. Does NOT insert the Op in any basic block """ _add_args(self.uses, op, op.args) def reset_uses(self): from pykit.analysis import defuse self.uses = defuse.defuse(self) def delete_all(self, delete): """ Delete all given operands, don't complain about uses from ops are that to be deleted. For example: %0 = myop(%arg0) %1 = add(%0, %arg1) delete = [%0, %1] """ for op in delete: op.set_args([]) for op in delete: op.delete() # ______________________________________________________________________ def __repr__(self): return "Function(%s)" % self.name
class Function(Value): """ Function consisting of basic blocks. Attributes ---------- module: Module Module owning the function name: name of the function args: [FuncArg] argnames: argument names ([str]) blocks: List of basic blocks in topological order startblock: Block The entry basic block exitblock: Block The last block in the list. This will only be the actual 'exit block' if the function is actually populated and has an exit block. values: { op_name: Operation } uses: { Operation : [Operation] } Operations that refer to this operation in their 'args' list temp: function, name -> tempname allocate a temporary name """ def __init__(self, name, argnames, type, temper=None): self.module = None self.name = name self.type = type self.temp = temper or make_temper() self.blocks = LinkedList() self.blockmap = dict((block.name, block) for block in self.blocks) self.argnames = argnames self.argdict = {} self.uses = defaultdict(set) # reserve names for argname in argnames: self.temp(argname) @property def args(self): return [self.get_arg(argname) for argname in self.argnames] @property def startblock(self): return self.blocks.head @property def exitblock(self): return self.blocks.tail @property def ops(self): """Get a flat iterable of all Ops in this function""" return chain(*self.blocks) def new_block(self, label, ops=None, after=None): """Create a new block with name `label` and append it""" assert label not in self.blockmap, label label = self.temp(label) return self.add_block(Block(label, self, ops), after) def add_block(self, block, after=None): """Add a Block at the end, or after `after`""" if block.parent is None: block.parent = self else: assert block.parent is self self.blockmap[block.name] = block if after is None: self.blocks.append(block) else: self.blocks.insert_after(block, after) return block def get_block(self, label): return self.blockmap[label] def del_block(self, block): self.blocks.remove(block) del self.blockmap[block.name] def get_arg(self, argname): """Get argument as a Value""" if argname in self.argdict: return self.argdict[argname] idx = self.argnames.index(argname) type = self.type.argtypes[idx] arg = FuncArg(self, argname, type) self.argdict[argname] = arg return arg @property def result(self): """We are a first-class value...""" return self.name # ______________________________________________________________________ # uses def add_op(self, op): """ Register a new Op as part of the function. Does NOT insert the Op in any basic block """ _add_args(self.uses, op, op.args) def reset_uses(self): from pykit.analysis import defuse self.uses = defuse.defuse(self) # ______________________________________________________________________ def __repr__(self): return "FunctionGraph(%s)" % self.blocks