@eagleoutice/flowr 2.2.14 → 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 +3 -3
- 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 +5 -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 +27 -43
- package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
- package/control-flow/cfg-dead-code.d.ts +4 -0
- package/control-flow/cfg-dead-code.js +124 -0
- package/control-flow/cfg-simplification.d.ts +19 -6
- package/control-flow/cfg-simplification.js +23 -19
- package/control-flow/control-flow-graph.d.ts +3 -1
- package/control-flow/control-flow-graph.js +5 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +9 -7
- package/control-flow/dfg-cfg-guided-visitor.js +16 -5
- package/control-flow/extract-cfg.d.ts +4 -2
- package/control-flow/extract-cfg.js +63 -59
- package/control-flow/semantic-cfg-guided-visitor.d.ts +36 -9
- package/control-flow/semantic-cfg-guided-visitor.js +73 -20
- package/control-flow/simple-visitor.d.ts +4 -0
- package/control-flow/simple-visitor.js +14 -0
- package/control-flow/syntax-cfg-guided-visitor.d.ts +2 -2
- 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 +4 -3
- package/dataflow/environments/built-in.d.ts +16 -1
- package/dataflow/environments/built-in.js +11 -5
- package/dataflow/environments/default-builtin-config.js +5 -3
- 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/environments/resolve-by-name.d.ts +0 -36
- package/dataflow/environments/resolve-by-name.js +0 -240
- package/dataflow/eval/resolve/alias-tracking.d.ts +92 -0
- package/dataflow/eval/resolve/alias-tracking.js +352 -0
- 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 +37 -0
- package/dataflow/eval/resolve/resolve.js +95 -0
- package/dataflow/eval/values/general.d.ts +27 -0
- package/dataflow/eval/values/general.js +73 -0
- package/dataflow/eval/values/intervals/interval-constants.d.ts +4 -0
- package/dataflow/eval/values/intervals/interval-constants.js +27 -0
- package/dataflow/eval/values/logical/logical-constants.d.ts +7 -0
- package/dataflow/eval/values/logical/logical-constants.js +31 -0
- package/dataflow/eval/values/r-value.d.ts +58 -0
- package/dataflow/eval/values/r-value.js +90 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.d.ts +15 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.js +35 -0
- package/dataflow/eval/values/sets/set-constants.d.ts +7 -0
- package/dataflow/eval/values/sets/set-constants.js +34 -0
- package/dataflow/eval/values/string/string-constants.d.ts +8 -0
- package/dataflow/eval/values/string/string-constants.js +45 -0
- package/dataflow/eval/values/vectors/vector-constants.d.ts +14 -0
- package/dataflow/eval/values/vectors/vector-constants.js +35 -0
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/graph/unknown-replacement.d.ts +11 -0
- package/dataflow/graph/unknown-replacement.js +12 -0
- package/dataflow/graph/unknown-side-effect.d.ts +7 -0
- package/dataflow/graph/unknown-side-effect.js +13 -0
- 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 +8 -5
- 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 +15 -13
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +20 -18
- 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 +5 -4
- 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 +11 -5
- 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 +26 -29
- 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 +23 -0
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -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.d.ts +6 -3
- package/documentation/doc-util/doc-query.js +6 -3
- 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 +10 -11
- package/documentation/print-core-wiki.js +5 -5
- package/documentation/print-dataflow-graph-wiki.js +14 -13
- package/documentation/print-engines-wiki.js +2 -3
- 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 +81 -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 +3 -0
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +20 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +81 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.js +34 -0
- 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 -115
- 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 +17 -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 +4 -4
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +3 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -22
- 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 +75 -15
- package/queries/query.js +2 -0
- 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 +18 -9
- 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 +32 -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/criterion/parse.d.ts +8 -0
- package/slicing/criterion/parse.js +20 -0
- 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
|
@@ -10,7 +10,10 @@ const edge_1 = require("../../../../../graph/edge");
|
|
|
10
10
|
const identifier_1 = require("../../../../../environments/identifier");
|
|
11
11
|
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
12
12
|
const unnamed_call_handling_1 = require("../unnamed-call-handling");
|
|
13
|
+
const general_1 = require("../../../../../eval/values/general");
|
|
14
|
+
const r_value_1 = require("../../../../../eval/values/r-value");
|
|
13
15
|
const log_1 = require("../../../../../../util/log");
|
|
16
|
+
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
14
17
|
function processApply(name, args, rootId, data, config) {
|
|
15
18
|
const { indexOfFunction = 1, nameOfFunctionArgument, unquoteFunction, resolveInEnvironment, resolveValue } = config;
|
|
16
19
|
/* as the length is one-based and the argument filter mapping is zero-based, we do not have to subtract 1 */
|
|
@@ -54,9 +57,9 @@ function processApply(name, args, rootId, data, config) {
|
|
|
54
57
|
else if (val.type === type_1.RType.Symbol) {
|
|
55
58
|
functionId = val.info.id;
|
|
56
59
|
if (resolveValue) {
|
|
57
|
-
const resolved = (0,
|
|
58
|
-
if (resolved?.length === 1 &&
|
|
59
|
-
functionName = resolved[0];
|
|
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
|
+
if (resolved?.elements.length === 1 && resolved.elements[0].type === 'string') {
|
|
62
|
+
functionName = (0, r_value_1.isValue)(resolved.elements[0].value) ? resolved.elements[0].value.str : undefined;
|
|
60
63
|
}
|
|
61
64
|
}
|
|
62
65
|
else {
|
|
@@ -72,7 +75,7 @@ function processApply(name, args, rootId, data, config) {
|
|
|
72
75
|
logger_1.dataflowLogger.warn(`Expected symbol or string as function argument at index ${index}, but got ${JSON.stringify(val)} instead.`);
|
|
73
76
|
return information;
|
|
74
77
|
}
|
|
75
|
-
const allOtherArguments = processedArguments.
|
|
78
|
+
const allOtherArguments = processedArguments.map((arg, i) => {
|
|
76
79
|
const counterpart = args[i];
|
|
77
80
|
if (arg && counterpart !== r_function_call_1.EmptyArgument) {
|
|
78
81
|
return {
|
|
@@ -85,7 +88,7 @@ function processApply(name, args, rootId, data, config) {
|
|
|
85
88
|
else {
|
|
86
89
|
return r_function_call_1.EmptyArgument;
|
|
87
90
|
}
|
|
88
|
-
});
|
|
91
|
+
}).filter((_, i) => i !== index);
|
|
89
92
|
if (anonymous) {
|
|
90
93
|
const rootFnId = functionId;
|
|
91
94
|
functionId = 'anon-' + rootFnId;
|
|
@@ -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,9 +17,10 @@ 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");
|
|
22
|
+
const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
|
|
23
|
+
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
23
24
|
function toReplacementSymbol(target, prefix, superAssignment) {
|
|
24
25
|
return {
|
|
25
26
|
type: type_1.RType.Symbol,
|
|
@@ -142,7 +143,7 @@ args, rootId, data, config) {
|
|
|
142
143
|
name, args: effectiveArgs, rootId, data, forceArgs: config.forceArgs,
|
|
143
144
|
origin: 'builtin:assignment'
|
|
144
145
|
}).information;
|
|
145
|
-
info.graph.
|
|
146
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(info.graph, info.environment, rootId);
|
|
146
147
|
return info;
|
|
147
148
|
}
|
|
148
149
|
function extractSourceAndTarget(args) {
|
|
@@ -214,10 +215,11 @@ function checkTargetReferenceType(source, sourceInfo) {
|
|
|
214
215
|
* @param nodeToDefine - `x`
|
|
215
216
|
* @param sourceIds - `v`
|
|
216
217
|
* @param rootIdOfAssignment - `<-`
|
|
217
|
-
* @param config -
|
|
218
|
+
* @param config - The flowr config
|
|
219
|
+
* @param assignmentConfig - configuration for the assignment processing
|
|
218
220
|
*/
|
|
219
|
-
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, config) {
|
|
220
|
-
if (
|
|
221
|
+
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, config, assignmentConfig) {
|
|
222
|
+
if (config.solver.pointerTracking) {
|
|
221
223
|
let indicesCollection = undefined;
|
|
222
224
|
if (sourceIds.length === 1) {
|
|
223
225
|
// support for tracking indices.
|
|
@@ -233,22 +235,22 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
|
|
|
233
235
|
}
|
|
234
236
|
}
|
|
235
237
|
// Indices defined by replacement operation e.g. $<-
|
|
236
|
-
if (
|
|
238
|
+
if (assignmentConfig?.indicesCollection !== undefined) {
|
|
237
239
|
// If there were indices stored in the vertex, then a container was defined
|
|
238
240
|
// and assigned to the index of another container e.g. a$b <- list(c = 1)
|
|
239
241
|
if (indicesCollection) {
|
|
240
|
-
indicesCollection = (0, containers_1.addSubIndicesToLeafIndices)(
|
|
242
|
+
indicesCollection = (0, containers_1.addSubIndicesToLeafIndices)(assignmentConfig.indicesCollection, indicesCollection);
|
|
241
243
|
}
|
|
242
244
|
else {
|
|
243
245
|
// No indices were defined for the vertex e.g. a$b <- 2
|
|
244
|
-
indicesCollection =
|
|
246
|
+
indicesCollection = assignmentConfig.indicesCollection;
|
|
245
247
|
}
|
|
246
248
|
}
|
|
247
249
|
nodeToDefine.indicesCollection ??= indicesCollection;
|
|
248
250
|
}
|
|
249
|
-
information.environment = (0, define_1.define)(nodeToDefine,
|
|
251
|
+
information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, config);
|
|
250
252
|
information.graph.setDefinitionOfVertex(nodeToDefine);
|
|
251
|
-
if (!
|
|
253
|
+
if (!assignmentConfig?.quoteSource) {
|
|
252
254
|
for (const sourceId of sourceIds) {
|
|
253
255
|
information.graph.addEdge(nodeToDefine, sourceId, edge_1.EdgeType.DefinedBy);
|
|
254
256
|
}
|
|
@@ -269,7 +271,7 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
|
|
|
269
271
|
function processAssignmentToSymbol(config) {
|
|
270
272
|
const { nameOfAssignmentFunction, source, args: [targetArg, sourceArg], target, rootId, data, information, makeMaybe, quoteSource } = config;
|
|
271
273
|
const referenceType = checkTargetReferenceType(source, sourceArg);
|
|
272
|
-
const aliases = (0,
|
|
274
|
+
const aliases = (0, alias_tracking_1.getAliases)([source.info.id], information.graph, information.environment);
|
|
273
275
|
const writeNodes = produceWrittenNodes(rootId, targetArg, referenceType, data, makeMaybe ?? false, aliases);
|
|
274
276
|
if (writeNodes.length !== 1 && log_1.log.settings.minLevel <= 4 /* LogLevel.Warn */) {
|
|
275
277
|
log_1.log.warn(`Unexpected write number in assignment: ${JSON.stringify(writeNodes)}`);
|
|
@@ -280,10 +282,10 @@ function processAssignmentToSymbol(config) {
|
|
|
280
282
|
{ nodeId: rootId, name: nameOfAssignmentFunction, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function },
|
|
281
283
|
...sourceArg.unknownReferences, ...sourceArg.in, ...targetArg.in.filter(i => i.nodeId !== target.info.id), ...readFromSourceWritten
|
|
282
284
|
];
|
|
283
|
-
information.environment = (0, overwrite_1.overwriteEnvironment)(
|
|
285
|
+
information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
|
|
284
286
|
// install assigned variables in environment
|
|
285
287
|
for (const write of writeNodes) {
|
|
286
|
-
markAsAssignment(information, write, [source.info.id], rootId, config);
|
|
288
|
+
markAsAssignment(information, write, [source.info.id], rootId, data.flowrConfig, config);
|
|
287
289
|
}
|
|
288
290
|
information.graph.addEdge(rootId, targetArg.entryPoint, edge_1.EdgeType.Returns);
|
|
289
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");
|
|
@@ -12,9 +11,12 @@ const log_1 = require("../../../../../../util/log");
|
|
|
12
11
|
const built_in_source_1 = require("./built-in-source");
|
|
13
12
|
const edge_1 = require("../../../../../graph/edge");
|
|
14
13
|
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
15
|
-
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
16
14
|
const append_1 = require("../../../../../environments/append");
|
|
17
15
|
const assert_1 = require("../../../../../../util/assert");
|
|
16
|
+
const general_1 = require("../../../../../eval/values/general");
|
|
17
|
+
const string_constants_1 = require("../../../../../eval/values/string/string-constants");
|
|
18
|
+
const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
|
|
19
|
+
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
18
20
|
const arrays_1 = require("../../../../../../util/collections/arrays");
|
|
19
21
|
function processEvalCall(name, args, rootId, data, config) {
|
|
20
22
|
if (args.length !== 1 || args[0] === r_function_call_1.EmptyArgument || !args[0].value) {
|
|
@@ -28,12 +30,12 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
28
30
|
if (config.includeFunctionCall) {
|
|
29
31
|
information.graph.addEdge(rootId, args[0].value.info.id, edge_1.EdgeType.Returns);
|
|
30
32
|
}
|
|
31
|
-
if (!
|
|
33
|
+
if (!data.flowrConfig.solver.evalStrings) {
|
|
32
34
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping eval call ${JSON.stringify(evalArgument)} (disabled in config file)`);
|
|
33
|
-
information.graph.
|
|
35
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
34
36
|
return information;
|
|
35
37
|
}
|
|
36
|
-
const code = resolveEvalToCode(evalArgument.value, data.environment, data.completeAst.idMap);
|
|
38
|
+
const code = resolveEvalToCode(evalArgument.value, data.environment, data.completeAst.idMap, data.flowrConfig);
|
|
37
39
|
if (code) {
|
|
38
40
|
const idGenerator = (0, decorate_1.sourcedDeterministicCountingIdGenerator)(name.lexeme + '::' + rootId, name.location);
|
|
39
41
|
data = {
|
|
@@ -62,10 +64,10 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
62
64
|
};
|
|
63
65
|
}
|
|
64
66
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(args)} for eval is currently not supported, skipping`);
|
|
65
|
-
information.graph.
|
|
67
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
66
68
|
return information;
|
|
67
69
|
}
|
|
68
|
-
function resolveEvalToCode(evalArgument, env, idMap) {
|
|
70
|
+
function resolveEvalToCode(evalArgument, env, idMap, config) {
|
|
69
71
|
const val = evalArgument;
|
|
70
72
|
if (val.type === type_1.RType.FunctionCall && val.named && val.functionName.content === 'parse') {
|
|
71
73
|
const arg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'text');
|
|
@@ -77,13 +79,13 @@ function resolveEvalToCode(evalArgument, env, idMap) {
|
|
|
77
79
|
return [arg.value.content.str];
|
|
78
80
|
}
|
|
79
81
|
else if (arg.value?.type === type_1.RType.Symbol) {
|
|
80
|
-
const
|
|
81
|
-
if (
|
|
82
|
-
return
|
|
82
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(arg.value.info.id, { environment: env, idMap: idMap, resolve: config.solver.variables }));
|
|
83
|
+
if (resolved) {
|
|
84
|
+
return (0, string_constants_1.collectStrings)(resolved.elements);
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
else if (arg.value?.type === type_1.RType.FunctionCall && arg.value.named && ['paste', 'paste0'].includes(arg.value.functionName.content)) {
|
|
86
|
-
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' ? [' '] : ['']);
|
|
87
89
|
}
|
|
88
90
|
return undefined;
|
|
89
91
|
}
|
|
@@ -96,7 +98,7 @@ function resolveEvalToCode(evalArgument, env, idMap) {
|
|
|
96
98
|
return undefined;
|
|
97
99
|
}
|
|
98
100
|
}
|
|
99
|
-
function getAsString(val, env, idMap) {
|
|
101
|
+
function getAsString(config, val, env, idMap) {
|
|
100
102
|
if (!val) {
|
|
101
103
|
return undefined;
|
|
102
104
|
}
|
|
@@ -104,17 +106,17 @@ function getAsString(val, env, idMap) {
|
|
|
104
106
|
return [val.content.str];
|
|
105
107
|
}
|
|
106
108
|
else if (val.type === type_1.RType.Symbol) {
|
|
107
|
-
const resolved = (0,
|
|
108
|
-
if (resolved
|
|
109
|
-
return
|
|
109
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(val.info.id, { environment: env, idMap: idMap, resolve: config.solver.variables }));
|
|
110
|
+
if (resolved) {
|
|
111
|
+
return (0, string_constants_1.collectStrings)(resolved.elements);
|
|
110
112
|
}
|
|
111
113
|
}
|
|
112
114
|
return undefined;
|
|
113
115
|
}
|
|
114
|
-
function handlePaste(args, env, idMap, sepDefault) {
|
|
116
|
+
function handlePaste(config, args, env, idMap, sepDefault) {
|
|
115
117
|
const sepArg = args.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'sep');
|
|
116
118
|
if (sepArg) {
|
|
117
|
-
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;
|
|
118
120
|
if (!res) {
|
|
119
121
|
// sep not resolvable clearly / unknown
|
|
120
122
|
return undefined;
|
|
@@ -123,7 +125,7 @@ function handlePaste(args, env, idMap, sepDefault) {
|
|
|
123
125
|
}
|
|
124
126
|
const allArgs = args
|
|
125
127
|
.filter(v => v !== r_function_call_1.EmptyArgument && v.name?.content !== 'sep' && v.value)
|
|
126
|
-
.map(v => getAsString(v.value, env, idMap));
|
|
128
|
+
.map(v => getAsString(config, v.value, env, idMap));
|
|
127
129
|
if (allArgs.some(assert_1.isUndefined)) {
|
|
128
130
|
return undefined;
|
|
129
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: [],
|
|
@@ -7,11 +7,12 @@ const known_call_handling_1 = require("../known-call-handling");
|
|
|
7
7
|
const common_1 = require("../common");
|
|
8
8
|
const unpack_argument_1 = require("../argument/unpack-argument");
|
|
9
9
|
const logger_1 = require("../../../../../logger");
|
|
10
|
-
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
11
10
|
const edge_1 = require("../../../../../graph/edge");
|
|
12
11
|
const append_1 = require("../../../../../environments/append");
|
|
13
12
|
const identifier_1 = require("../../../../../environments/identifier");
|
|
14
13
|
const environment_1 = require("../../../../../environments/environment");
|
|
14
|
+
const general_1 = require("../../../../../eval/values/general");
|
|
15
|
+
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
15
16
|
function processIfThenElse(name, args, rootId, data) {
|
|
16
17
|
if (args.length !== 2 && args.length !== 3) {
|
|
17
18
|
logger_1.dataflowLogger.warn(`If-then-else ${name.content} has something different from 2 or 3 arguments, skipping`);
|
|
@@ -33,9 +34,9 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
33
34
|
let then;
|
|
34
35
|
let makeThenMaybe = false;
|
|
35
36
|
// we should defer this to the abstract interpretation
|
|
36
|
-
const values = (0,
|
|
37
|
-
const conditionIsAlwaysFalse = values?.every(d => d === false) ?? false;
|
|
38
|
-
const conditionIsAlwaysTrue = values?.every(d => d === true) ?? false;
|
|
37
|
+
const values = (0, alias_tracking_1.resolveIdToValue)(condArg?.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.flowrConfig.solver.variables });
|
|
38
|
+
const conditionIsAlwaysFalse = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === false) ?? false;
|
|
39
|
+
const conditionIsAlwaysTrue = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === true) ?? false;
|
|
39
40
|
if (!conditionIsAlwaysFalse) {
|
|
40
41
|
then = (0, processor_1.processDataflowFor)(thenArg, data);
|
|
41
42
|
if (then.entryPoint) {
|
|
@@ -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,11 +12,11 @@ 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");
|
|
19
18
|
const identifier_1 = require("../../../../../environments/identifier");
|
|
19
|
+
const unknown_replacement_1 = require("../../../../../graph/unknown-replacement");
|
|
20
20
|
function processReplacementFunction(name,
|
|
21
21
|
/** The last one has to be the value */
|
|
22
22
|
args, rootId, data, config) {
|
|
@@ -27,7 +27,7 @@ args, rootId, data, config) {
|
|
|
27
27
|
/* we only get here if <-, <<-, ... or whatever is part of the replacement is not overwritten */
|
|
28
28
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Replacement ${name.content} with ${JSON.stringify(args)}, processing`);
|
|
29
29
|
let indices = config.activeIndices;
|
|
30
|
-
if (
|
|
30
|
+
if (data.flowrConfig.solver.pointerTracking) {
|
|
31
31
|
indices ??= constructAccessedIndices(name.content, args);
|
|
32
32
|
}
|
|
33
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 */
|
|
@@ -60,9 +60,15 @@ args, rootId, data, config) {
|
|
|
60
60
|
origin: 'builtin:replacement',
|
|
61
61
|
link: config.assignRootId ? { origin: [config.assignRootId] } : undefined
|
|
62
62
|
});
|
|
63
|
-
const firstArg = (0, unpack_argument_1.unpackArgument)(args[0])
|
|
63
|
+
const firstArg = (0, unpack_argument_1.unpackArgument)(args[0]);
|
|
64
|
+
(0, unknown_replacement_1.handleReplacementOperator)({
|
|
65
|
+
operator: name.content,
|
|
66
|
+
target: firstArg?.lexeme,
|
|
67
|
+
env: res.environment,
|
|
68
|
+
id: rootId
|
|
69
|
+
});
|
|
64
70
|
if (firstArg) {
|
|
65
|
-
res.graph.addEdge(firstArg, rootId, edge_1.EdgeType.DefinedBy | edge_1.EdgeType.Reads);
|
|
71
|
+
res.graph.addEdge(firstArg.info.id, rootId, edge_1.EdgeType.DefinedBy | edge_1.EdgeType.Reads);
|
|
66
72
|
}
|
|
67
73
|
/* a replacement reads all of its call args as well, at least as far as I am aware of */
|
|
68
74
|
for (const arg of callArgs) {
|
|
@@ -72,7 +78,7 @@ args, rootId, data, config) {
|
|
|
72
78
|
}
|
|
73
79
|
}
|
|
74
80
|
const fa = (0, unpack_argument_1.unpackArgument)(args[0]);
|
|
75
|
-
if (!
|
|
81
|
+
if (!data.flowrConfig.solver.pointerTracking && fa) {
|
|
76
82
|
res = {
|
|
77
83
|
...res,
|
|
78
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: {
|
|
@@ -23,9 +23,12 @@ const log_1 = require("../../../../../../util/log");
|
|
|
23
23
|
const fs_1 = __importDefault(require("fs"));
|
|
24
24
|
const parser_1 = require("../../../../../../r-bridge/lang-4.x/ast/parser/json/parser");
|
|
25
25
|
const shell_executor_1 = require("../../../../../../r-bridge/shell-executor");
|
|
26
|
-
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
27
26
|
const assert_1 = require("../../../../../../util/assert");
|
|
28
27
|
const path_1 = __importDefault(require("path"));
|
|
28
|
+
const general_1 = require("../../../../../eval/values/general");
|
|
29
|
+
const r_value_1 = require("../../../../../eval/values/r-value");
|
|
30
|
+
const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
|
|
31
|
+
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
29
32
|
let sourceProvider = (0, retriever_1.requestProviderFromFile)();
|
|
30
33
|
function setSourceProvider(provider) {
|
|
31
34
|
sourceProvider = provider;
|
|
@@ -65,18 +68,18 @@ function applyReplacements(path, replacements) {
|
|
|
65
68
|
}
|
|
66
69
|
/**
|
|
67
70
|
* Tries to find sourced by a source request and returns the first path that exists
|
|
68
|
-
* @param
|
|
69
|
-
* @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
|
|
70
74
|
*/
|
|
71
|
-
function findSource(seed, data) {
|
|
72
|
-
const
|
|
73
|
-
const capitalization = config?.ignoreCapitalization ?? false;
|
|
75
|
+
function findSource(resolveSource, seed, data) {
|
|
76
|
+
const capitalization = resolveSource?.ignoreCapitalization ?? false;
|
|
74
77
|
const explorePaths = [
|
|
75
|
-
...(
|
|
76
|
-
...(inferWdFromScript(
|
|
78
|
+
...(resolveSource?.searchPath ?? []),
|
|
79
|
+
...(inferWdFromScript(resolveSource?.inferWorkingDirectory ?? config_1.InferWorkingDirectory.No, data.referenceChain))
|
|
77
80
|
];
|
|
78
81
|
let tryPaths = [seed];
|
|
79
|
-
switch (
|
|
82
|
+
switch (resolveSource?.dropPaths ?? config_1.DropPathsOption.No) {
|
|
80
83
|
case config_1.DropPathsOption.Once: {
|
|
81
84
|
const first = platformBasename(seed);
|
|
82
85
|
tryPaths.push(first);
|
|
@@ -98,8 +101,8 @@ function findSource(seed, data) {
|
|
|
98
101
|
case config_1.DropPathsOption.No:
|
|
99
102
|
break;
|
|
100
103
|
}
|
|
101
|
-
if (
|
|
102
|
-
const r =
|
|
104
|
+
if (resolveSource?.applyReplacements) {
|
|
105
|
+
const r = resolveSource.applyReplacements;
|
|
103
106
|
tryPaths = tryPaths.flatMap(t => applyReplacements(t, r));
|
|
104
107
|
}
|
|
105
108
|
const found = [];
|
|
@@ -126,9 +129,9 @@ function processSourceCall(name, args, rootId, data, config) {
|
|
|
126
129
|
(0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'builtin:source' }).information
|
|
127
130
|
: (0, info_1.initializeCleanDataflowInformation)(rootId, data);
|
|
128
131
|
const sourceFileArgument = args[0];
|
|
129
|
-
if (!config.forceFollow &&
|
|
132
|
+
if (!config.forceFollow && data.flowrConfig.ignoreSourceCalls) {
|
|
130
133
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Skipping source call ${JSON.stringify(sourceFileArgument)} (disabled in config file)`);
|
|
131
|
-
information.graph.
|
|
134
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
132
135
|
return information;
|
|
133
136
|
}
|
|
134
137
|
let sourceFile;
|
|
@@ -136,36 +139,30 @@ function processSourceCall(name, args, rootId, data, config) {
|
|
|
136
139
|
sourceFile = [(0, retriever_1.removeRQuotes)(sourceFileArgument.lexeme)];
|
|
137
140
|
}
|
|
138
141
|
else if (sourceFileArgument !== r_function_call_1.EmptyArgument) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
return x.str;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
return undefined;
|
|
145
|
-
}
|
|
146
|
-
}).filter(assert_1.isNotUndefined);
|
|
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
|
+
sourceFile = resolved?.elements.map(r => r.type === 'string' && (0, r_value_1.isValue)(r.value) ? r.value.str : undefined).filter(assert_1.isNotUndefined);
|
|
147
144
|
}
|
|
148
145
|
if (sourceFile && sourceFile.length === 1) {
|
|
149
146
|
const path = (0, retriever_1.removeRQuotes)(sourceFile[0]);
|
|
150
|
-
let filepath = path ? findSource(path, data) : path;
|
|
147
|
+
let filepath = path ? findSource(data.flowrConfig.solver.resolveSource, path, data) : path;
|
|
151
148
|
if (Array.isArray(filepath)) {
|
|
152
149
|
filepath = filepath?.[0];
|
|
153
150
|
}
|
|
154
151
|
if (filepath !== undefined) {
|
|
155
152
|
const request = sourceProvider.createRequest(filepath);
|
|
156
153
|
// check if the sourced file has already been dataflow analyzed, and if so, skip it
|
|
157
|
-
const limit =
|
|
154
|
+
const limit = data.flowrConfig.solver.resolveSource?.repeatedSourceLimit ?? 0;
|
|
158
155
|
const findCount = data.referenceChain.filter(e => e.request === request.request && e.content === request.content).length;
|
|
159
156
|
if (findCount > limit) {
|
|
160
157
|
logger_1.dataflowLogger.warn(`Found cycle (>=${limit + 1}) in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
|
|
161
|
-
information.graph.
|
|
158
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
162
159
|
return information;
|
|
163
160
|
}
|
|
164
161
|
return sourceRequest(rootId, request, data, information, (0, decorate_1.sourcedDeterministicCountingIdGenerator)((findCount > 0 ? findCount + '::' : '') + path, name.location));
|
|
165
162
|
}
|
|
166
163
|
}
|
|
167
164
|
(0, log_1.expensiveTrace)(logger_1.dataflowLogger, () => `Non-constant argument ${JSON.stringify(sourceFile)} for source is currently not supported, skipping`);
|
|
168
|
-
information.graph.
|
|
165
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
169
166
|
return information;
|
|
170
167
|
}
|
|
171
168
|
function sourceRequest(rootId, request, data, information, getId) {
|
|
@@ -173,7 +170,7 @@ function sourceRequest(rootId, request, data, information, getId) {
|
|
|
173
170
|
/* check if the file exists and if not, fail */
|
|
174
171
|
if (!fs_1.default.existsSync(request.content)) {
|
|
175
172
|
logger_1.dataflowLogger.warn(`Failed to analyze sourced file ${JSON.stringify(request)}: file does not exist`);
|
|
176
|
-
information.graph.
|
|
173
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
177
174
|
return information;
|
|
178
175
|
}
|
|
179
176
|
}
|
|
@@ -184,7 +181,7 @@ function sourceRequest(rootId, request, data, information, getId) {
|
|
|
184
181
|
const file = request.request === 'file' ? request.content : undefined;
|
|
185
182
|
const parsed = (!data.parser.async ? data.parser : new shell_executor_1.RShellExecutor()).parse(request);
|
|
186
183
|
normalized = (typeof parsed !== 'string' ?
|
|
187
|
-
(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));
|
|
188
185
|
dataflow = (0, processor_1.processDataflowFor)(normalized.ast, {
|
|
189
186
|
...data,
|
|
190
187
|
currentRequest: request,
|
|
@@ -195,7 +192,7 @@ function sourceRequest(rootId, request, data, information, getId) {
|
|
|
195
192
|
catch (e) {
|
|
196
193
|
logger_1.dataflowLogger.error(`Failed to analyze sourced file ${JSON.stringify(request)}, skipping: ${e.message}`);
|
|
197
194
|
logger_1.dataflowLogger.error(e.stack);
|
|
198
|
-
information.graph.
|
|
195
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
199
196
|
return information;
|
|
200
197
|
}
|
|
201
198
|
// take the entry point as well as all the written references, and give them a control dependency to the source call to show that they are conditional
|
|
@@ -229,7 +226,7 @@ function standaloneSourceFile(inputRequest, data, uniqueSourceId, information) {
|
|
|
229
226
|
// check if the sourced file has already been dataflow analyzed, and if so, skip it
|
|
230
227
|
if (data.referenceChain.find(e => e.request === request.request && e.content === request.content)) {
|
|
231
228
|
logger_1.dataflowLogger.info(`Found loop in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
|
|
232
|
-
information.graph.
|
|
229
|
+
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, uniqueSourceId);
|
|
233
230
|
return information;
|
|
234
231
|
}
|
|
235
232
|
return sourceRequest(uniqueSourceId, 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 = {
|