def test_hashmap_builtin_pymethods(self): x = HashMap() x['a'] = 1 x[(1, 2)] = 'xyz' self.assertEqual({tup for tup in x.items()}, {('a', 1), ((1, 2), 'xyz')}) self.assertEqual(str(x), repr(x)) self.assertEqual(type(str(x)), type(repr(x)))
class FunType(Type): """ generated source for class FunType """ #@__init__.register(object, FunctionDef, Scope) def __init__(self, func=None, env=None): self.arrows = HashMap() self.cls = None self.defaultTypes = List() self.selfType = None self.func = None from pysonarsq.java.Analyzer import Analyzer super(FunType, self).__init__() self.env = None if isinstance(func, FunctionDef): self.func = func self.env = env elif isinstance(func, Type): from_, to = func, env self.addMapping(from_, to) self.getTable().addSuper(Analyzer.self.builtins.BaseFunction.getTable()) self.getTable().setPath(Analyzer.self.builtins.BaseFunction.getTable().getPath()) def addMapping(self, from_, to): if len(self.arrows) < 5: self.arrows[from_] = to oldArrows = self.arrows; self.arrows = self.compressArrows(self.arrows) if len(str(self)) > 900: self.arrows = oldArrows def getMapping(self, from_): return self.arrows.get(from_) def getReturnType(self): from pysonarsq.java.Analyzer import Analyzer if not _.isEmpty(self.arrows): #return self.arrows.values().iterator().next() return self.arrows.values()[0] else: return Analyzer.self.builtins.unknown def getFunc(self): return self.func def getEnv(self): return self.env def getCls(self): return self.cls def setCls(self, cls): self.cls = cls def getSelfType(self): return self.selfType def setSelfType(self, selfType): self.selfType = selfType def clearSelfType(self): self.selfType = None def getDefaultTypes(self): return self.defaultTypes def setDefaultTypes(self, defaultTypes): self.defaultTypes = defaultTypes def __eq__(self, other): if isinstance(other, (FunType, )): fo = other # cast in java code, should have been picked up by java2python return fo.getTable().getPath() == self.getTable().getPath() or self is other else: return False @classmethod def removeNoneReturn(cls, toType): from pysonarsq.java.Analyzer import Analyzer """ generated source for method removeNoneReturn """ if toType.isUnionType(): types.remove(Analyzer.self.builtins.Cont) return UnionType.newUnion(types) else: return toType def hashCode(self): return hash("FunType") def subsumed(self, type1, type2): return self.subsumedInner(type1, type2, TypeStack()) def subsumedInner(self, type1, type2, typeStack): from pysonarsq.java.Analyzer import Analyzer if typeStack.contains(type1, type2): return True if type1.isUnknownType() or type1 == Analyzer.self.builtins.None_ or type1 == type2: return True if isinstance(type1, (TupleType, )) and isinstance(type2, (TupleType, )): elems1 = type1.getElementTypes(); elems2 = type2.getElementTypes(); if len(elems1) == len(elems2): typeStack.push(type1, type2) for i in range(len(elems1)): if not self.subsumedInner(elems1[i], elems2[i], self.typeStack): self.typeStack.pop(type1, type2) return False return True return False def compressArrows(self, arrows): ret = HashMap() for e1 in arrows.items(): subsumed = False for e2 in arrows.items(): if e1 != e2 and self.subsumed(e1[0], e2[0]): subsumed = True break if not subsumed: ret[e1[0]] = e1[1] return ret def printType(self, ctr): from pysonarsq.java.Analyzer import Analyzer if _.isEmpty(self.arrows): return "? -> ?" sb = [] num = ctr.visit(self) if num is not None: sb.append("#") sb.append(num) else: newNum = ctr.push(self); i = 0; seen = set() for e in self.arrows.items(): as_ = e[0].printType(ctr) + " -> " + e[1].printType(ctr); if not as_ in seen: if i != 0: if Analyzer.self.multilineFunType: sb.append("\n| ") else: sb.append(" | ") sb.append(as_) seen.add(as_) i += 1 if ctr.isUsed(self): sb.append("=#") sb.append(newNum) sb.append(": ") ctr.pop(self) return ''.join(map(str,sb))
class FunType(Type): """ generated source for class FunType """ #@__init__.register(object, FunctionDef, Scope) def __init__(self, func=None, env=None): self.arrows = HashMap() self.cls = None self.defaultTypes = List() self.selfType = None self.func = None from pysonarsq.java.Analyzer import Analyzer super(FunType, self).__init__() self.env = None if isinstance(func, FunctionDef): self.func = func self.env = env elif isinstance(func, Type): from_, to = func, env self.addMapping(from_, to) self.getTable().addSuper( Analyzer.self.builtins.BaseFunction.getTable()) self.getTable().setPath( Analyzer.self.builtins.BaseFunction.getTable().getPath()) def addMapping(self, from_, to): if len(self.arrows) < 5: self.arrows[from_] = to oldArrows = self.arrows self.arrows = self.compressArrows(self.arrows) if len(str(self)) > 900: self.arrows = oldArrows def getMapping(self, from_): return self.arrows.get(from_) def getReturnType(self): from pysonarsq.java.Analyzer import Analyzer if not _.isEmpty(self.arrows): #return self.arrows.values().iterator().next() return self.arrows.values()[0] else: return Analyzer.self.builtins.unknown def getFunc(self): return self.func def getEnv(self): return self.env def getCls(self): return self.cls def setCls(self, cls): self.cls = cls def getSelfType(self): return self.selfType def setSelfType(self, selfType): self.selfType = selfType def clearSelfType(self): self.selfType = None def getDefaultTypes(self): return self.defaultTypes def setDefaultTypes(self, defaultTypes): self.defaultTypes = defaultTypes def __eq__(self, other): if isinstance(other, (FunType, )): fo = other # cast in java code, should have been picked up by java2python return fo.getTable().getPath() == self.getTable().getPath( ) or self is other else: return False @classmethod def removeNoneReturn(cls, toType): from pysonarsq.java.Analyzer import Analyzer """ generated source for method removeNoneReturn """ if toType.isUnionType(): types.remove(Analyzer.self.builtins.Cont) return UnionType.newUnion(types) else: return toType def hashCode(self): return hash("FunType") def subsumed(self, type1, type2): return self.subsumedInner(type1, type2, TypeStack()) def subsumedInner(self, type1, type2, typeStack): from pysonarsq.java.Analyzer import Analyzer if typeStack.contains(type1, type2): return True if type1.isUnknownType( ) or type1 == Analyzer.self.builtins.None_ or type1 == type2: return True if isinstance(type1, (TupleType, )) and isinstance(type2, (TupleType, )): elems1 = type1.getElementTypes() elems2 = type2.getElementTypes() if len(elems1) == len(elems2): typeStack.push(type1, type2) for i in range(len(elems1)): if not self.subsumedInner(elems1[i], elems2[i], self.typeStack): self.typeStack.pop(type1, type2) return False return True return False def compressArrows(self, arrows): ret = HashMap() for e1 in arrows.items(): subsumed = False for e2 in arrows.items(): if e1 != e2 and self.subsumed(e1[0], e2[0]): subsumed = True break if not subsumed: ret[e1[0]] = e1[1] return ret def printType(self, ctr): from pysonarsq.java.Analyzer import Analyzer if _.isEmpty(self.arrows): return "? -> ?" sb = [] num = ctr.visit(self) if num is not None: sb.append("#") sb.append(num) else: newNum = ctr.push(self) i = 0 seen = set() for e in self.arrows.items(): as_ = e[0].printType(ctr) + " -> " + e[1].printType(ctr) if not as_ in seen: if i != 0: if Analyzer.self.multilineFunType: sb.append("\n| ") else: sb.append(" | ") sb.append(as_) seen.add(as_) i += 1 if ctr.isUsed(self): sb.append("=#") sb.append(newNum) sb.append(": ") ctr.pop(self) return ''.join(map(str, sb))
class Scope(object): #@overloaded def __init__(self, parent=None, type_=None): # stays null for most scopes (mem opt) # all are non-null except global table # link to the closest non-class scope, for lifting functions out # .... if not hasattr(self, 'scopeType'): self.scopeType = None self.supers = List() self.globalNames = Set() self.type_ = None self.path = "" self.parent = parent self.setScopeType(type_) self.forwarding = None self.table = Map() if isinstance(parent, Scope) and type_ is None: s = parent # case of creating a new scope from an existing one if s.table is not None: self.table = HashMap() self.table.update(s.table) self.parent = s.parent self.setScopeType(s.scopeType) self.forwarding = s.forwarding self.supers = s.supers self.globalNames = s.globalNames self.type_ = s.type_ self.path = s.path elif parent is not None: self.parent = parent self.setScopeType(type_) if type_ == self.ScopeType.CLASS: self.forwarding = (None if parent is None else parent.getForwarding()) else: self.forwarding = self # erase and overwrite this to s's contents def overwrite(self, s): self.table = s.table self.parent = s.parent self.setScopeType(s.scopeType) self.forwarding = s.forwarding self.supers = s.supers self.globalNames = s.globalNames self.type_ = s.type_ self.path = s.path def copy(self): return Scope(self) #@overloaded def _merge(self, other): for e1 in self.getInternalTable().items(): b1 = e1[1] b2 = other.getInternalTable().get(e1[0]) # both branch have the same name, need merge if b2 is not None and b1 != b2: b1 += b2 for e2 in other.getInternalTable().items(): b1 = self.getInternalTable().get(e2[0]); b2 = e2[1] # both branch have the same name, need merge if b1 is None and b1 != b2: self.update(e2[0], b2) return self @classmethod def merge(cls, scope1, scope2=None): if scope2 is not None: return scope1._merge(scope2) else: ret = scope1.copy() ret.merge(scope2) return ret def setParent(self, parent): if parent is not None: self.parent = parent def getParent(self): return self.parent def getForwarding(self): if self.forwarding is not None: return self.forwarding else: return self def addSuper(self, sup): if self.supers is None: self.supers = ArrayList() self.supers.append(sup) def setScopeType(self, type_): if type_ is not None: self.scopeType = type_ def getScopeType(self): return self.scopeType def addGlobalName(self, name): if self.globalNames is None: self.globalNames = HashSet() self.globalNames.add(name) def isGlobalName(self, name): if self.globalNames is not None: return name in self.globalNames elif self.parent is not None: return self.parent.isGlobalName(name) else: return False def remove(self, _id): if self.table is not None: if _id in self.table: del self.table[_id] # create new binding and insert def insert(self, id, node, type_, kind): b = Binding(id, node, type_, kind) if type_.isModuleType(): b.setQname(type_.asModuleType().getQname()) else: b.setQname(self.extendPath(id)) self.update(id, b) # directly insert a given binding #@overloaded def update(self, id, bs): if hasattr(bs, '__len__'): self.getInternalTable()[id] = bs else: bs = [bs] self.getInternalTable()[id] = bs return bs def setPath(self, path): self.path = path def getPath(self): return self.path def getType(self): return self.type_ def setType(self, type_): self.type_ = type_ # # * Look up a name in the current symbol table only. Don't recurse on the # * parent table. # def lookupLocal(self, name): if self.table is None: return None else: return self.table.get(name) # # * Look up a name (String) in the current symbol table. If not found, # * recurse on the parent table. # def lookup(self, name): b = self.getModuleBindingIfGlobal(name) if b is not None: return b else: ent = self.lookupLocal(name) if ent is not None: return ent elif self.getParent() is not None: return self.getParent().lookup(name) else: return None # # * Look up a name in the module if it is declared as global, otherwise look # * it up locally. # def lookupScope(self, name): b = self.getModuleBindingIfGlobal(name) if b is not None: return b else: return self.lookupLocal(name) # # * Look up an attribute in the type hierarchy. Don't look at parent link, # * because the enclosing scope may not be a super class. The search is # * "depth first, left to right" as in Python's (old) multiple inheritance # * rule. The new MRO can be implemented, but will probably not introduce # * much difference. # looked = HashSet() # circularity prevention def lookupAttr(self, attr): if self in self.looked: return None else: b = self.lookupLocal(attr); if b is not None: return b else: if self.supers is not None and len(self.supers): self.looked.add(self) for p in self.supers: b = p.lookupAttr(attr) if b is not None: self.looked.remove(self) return b self.looked.remove(self) return None else: return None # # * Look for a binding named {@code name} and if found, return its type. # def lookupType(self, name): bs = self.lookup(name) if bs is None: return None else: return self.makeUnion(bs) # # * Look for a attribute named {@code attr} and if found, return its type. # def lookupAttrType(self, attr): bs = self.lookupAttr(attr) if bs is None: return None else: return self.makeUnion(bs) @classmethod def makeUnion(cls, bs): from pysonarsq.java.Analyzer import Analyzer t = Analyzer.self.builtins.unknown for b in bs: t = UnionType.union(t, b.getType()) return t # # * Find a symbol table of a certain type in the enclosing scopes. # def getSymtabOfType(self, type_): if self.scopeType == type_: return self elif self.parent is None: return None else: return self.parent.getSymtabOfType(type_) # # * Returns the global scope (i.e. the module scope for the current module). # def getGlobalTable(self): result = self.getSymtabOfType(self.ScopeType.MODULE) if result is not None: return result else: _.die("Couldn't find global table. Shouldn't happen") return self # # * If {@code name} is declared as a global, return the module binding. # def getModuleBindingIfGlobal(self, name): if self.isGlobalName(name): module_ = self.getGlobalTable(); if module_ != self: return module_.lookupLocal(name) return None def putAll(self, other): self.getInternalTable().update(other.getInternalTable()) def keySet(self): if self.table is not None: return self.table.items() else: return set() def values(self): if self.table is not None: ret = list() for bs in self.table.values(): ret += bs return ret return Collections.emptySet() def entrySet(self): if self.table is not None: return self.table.items() return set() def isEmpty(self): return self.table is None or self.table.isEmpty() def extendPath(self, name): name = _.moduleName(name) if self.path == "": return name return self.path + "." + name def getInternalTable(self): if self.table is None: self.table = HashMap() return self.table def __str__(self): return "<Scope:" + str(self.getScopeType()) + ":" + str("{}" if self.table is None else self.table.items()) + ">"
class Scope(object): #@overloaded def __init__(self, parent=None, type_=None): # stays null for most scopes (mem opt) # all are non-null except global table # link to the closest non-class scope, for lifting functions out # .... if not hasattr(self, 'scopeType'): self.scopeType = None self.supers = List() self.globalNames = Set() self.type_ = None self.path = "" self.parent = parent self.setScopeType(type_) self.forwarding = None self.table = Map() if isinstance(parent, Scope) and type_ is None: s = parent # case of creating a new scope from an existing one if s.table is not None: self.table = HashMap() self.table.update(s.table) self.parent = s.parent self.setScopeType(s.scopeType) self.forwarding = s.forwarding self.supers = s.supers self.globalNames = s.globalNames self.type_ = s.type_ self.path = s.path elif parent is not None: self.parent = parent self.setScopeType(type_) if type_ == self.ScopeType.CLASS: self.forwarding = (None if parent is None else parent.getForwarding()) else: self.forwarding = self # erase and overwrite this to s's contents def overwrite(self, s): self.table = s.table self.parent = s.parent self.setScopeType(s.scopeType) self.forwarding = s.forwarding self.supers = s.supers self.globalNames = s.globalNames self.type_ = s.type_ self.path = s.path def copy(self): return Scope(self) #@overloaded def _merge(self, other): for e1 in self.getInternalTable().items(): b1 = e1[1] b2 = other.getInternalTable().get(e1[0]) # both branch have the same name, need merge if b2 is not None and b1 != b2: b1 += b2 for e2 in other.getInternalTable().items(): b1 = self.getInternalTable().get(e2[0]) b2 = e2[1] # both branch have the same name, need merge if b1 is None and b1 != b2: self.update(e2[0], b2) return self @classmethod def merge(cls, scope1, scope2=None): if scope2 is not None: return scope1._merge(scope2) else: ret = scope1.copy() ret.merge(scope2) return ret def setParent(self, parent): if parent is not None: self.parent = parent def getParent(self): return self.parent def getForwarding(self): if self.forwarding is not None: return self.forwarding else: return self def addSuper(self, sup): if self.supers is None: self.supers = ArrayList() self.supers.append(sup) def setScopeType(self, type_): if type_ is not None: self.scopeType = type_ def getScopeType(self): return self.scopeType def addGlobalName(self, name): if self.globalNames is None: self.globalNames = HashSet() self.globalNames.add(name) def isGlobalName(self, name): if self.globalNames is not None: return name in self.globalNames elif self.parent is not None: return self.parent.isGlobalName(name) else: return False def remove(self, _id): if self.table is not None: if _id in self.table: del self.table[_id] # create new binding and insert def insert(self, id, node, type_, kind): b = Binding(id, node, type_, kind) if type_.isModuleType(): b.setQname(type_.asModuleType().getQname()) else: b.setQname(self.extendPath(id)) self.update(id, b) # directly insert a given binding #@overloaded def update(self, id, bs): if hasattr(bs, '__len__'): self.getInternalTable()[id] = bs else: bs = [bs] self.getInternalTable()[id] = bs return bs def setPath(self, path): self.path = path def getPath(self): return self.path def getType(self): return self.type_ def setType(self, type_): self.type_ = type_ # # * Look up a name in the current symbol table only. Don't recurse on the # * parent table. # def lookupLocal(self, name): if self.table is None: return None else: return self.table.get(name) # # * Look up a name (String) in the current symbol table. If not found, # * recurse on the parent table. # def lookup(self, name): b = self.getModuleBindingIfGlobal(name) if b is not None: return b else: ent = self.lookupLocal(name) if ent is not None: return ent elif self.getParent() is not None: return self.getParent().lookup(name) else: return None # # * Look up a name in the module if it is declared as global, otherwise look # * it up locally. # def lookupScope(self, name): b = self.getModuleBindingIfGlobal(name) if b is not None: return b else: return self.lookupLocal(name) # # * Look up an attribute in the type hierarchy. Don't look at parent link, # * because the enclosing scope may not be a super class. The search is # * "depth first, left to right" as in Python's (old) multiple inheritance # * rule. The new MRO can be implemented, but will probably not introduce # * much difference. # looked = HashSet() # circularity prevention def lookupAttr(self, attr): if self in self.looked: return None else: b = self.lookupLocal(attr) if b is not None: return b else: if self.supers is not None and len(self.supers): self.looked.add(self) for p in self.supers: b = p.lookupAttr(attr) if b is not None: self.looked.remove(self) return b self.looked.remove(self) return None else: return None # # * Look for a binding named {@code name} and if found, return its type. # def lookupType(self, name): bs = self.lookup(name) if bs is None: return None else: return self.makeUnion(bs) # # * Look for a attribute named {@code attr} and if found, return its type. # def lookupAttrType(self, attr): bs = self.lookupAttr(attr) if bs is None: return None else: return self.makeUnion(bs) @classmethod def makeUnion(cls, bs): from pysonarsq.java.Analyzer import Analyzer t = Analyzer.self.builtins.unknown for b in bs: t = UnionType.union(t, b.getType()) return t # # * Find a symbol table of a certain type in the enclosing scopes. # def getSymtabOfType(self, type_): if self.scopeType == type_: return self elif self.parent is None: return None else: return self.parent.getSymtabOfType(type_) # # * Returns the global scope (i.e. the module scope for the current module). # def getGlobalTable(self): result = self.getSymtabOfType(self.ScopeType.MODULE) if result is not None: return result else: _.die("Couldn't find global table. Shouldn't happen") return self # # * If {@code name} is declared as a global, return the module binding. # def getModuleBindingIfGlobal(self, name): if self.isGlobalName(name): module_ = self.getGlobalTable() if module_ != self: return module_.lookupLocal(name) return None def putAll(self, other): self.getInternalTable().update(other.getInternalTable()) def keySet(self): if self.table is not None: return self.table.items() else: return set() def values(self): if self.table is not None: ret = list() for bs in self.table.values(): ret += bs return ret return Collections.emptySet() def entrySet(self): if self.table is not None: return self.table.items() return set() def isEmpty(self): return self.table is None or self.table.isEmpty() def extendPath(self, name): name = _.moduleName(name) if self.path == "": return name return self.path + "." + name def getInternalTable(self): if self.table is None: self.table = HashMap() return self.table def __str__(self): return "<Scope:" + str(self.getScopeType()) + ":" + str( "{}" if self.table is None else self.table.items()) + ">"