UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

82 lines 3.88 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CriteriaParseError = void 0; exports.slicingCriterionToId = slicingCriterionToId; exports.convertAllSlicingCriteriaToIds = convertAllSlicingCriteriaToIds; const log_1 = require("../../util/log"); const node_id_1 = require("../../r-bridge/lang-4.x/ast/model/processing/node-id"); const static_slicer_1 = require("../static/static-slicer"); const type_1 = require("../../r-bridge/lang-4.x/ast/model/type"); /** * Thrown if the given slicing criteria can not be found */ class CriteriaParseError extends Error { constructor(message) { super(message); this.name = 'CriteriaParseError'; } } exports.CriteriaParseError = CriteriaParseError; /** * Takes a criterion in the form of `line:column` or `line@variable-name` and returns the corresponding node id */ function slicingCriterionToId(criterion, idMap) { let resolved; if (criterion.startsWith('$')) { resolved = (0, node_id_1.normalizeIdToNumberIfPossible)(criterion.substring(1)); } else if (criterion.includes(':')) { const [line, column] = criterion.split(':').map(c => parseInt(c)); resolved = locationToId([line, column], idMap); } else if (criterion.includes('@')) { const [line, name] = criterion.split(/@(.*)/s); // only split at first occurrence resolved = conventionalCriteriaToId(parseInt(line), name, idMap); } if (resolved === undefined) { throw new CriteriaParseError(`invalid slicing criterion ${criterion}`); } return resolved; } function locationToId(location, dataflowIdMap) { let candidate; for (const [id, nodeInfo] of dataflowIdMap.entries()) { if (nodeInfo.location === undefined || nodeInfo.location[0] !== location[0] || nodeInfo.location[1] !== location[1]) { continue; // only consider those with position information } (0, log_1.expensiveTrace)(static_slicer_1.slicerLogger, () => `can resolve id ${id} (${JSON.stringify(nodeInfo.location)}) for location ${JSON.stringify(location)}`); // function calls have the same location as the symbol they refer to, so we need to prefer the function call if (candidate !== undefined && nodeInfo.type !== type_1.RType.FunctionCall || nodeInfo.type === type_1.RType.Argument || nodeInfo.type === type_1.RType.ExpressionList) { continue; } candidate = nodeInfo; } const id = candidate?.info.id; if (id) { (0, log_1.expensiveTrace)(static_slicer_1.slicerLogger, () => `resolve id ${id} (${JSON.stringify(candidate?.info)}) for location ${JSON.stringify(location)}`); } return id; } function conventionalCriteriaToId(line, name, dataflowIdMap) { let candidate; for (const [id, nodeInfo] of dataflowIdMap.entries()) { if (nodeInfo.location === undefined || nodeInfo.location[0] !== line || nodeInfo.lexeme !== name) { continue; } static_slicer_1.slicerLogger.trace(`can resolve id ${id} (${JSON.stringify(nodeInfo)}) for line ${line} and name ${name}`); // function calls have the same location as the symbol they refer to, so we need to prefer the function call if (candidate !== undefined && nodeInfo.type !== type_1.RType.FunctionCall || nodeInfo.type === type_1.RType.Argument || nodeInfo.type === type_1.RType.ExpressionList) { continue; } candidate = nodeInfo; } const id = candidate?.info.id; if (id) { static_slicer_1.slicerLogger.trace(`resolve id ${id} (${JSON.stringify(candidate?.info)}) for line ${line} and name ${name}`); } return id; } function convertAllSlicingCriteriaToIds(criteria, decorated) { return criteria.map(l => ({ criterion: l, id: slicingCriterionToId(l, decorated) })); } //# sourceMappingURL=parse.js.map