def enumToClause(enum, body): """Generate a For or If clause (with the specified body) that corresponds to an enumerator.""" ### Could use a little refactoring; break off AttrEnum stuff into separate method. if dha.isPosEnum(enum): if dha.isAttrEnum(enum): code = [dha.For(dha.PatMatch(dka.copy(enum.target), dha.selectorToAttr(enum.iter)), body)] else: code = [dha.For(dha.PatMatchName(dka.copy(enum.target), enum.iter), body)] else: if dha.isAttrEnum(enum): code = [dha.If([dha.CondCase(dha.BinOp(dha.patternToValue(enum.target), dha.NotIn(), dha.selectorToAttr(enum.iter)), body)])] else: code = [dha.If([dha.CondCase(dha.BinOp(dha.patternToValue(enum.target), dha.NotIn(), dha.Name(enum.iter)), body)])] return code
def genDSetBlock(self, enumnum, upvalexpr): compnode = self.compnode enumvars = self.info.enumvars enums = dka.copy(compnode.enums) conds = dka.copy(compnode.conds) st.cleanPatterns(enums) suffix = '_up' + str(enumnum) wittarget = dka.copy(enums[enumnum].target) upval = dka.copy(upvalexpr) upvalassign = dha.Assign(wittarget, upval) elt = du.genDTuple([s for s in enumvars]) if len(enums) > 1: maintenums = enums[:enumnum] + enums[enumnum+1:] maintcomp = dha.RelSetComp(elt, maintenums, conds, dka.Symtab()) maintupdate = dha.SetUpdate(self.diffsym, dha.UpUnionNS(), maintcomp) else: maintupdate = dha.SetUpdate(self.diffsym, dha.UpAddNS(), elt) code = [upvalassign, maintupdate] repldict = {s: dha.VSymbol(s.name + suffix) for s in enumvars} st.replaceSymbols(code, repldict) return code
def visit_SetUpdate(self, node): self.generic_visit(node) ssym = node.target if ismember(ssym): cont, val = matchpair(dka.copy(node.value)) dka.assertnodetype(cont, {dha.Name, dha.PatVar}) newnode = dha.SetUpdate(cont.id, dka.copy(node.op), val) return [newnode, node] return node
def helper(self, target, id): syms = st.gatherSymbols(target) newtarget = du.genDPatTuple([dha.PatVar(s, dha.P_UNKNOWN) for s in syms]) # Generate wildcard comprehension. elt = du.genDTuple([dha.Name(s) for s in syms]) enumtarget = dka.copy(target) st.cleanPatterns(enumtarget) WildcardFiller().run(enumtarget) enum = dha.RelEnum(enumtarget, id) comp = dha.RelSetComp(elt, [enum], [], dka.Symtab()) num = next(wildcard_uid) repldict = {s: dha.VSymbol(s.name + '_W' + num) for s in syms} st.replaceSymbols(comp, repldict) newid = dha.VSymbol(id.name + '_W' + num) invdef = dha.InvDef(newid, comp) ### Need a more robust way to do this part. oldccb = self.code_callback newccb = \ (lambda ccb: oldccb(ccb) + [invdef] if ccb is self.CCB_NORMAL or ccb is self.CCB_LOOP_ENTRY else []) return newtarget, newid, newccb
def visit_BinOp(self, node): self.generic_visit(node) op = node.op if dka.hasnodetype(op, {dha.In, dha.NotIn}): if dka.hasnodetype(node.right, dha.Name): ssym = node.right.id if not isfield(ssym): return node attr = ssym.attr cont, val = matchpair(node.left) has = dha.HasAttr(cont, attr) matches = dha.BinOp(dha.Attribute(dka.copy(cont), attr), dha.Eq(), val) cond = dha.BoolOp(dha.And(), [has, matches]) if dka.hasnodetype(op, dha.NotIn): cond = dha.Not(cond) return cond return node
def getAuxSym(self, ssym, mask, pat): """Retrieve the auxiliary map symbol for the given set symbol and mask.""" if (ssym, mask) in self.auxmaskmap: auxsym = self.auxmaskmap[(ssym, mask)] return auxsym else: auxsym = AuxMapSymbol(ssym, mask, dka.copy(pat)) self.auxmaskmap[(ssym, mask)] = auxsym return auxsym
def visit_SetCompDef(self, node): if node.id is not self.comp: return taginfo = self.comp.info.taginfo code = [] for tc in taginfo.tagcomps: newtc = dka.copy(tc) code.append(newtc) sym = tc.id sym.compdefs.add(newtc) self.tagcompsyms.append(sym) code.append(dka.copy(node)) return code
def visit_SetUpdate(self, node): isaddup = dha.isAddUpdate(node) if node.op.mod is not dha.UP_NONSTRICT: return has = dha.Match(dha.PatMatch(dha.valueToPattern(dka.copy(node.value)), dha.Name(node.target)), dka.Symtab()) if isaddup: test = dha.UnaryOp(dha.Not(), has) else: test = has newupdate = dka.copy(node) newupdate.op.mod = dha.UP_STRICT blk = dha.Block([newupdate]) return dha.If([dha.CondCase(test, blk)])
def visit_If(self, node): self.marker = node self.generic_visit(node) if not (len(node.cases) == 1 and dka.hasnodetype(node.cases[0], dha.ApplCase)): return case = node.cases[0] wipepat = wipePattern(dka.copy(case.target)) assign = dha.Assign(dka.copy(case.target), dka.copy(case.value)) bodycode = eliminatedecomp(assign, case.body.stmtlist) check = dha.CompatTuple(wipepat, dka.copy(case.value)) newcase = dha.CondCase(check, dha.Block(bodycode)) code = dha.If([newcase], node.orelse) return code
def patmatchToNormal(patmatch): target = patmatch.target if dka.hasnodetype(patmatch, PatMatchName): iter = Name(patmatch.id) elif dka.hasnodetype(patmatch, PatMatchLookup): iter = Lookup(patmatch.id, dka.copy(patmatch.key)) else: assert() return PatMatch(target, iter)
def visit_PatMatchName(self, node): self.generic_visit(node) id = node.iter info = id.info params = info.enumparams if len(params) > 0: paramtup = du.genDPatTuple([dha.genBoundVar(sym) for sym in params]) newtarget = dha.PatTuple([paramtup, dka.copy(node.target)]) node.target = newtarget else: pass
def patmatch_helper(self, patmatch): target = patmatch.target if dka.hasnodetype(patmatch, dha.PatMatchName): iter = dha.Name(patmatch.id) elif dka.hasnodetype(patmatch, dha.PatMatchLookup): iter = dha.Lookup(patmatch.id, dka.copy(patmatch.key)) else: assert () return target, iter
def visit_SetUpdate(self, node): ssym = node.target code = [node] for mask, auxsym in sorted(self.maskmap[ssym], key=lambda elem: elem[1].name): pat = auxsym.pat tupletree, bounds, unbounds = getDecomposition(pat) update = [dha.MapUpdate(auxsym, bounds, dka.copy(node.op), unbounds)] newcode = [dha.If([dha.ApplCase(tupletree, node.value, dha.Block(update))])] code.extend(newcode) return code
def visit_RelEnum(self, node): self.generic_visit(node) id = node.iter if not id.hasflag(dha.FLAG_INV): return info = id.info params = info.enumparams if len(params) > 0: paramtup = du.genDPatTuple([dha.genBoundVar(sym) for sym in params]) newtarget = dha.PatTuple([paramtup, dka.copy(node.target)]) node.target = newtarget else: pass
def visit_SetUpdate(self, node): self.generic_visit(node) ssym = node.target if isfield(ssym): attr = ssym.attr cont, val = matchpair(dka.copy(node.value)) dka.assertnodetype(cont, {dha.Name, dha.PatVar}) if dha.isAddUpdate(node): newnode = dha.AttrUpdate(cont.id, attr, val) else: newnode = dha.DelAttr(cont.id, attr) return [newnode, node] return node
def visit_SetUpdate(self, node): sym = node.target if hasattr(sym, 'needsmulti') and sym.needsmulti: self.multisyms.add(sym) else: return isaddup = dha.isAddUpdate(node) has = dha.Match(dha.PatMatchName(dha.valueToPattern(dka.copy(node.value)), node.target), dka.Symtab()) if isaddup: test1 = dha.UnaryOp(dha.Not(), has) inc1 = dha.RefUpdate(node.target, dka.copy(node.op), dka.copy(node.value)) inc2 = dka.copy(inc1) body = dha.Block([dka.copy(node), inc1]) orelse = dha.Block([inc2]) code = dha.If([dha.CondCase(test1, body)], orelse) else: test1 = has test2 = dha.BinOp(dha.GetRefCount(node.target, dka.copy(node.value)), dha.Eq(), dha.Num(0)) body2 = dha.Block([dka.copy(node)]) remif = dha.If([dha.CondCase(test2, body2)]) body1 = [dha.RefUpdate(node.target, dka.copy(node.op), dka.copy(node.value)), remif] # code = dha.If([dha.CondCase(test1, body1)]) code = body1 return code
def genHandler(self, setparam, isaddition): compnode = self.compnode code = [] # Compute differential assignment set. for i, enum in enumerate(compnode.enums): if enum.iter is setparam: code.extend(self.genDSetBlock(i)) # Compute change to result set. vartup = du.genDPatTuple([s for s in enumvars]) match = dha.PatMatchName(vartup, self.diffsym) resexpr = dka.copy(compnode.elt) # update = dha.SetUpdate(self.resmapsym, dha.UpAddNS(), resexpr) update = dha.SetUpdate(self.resmapsym, dha.UpAdd(), resexpr) loop = dha.For(match, dha.Block([update])) code.extend([loop])
def visit_InvDef(self, node): dka.assertnodetype(node.value, dha.RelSetComp) self.generic_visit(node) compnode = node.value info = node.id.info params = info.enumparams repldict = {sym: dha.VSymbol(sym.name + '_local') for sym in params} if len(params) > 0: paramtup = du.genDTuple([dha.Name(sym) for sym in params]) newelt = dha.Tuple([paramtup, dka.copy(compnode.elt)]) compnode.elt = newelt else: pass st.cleanPatterns(compnode) st.replaceSymbols(compnode, repldict)
def visit_PatWhile(self, node): # Transform the PatMatch node first. self.generic_visit(node) target, iter = self.patmatch_helper(node.match) mask = getPatMask(target) # If fully bound, replace with a condition While. if maskAllBound(mask): test = dha.BinOp(dha.patternToValue(target), dha.In(), iter) code = dha.While(test, node.body, node.orelse) # Otherwise, test non-emptiness and bind. else: elem = dha.UnaryOp(dha.Any(), iter) node.body.stmtlist[:0] = [dha.Assign(target, elem)] emptytest = dha.UnaryOp(dha.NotEmpty(), dka.copy(iter)) code = dha.While(emptytest, node.body, node.orelse) return code
def visit_For(self, node): self.generic_visit(node) match = node.match if dka.hasnodetype(match, dha.PatMatch): return ssym = match.id if isfield(ssym): attr = ssym.attr elif isfieldaux(ssym): attr = ssym.host.attr else: assert() if isforwardfield(ssym): cont, val = match.key, match.target has = dha.HasAttr(cont, attr) bind = dha.Assign(val, dha.Attribute(dka.copy(cont), attr)) newbody = dha.Block([bind] + node.body.stmtlist) return dha.If([dha.CondCase(has, newbody)], node.orelse) else: newmatch = dha.patmatchToNormal(node.match) return dha.For(newmatch, node.body, node.orelse)
def addCode(self, code): assert(isinstance(code, list)) incode = dka.copy(code) last = self.code_callback(self.CCB_UNKNOWN) newcode = last + incode self.code_callback = lambda ccb: dka.copy(newcode)
def visit_Name(self, node): if node.id in self.symmapping: return dka.copy(self.symmapping[node.id]) else: if self.strict: assert()
def setCode(self, code): assert(isinstance(code, list)) incode = dka.copy(code) self.code_callback = lambda ccb: dka.copy(incode)