Пример #1
0
    def setUp(self):
        super(SpMtxAggregate, self).setUp()

        from astvis import services
        core.registerServices(services.dataflow)
        core.registerServices(services.controlflow)
        core.registerServices(services.references)
        
        self.service = core.getService('DataflowService')
        subprogram = self.astModel.files[0].units[0].subprograms[0]
        cfService = core.getService('ControlflowService')
        self.flowModel = cfService.getModel(subprogram)
Пример #2
0
 def showObject(self, obj):
     self.model.clear()
     resolver = core.getService("ReferenceResolver")
     refs = resolver.getReferringObjects(obj).keys()
     for ref in refs:
         print ref
         self.model.append((str(ref),))
Пример #3
0
    def _notify(self, obj, event, args, dargs):
        """Notified when objects are added to or removed from diagram.

        @todo: reimplement calle[er]Names with ReferenceResolver"""
        
        LOG.debug('%s', obj)
        if event==ADDED_TO_DIAGRAM and args[0]==self:
            # add container connector
            if self.hasObject(obj.parent):
                connector = ContainerConnector(obj.parent, obj, self)
                self.addConnector(connector, connector)
            for child in obj.getChildren():
                if self.hasObject(child):
                    connector = ContainerConnector(obj, child, self)
                    self.addConnector(connector, connector)
            
            # get all calls/callers for obj and add connectors
            resolver = core.getService('ReferenceResolver')
            refObjs = resolver.getReferencedObjects(obj)            
            for refObj in refObjs:
                if not isinstance(refObj, (basic.ProgramUnit, basic.Subprogram)):
                    continue
                callee = refObj.astObject
                if callee and self.hasObject(callee):
                    connector = CallConnector(obj, callee, self)
                    self.addConnector(connector, connector)

            basicObj = obj.model.basicModel.getObjectByASTObject(obj)
            refObjs = resolver.getReferringObjects(basicObj).keys()
            for refObj in refObjs:
                caller = refObj
                if caller and self.hasObject(caller):
                    connector = CallConnector(caller, obj, self)
                    self.addConnector(connector, connector)
Пример #4
0
    def getLiveVariables(self, astNode, context=None):
        """For each basic block calculates (variable) uses that are reached from this code location.
        
        @return: (ins, outs) - uses on enter/leave of each basic block
        @rtype: (d, d) where d = {block: {name: set((block, indexInBlock))}}
        """
        
        astScope = astNode.model.getScope(astNode, False)
        # check for cached version
        if self._liveVariables.has_key(astScope):
            return self._liveVariables[astScope]

        # else calculate
        localEntities = []
        for decl in astScope.declarationBlock.statements:
            localEntities.extend(decl.entities)

        localNames = map(lambda e:e.name.lower(), localEntities)
        cfservice = core.getService('ControlflowService')
        flowModel = cfservice.getModel(astScope)

        ins = {} # { block: {name: set((block,indexInBlock,astNode))}}
        outs = {} # { block: {name: set((block,indexInBlock,astNode))}}

        # some help functions
        def IN(block, createNew=True):
            if not ins.has_key(block):
                if not createNew:
                    return None
                ins[block] = df.LiveVariableDict()
            return ins[block]

        def OUT(block):
            if not outs.has_key(block):
                outs[block] = df.LiveVariableDict()
            return outs[block]

        # start main loop which works until converging of IN/OUT states
        
        working = [] # blocks that have their IN redefined
        working.append(flowModel._endBlock)

        while working:
            block = working.pop()
            outUses = OUT(block)
            oldInUses = IN(block, False)
            inUses = self._backTransform(outUses, block)
            changed = (inUses != oldInUses)
            if changed:
                ins[block] = inUses
                # IN has changed since the last try
                #  add following basic blocks to the working set as their OUTs change
                for prevBlock in block.getPreviousBasicBlocks():
                    prevOutUses = OUT(prevBlock)
                    prevOutUses.update(inUses)
                    working.append(prevBlock)

        self._liveVariables[astScope] = (ins, outs)
        return ins, outs
Пример #5
0
 def showUsedDefinitions(self, target, context):
     "Show used (variable) definitions for the block (Use-Definition chain)."
     
     ocItem = target
     
     dfService = core.getService('DataflowService')
     usedDefs = dfService.getUsedDefinitions(ocItem.block)
     self.project.root.openUsedDefinitionsList(self, ocItem.block, usedDefs)
Пример #6
0
 def showActiveObjects(self, target, context):
     "Show active objects (used variables) in block."
     
     ocItem = target
     if ocItem.block!=None:
         block=ocItem.block
         service = core.getService('DataflowService')
         service.getActiveDefinitionsByBlock(block)
Пример #7
0
    def showBlockDefinitions(self, target, context):
        "Show definitions that reach the block output (in Reaching Definitions)."
        
        ocItem = target
        block = ocItem.block
        diagram = context
        
        dfService = core.getService('DataflowService')
        blockDefs = dfService.getBlockDefinitions(block)

        print blockDefs
Пример #8
0
    def _modifySubTags(self, obj, child, added, removed, isSource=False):

        if not isSource:
            # handle subtags
            subTags = self._subTags.get(obj, {})

            # added and removed contain tags that were changed in child

            for tag in added.copy():
                if not subTags.has_key(tag):
                    subTags[tag] = set()
                # add object as a child that contains the tag
                if not child in subTags[tag]:
                    if subTags[tag]:
                        added.remove(tag)
                    subTags[tag].add(child)
                else:
                    added.remove(tag)

            for tag in removed.copy():
                if subTags.has_key(tag):
                    # remove object as containing the tag
                    if child in subTags[tag]:
                        subTags[tag].remove(child)
                        if not subTags[tag]: # subtags empty
                            del subTags[tag]
                            if tag in self.get(obj, set()): # but tag is present
                                removed.remove(tag)
                        else:
                            removed.remove(tag)

            # now added and removed contain tags that were changed in obj (ie parent)
            #  and subTags are new obj sub-tags
            self._subTags[obj] = subTags

        # if it is callable follow call tags
        if isinstance(obj,ast.Subprogram):
            service = core.getService('ReferenceResolver')

            basicObj = obj.model.basicModel.getObjectByASTObject(obj)
            callers = service.getReferringObjects(basicObj)

            for caller,stmts in callers.items():
                for stmt in stmts:
                    self._modifyCallTags(stmt, obj, added.copy(), removed.copy(), isSource=True)

        # notify widgets
        event.manager.notifyObservers(self, event.PROPERTY_CHANGED,
                (None,event.PC_CHANGED,None,None), dargs={'key':obj})

        # handle parent
        if added or removed:
            if hasattr(obj,'parent') and obj.parent!=None:
                self._modifySubTags(obj.parent, obj, added, removed)
Пример #9
0
    def hideReferences(self, target, context):
        name = target
        service = core.getService('ReferenceResolver')
        astCode = self.flowModel.code
        basicModel = astCode.model.basicModel
        scope = basicModel.getObjectByASTObject(astCode)
        references = service.getReferringObjects(scope.variables[name])

        for ref in references.get(astCode, []):
            blocks = self.flowModel.findBlocksByObject(ref)
            for block in blocks:
                isAssign = ref.isAssignment()
                op = isAssign is True and 'write' or isAssign is False and 'read' or 'unknown'
                self._tagGraph.removeTag((scope.variables[name],op), block, ref)

        self._referenceTags.remove(name)
Пример #10
0
    def showOutDefinitions(self, target, context):
        "Show definitions that reach the block output (in Reaching Definitions)."
        
        ocItem = target
        block = ocItem.block
        code = block.model.code
        diagram = context
        
        dfService = core.getService('DataflowService')
        ins, outs = dfService.getReachingDefinitions(code)

        blockGraph = diagram._hgraph
        outDefs = set()
        for edge in blockGraph.outEdges[block]:
            for fromBlock, toBlock in blockGraph.edges[edge]:
                outDefs.update(outs[fromBlock].keys())
        print outDefs
Пример #11
0
    def showLVInDefinitions(self, target, context):
        "Show uses that the block input has (in Live Variables)."
        
        ocItem = target
        block = ocItem.block
        code = block.model.code
        diagram = context
        
        dfService = core.getService('DataflowService')
        ins, outs = dfService.getLiveVariables(code)

        blockGraph = diagram._hgraph
        inUses = set()
        for edge in blockGraph.inEdges[block]:
            for fromBlock, toBlock in blockGraph.edges[edge]:
                inUses.update(ins[toBlock].keys())
        print inUses
Пример #12
0
    def getReachingDefinitions(self, astNode, context=None):
        """For each basic block calculates (variable) definitions that reach this code location.
        
        @return: (ins, outs) - definitions on enter/leave of each basic block
        @rtype: (d, d) where d = {block: {name: set((block, indexInBlock))}}
        """
        
        astScope = astNode.model.getScope(astNode, False)
        # check for cached version
        if self._reachingDefinitions.has_key(astScope):
            return self._reachingDefinitions[astScope]

        # else calculate
        cfservice = core.getService('ControlflowService')
        flowModel = cfservice.getModel(astScope)

        rd = ReachingDefinitions(flowModel)
        self._reachingDefinitions[astScope] = (rd.ins, rd.outs)
        return rd.ins, rd.outs
Пример #13
0
    def _addObject(self, obj, refs, iParent, shown):
        
        data = factory.getRow((obj, refs))
        iObj = self.model.append(iParent, data)

        if obj in shown:
            return
        else:
            shown.add(obj)
        
        resolver = core.getService('ReferenceResolver')
        references = resolver.getReferringObjects(obj)

        if LOG.isEnabledFor(FINER):
            LOG.log(FINER, "Number of referring objects for %s: %d", obj, len(references.keys()))
        for refScope, refs in references.items():
            basicObj = refScope.model.basicModel.getObjectByASTObject(refScope)
            self._addObject(basicObj, refs, iObj, shown)

        self.view.expand_row(self.model.get_path(iObj), False)
Пример #14
0
    def _dragDataRecv(self, widget, context, x, y, data, info, timestamp):
        if self.flowModel != None:
            return
        
        LOG.debug("GTK DnD data_recv with info=%d"%info)
        if info==INFO_OBJECT_PATH.number:
            clazz, path = pickle.loads(data.data)
            if issubclass(clazz, ast.Code):
                # get canvas coordinates
                m = cairo.Matrix(*widget.matrix)
                m.invert()
                cx, cy = m.transform_point(x,y)
                # add item
                obj = self.project.astModel.getObjectByPath(path)
                cfservice = core.getService('ControlflowService')
                self.setModel(cfservice.getModel(obj), (cx,cy))

                context.drop_finish(True, timestamp)
            else:
                context.drop_finish(False, timestamp)                
        else:
            context.drop_finish(False, timestamp)
Пример #15
0
    def getActiveDefinitionsByBlock(self, block):
        """Return all references and calls in the control flow block.

        @type block: L{astvis.model.flow.Block}
        """
        
        # collect AST objects
        objs = []
        def cb(block):
            if isinstance(block, flow.BasicBlock):
                objs.extend(block.executions)

        block.itertree(cb)

        # find references in every AST object
        unknown = set()
        written = set()
        read = set()
        called = set()
        service = core.getService('ASTTreeWalker')
        for obj in objs:
            refs = service.getReferencesFrom(obj)
            for ref in refs:
                if isinstance(ref, ast.Statement) and ref.type=='call' \
                       or isinstance(ref, ast.Call):
                    called.add(ref.name.lower())
                elif ref.base==None:
                    isA = ref.isAssignment()
                    if isA is None:
                        unknown.add(ref.name.lower())
                    elif isA:
                        written.add(ref.name.lower())
                    else:
                        read.add(ref.name.lower())
        print 'called = ', called
        print 'unknown = ', unknown
        print 'written = ', written
        print 'read = ', read
Пример #16
0
    def _getDefinitions(self, execution):
        "Return names that are assigned values with ast object as value."
        astWalkerService = core.getService('ASTTreeWalker')

        defs = {}
        refs = astWalkerService.getReferencesFrom(execution)
        for ref in refs:
            if isinstance(ref, ast.Statement) and ref.type=='call' \
                   or isinstance(ref, ast.Call):
                pass # ignore calls
            elif isinstance(ref, ast.Reference) and ref.isFinalComponent():
                isA = ref.getPrimaryBase().isAssignment()
                if isA is None or isA: # consider unknown as write
                    # replace the previous definition
                    names = []
                    workRef = ref
                    while workRef!=None:
                        names.append(workRef.name.lower())
                        workRef = workRef.base
                    names.reverse()
                    assignName = tuple(names)
                    defs[assignName]=ref
        return defs
Пример #17
0
    def _backTransform(self, outUses, block):
        """Transform function for the 'live variables' algorithm.
        """

        if isinstance(block, flow.EndBlock):
            return self._backTransformWithEndBlock(outUses, block)

        astWalkerService = core.getService('ASTTreeWalker')

        inUses = df.LiveVariableDict(outUses)

        executions = list(block.executions)
        n = len(executions)
        executions.reverse()
        for i,execution in enumerate(executions):
            refs = astWalkerService.getReferencesFrom(execution)
            for ref in refs:
                if isinstance(ref, ast.Statement) and ref.type=='call' \
                       or isinstance(ref, ast.Call):
                    pass # ignore calls
                elif isinstance(ref, ast.Reference) and ref.isFinalComponent():
                    isA = ref.isAssignment()
                    name = self._getFullName(ref)
                    
                    # if assignment, remove all uses that match
                    if isA is None or isA==True: # consider unknown as write
                        if not ref.isPartial():
                            inUses.remove(name)

                    # if not assignment, add this use
                    if isA is None or isA==False: # consider unknown as read
                        # replace the previous use
                        loc = cf.ASTLocation(block,n-1-i,ref)
                        inUses.add(name,loc)


        return inUses
Пример #18
0
    def showObject(self, obj):
        self._clearModel()
    
        black = gtk.gdk.color_parse("black")
        green = gtk.gdk.color_parse("darkgreen")
        
        data = factory.getRow(obj)
        data[3] = black # self.root.diagram.hasObject(obj) and green or black
        iObj = self.model.append(None, data)
        
        resolver = core.getService('ASTTreeWalker')
        references = resolver.getReferencesFrom(obj)
        LOG.log(FINE, "Number of references for %s: %d" %(obj, len(references)))
        for ref in references:
            # generate row for subprograms only
            if not (isinstance(ref, ast.Statement) and ref.type=='call'\
                    or isinstance(ref, ast.Call)):
                continue
            
            astModel = ref.getModel()
            astScope = astModel.getScope(ref)
            basicModel = astModel.basicModel
            scope = basicModel.getObjectByASTObject(astScope)
            callee = basicModel.getObjectByName(ref.name.lower(), scope)
          
            if callee is not None:
                callObj = callee.astObject
                data = factory.getRow(callObj)
                color = black #self.root.diagram.hasObject(callObj) and green or black
                data[3] = color
            else:
                data = (ref.name, None, None, black)
            self.model.append(iObj, data)

        self.view.expand_row(self.model.get_path(iObj), False)        
        self.show()
Пример #19
0
 def showDefinedUses(self, target, context):
     ocItem = target
     
     dfService = core.getService('DataflowService')
     defdUses = dfService.getDefinedUses(ocItem.block)
     self.project.root.openUsedDefinitionsList(self, ocItem.block, defdUses)
Пример #20
0
 def _reloadService(name):
     import sys
     s=core.getService(name)
     reload(sys.modules[s.__module__])
     clazz=getattr(sys.modules[s.__module__], s.__class__.__name__)
     core.registerService(name, clazz())