| #!/usr/bin/env python |
| # This Source Code Form is subject to the terms of the Mozilla Public |
| # License, v. 2.0. If a copy of the MPL was not distributed with this |
| # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
| |
| from collections import defaultdict |
| |
| # Simplified version of the body info. |
| class Body(dict): |
| def __init__(self, body): |
| self['BlockIdKind'] = body['BlockId']['Kind'] |
| if 'Variable' in body['BlockId']: |
| self['BlockName'] = body['BlockId']['Variable']['Name'][0].split("$")[-1] |
| loc = body['Location'] |
| self['LineRange'] = (loc[0]['Line'], loc[1]['Line']) |
| self['Filename'] = loc[0]['CacheString'] |
| self['Edges'] = body.get('PEdge', []) |
| self['Points'] = { i: p['Location']['Line'] for i, p in enumerate(body['PPoint'], 1) } |
| self['Index'] = body['Index'] |
| self['Variables'] = { x['Variable']['Name'][0].split("$")[-1]: x['Type'] for x in body['DefineVariable'] } |
| |
| # Indexes |
| self['Line2Points'] = defaultdict(list) |
| for point, line in self['Points'].items(): |
| self['Line2Points'][line].append(point) |
| self['SrcPoint2Edges'] = defaultdict(list) |
| for edge in self['Edges']: |
| src, dst = edge['Index'] |
| self['SrcPoint2Edges'][src].append(edge) |
| self['Line2Edges'] = defaultdict(list) |
| for (src, edges) in self['SrcPoint2Edges'].items(): |
| line = self['Points'][src] |
| self['Line2Edges'][line].extend(edges) |
| |
| def lookup(self, line=None, point=None): |
| if line is not None: |
| return edges_from_line(line) |
| if point is not None: |
| return edges_from_point(point) |
| |
| def edges_from_line(self, line): |
| return self['Line2Edges'][line] |
| |
| def edge_from_line(self, line): |
| edges = self.edges_from_line(line) |
| assert(len(edges) == 1) |
| return edges[0] |
| |
| def edges_from_point(self, point): |
| return self['SrcPoint2Edges'][point] |
| |
| def edge_from_point(self, point): |
| edges = self.edges_from_point(point) |
| assert(len(edges) == 1) |
| return edges[0] |
| |
| def assignment_point(self, varname): |
| for edge in self['Edges']: |
| if edge['Kind'] != 'Assign': |
| continue |
| dst = edge['Exp'][0] |
| if dst['Kind'] != 'Var': |
| continue |
| if dst['Variable']['Name'][0] == varname: |
| return edge['Index'][0] |
| raise Exception("assignment to variable %s not found" % varname) |
| |
| def assignment_line(self, varname): |
| return self['Points'][self.assignment_point(varname)] |