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