#!/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 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)]