@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
115 lines • 4.55 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveSingleIndex = resolveSingleIndex;
exports.filterIndices = filterIndices;
exports.constructNestedAccess = constructNestedAccess;
exports.addSubIndicesToLeafIndices = addSubIndicesToLeafIndices;
const resolve_by_name_1 = require("../dataflow/environments/resolve-by-name");
const vertex_1 = require("../dataflow/graph/vertex");
const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
const type_1 = require("../r-bridge/lang-4.x/ast/model/type");
/**
* Resolves {@link accessedArg} in the {@link environment} and filters its indices according to {@link accessArg}.
*
* @param accessedArg - The argument to resolve
* @param accessArg - The argument which is used to filter the indices
* @param environment - The environment in which {@link accessedArg} is resolved
* @returns The filtered {@link ContainerIndicesCollection} of the resolved {@link accessedArg}
*/
function resolveSingleIndex(accessedArg, accessArg, environment) {
const definitions = (0, resolve_by_name_1.resolveByName)(accessedArg.lexeme, environment);
const indicesCollection = definitions?.flatMap(def => def?.indicesCollection ?? []);
const accessedIndicesCollection = filterIndices(indicesCollection, accessArg);
return accessedIndicesCollection;
}
/**
* Filters the single indices of the {@link indicesCollection} according to the lexeme of the {@link accessArg}.
*
* @param indicesCollection - The {@link ContainerIndicesCollection} to filter
* @param accessArg - The argument which is used to filter {@link indicesCollection}
* @returns The filtered copy of {@link indicesCollection}
*/
function filterIndices(indicesCollection, accessArg) {
let accessedIndicesCollection = undefined;
for (const indices of indicesCollection ?? []) {
const filteredIndices = indices.indices.filter(index => accessArg.lexeme === index.lexeme);
if (filteredIndices.length == 0) {
continue;
}
accessedIndicesCollection ??= [];
accessedIndicesCollection.push({
indices: filteredIndices,
isContainer: indices.isContainer
});
}
return accessedIndicesCollection;
}
/**
* Constructs the definition of a nested access.
*
* Example:
* ```r
* person$credentials$username
* ```
* would result in a list with the index `credentials`, which has the subIndex `username`.
*
* @param accessedArg - The top level argument that is accessed
* @param leafIndices - The index at the end of the nested access i.e. `c` in `a$b$c`.
* @returns The constructed nested access
*/
function constructNestedAccess(accessedArg, leafIndices) {
const accessed = accessedArg.accessed;
const accesses = accessedArg.access.filter(arg => arg !== r_function_call_1.EmptyArgument).map(arg => arg);
const indices = [];
for (const access of accesses) {
const newIndices = {
indices: [
{
lexeme: access.lexeme,
nodeId: access.info.id,
subIndices: [leafIndices],
}
],
isContainer: false,
};
if (accessed.type === type_1.RType.Access) {
const nestedIndices = constructNestedAccess(accessed, newIndices);
indices.push(...nestedIndices);
}
else {
indices.push(newIndices);
}
}
return indices;
}
/**
* Adds the passed list of {@link leafSubIndices} to the leaf (sub-)indices of {@link indicesCollection}.
*
* @param indicesCollection - Indices where to add the sub indices.
* @param leafSubIndices - Indices that are added to the leaf indices.
*/
function addSubIndicesToLeafIndices(indicesCollection, leafSubIndices) {
const result = [];
for (const indices of indicesCollection) {
const newIndices = [];
for (const index of indices.indices) {
let newSubIndices = [];
if ((0, vertex_1.isParentContainerIndex)(index)) {
newSubIndices = addSubIndicesToLeafIndices(index.subIndices, leafSubIndices);
}
else {
newSubIndices = leafSubIndices;
}
newIndices.push({
...index,
subIndices: newSubIndices,
});
}
result.push({
...indices,
indices: newIndices,
});
}
return result;
}
//# sourceMappingURL=list-access.js.map