@eagleoutice/flowr 2.2.15 → 2.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -6
- package/benchmark/slicer.d.ts +3 -1
- package/benchmark/slicer.js +8 -5
- package/benchmark/summarizer/first-phase/process.d.ts +2 -1
- package/benchmark/summarizer/first-phase/process.js +2 -2
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +4 -1
- package/cli/benchmark-helper-app.d.ts +1 -0
- package/cli/benchmark-helper-app.js +7 -8
- package/cli/common/options.js +2 -0
- package/cli/export-quads-app.js +2 -1
- package/cli/flowr.js +58 -57
- package/cli/repl/commands/repl-cfg.js +13 -13
- package/cli/repl/commands/repl-commands.js +2 -2
- package/cli/repl/commands/repl-dataflow.js +10 -10
- package/cli/repl/commands/repl-execute.d.ts +2 -3
- package/cli/repl/commands/repl-execute.js +4 -4
- package/cli/repl/commands/repl-lineage.js +4 -4
- package/cli/repl/commands/repl-main.d.ts +12 -1
- package/cli/repl/commands/repl-normalize.js +6 -6
- package/cli/repl/commands/repl-parse.js +2 -2
- package/cli/repl/commands/repl-query.js +9 -9
- package/cli/repl/commands/repl-version.js +1 -1
- package/cli/repl/core.d.ts +5 -2
- package/cli/repl/core.js +10 -8
- package/cli/repl/server/connection.d.ts +3 -1
- package/cli/repl/server/connection.js +7 -5
- package/cli/repl/server/server.d.ts +3 -2
- package/cli/repl/server/server.js +4 -2
- package/cli/script-core/statistics-core.d.ts +2 -1
- package/cli/script-core/statistics-core.js +2 -2
- package/cli/script-core/statistics-helper-core.d.ts +2 -1
- package/cli/script-core/statistics-helper-core.js +5 -4
- package/cli/slicer-app.js +4 -2
- package/cli/statistics-app.js +2 -1
- package/cli/statistics-helper-app.js +2 -1
- package/config.d.ts +12 -10
- package/config.js +26 -42
- package/control-flow/cfg-dead-code.js +45 -2
- package/control-flow/cfg-simplification.d.ts +2 -0
- package/control-flow/control-flow-graph.d.ts +1 -0
- package/control-flow/control-flow-graph.js +4 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +5 -3
- package/control-flow/dfg-cfg-guided-visitor.js +15 -4
- package/control-flow/extract-cfg.d.ts +4 -2
- package/control-flow/extract-cfg.js +4 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +19 -1
- package/control-flow/semantic-cfg-guided-visitor.js +23 -3
- package/core/pipeline-executor.d.ts +4 -1
- package/core/pipeline-executor.js +6 -5
- package/core/steps/all/core/10-normalize.d.ts +2 -0
- package/core/steps/all/core/10-normalize.js +1 -1
- package/core/steps/all/core/11-normalize-tree-sitter.d.ts +2 -1
- package/core/steps/all/core/11-normalize-tree-sitter.js +2 -2
- package/core/steps/all/core/20-dataflow.d.ts +2 -1
- package/core/steps/all/core/20-dataflow.js +2 -2
- package/core/steps/all/static-slicing/00-slice.d.ts +2 -1
- package/core/steps/all/static-slicing/00-slice.js +2 -2
- package/core/steps/pipeline/default-pipelines.d.ts +32 -31
- package/core/steps/pipeline/default-pipelines.js +8 -8
- package/core/steps/pipeline-step.d.ts +2 -1
- package/dataflow/environments/built-in-config.d.ts +3 -3
- package/dataflow/environments/built-in.d.ts +7 -1
- package/dataflow/environments/built-in.js +2 -2
- package/dataflow/environments/default-builtin-config.js +4 -2
- package/dataflow/environments/define.d.ts +2 -1
- package/dataflow/environments/define.js +4 -5
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +29 -0
- package/dataflow/eval/resolve/alias-tracking.d.ts +7 -2
- package/dataflow/eval/resolve/alias-tracking.js +9 -6
- package/dataflow/eval/resolve/resolve-argument.d.ts +8 -0
- package/dataflow/eval/resolve/resolve-argument.js +118 -0
- package/dataflow/eval/resolve/resolve.d.ts +18 -15
- package/dataflow/eval/resolve/resolve.js +20 -18
- package/dataflow/eval/values/string/string-constants.d.ts +1 -1
- package/dataflow/eval/values/string/string-constants.js +7 -2
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +5 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +4 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +11 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +10 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +7 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +15 -15
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +1 -1
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/process-parameter.js +1 -1
- package/dataflow/origin/dfg-get-symbol-refs.d.ts +21 -0
- package/dataflow/origin/dfg-get-symbol-refs.js +50 -0
- package/dataflow/processor.d.ts +5 -0
- package/documentation/doc-util/doc-cfg.js +4 -3
- package/documentation/doc-util/doc-code.d.ts +1 -1
- package/documentation/doc-util/doc-dfg.js +3 -2
- package/documentation/doc-util/doc-functions.d.ts +24 -0
- package/documentation/doc-util/doc-functions.js +65 -0
- package/documentation/doc-util/doc-normalized-ast.js +3 -2
- package/documentation/doc-util/doc-print.d.ts +5 -0
- package/documentation/doc-util/doc-print.js +36 -0
- package/documentation/doc-util/doc-query.js +3 -2
- package/documentation/doc-util/doc-repl.js +2 -1
- package/documentation/doc-util/doc-search.js +3 -2
- package/documentation/doc-util/doc-types.d.ts +28 -6
- package/documentation/doc-util/doc-types.js +89 -45
- package/documentation/print-cfg-wiki.js +6 -7
- package/documentation/print-core-wiki.js +5 -5
- package/documentation/print-dataflow-graph-wiki.js +10 -10
- package/documentation/print-engines-wiki.js +1 -2
- package/documentation/print-faq-wiki.js +8 -2
- package/documentation/print-interface-wiki.js +1 -2
- package/documentation/print-linter-issue.d.ts +1 -0
- package/documentation/print-linter-issue.js +71 -0
- package/documentation/print-linter-wiki.js +219 -34
- package/documentation/print-linting-and-testing-wiki.js +2 -4
- package/documentation/print-normalized-ast-wiki.js +3 -3
- package/documentation/print-query-wiki.js +1 -2
- package/documentation/print-readme.js +24 -1
- package/documentation/print-search-wiki.js +1 -2
- package/linter/linter-executor.d.ts +3 -1
- package/linter/linter-executor.js +3 -2
- package/linter/linter-format.d.ts +67 -7
- package/linter/linter-format.js +12 -1
- package/linter/linter-rules.d.ts +155 -16
- package/linter/linter-rules.js +12 -4
- package/linter/linter-tags.d.ts +80 -0
- package/linter/linter-tags.js +85 -0
- package/linter/rules/absolute-path.d.ts +71 -0
- package/linter/rules/absolute-path.js +177 -0
- package/linter/rules/deprecated-functions.d.ts +43 -0
- package/linter/rules/deprecated-functions.js +58 -0
- package/linter/rules/{2-file-path-validity.d.ts → file-path-validity.d.ts} +16 -6
- package/linter/rules/{2-file-path-validity.js → file-path-validity.js} +21 -13
- package/linter/rules/naming-convention.d.ts +71 -0
- package/linter/rules/naming-convention.js +164 -0
- package/linter/rules/seeded-randomness.d.ts +65 -0
- package/linter/rules/seeded-randomness.js +122 -0
- package/linter/rules/unused-definition.d.ts +41 -0
- package/linter/rules/unused-definition.js +105 -0
- package/package.json +4 -1
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.js +2 -3
- package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +1 -1
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +2 -2
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -116
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.js +2 -2
- package/queries/catalog/linter-query/linter-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-format.js +16 -12
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
- package/queries/catalog/origin-query/origin-query-format.d.ts +1 -1
- package/queries/catalog/project-query/project-query-format.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +2 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.js +2 -2
- package/queries/catalog/search-query/search-query-format.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -2
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
- package/queries/query.d.ts +15 -15
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +4 -2
- package/r-bridge/lang-4.x/convert-values.js +2 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +3 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +7 -5
- package/r-bridge/shell.d.ts +3 -2
- package/r-bridge/shell.js +4 -5
- package/search/flowr-search-builder.d.ts +6 -2
- package/search/flowr-search-builder.js +7 -0
- package/search/flowr-search-filters.d.ts +32 -8
- package/search/flowr-search-filters.js +42 -15
- package/search/flowr-search.d.ts +4 -0
- package/search/search-executor/search-enrichers.d.ts +7 -3
- package/search/search-executor/search-enrichers.js +29 -20
- package/search/search-executor/search-generators.js +1 -1
- package/search/search-executor/search-transformer.d.ts +2 -0
- package/search/search-executor/search-transformer.js +10 -1
- package/slicing/static/static-slicer.d.ts +1 -1
- package/slicing/static/static-slicer.js +2 -3
- package/statistics/statistics.d.ts +3 -1
- package/statistics/statistics.js +5 -4
- package/util/containers.d.ts +12 -9
- package/util/containers.js +12 -9
- package/util/objects.d.ts +5 -4
- package/util/range.d.ts +5 -1
- package/util/range.js +11 -3
- package/util/text/strings.d.ts +6 -0
- package/util/text/strings.js +35 -0
- package/util/version.js +1 -1
- package/linter/rules/1-deprecated-functions.d.ts +0 -34
- package/linter/rules/1-deprecated-functions.js +0 -54
|
@@ -13,7 +13,6 @@ const built_in_assignment_1 = require("./built-in-assignment");
|
|
|
13
13
|
const identifier_1 = require("../../../../../environments/identifier");
|
|
14
14
|
const vertex_1 = require("../../../../../graph/vertex");
|
|
15
15
|
const containers_1 = require("../../../../../../util/containers");
|
|
16
|
-
const config_1 = require("../../../../../../config");
|
|
17
16
|
function tableAssignmentProcessor(name, args, rootId, data, outInfo) {
|
|
18
17
|
outInfo.definitionRootNodes.push(rootId);
|
|
19
18
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'table:assign' }).information;
|
|
@@ -30,8 +29,8 @@ function tableAssignmentProcessor(name, args, rootId, data, outInfo) {
|
|
|
30
29
|
* ```
|
|
31
30
|
*/
|
|
32
31
|
function processAccess(name, args, rootId, data, config) {
|
|
33
|
-
if (args.length <
|
|
34
|
-
logger_1.dataflowLogger.warn(`Access ${name.content} has less than
|
|
32
|
+
if (args.length < 1) {
|
|
33
|
+
logger_1.dataflowLogger.warn(`Access ${name.content} has less than 1 argument, skipping`);
|
|
35
34
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: config.forceArgs, origin: 'default' }).information;
|
|
36
35
|
}
|
|
37
36
|
const head = args[0];
|
|
@@ -113,9 +112,9 @@ function processNumberBasedAccess(data, name, args, rootId, config, head) {
|
|
|
113
112
|
data.environment.current.memory.set(':=', existing);
|
|
114
113
|
}
|
|
115
114
|
if (head.value && outInfo.definitionRootNodes.length > 0) {
|
|
116
|
-
(0, built_in_assignment_1.markAsAssignment)(fnCall.information, { type: identifier_1.ReferenceType.Variable, name: head.value.lexeme ?? '', nodeId: head.value.info.id, definedAt: rootId, controlDependencies: [] }, outInfo.definitionRootNodes, rootId);
|
|
115
|
+
(0, built_in_assignment_1.markAsAssignment)(fnCall.information, { type: identifier_1.ReferenceType.Variable, name: head.value.lexeme ?? '', nodeId: head.value.info.id, definedAt: rootId, controlDependencies: [] }, outInfo.definitionRootNodes, rootId, data.flowrConfig);
|
|
117
116
|
}
|
|
118
|
-
if (
|
|
117
|
+
if (data.flowrConfig.solver.pointerTracking) {
|
|
119
118
|
referenceAccessedIndices(args, data, fnCall, rootId, true);
|
|
120
119
|
}
|
|
121
120
|
return fnCall;
|
|
@@ -157,7 +156,7 @@ function processStringBasedAccess(args, data, name, rootId, config) {
|
|
|
157
156
|
const fnCall = (0, known_call_handling_1.processKnownFunctionCall)({ name, args: newArgs, rootId, data, forceArgs: config.forceArgs,
|
|
158
157
|
origin: 'builtin:access'
|
|
159
158
|
});
|
|
160
|
-
if (
|
|
159
|
+
if (data.flowrConfig.solver.pointerTracking) {
|
|
161
160
|
referenceAccessedIndices(newArgs, data, fnCall, rootId, false);
|
|
162
161
|
}
|
|
163
162
|
return fnCall;
|
|
@@ -57,7 +57,7 @@ function processApply(name, args, rootId, data, config) {
|
|
|
57
57
|
else if (val.type === type_1.RType.Symbol) {
|
|
58
58
|
functionId = val.info.id;
|
|
59
59
|
if (resolveValue) {
|
|
60
|
-
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(val.info.id, { environment: data.environment, idMap: data.completeAst.idMap }));
|
|
60
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(val.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.flowrConfig.solver.variables }));
|
|
61
61
|
if (resolved?.elements.length === 1 && resolved.elements[0].type === 'string') {
|
|
62
62
|
functionName = (0, r_value_1.isValue)(resolved.elements[0].value) ? resolved.elements[0].value.str : undefined;
|
|
63
63
|
}
|
|
@@ -10,6 +10,7 @@ import type { ContainerIndicesCollection } from '../../../../../graph/vertex';
|
|
|
10
10
|
import type { ForceArguments } from '../common';
|
|
11
11
|
import type { REnvironmentInformation } from '../../../../../environments/environment';
|
|
12
12
|
import type { DataflowGraph } from '../../../../../graph/graph';
|
|
13
|
+
import type { FlowrConfigOptions } from '../../../../../../config';
|
|
13
14
|
export interface AssignmentConfiguration extends ForceArguments {
|
|
14
15
|
readonly superAssignment?: boolean;
|
|
15
16
|
readonly swapSourceAndTarget?: boolean;
|
|
@@ -43,9 +44,10 @@ export interface AssignmentToSymbolParameters<OtherInfo> extends AssignmentConfi
|
|
|
43
44
|
* @param nodeToDefine - `x`
|
|
44
45
|
* @param sourceIds - `v`
|
|
45
46
|
* @param rootIdOfAssignment - `<-`
|
|
46
|
-
* @param config -
|
|
47
|
+
* @param config - The flowr config
|
|
48
|
+
* @param assignmentConfig - configuration for the assignment processing
|
|
47
49
|
*/
|
|
48
50
|
export declare function markAsAssignment(information: {
|
|
49
51
|
environment: REnvironmentInformation;
|
|
50
52
|
graph: DataflowGraph;
|
|
51
|
-
}, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId, config?: AssignmentConfiguration): void;
|
|
53
|
+
}, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId, config: FlowrConfigOptions, assignmentConfig?: AssignmentConfiguration): void;
|
|
@@ -17,7 +17,6 @@ const define_1 = require("../../../../../environments/define");
|
|
|
17
17
|
const edge_1 = require("../../../../../graph/edge");
|
|
18
18
|
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
19
19
|
const containers_1 = require("../../../../../../util/containers");
|
|
20
|
-
const config_1 = require("../../../../../../config");
|
|
21
20
|
const named_call_handling_1 = require("../named-call-handling");
|
|
22
21
|
const built_in_1 = require("../../../../../environments/built-in");
|
|
23
22
|
const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
|
|
@@ -216,10 +215,11 @@ function checkTargetReferenceType(source, sourceInfo) {
|
|
|
216
215
|
* @param nodeToDefine - `x`
|
|
217
216
|
* @param sourceIds - `v`
|
|
218
217
|
* @param rootIdOfAssignment - `<-`
|
|
219
|
-
* @param config -
|
|
218
|
+
* @param config - The flowr config
|
|
219
|
+
* @param assignmentConfig - configuration for the assignment processing
|
|
220
220
|
*/
|
|
221
|
-
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, config) {
|
|
222
|
-
if (
|
|
221
|
+
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, config, assignmentConfig) {
|
|
222
|
+
if (config.solver.pointerTracking) {
|
|
223
223
|
let indicesCollection = undefined;
|
|
224
224
|
if (sourceIds.length === 1) {
|
|
225
225
|
// support for tracking indices.
|
|
@@ -235,22 +235,22 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
|
|
|
235
235
|
}
|
|
236
236
|
}
|
|
237
237
|
// Indices defined by replacement operation e.g. $<-
|
|
238
|
-
if (
|
|
238
|
+
if (assignmentConfig?.indicesCollection !== undefined) {
|
|
239
239
|
// If there were indices stored in the vertex, then a container was defined
|
|
240
240
|
// and assigned to the index of another container e.g. a$b <- list(c = 1)
|
|
241
241
|
if (indicesCollection) {
|
|
242
|
-
indicesCollection = (0, containers_1.addSubIndicesToLeafIndices)(
|
|
242
|
+
indicesCollection = (0, containers_1.addSubIndicesToLeafIndices)(assignmentConfig.indicesCollection, indicesCollection);
|
|
243
243
|
}
|
|
244
244
|
else {
|
|
245
245
|
// No indices were defined for the vertex e.g. a$b <- 2
|
|
246
|
-
indicesCollection =
|
|
246
|
+
indicesCollection = assignmentConfig.indicesCollection;
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
nodeToDefine.indicesCollection ??= indicesCollection;
|
|
250
250
|
}
|
|
251
|
-
information.environment = (0, define_1.define)(nodeToDefine,
|
|
251
|
+
information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, config);
|
|
252
252
|
information.graph.setDefinitionOfVertex(nodeToDefine);
|
|
253
|
-
if (!
|
|
253
|
+
if (!assignmentConfig?.quoteSource) {
|
|
254
254
|
for (const sourceId of sourceIds) {
|
|
255
255
|
information.graph.addEdge(nodeToDefine, sourceId, edge_1.EdgeType.DefinedBy);
|
|
256
256
|
}
|
|
@@ -282,10 +282,10 @@ function processAssignmentToSymbol(config) {
|
|
|
282
282
|
{ nodeId: rootId, name: nameOfAssignmentFunction, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function },
|
|
283
283
|
...sourceArg.unknownReferences, ...sourceArg.in, ...targetArg.in.filter(i => i.nodeId !== target.info.id), ...readFromSourceWritten
|
|
284
284
|
];
|
|
285
|
-
information.environment = (0, overwrite_1.overwriteEnvironment)(
|
|
285
|
+
information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
|
|
286
286
|
// install assigned variables in environment
|
|
287
287
|
for (const write of writeNodes) {
|
|
288
|
-
markAsAssignment(information, write, [source.info.id], rootId, config);
|
|
288
|
+
markAsAssignment(information, write, [source.info.id], rootId, data.flowrConfig, config);
|
|
289
289
|
}
|
|
290
290
|
information.graph.addEdge(rootId, targetArg.entryPoint, edge_1.EdgeType.Returns);
|
|
291
291
|
if (quoteSource) {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.processEvalCall = processEvalCall;
|
|
4
4
|
const info_1 = require("../../../../../info");
|
|
5
|
-
const config_1 = require("../../../../../../config");
|
|
6
5
|
const known_call_handling_1 = require("../known-call-handling");
|
|
7
6
|
const retriever_1 = require("../../../../../../r-bridge/retriever");
|
|
8
7
|
const decorate_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate");
|
|
@@ -31,12 +30,12 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
31
30
|
if (config.includeFunctionCall) {
|
|
32
31
|
information.graph.addEdge(rootId, args[0].value.info.id, edge_1.EdgeType.Returns);
|
|
33
32
|
}
|
|
34
|
-
if (!
|
|
33
|
+
if (!data.flowrConfig.solver.evalStrings) {
|
|
35
34
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping eval call ${JSON.stringify(evalArgument)} (disabled in config file)`);
|
|
36
35
|
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
37
36
|
return information;
|
|
38
37
|
}
|
|
39
|
-
const code = resolveEvalToCode(evalArgument.value, data.environment, data.completeAst.idMap);
|
|
38
|
+
const code = resolveEvalToCode(evalArgument.value, data.environment, data.completeAst.idMap, data.flowrConfig);
|
|
40
39
|
if (code) {
|
|
41
40
|
const idGenerator = (0, decorate_1.sourcedDeterministicCountingIdGenerator)(name.lexeme + '::' + rootId, name.location);
|
|
42
41
|
data = {
|
|
@@ -68,7 +67,7 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
68
67
|
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
69
68
|
return information;
|
|
70
69
|
}
|
|
71
|
-
function resolveEvalToCode(evalArgument, env, idMap) {
|
|
70
|
+
function resolveEvalToCode(evalArgument, env, idMap, config) {
|
|
72
71
|
const val = evalArgument;
|
|
73
72
|
if (val.type === type_1.RType.FunctionCall && val.named && val.functionName.content === 'parse') {
|
|
74
73
|
const arg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'text');
|
|
@@ -80,13 +79,13 @@ function resolveEvalToCode(evalArgument, env, idMap) {
|
|
|
80
79
|
return [arg.value.content.str];
|
|
81
80
|
}
|
|
82
81
|
else if (arg.value?.type === type_1.RType.Symbol) {
|
|
83
|
-
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(arg.value.info.id, { environment: env, idMap: idMap }));
|
|
82
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(arg.value.info.id, { environment: env, idMap: idMap, resolve: config.solver.variables }));
|
|
84
83
|
if (resolved) {
|
|
85
84
|
return (0, string_constants_1.collectStrings)(resolved.elements);
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
87
|
else if (arg.value?.type === type_1.RType.FunctionCall && arg.value.named && ['paste', 'paste0'].includes(arg.value.functionName.content)) {
|
|
89
|
-
return handlePaste(arg.value.arguments, env, idMap, arg.value.functionName.content === 'paste' ? [' '] : ['']);
|
|
88
|
+
return handlePaste(config, arg.value.arguments, env, idMap, arg.value.functionName.content === 'paste' ? [' '] : ['']);
|
|
90
89
|
}
|
|
91
90
|
return undefined;
|
|
92
91
|
}
|
|
@@ -99,7 +98,7 @@ function resolveEvalToCode(evalArgument, env, idMap) {
|
|
|
99
98
|
return undefined;
|
|
100
99
|
}
|
|
101
100
|
}
|
|
102
|
-
function getAsString(val, env, idMap) {
|
|
101
|
+
function getAsString(config, val, env, idMap) {
|
|
103
102
|
if (!val) {
|
|
104
103
|
return undefined;
|
|
105
104
|
}
|
|
@@ -107,17 +106,17 @@ function getAsString(val, env, idMap) {
|
|
|
107
106
|
return [val.content.str];
|
|
108
107
|
}
|
|
109
108
|
else if (val.type === type_1.RType.Symbol) {
|
|
110
|
-
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(val.info.id, { environment: env, idMap: idMap }));
|
|
109
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(val.info.id, { environment: env, idMap: idMap, resolve: config.solver.variables }));
|
|
111
110
|
if (resolved) {
|
|
112
111
|
return (0, string_constants_1.collectStrings)(resolved.elements);
|
|
113
112
|
}
|
|
114
113
|
}
|
|
115
114
|
return undefined;
|
|
116
115
|
}
|
|
117
|
-
function handlePaste(args, env, idMap, sepDefault) {
|
|
116
|
+
function handlePaste(config, args, env, idMap, sepDefault) {
|
|
118
117
|
const sepArg = args.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'sep');
|
|
119
118
|
if (sepArg) {
|
|
120
|
-
const res = sepArg !== r_function_call_1.EmptyArgument && sepArg.value ? getAsString(sepArg.value, env, idMap) : undefined;
|
|
119
|
+
const res = sepArg !== r_function_call_1.EmptyArgument && sepArg.value ? getAsString(config, sepArg.value, env, idMap) : undefined;
|
|
121
120
|
if (!res) {
|
|
122
121
|
// sep not resolvable clearly / unknown
|
|
123
122
|
return undefined;
|
|
@@ -126,7 +125,7 @@ function handlePaste(args, env, idMap, sepDefault) {
|
|
|
126
125
|
}
|
|
127
126
|
const allArgs = args
|
|
128
127
|
.filter(v => v !== r_function_call_1.EmptyArgument && v.name?.content !== 'sep' && v.value)
|
|
129
|
-
.map(v => getAsString(v.value, env, idMap));
|
|
128
|
+
.map(v => getAsString(config, v.value, env, idMap));
|
|
130
129
|
if (allArgs.some(assert_1.isUndefined)) {
|
|
131
130
|
return undefined;
|
|
132
131
|
}
|
|
@@ -18,6 +18,7 @@ const built_in_1 = require("../../../../../environments/built-in");
|
|
|
18
18
|
const overwrite_1 = require("../../../../../environments/overwrite");
|
|
19
19
|
const logger_1 = require("../../../../../logger");
|
|
20
20
|
const log_1 = require("../../../../../../util/log");
|
|
21
|
+
const remove_1 = require("../../../../../environments/remove");
|
|
21
22
|
const dotDotDotAccess = /^\.\.\d+$/;
|
|
22
23
|
function linkReadNameToWriteIfPossible(read, environments, listEnvironments, remainingRead, nextGraph) {
|
|
23
24
|
const readName = read.name && dotDotDotAccess.test(read.name) ? '...' : read.name;
|
|
@@ -53,7 +54,7 @@ function processNextExpression(currentElement, environment, listEnvironments, re
|
|
|
53
54
|
linkReadNameToWriteIfPossible(read, environment, listEnvironments, remainingRead, nextGraph);
|
|
54
55
|
}
|
|
55
56
|
}
|
|
56
|
-
function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextGraph) {
|
|
57
|
+
function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextGraph, localDefs) {
|
|
57
58
|
for (const { functionCall, called } of calledEnvs) {
|
|
58
59
|
const callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
|
|
59
60
|
for (const calledFn of called) {
|
|
@@ -79,6 +80,10 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
|
|
|
79
80
|
}
|
|
80
81
|
if (hasUpdate) {
|
|
81
82
|
// we update all definitions to be linked with the corresponding function call
|
|
83
|
+
// we, however, have to ignore expression-local writes!
|
|
84
|
+
if (localDefs.length > 0) {
|
|
85
|
+
environment = (0, remove_1.removeAll)(localDefs, environment);
|
|
86
|
+
}
|
|
82
87
|
inputEnvironment = (0, overwrite_1.overwriteEnvironment)(inputEnvironment, environment, callDependencies);
|
|
83
88
|
}
|
|
84
89
|
}
|
|
@@ -124,7 +129,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
124
129
|
environment = exitPoints.length > 0 ? (0, overwrite_1.overwriteEnvironment)(environment, processed.environment) : processed.environment;
|
|
125
130
|
const calledEnvs = (0, linker_1.linkFunctionCalls)(nextGraph, data.completeAst.idMap, processed.graph);
|
|
126
131
|
// if the called function has global redefinitions, we have to keep them within our environment
|
|
127
|
-
environment = updateSideEffectsForCalledFunctions(calledEnvs, environment, nextGraph);
|
|
132
|
+
environment = updateSideEffectsForCalledFunctions(calledEnvs, environment, nextGraph, processed.out);
|
|
128
133
|
for (const { nodeId } of processed.out) {
|
|
129
134
|
listEnvironments.add(nodeId);
|
|
130
135
|
}
|
|
@@ -35,7 +35,7 @@ function processForLoop(name, args, rootId, data) {
|
|
|
35
35
|
const headGraph = variable.graph.mergeWith(vector.graph);
|
|
36
36
|
const writtenVariable = [...variable.unknownReferences, ...variable.in];
|
|
37
37
|
for (const write of writtenVariable) {
|
|
38
|
-
headEnvironments = (0, define_1.define)({ ...write, definedAt: name.info.id, type: identifier_1.ReferenceType.Variable }, false, headEnvironments);
|
|
38
|
+
headEnvironments = (0, define_1.define)({ ...write, definedAt: name.info.id, type: identifier_1.ReferenceType.Variable }, false, headEnvironments, data.flowrConfig);
|
|
39
39
|
}
|
|
40
40
|
data = { ...data, environment: headEnvironments };
|
|
41
41
|
const body = (0, processor_1.processDataflowFor)(bodyArg, data);
|
|
@@ -60,8 +60,7 @@ function processForLoop(name, args, rootId, data) {
|
|
|
60
60
|
});
|
|
61
61
|
/* mark the last argument as nse */
|
|
62
62
|
nextGraph.addEdge(rootId, body.entryPoint, edge_1.EdgeType.NonStandardEvaluation);
|
|
63
|
-
// as the for-loop always evaluates its
|
|
64
|
-
nextGraph.addEdge(name.info.id, variable.entryPoint, edge_1.EdgeType.Reads);
|
|
63
|
+
// as the for-loop always evaluates its condition
|
|
65
64
|
nextGraph.addEdge(name.info.id, vector.entryPoint, edge_1.EdgeType.Reads);
|
|
66
65
|
return {
|
|
67
66
|
unknownReferences: [],
|
|
@@ -34,7 +34,7 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
34
34
|
let then;
|
|
35
35
|
let makeThenMaybe = false;
|
|
36
36
|
// we should defer this to the abstract interpretation
|
|
37
|
-
const values = (0, alias_tracking_1.resolveIdToValue)(condArg?.info.id, { environment: data.environment, idMap: data.completeAst.idMap });
|
|
37
|
+
const values = (0, alias_tracking_1.resolveIdToValue)(condArg?.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.flowrConfig.solver.variables });
|
|
38
38
|
const conditionIsAlwaysFalse = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === false) ?? false;
|
|
39
39
|
const conditionIsAlwaysTrue = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === true) ?? false;
|
|
40
40
|
if (!conditionIsAlwaysFalse) {
|
|
@@ -16,7 +16,7 @@ const containers_1 = require("../../../../../../util/containers");
|
|
|
16
16
|
*/
|
|
17
17
|
function processList(name, args, rootId, data) {
|
|
18
18
|
const fnCall = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'builtin:list' });
|
|
19
|
-
if (!
|
|
19
|
+
if (!data.flowrConfig.solver.pointerTracking) {
|
|
20
20
|
return fnCall.information;
|
|
21
21
|
}
|
|
22
22
|
const listArgs = [];
|
|
@@ -67,7 +67,7 @@ function processList(name, args, rootId, data) {
|
|
|
67
67
|
}
|
|
68
68
|
listArgs.push(newIndex);
|
|
69
69
|
}
|
|
70
|
-
if ((0, config_1.isOverPointerAnalysisThreshold)(listArgs.length)) {
|
|
70
|
+
if ((0, config_1.isOverPointerAnalysisThreshold)(data.flowrConfig, listArgs.length)) {
|
|
71
71
|
return fnCall.information;
|
|
72
72
|
}
|
|
73
73
|
const indices = {
|
|
@@ -12,7 +12,6 @@ const graph_1 = require("../../../../../graph/graph");
|
|
|
12
12
|
const edge_1 = require("../../../../../graph/edge");
|
|
13
13
|
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
14
14
|
const containers_1 = require("../../../../../../util/containers");
|
|
15
|
-
const config_1 = require("../../../../../../config");
|
|
16
15
|
const unpack_argument_1 = require("../argument/unpack-argument");
|
|
17
16
|
const built_in_access_1 = require("./built-in-access");
|
|
18
17
|
const built_in_1 = require("../../../../../environments/built-in");
|
|
@@ -28,7 +27,7 @@ args, rootId, data, config) {
|
|
|
28
27
|
/* we only get here if <-, <<-, ... or whatever is part of the replacement is not overwritten */
|
|
29
28
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Replacement ${name.content} with ${JSON.stringify(args)}, processing`);
|
|
30
29
|
let indices = config.activeIndices;
|
|
31
|
-
if (
|
|
30
|
+
if (data.flowrConfig.solver.pointerTracking) {
|
|
32
31
|
indices ??= constructAccessedIndices(name.content, args);
|
|
33
32
|
}
|
|
34
33
|
/* we assign the first argument by the last for now and maybe mark as maybe!, we can keep the symbol as we now know we have an assignment */
|
|
@@ -79,7 +78,7 @@ args, rootId, data, config) {
|
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
const fa = (0, unpack_argument_1.unpackArgument)(args[0]);
|
|
82
|
-
if (!
|
|
81
|
+
if (!data.flowrConfig.solver.pointerTracking && fa) {
|
|
83
82
|
res = {
|
|
84
83
|
...res,
|
|
85
84
|
in: [...res.in, { name: fa.lexeme, type: identifier_1.ReferenceType.Variable, nodeId: fa.info.id, controlDependencies: data.controlDependencies }]
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type DataflowProcessorInformation } from '../../../../../processor';
|
|
2
2
|
import type { DataflowInformation } from '../../../../../info';
|
|
3
|
+
import type { FlowrLaxSourcingOptions } from '../../../../../../config';
|
|
3
4
|
import { InferWorkingDirectory } from '../../../../../../config';
|
|
4
5
|
import type { RParseRequest, RParseRequestProvider } from '../../../../../../r-bridge/retriever';
|
|
5
6
|
import type { IdGenerator, ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
@@ -11,10 +12,11 @@ export declare function setSourceProvider(provider: RParseRequestProvider): void
|
|
|
11
12
|
export declare function inferWdFromScript(option: InferWorkingDirectory, referenceChain: readonly RParseRequest[]): string[];
|
|
12
13
|
/**
|
|
13
14
|
* Tries to find sourced by a source request and returns the first path that exists
|
|
14
|
-
* @param
|
|
15
|
-
* @param
|
|
15
|
+
* @param resolveSource - options for lax file sourcing
|
|
16
|
+
* @param seed - the path originally requested in the `source` call
|
|
17
|
+
* @param data - more information on the loading context
|
|
16
18
|
*/
|
|
17
|
-
export declare function findSource(seed: string, data: {
|
|
19
|
+
export declare function findSource(resolveSource: FlowrLaxSourcingOptions | undefined, seed: string, data: {
|
|
18
20
|
referenceChain: readonly RParseRequest[];
|
|
19
21
|
}): string[] | undefined;
|
|
20
22
|
export declare function processSourceCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
|
|
@@ -68,18 +68,18 @@ function applyReplacements(path, replacements) {
|
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* Tries to find sourced by a source request and returns the first path that exists
|
|
71
|
-
* @param
|
|
72
|
-
* @param
|
|
71
|
+
* @param resolveSource - options for lax file sourcing
|
|
72
|
+
* @param seed - the path originally requested in the `source` call
|
|
73
|
+
* @param data - more information on the loading context
|
|
73
74
|
*/
|
|
74
|
-
function findSource(seed, data) {
|
|
75
|
-
const
|
|
76
|
-
const capitalization = config?.ignoreCapitalization ?? false;
|
|
75
|
+
function findSource(resolveSource, seed, data) {
|
|
76
|
+
const capitalization = resolveSource?.ignoreCapitalization ?? false;
|
|
77
77
|
const explorePaths = [
|
|
78
|
-
...(
|
|
79
|
-
...(inferWdFromScript(
|
|
78
|
+
...(resolveSource?.searchPath ?? []),
|
|
79
|
+
...(inferWdFromScript(resolveSource?.inferWorkingDirectory ?? config_1.InferWorkingDirectory.No, data.referenceChain))
|
|
80
80
|
];
|
|
81
81
|
let tryPaths = [seed];
|
|
82
|
-
switch (
|
|
82
|
+
switch (resolveSource?.dropPaths ?? config_1.DropPathsOption.No) {
|
|
83
83
|
case config_1.DropPathsOption.Once: {
|
|
84
84
|
const first = platformBasename(seed);
|
|
85
85
|
tryPaths.push(first);
|
|
@@ -101,8 +101,8 @@ function findSource(seed, data) {
|
|
|
101
101
|
case config_1.DropPathsOption.No:
|
|
102
102
|
break;
|
|
103
103
|
}
|
|
104
|
-
if (
|
|
105
|
-
const r =
|
|
104
|
+
if (resolveSource?.applyReplacements) {
|
|
105
|
+
const r = resolveSource.applyReplacements;
|
|
106
106
|
tryPaths = tryPaths.flatMap(t => applyReplacements(t, r));
|
|
107
107
|
}
|
|
108
108
|
const found = [];
|
|
@@ -129,7 +129,7 @@ function processSourceCall(name, args, rootId, data, config) {
|
|
|
129
129
|
(0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'builtin:source' }).information
|
|
130
130
|
: (0, info_1.initializeCleanDataflowInformation)(rootId, data);
|
|
131
131
|
const sourceFileArgument = args[0];
|
|
132
|
-
if (!config.forceFollow &&
|
|
132
|
+
if (!config.forceFollow && data.flowrConfig.ignoreSourceCalls) {
|
|
133
133
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping source call ${JSON.stringify(sourceFileArgument)} (disabled in config file)`);
|
|
134
134
|
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
135
135
|
return information;
|
|
@@ -139,19 +139,19 @@ function processSourceCall(name, args, rootId, data, config) {
|
|
|
139
139
|
sourceFile = [(0, retriever_1.removeRQuotes)(sourceFileArgument.lexeme)];
|
|
140
140
|
}
|
|
141
141
|
else if (sourceFileArgument !== r_function_call_1.EmptyArgument) {
|
|
142
|
-
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(sourceFileArgument.info.id, { environment: data.environment, idMap: data.completeAst.idMap }));
|
|
142
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(sourceFileArgument.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.flowrConfig.solver.variables }));
|
|
143
143
|
sourceFile = resolved?.elements.map(r => r.type === 'string' && (0, r_value_1.isValue)(r.value) ? r.value.str : undefined).filter(assert_1.isNotUndefined);
|
|
144
144
|
}
|
|
145
145
|
if (sourceFile && sourceFile.length === 1) {
|
|
146
146
|
const path = (0, retriever_1.removeRQuotes)(sourceFile[0]);
|
|
147
|
-
let filepath = path ? findSource(path, data) : path;
|
|
147
|
+
let filepath = path ? findSource(data.flowrConfig.solver.resolveSource, path, data) : path;
|
|
148
148
|
if (Array.isArray(filepath)) {
|
|
149
149
|
filepath = filepath?.[0];
|
|
150
150
|
}
|
|
151
151
|
if (filepath !== undefined) {
|
|
152
152
|
const request = sourceProvider.createRequest(filepath);
|
|
153
153
|
// check if the sourced file has already been dataflow analyzed, and if so, skip it
|
|
154
|
-
const limit =
|
|
154
|
+
const limit = data.flowrConfig.solver.resolveSource?.repeatedSourceLimit ?? 0;
|
|
155
155
|
const findCount = data.referenceChain.filter(e => e.request === request.request && e.content === request.content).length;
|
|
156
156
|
if (findCount > limit) {
|
|
157
157
|
logger_1.dataflowLogger.warn(`Found cycle (>=${limit + 1}) in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
|
|
@@ -181,7 +181,7 @@ function sourceRequest(rootId, request, data, information, getId) {
|
|
|
181
181
|
const file = request.request === 'file' ? request.content : undefined;
|
|
182
182
|
const parsed = (!data.parser.async ? data.parser : new shell_executor_1.RShellExecutor()).parse(request);
|
|
183
183
|
normalized = (typeof parsed !== 'string' ?
|
|
184
|
-
(0, parser_1.normalizeTreeSitter)({ parsed }, getId, file) : (0, parser_1.normalize)({ parsed }, getId, file));
|
|
184
|
+
(0, parser_1.normalizeTreeSitter)({ parsed }, getId, data.flowrConfig, file) : (0, parser_1.normalize)({ parsed }, getId, file));
|
|
185
185
|
dataflow = (0, processor_1.processDataflowFor)(normalized.ast, {
|
|
186
186
|
...data,
|
|
187
187
|
currentRequest: request,
|
|
@@ -16,7 +16,7 @@ const containers_1 = require("../../../../../../util/containers");
|
|
|
16
16
|
*/
|
|
17
17
|
function processVector(name, args, rootId, data) {
|
|
18
18
|
const fnCall = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'builtin:vector' });
|
|
19
|
-
if (!
|
|
19
|
+
if (!data.flowrConfig.solver.pointerTracking) {
|
|
20
20
|
return fnCall.information;
|
|
21
21
|
}
|
|
22
22
|
let vectorArgs = [];
|
|
@@ -52,7 +52,7 @@ function processVector(name, args, rootId, data) {
|
|
|
52
52
|
vectorArgs = vectorArgs.concat(flattenedIndices);
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
if ((0, config_1.isOverPointerAnalysisThreshold)(vectorArgs.length)) {
|
|
55
|
+
if ((0, config_1.isOverPointerAnalysisThreshold)(data.flowrConfig, vectorArgs.length)) {
|
|
56
56
|
return fnCall.information;
|
|
57
57
|
}
|
|
58
58
|
const indices = {
|
|
@@ -24,7 +24,7 @@ function processWhileLoop(name, args, rootId, data) {
|
|
|
24
24
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
25
25
|
}
|
|
26
26
|
// we should defer this to the abstract interpretation
|
|
27
|
-
const values = (0, alias_tracking_1.resolveIdToValue)(unpackedArgs[0]?.info.id, { environment: data.environment, idMap: data.completeAst.idMap });
|
|
27
|
+
const values = (0, alias_tracking_1.resolveIdToValue)(unpackedArgs[0]?.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.flowrConfig.solver.variables });
|
|
28
28
|
const conditionIsAlwaysFalse = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === false) ?? false;
|
|
29
29
|
//We don't care about the body if it never executes
|
|
30
30
|
if (conditionIsAlwaysFalse) {
|
|
@@ -83,7 +83,7 @@ function processAllArguments({ functionName, args, data, finalGraph, functionRoo
|
|
|
83
83
|
// When only a single index is referenced, we don't need to reference the whole object
|
|
84
84
|
const resolvedInGraphDef = resolved;
|
|
85
85
|
const isContainer = checkForContainer(resolvedInGraphDef?.indicesCollection);
|
|
86
|
-
if (isContainer
|
|
86
|
+
if (isContainer !== false) {
|
|
87
87
|
finalGraph.addEdge(ingoing.nodeId, resolved.nodeId, edge_1.EdgeType.Reads);
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -20,7 +20,7 @@ function processFunctionParameter(parameter, data) {
|
|
|
20
20
|
for (const writtenNode of writtenNodes) {
|
|
21
21
|
log_1.log.trace(`parameter ${writtenNode.name} (${writtenNode.nodeId}) is defined at id ${writtenNode.definedAt} with ${defaultValue === undefined ? 'no default value' : ' no default value'}`);
|
|
22
22
|
graph.setDefinitionOfVertex(writtenNode);
|
|
23
|
-
environment = (0, define_1.define)(writtenNode, false, environment);
|
|
23
|
+
environment = (0, define_1.define)(writtenNode, false, environment, data.flowrConfig);
|
|
24
24
|
if (defaultValue !== undefined) {
|
|
25
25
|
if (parameter.defaultValue?.type === type_1.RType.FunctionDefinition) {
|
|
26
26
|
graph.addEdge(writtenNode, parameter.defaultValue.info.id, edge_1.EdgeType.DefinedBy);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
|
+
import type { DataflowGraph } from '../graph/graph';
|
|
3
|
+
/**
|
|
4
|
+
* Finds the definition of a variable and all other uses from that point on
|
|
5
|
+
*
|
|
6
|
+
* For example, for the following code
|
|
7
|
+
* ```ts
|
|
8
|
+
* y <- 5
|
|
9
|
+
* f <- function() {
|
|
10
|
+
* y <- 8
|
|
11
|
+
* print(y)
|
|
12
|
+
* }
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @example getAllRefsToSymbol('3\@y') returns ['3\@y', '4\@y']
|
|
16
|
+
*
|
|
17
|
+
* @param graph - Dataflow Graph
|
|
18
|
+
* @param nodeId - NodeId of Symbol to resolve
|
|
19
|
+
* @returns List including the Definitions and Refereneces to that definition
|
|
20
|
+
*/
|
|
21
|
+
export declare function getAllRefsToSymbol(graph: DataflowGraph, nodeId: NodeId): NodeId[] | undefined;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAllRefsToSymbol = getAllRefsToSymbol;
|
|
4
|
+
const edge_1 = require("../graph/edge");
|
|
5
|
+
const info_1 = require("../info");
|
|
6
|
+
const dfg_get_origin_1 = require("./dfg-get-origin");
|
|
7
|
+
/**
|
|
8
|
+
* Finds the definition of a variable and all other uses from that point on
|
|
9
|
+
*
|
|
10
|
+
* For example, for the following code
|
|
11
|
+
* ```ts
|
|
12
|
+
* y <- 5
|
|
13
|
+
* f <- function() {
|
|
14
|
+
* y <- 8
|
|
15
|
+
* print(y)
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example getAllRefsToSymbol('3\@y') returns ['3\@y', '4\@y']
|
|
20
|
+
*
|
|
21
|
+
* @param graph - Dataflow Graph
|
|
22
|
+
* @param nodeId - NodeId of Symbol to resolve
|
|
23
|
+
* @returns List including the Definitions and Refereneces to that definition
|
|
24
|
+
*/
|
|
25
|
+
function getAllRefsToSymbol(graph, nodeId) {
|
|
26
|
+
// Get all origins and filter for ones that happen for sure
|
|
27
|
+
const origins = (0, dfg_get_origin_1.getOriginInDfg)(graph, nodeId);
|
|
28
|
+
if (origins === undefined) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const definitiveOrigins = origins.filter(o => (0, info_1.happensInEveryBranch)(graph.getVertex(o.id)?.cds));
|
|
32
|
+
if (definitiveOrigins.length === 0) {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
// Gather all the references
|
|
36
|
+
const res = new Set();
|
|
37
|
+
for (const origin of definitiveOrigins) {
|
|
38
|
+
res.add(origin.id);
|
|
39
|
+
graph.ingoingEdges(origin.id)
|
|
40
|
+
?.entries()
|
|
41
|
+
.filter(([_, edge]) => (0, edge_1.edgeIncludesType)(edge.types, edge_1.EdgeType.Reads))
|
|
42
|
+
.forEach(([node, _]) => res.add(node));
|
|
43
|
+
graph.outgoingEdges(origin.id)
|
|
44
|
+
?.entries()
|
|
45
|
+
.filter(([_, edge]) => (0, edge_1.edgeIncludesType)(edge.types, edge_1.EdgeType.DefinedByOnCall))
|
|
46
|
+
.forEach(([node, _]) => res.add(node));
|
|
47
|
+
}
|
|
48
|
+
return [...res];
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=dfg-get-symbol-refs.js.map
|
package/dataflow/processor.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { REnvironmentInformation } from './environments/environment';
|
|
|
7
7
|
import type { RParseRequest } from '../r-bridge/retriever';
|
|
8
8
|
import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
|
|
9
9
|
import type { KnownParserType, Parser } from '../r-bridge/parser';
|
|
10
|
+
import type { FlowrConfigOptions } from '../config';
|
|
10
11
|
export interface DataflowProcessorInformation<OtherInfo> {
|
|
11
12
|
readonly parser: Parser<KnownParserType>;
|
|
12
13
|
/**
|
|
@@ -35,6 +36,10 @@ export interface DataflowProcessorInformation<OtherInfo> {
|
|
|
35
36
|
* The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
|
|
36
37
|
*/
|
|
37
38
|
readonly controlDependencies: ControlDependency[] | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* The flowr configuration used for environment seeding, and precision control
|
|
41
|
+
*/
|
|
42
|
+
readonly flowrConfig: FlowrConfigOptions;
|
|
38
43
|
}
|
|
39
44
|
export type DataflowProcessor<OtherInfo, NodeType extends RNodeWithParent<OtherInfo>> = (node: NodeType, data: DataflowProcessorInformation<OtherInfo>) => DataflowInformation;
|
|
40
45
|
type NodeWithKey<OtherInfo, Key> = RNode<OtherInfo & ParentInformation> & {
|
|
@@ -11,13 +11,14 @@ const doc_files_1 = require("./doc-files");
|
|
|
11
11
|
const cfg_1 = require("../../util/mermaid/cfg");
|
|
12
12
|
const doc_code_1 = require("./doc-code");
|
|
13
13
|
const cfg_simplification_1 = require("../../control-flow/cfg-simplification");
|
|
14
|
+
const config_1 = require("../../config");
|
|
14
15
|
async function getCfg(parser, code, simplifications = [], useDfg = true) {
|
|
15
16
|
const result = useDfg ? await (0, default_pipelines_1.createDataflowPipeline)(parser, {
|
|
16
17
|
request: (0, retriever_1.requestFromInput)(code)
|
|
17
|
-
}).allRemainingSteps() : await (0, default_pipelines_1.createNormalizePipeline)(parser, {
|
|
18
|
+
}, config_1.defaultConfigOptions).allRemainingSteps() : await (0, default_pipelines_1.createNormalizePipeline)(parser, {
|
|
18
19
|
request: (0, retriever_1.requestFromInput)(code)
|
|
19
|
-
}).allRemainingSteps();
|
|
20
|
-
const cfg = (0, extract_cfg_1.extractCfg)(result.normalize, useDfg ? result.dataflow.graph : undefined, [...cfg_simplification_1.DefaultCfgSimplificationOrder, ...simplifications]);
|
|
20
|
+
}, config_1.defaultConfigOptions).allRemainingSteps();
|
|
21
|
+
const cfg = (0, extract_cfg_1.extractCfg)(result.normalize, config_1.defaultConfigOptions, useDfg ? result.dataflow.graph : undefined, [...cfg_simplification_1.DefaultCfgSimplificationOrder, ...simplifications]);
|
|
21
22
|
return {
|
|
22
23
|
info: cfg,
|
|
23
24
|
ast: result.normalize,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare function codeBlock(language: string, code: string
|
|
1
|
+
export declare function codeBlock(language: string, code: string): string;
|
|
2
2
|
export declare function codeInline(code: string): string;
|
|
3
3
|
export declare function jsonWithLimit(object: object, maxLength?: number, tooLongText?: string): string;
|