UNPKG

@eagleoutice/flowr-dev

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

142 lines 5.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.withAppliedCds = withAppliedCds; exports.makeReferenceMaybe = makeReferenceMaybe; exports.makeAllMaybe = makeAllMaybe; exports.applyCdsToAllInGraphButConstants = applyCdsToAllInGraphButConstants; exports.applyCdToReferences = applyCdToReferences; const identifier_1 = require("./identifier"); const info_1 = require("../info"); const built_in_s_seven_dispatch_1 = require("../internal/process/functions/call/built-in/built-in-s-seven-dispatch"); const vertex_1 = require("../graph/vertex"); const resolve_helper_1 = require("./resolve-helper"); /** copy of the definition with the given cds attached, marking it as maybe */ function withAppliedCds(definition, defaultCd) { return { ...definition, cds: (0, info_1.withCds)(definition.cds, defaultCd) }; } /** replaces the definitions stored under the given key by copies carrying the additional cds */ function replaceDefinitions(env, key, toUpdate, defaultCd) { const defs = env.memory.get(key); if (defs?.some(d => toUpdate.has(d))) { env.writableMemory.set(key, defs.map(d => toUpdate.has(d) ? withAppliedCds(d, defaultCd) : d)); } env.cache?.delete(key); } /** * Attaches the given control dependencies to the definition made by `nodeId` within the environment chain. * Definitions of the same name made elsewhere survive whenever the conditional definition does not happen. * Copy-on-write: definitions are replaced, never mutated in place, so previously cloned * environments (e.g., snapshots stored in the dataflow graph) keep their state. */ function applyCdsToDefinitions(environments, name, type, definitions, nodeId, defaultCd) { const toUpdate = new Set(); for (const definition of definitions) { if (definition.nodeId === nodeId && definition.type !== identifier_1.ReferenceType.BuiltInFunction && definition.type !== identifier_1.ReferenceType.BuiltInConstant && (defaultCd !== undefined || definition.cds === undefined)) { toUpdate.add(definition); } } if (toUpdate.size === 0) { return; } const [plainName] = identifier_1.Identifier.toArray(name); const prefix = type === identifier_1.ReferenceType.S3MethodPrefix ? plainName + '.' : type === identifier_1.ReferenceType.S7MethodPrefix ? plainName + built_in_s_seven_dispatch_1.S7DispatchSeparator : undefined; let current = environments.current; while (!current.builtInEnv) { if (prefix === undefined) { replaceDefinitions(current, plainName, toUpdate, defaultCd); } else { for (const key of current.memory.keys()) { if (key.startsWith(prefix)) { replaceDefinitions(current, key, toUpdate, defaultCd); } } } current = current.parent; } } /** * Marks the reference as maybe (i.e., as controlled by a set of {@link IdentifierReference#cds|control dependencies}). * With `includeDefs`, the cds are also attached (copy-on-write) to the definition the reference * itself made, see {@link applyCdsToDefinitions}. */ function makeReferenceMaybe(ref, graph, environments, includeDefs, defaultCd = undefined) { if (includeDefs && ref.name) { const definitions = resolve_helper_1.Resolve.byNameAndType(ref.name, environments, ref.type); if (definitions && definitions.length > 0) { applyCdsToDefinitions(environments, ref.name, ref.type, definitions, ref.nodeId, defaultCd); } } const node = graph.getVertex(ref.nodeId); if (node) { if (node.cds) { (0, info_1.appendCds)(node.cds, defaultCd); } else { node.cds = defaultCd ? Array.from(defaultCd) : []; } } if (ref.cds) { if (defaultCd) { return { ...ref, cds: (0, info_1.withCds)(ref.cds, defaultCd) }; } } else { return { ...ref, cds: defaultCd ? Array.from(defaultCd) : [] }; } return ref; } /** * Marks all references as maybe (i.e., as controlled by a set of {@link IdentifierReference#cds|control dependencies}). * @see {@link makeReferenceMaybe} */ function makeAllMaybe(references, graph, environments, includeDefs, applyCds = undefined) { if (references === undefined || references.length === 0) { return []; } return references.map(ref => makeReferenceMaybe(ref, graph, environments, includeDefs, applyCds)); } /** * apply the given cds to all elements in the graph and also transform the given references similar to {@link makeAllMaybe}. */ function applyCdsToAllInGraphButConstants(graph, references, cds) { for (const [, v] of graph.vertices(true)) { if (vertex_1.ValueVertex.is(v)) { continue; } if (v.cds) { (0, info_1.appendCds)(v.cds, cds); } else { v.cds = Array.from(cds); } } for (const ref of references) { if (ref.cds) { (0, info_1.appendCds)(ref.cds, cds); } else { ref.cds = Array.from(cds); } } } /** * apply the given cds to all given references, but not to the graph. This is useful if we want to mark the references as maybe without marking all other nodes in the graph as maybe. */ function applyCdToReferences(references, cds) { if (cds.length === 0) { return; } for (const ref of references) { if (ref.cds) { (0, info_1.appendCds)(ref.cds, cds); } else { ref.cds = Array.from(cds); } } } //# sourceMappingURL=reference-to-maybe.js.map