@eagleoutice/flowr-dev
Version:
Static Dataflow Analyzer and Program Slicer for the R Programming Language
124 lines • 5.48 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NodeId = void 0;
exports.recoverName = recoverName;
exports.recoverContent = recoverContent;
const vertex_1 = require("../../../../../dataflow/graph/vertex");
const retriever_1 = require("../../../../retriever");
const identifier_1 = require("../../../../../dataflow/environments/identifier");
/**
* The type of the id assigned to each node. Branded to avoid problematic usages with other string or numeric types.
* The default ids are numeric, but we use a branded type to avoid confusion with other numeric types.
* Custom ids or scoped ids can be strings, but they will be normalized to numbers if they are numeric strings.
*/
/** whether the id starts as a number does, which `+id` alone does not tell: it turns a blank string into `0` */
function startsNumeric(id) {
const c = id.charCodeAt(0);
return c >= 48 && c <= 57 /* 0-9 */ || c === 45 /* - */ || c === 43 /* + */ || c === 46 /* . */;
}
exports.NodeId = {
name: 'NodeId',
/**
* Normalizes a node id by converting numeric strings to numbers.
* This allows us to use numeric ids without storing them as strings, while still allowing custom string ids if needed.
*/
normalize(id) {
if (typeof id === 'string' && startsNumeric(id)) {
const num = +id;
if (!Number.isNaN(num)) {
return num;
}
}
return id;
},
/**
* The prefix used for built-in function or operator ids.
*/
builtInPrefix: 'built-in:',
/**
* Checks if a given node id is a built-in function or operator id by checking if it is a string that starts with the built-in prefix.
* @see {@link toBuiltIn} - to convert a built-in function or operator name to a built-in id
* @see {@link fromBuiltIn} - to recover the built-in function or operator name from a built-in id
*/
isBuiltIn(id) {
return typeof id === 'string' && id.startsWith(exports.NodeId.builtInPrefix);
},
/**
* Converts a built-in function or operator name to a built-in id by prefixing it with the built-in prefix.
* @see {@link isBuiltIn} - to check if a given node id is a built-in function or operator id
* @see {@link fromBuiltIn} - to recover the built-in function or operator name from a built-in id
*/
toBuiltIn(name) {
return `built-in:${name}`;
},
/**
* The canonical `pkg:fn` identifier of a package's exported function (e.g. `ggplot2:ggplot`). The single
* source of this form: `Package.functionIdentifier` delegates here, and {@link fromPkgFn} wraps it.
*/
pkgFnName(pkg, fn) {
return `${pkg}:${fn}`;
},
/**
* The built-in id of a package's exported function, e.g. `fromPkgFn('ggplot2', 'ggplot')` yields
* `built-in:ggplot2:ggplot` -- {@link toBuiltIn} over the {@link pkgFnName} `pkg:fn` form.
*/
fromPkgFn(pkg, fn) {
return exports.NodeId.toBuiltIn(exports.NodeId.pkgFnName(pkg, fn));
},
/**
* Inverse of {@link fromPkgFn}: split a package-function built-in id (`built-in:pkg:fn`) into its `[pkg, fn]`
* parts, or `undefined` when `id` is not one (a non-builtin id, or a bare builtin without a package such as
* `built-in:print`). A package name never contains a `:`, so the first one separates it from the function.
*/
toPkgFn(id) {
if (!exports.NodeId.isBuiltIn(id)) {
return undefined;
}
const rest = exports.NodeId.fromBuiltIn(id);
const sep = rest.indexOf(':');
return sep > 0 ? [rest.slice(0, sep), rest.slice(sep + 1)] : undefined;
},
/**
* Converts a built-in function or operator name or id to a built-in id by prefixing it with the built-in prefix if it is not already a built-in id.
* This allows us to accept both built-in names and ids in contexts where we want to work with built-in ids.
*/
mapBuiltInProc(proc) {
const bi = 'builtin:';
return exports.NodeId.toBuiltIn(proc.startsWith(bi) ? proc.slice(bi.length) : proc);
},
/**
* Recovers the built-in function or operator name from a built-in id by removing the built-in prefix.
* @see {@link isBuiltIn} - to check if a given node id is a built-in function or operator id
* @see {@link toBuiltIn} - to convert a built-in function or operator name to a built-in id
*/
fromBuiltIn(id) {
return id.slice(builtInPrefixLength);
}
};
const builtInPrefixLength = exports.NodeId.builtInPrefix.length;
/**
* Recovers the lexeme of a {@link RNode|node} from its id in the {@link AstIdMap|id map}.
* @see {@link recoverContent} - to recover the content of a node
*/
function recoverName(id, idMap) {
return idMap?.get(id)?.lexeme;
}
/**
* Recovers the content of a {@link RNode|node} from its id in the {@link DataflowGraph|dataflow graph}.
*/
function recoverContent(id, graph) {
const vertex = graph.getVertex(id);
if (vertex && vertex_1.FunctionCallVertex.is(vertex) && vertex.name) {
return identifier_1.Identifier.toString(vertex.name);
}
const node = graph.idMap?.get(id);
if (node === undefined) {
return undefined;
}
const lexeme = node.lexeme ?? node.info.fullLexeme ?? '';
if (vertex_1.UseVertex.is(vertex)) {
return (0, retriever_1.removeRQuotes)(lexeme);
}
return lexeme;
}
//# sourceMappingURL=node-id.js.map