@eagleoutice/flowr 2.6.3 → 2.7.0
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 +13 -13
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +1 -1
- package/abstract-interpretation/data-frame/absint-visitor.js +3 -3
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +4 -7
- package/abstract-interpretation/data-frame/dataframe-domain.js +5 -11
- package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +3 -1
- package/abstract-interpretation/data-frame/mappers/access-mapper.js +3 -2
- package/abstract-interpretation/data-frame/mappers/arguments.js +2 -2
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +3 -1
- package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +3 -2
- package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +1 -1
- package/abstract-interpretation/data-frame/mappers/function-mapper.js +8 -8
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +3 -1
- package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +3 -2
- package/abstract-interpretation/data-frame/semantics.js +47 -42
- package/abstract-interpretation/data-frame/shape-inference.d.ts +1 -1
- package/abstract-interpretation/domains/abstract-domain.d.ts +1 -0
- package/abstract-interpretation/domains/abstract-domain.js +3 -2
- package/abstract-interpretation/domains/bounded-set-domain.js +1 -1
- package/abstract-interpretation/domains/interval-domain.d.ts +2 -2
- package/abstract-interpretation/domains/interval-domain.js +3 -6
- package/abstract-interpretation/domains/lattice.d.ts +2 -0
- package/abstract-interpretation/domains/lattice.js +3 -1
- package/abstract-interpretation/domains/positive-interval-domain.d.ts +1 -1
- package/abstract-interpretation/domains/positive-interval-domain.js +1 -1
- package/abstract-interpretation/domains/satisfiable-domain.d.ts +2 -2
- package/abstract-interpretation/domains/satisfiable-domain.js +2 -2
- package/abstract-interpretation/domains/set-range-domain.d.ts +98 -0
- package/abstract-interpretation/domains/set-range-domain.js +400 -0
- package/abstract-interpretation/domains/set-upper-bound-domain.js +2 -2
- package/abstract-interpretation/domains/singleton-domain.js +2 -2
- package/benchmark/slicer.d.ts +2 -1
- package/benchmark/slicer.js +37 -15
- package/benchmark/stats/print.js +8 -5
- package/benchmark/stats/stats.d.ts +3 -2
- package/benchmark/summarizer/data.d.ts +11 -8
- package/benchmark/summarizer/first-phase/process.js +11 -8
- package/benchmark/summarizer/second-phase/process.js +24 -18
- package/control-flow/cfg-dead-code.js +3 -2
- package/control-flow/useless-loop.js +4 -2
- package/core/steps/all/static-slicing/00-slice.d.ts +3 -0
- package/core/steps/all/static-slicing/00-slice.js +2 -1
- package/core/steps/pipeline/default-pipelines.d.ts +42 -42
- package/dataflow/cluster.js +2 -2
- package/dataflow/environments/append.d.ts +5 -0
- package/dataflow/environments/append.js +6 -20
- package/dataflow/environments/built-in.d.ts +2 -1
- package/dataflow/environments/clone.d.ts +1 -1
- package/dataflow/environments/clone.js +3 -27
- package/dataflow/environments/define.d.ts +7 -3
- package/dataflow/environments/define.js +9 -56
- package/dataflow/environments/diff.js +1 -1
- package/dataflow/environments/environment.d.ts +48 -28
- package/dataflow/environments/environment.js +187 -62
- package/dataflow/environments/overwrite.js +2 -45
- package/dataflow/environments/reference-to-maybe.d.ts +13 -0
- package/dataflow/environments/reference-to-maybe.js +54 -0
- package/dataflow/environments/resolve-by-name.d.ts +6 -1
- package/dataflow/environments/resolve-by-name.js +56 -4
- package/dataflow/environments/scoping.d.ts +2 -2
- package/dataflow/environments/scoping.js +7 -7
- package/dataflow/eval/resolve/alias-tracking.d.ts +10 -4
- package/dataflow/eval/resolve/alias-tracking.js +15 -13
- package/dataflow/eval/resolve/resolve-argument.d.ts +2 -1
- package/dataflow/eval/resolve/resolve-argument.js +8 -8
- package/dataflow/eval/resolve/resolve.d.ts +13 -11
- package/dataflow/eval/resolve/resolve.js +16 -15
- package/dataflow/extractor.js +1 -7
- package/dataflow/fn/higher-order-function.d.ts +2 -1
- package/dataflow/fn/higher-order-function.js +4 -4
- package/dataflow/graph/dataflowgraph-builder.d.ts +9 -5
- package/dataflow/graph/dataflowgraph-builder.js +21 -11
- package/dataflow/graph/diff-dataflow-graph.js +2 -2
- package/dataflow/graph/graph.d.ts +10 -2
- package/dataflow/graph/graph.js +41 -12
- package/dataflow/graph/invert-dfg.d.ts +3 -2
- package/dataflow/graph/invert-dfg.js +3 -3
- package/dataflow/graph/resolve-graph.d.ts +2 -1
- package/dataflow/graph/resolve-graph.js +2 -2
- package/dataflow/graph/vertex.d.ts +3 -3
- package/dataflow/graph/vertex.js +3 -3
- package/dataflow/info.d.ts +1 -1
- package/dataflow/internal/linker.js +3 -7
- package/dataflow/internal/process/functions/call/argument/unpack-argument.d.ts +7 -1
- package/dataflow/internal/process/functions/call/argument/unpack-argument.js +12 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +9 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +9 -7
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +9 -13
- package/dataflow/internal/process/functions/call/built-in/built-in-get.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.d.ts +3 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +8 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-library.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-pipe.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +6 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +5 -5
- package/dataflow/internal/process/functions/call/common.js +2 -3
- package/dataflow/internal/process/functions/call/known-call-handling.js +1 -1
- package/dataflow/internal/process/functions/call/unnamed-call-handling.js +1 -1
- package/dataflow/internal/process/functions/process-argument.js +1 -1
- package/dataflow/internal/process/process-symbol.js +1 -1
- package/dataflow/internal/process/process-value.d.ts +1 -1
- package/dataflow/internal/process/process-value.js +7 -7
- package/dataflow/processor.d.ts +1 -5
- package/documentation/doc-util/doc-dfg.js +3 -2
- package/documentation/doc-util/doc-normalized-ast.js +3 -2
- package/documentation/doc-util/doc-types.d.ts +1 -1
- package/documentation/doc-util/doc-types.js +2 -2
- package/documentation/wiki-analyzer.js +14 -1
- package/documentation/wiki-dataflow-graph.js +4 -5
- package/documentation/wiki-faq.js +0 -1
- package/documentation/wiki-linter.js +1 -1
- package/documentation/wiki-mk/doc-maker.js +2 -1
- package/linter/linter-rules.d.ts +2 -2
- package/linter/rules/absolute-path.js +4 -4
- package/linter/rules/dataframe-access-validation.d.ts +1 -1
- package/linter/rules/dataframe-access-validation.js +1 -1
- package/linter/rules/function-finder-util.d.ts +2 -2
- package/linter/rules/function-finder-util.js +1 -1
- package/linter/rules/network-functions.js +1 -1
- package/linter/rules/seeded-randomness.d.ts +1 -1
- package/linter/rules/seeded-randomness.js +5 -5
- package/package.json +1 -2
- package/project/context/flowr-analyzer-context.d.ts +7 -0
- package/project/context/flowr-analyzer-context.js +3 -0
- package/project/context/flowr-analyzer-environment-context.d.ts +47 -0
- package/project/context/flowr-analyzer-environment-context.js +50 -0
- package/queries/catalog/call-context-query/call-context-query-executor.js +1 -4
- package/queries/catalog/control-flow-query/control-flow-query-format.js +3 -2
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-executor.js +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -4
- package/queries/catalog/df-shape-query/df-shape-query-executor.d.ts +1 -1
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +1 -1
- package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +4 -4
- package/queries/catalog/df-shape-query/df-shape-query-format.js +2 -2
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +3 -3
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +1 -1
- package/slicing/static/slice-call.d.ts +3 -2
- package/slicing/static/slice-call.js +4 -4
- package/slicing/static/static-slicer.d.ts +3 -1
- package/slicing/static/static-slicer.js +6 -7
- package/statistics/features/supported/control-flow/control-flow.js +1 -1
- package/statistics/features/supported/used-functions/used-functions.js +1 -1
- package/statistics/features/supported/variables/variables.js +2 -1
- package/util/containers.js +1 -1
- package/util/mermaid/dfg.d.ts +1 -0
- package/util/mermaid/dfg.js +3 -3
- package/util/simple-df/dfg-view.d.ts +2 -1
- package/util/simple-df/dfg-view.js +2 -2
- package/util/version.js +1 -1
- package/dataflow/environments/remove.d.ts +0 -12
- package/dataflow/environments/remove.js +0 -52
|
@@ -16,7 +16,6 @@ const identifier_1 = require("../../../../../environments/identifier");
|
|
|
16
16
|
const overwrite_1 = require("../../../../../environments/overwrite");
|
|
17
17
|
const vertex_1 = require("../../../../../graph/vertex");
|
|
18
18
|
const scoping_1 = require("../../../../../environments/scoping");
|
|
19
|
-
const environment_1 = require("../../../../../environments/environment");
|
|
20
19
|
const resolve_by_name_1 = require("../../../../../environments/resolve-by-name");
|
|
21
20
|
const edge_1 = require("../../../../../graph/edge");
|
|
22
21
|
const log_1 = require("../../../../../../util/log");
|
|
@@ -31,7 +30,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
31
30
|
}
|
|
32
31
|
/* we remove the last argument, as it is the body */
|
|
33
32
|
const parameters = args.slice(0, -1);
|
|
34
|
-
const bodyArg = (0, unpack_argument_1.
|
|
33
|
+
const bodyArg = (0, unpack_argument_1.unpackNonameArg)(args[args.length - 1]);
|
|
35
34
|
(0, assert_1.guard)(bodyArg !== undefined, () => `Function Definition ${JSON.stringify(args)} has missing body! This is bad!`);
|
|
36
35
|
const originalEnvironment = data.environment;
|
|
37
36
|
// within a function def we do not pass on the outer binds as they could be overwritten when called
|
|
@@ -74,7 +73,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
74
73
|
id: read.nodeId,
|
|
75
74
|
environment: undefined,
|
|
76
75
|
cds: undefined
|
|
77
|
-
});
|
|
76
|
+
}, data.ctx.env.makeCleanEnv());
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
79
|
const flow = {
|
|
@@ -95,7 +94,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
95
94
|
cds: data.controlDependencies,
|
|
96
95
|
subflow: flow,
|
|
97
96
|
exitPoints: exitPoints?.filter(e => e.type === 1 /* ExitPointType.Return */ || e.type === 0 /* ExitPointType.Default */).map(e => e.nodeId) ?? []
|
|
98
|
-
});
|
|
97
|
+
}, data.ctx.env.makeCleanEnv());
|
|
99
98
|
return {
|
|
100
99
|
/* nothing escapes a function definition, but the function itself, will be forced in assignment: { nodeId: functionDefinition.info.id, scope: data.activeScope, used: 'always', name: functionDefinition.info.id as string } */
|
|
101
100
|
unknownReferences: [],
|
|
@@ -112,8 +111,8 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
112
111
|
/**
|
|
113
112
|
*
|
|
114
113
|
*/
|
|
115
|
-
function retrieveActiveEnvironment(callerEnvironment, baseEnvironment) {
|
|
116
|
-
callerEnvironment ??=
|
|
114
|
+
function retrieveActiveEnvironment(callerEnvironment, baseEnvironment, ctx) {
|
|
115
|
+
callerEnvironment ??= ctx.env.makeCleanEnv();
|
|
117
116
|
let level = callerEnvironment.level ?? 0;
|
|
118
117
|
if (baseEnvironment.level !== level) {
|
|
119
118
|
while (baseEnvironment.level < level) {
|
|
@@ -135,10 +134,7 @@ function retrieveActiveEnvironment(callerEnvironment, baseEnvironment) {
|
|
|
135
134
|
function updateNestedFunctionClosures(graph, outEnvironment, fnId) {
|
|
136
135
|
// track *all* function definitions - including those nested within the current graph,
|
|
137
136
|
// try to resolve their 'in' by only using the lowest scope which will be popped after this definition
|
|
138
|
-
for (const [id, { subflow
|
|
139
|
-
if (tag !== vertex_1.VertexType.FunctionDefinition) {
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
137
|
+
for (const [id, { subflow }] of graph.verticesOfType(vertex_1.VertexType.FunctionDefinition)) {
|
|
142
138
|
const ingoingRefs = subflow.in;
|
|
143
139
|
const remainingIn = [];
|
|
144
140
|
for (const ingoing of ingoingRefs) {
|
|
@@ -171,8 +167,8 @@ function updateNestedFunctionClosures(graph, outEnvironment, fnId) {
|
|
|
171
167
|
function updateNestedFunctionCalls(graph, outEnvironment) {
|
|
172
168
|
// track *all* function definitions - including those nested within the current graph,
|
|
173
169
|
// try to resolve their 'in' by only using the lowest scope which will be popped after this definition
|
|
174
|
-
for (const [id, { onlyBuiltin,
|
|
175
|
-
if (
|
|
170
|
+
for (const [id, { onlyBuiltin, environment, name }] of graph.verticesOfType(vertex_1.VertexType.FunctionCall)) {
|
|
171
|
+
if (!name || onlyBuiltin) {
|
|
176
172
|
continue;
|
|
177
173
|
}
|
|
178
174
|
// only the call environment counts!
|
|
@@ -218,7 +214,7 @@ function updateNestedFunctionCalls(graph, outEnvironment) {
|
|
|
218
214
|
}
|
|
219
215
|
}
|
|
220
216
|
function prepareFunctionEnvironment(data) {
|
|
221
|
-
let env =
|
|
217
|
+
let env = data.ctx.env.makeCleanEnv();
|
|
222
218
|
for (let i = 0; i < data.environment.level + 1 /* add another env */; i++) {
|
|
223
219
|
env = (0, scoping_1.pushLocalEnvironment)(env);
|
|
224
220
|
}
|
|
@@ -16,7 +16,7 @@ function processGet(name, args, rootId, data) {
|
|
|
16
16
|
logger_1.dataflowLogger.warn(`symbol access with ${name.content} has not 1 argument, skipping`);
|
|
17
17
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
18
18
|
}
|
|
19
|
-
const retrieve = (0, unpack_argument_1.
|
|
19
|
+
const retrieve = (0, unpack_argument_1.unpackNonameArg)(args[0]);
|
|
20
20
|
if (retrieve === undefined || retrieve.type !== type_1.RType.String) {
|
|
21
21
|
logger_1.dataflowLogger.warn(`symbol access with ${name.content} has not 1 argument, skipping`);
|
|
22
22
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
@@ -5,6 +5,8 @@ import type { ParentInformation } from '../../../../../../r-bridge/lang-4.x/ast/
|
|
|
5
5
|
import type { RFunctionArgument } from '../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
|
|
6
6
|
import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Processes an if-then-else built-in function call.
|
|
9
|
+
* For example, `if(cond) thenExpr else elseExpr` and `if(cond) thenExpr`.
|
|
10
|
+
* The arguments will be either `[cond, thenExpr]` or `[cond, thenExpr, elseExpr]`.
|
|
9
11
|
*/
|
|
10
12
|
export declare function processIfThenElse<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly RFunctionArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>): DataflowInformation;
|
|
@@ -10,18 +10,20 @@ const logger_1 = require("../../../../../logger");
|
|
|
10
10
|
const edge_1 = require("../../../../../graph/edge");
|
|
11
11
|
const append_1 = require("../../../../../environments/append");
|
|
12
12
|
const identifier_1 = require("../../../../../environments/identifier");
|
|
13
|
-
const environment_1 = require("../../../../../environments/environment");
|
|
14
13
|
const general_1 = require("../../../../../eval/values/general");
|
|
15
14
|
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
15
|
+
const reference_to_maybe_1 = require("../../../../../environments/reference-to-maybe");
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* Processes an if-then-else built-in function call.
|
|
18
|
+
* For example, `if(cond) thenExpr else elseExpr` and `if(cond) thenExpr`.
|
|
19
|
+
* The arguments will be either `[cond, thenExpr]` or `[cond, thenExpr, elseExpr]`.
|
|
18
20
|
*/
|
|
19
21
|
function processIfThenElse(name, args, rootId, data) {
|
|
20
22
|
if (args.length !== 2 && args.length !== 3) {
|
|
21
23
|
logger_1.dataflowLogger.warn(`If-then-else ${name.content} has something different from 2 or 3 arguments, skipping`);
|
|
22
24
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
23
25
|
}
|
|
24
|
-
const [condArg, thenArg, otherwiseArg] = args.map(e => (0, unpack_argument_1.
|
|
26
|
+
const [condArg, thenArg, otherwiseArg] = args.map(e => (0, unpack_argument_1.unpackNonameArg)(e));
|
|
25
27
|
if (condArg === undefined || thenArg === undefined) {
|
|
26
28
|
logger_1.dataflowLogger.warn(`If-then-else ${name.content} has empty condition or then case in ${JSON.stringify(args)}, skipping`);
|
|
27
29
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
@@ -37,7 +39,7 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
37
39
|
let then;
|
|
38
40
|
let makeThenMaybe = false;
|
|
39
41
|
// we should defer this to the abstract interpretation
|
|
40
|
-
const values = (0, alias_tracking_1.resolveIdToValue)(condArg?.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.ctx.config.solver.variables });
|
|
42
|
+
const values = (0, alias_tracking_1.resolveIdToValue)(condArg?.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.ctx.config.solver.variables, ctx: data.ctx });
|
|
41
43
|
const conditionIsAlwaysFalse = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === false) ?? false;
|
|
42
44
|
const conditionIsAlwaysTrue = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === true) ?? false;
|
|
43
45
|
if (!conditionIsAlwaysFalse) {
|
|
@@ -77,10 +79,10 @@ function processIfThenElse(name, args, rootId, data) {
|
|
|
77
79
|
const cdTrue = { id: rootId, when: true };
|
|
78
80
|
const cdFalse = { id: rootId, when: false };
|
|
79
81
|
// again within an if-then-else we consider all actives to be read
|
|
80
|
-
const ingoing = cond.in.concat(makeThenMaybe ? (0,
|
|
82
|
+
const ingoing = cond.in.concat(makeThenMaybe ? (0, reference_to_maybe_1.makeAllMaybe)(then?.in, nextGraph, finalEnvironment, false, cdTrue) : then?.in ?? [], makeOtherwiseMaybe ? (0, reference_to_maybe_1.makeAllMaybe)(otherwise?.in, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.in ?? [], cond.unknownReferences, makeThenMaybe ? (0, reference_to_maybe_1.makeAllMaybe)(then?.unknownReferences, nextGraph, finalEnvironment, false, cdTrue) : then?.unknownReferences ?? [], makeOtherwiseMaybe ? (0, reference_to_maybe_1.makeAllMaybe)(otherwise?.unknownReferences, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.unknownReferences ?? []);
|
|
81
83
|
// we assign all with a maybe marker
|
|
82
84
|
// we do not merge even if they appear in both branches because the maybe links will refer to different ids
|
|
83
|
-
const outgoing = cond.out.concat((makeThenMaybe ? (0,
|
|
85
|
+
const outgoing = cond.out.concat((makeThenMaybe ? (0, reference_to_maybe_1.makeAllMaybe)(then?.out, nextGraph, finalEnvironment, true, cdTrue) : then?.out ?? []), (makeOtherwiseMaybe ? (0, reference_to_maybe_1.makeAllMaybe)(otherwise?.out, nextGraph, finalEnvironment, true, cdFalse) : otherwise?.out ?? []));
|
|
84
86
|
(0, common_1.patchFunctionCall)({
|
|
85
87
|
nextGraph,
|
|
86
88
|
rootId,
|
|
@@ -15,7 +15,7 @@ function processLibrary(name, args, rootId, data) {
|
|
|
15
15
|
logger_1.dataflowLogger.warn(`Currently only one-arg library-likes are allows (for ${name.content}), skipping`);
|
|
16
16
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, hasUnknownSideEffect: true, origin: 'default' }).information;
|
|
17
17
|
}
|
|
18
|
-
const nameToLoad = (0, unpack_argument_1.
|
|
18
|
+
const nameToLoad = (0, unpack_argument_1.unpackNonameArg)(args[0]);
|
|
19
19
|
if (nameToLoad === undefined || nameToLoad.type !== type_1.RType.Symbol) {
|
|
20
20
|
logger_1.dataflowLogger.warn('No library name provided, skipping');
|
|
21
21
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, hasUnknownSideEffect: true, origin: 'default' }).information;
|
|
@@ -18,7 +18,7 @@ function processPipe(name, args, rootId, data) {
|
|
|
18
18
|
logger_1.dataflowLogger.warn(`Pipe ${name.content} has something else than 2 arguments, skipping`);
|
|
19
19
|
return information;
|
|
20
20
|
}
|
|
21
|
-
const [lhs, rhs] = args.map(e => (0, unpack_argument_1.
|
|
21
|
+
const [lhs, rhs] = args.map(e => (0, unpack_argument_1.unpackNonameArg)(e));
|
|
22
22
|
(0, assert_1.guard)(lhs !== undefined && rhs !== undefined, () => `lhs and rhs must be present, but ${JSON.stringify(lhs)} and ${JSON.stringify(rhs)} were found instead.`);
|
|
23
23
|
if (rhs.type !== type_1.RType.FunctionCall) {
|
|
24
24
|
logger_1.dataflowLogger.warn(`Expected rhs of pipe to be a function call, but got ${rhs.type} instead.`);
|
|
@@ -21,7 +21,7 @@ function processRepeatLoop(name, args, rootId, data) {
|
|
|
21
21
|
logger_1.dataflowLogger.warn(`Repeat-Loop ${name.content} does not have 1 argument, skipping`);
|
|
22
22
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
23
23
|
}
|
|
24
|
-
const unpacked = (0, unpack_argument_1.
|
|
24
|
+
const unpacked = (0, unpack_argument_1.unpackNonameArg)(args[0]);
|
|
25
25
|
const { information, processedArguments } = (0, known_call_handling_1.processKnownFunctionCall)({
|
|
26
26
|
name,
|
|
27
27
|
args: unpacked ? [unpacked] : args,
|
|
@@ -59,11 +59,11 @@ args, rootId, data, config) {
|
|
|
59
59
|
data,
|
|
60
60
|
rootId,
|
|
61
61
|
name,
|
|
62
|
-
argumentProcessResult: args.map(a => a === r_function_call_1.EmptyArgument ? undefined : { entryPoint: (0, unpack_argument_1.
|
|
62
|
+
argumentProcessResult: args.map(a => a === r_function_call_1.EmptyArgument ? undefined : { entryPoint: (0, unpack_argument_1.unpackNonameArg)(a)?.info.id }),
|
|
63
63
|
origin: 'builtin:replacement',
|
|
64
64
|
link: config.assignRootId ? { origin: [config.assignRootId] } : undefined
|
|
65
65
|
});
|
|
66
|
-
const firstArg = (0, unpack_argument_1.
|
|
66
|
+
const firstArg = (0, unpack_argument_1.unpackNonameArg)(args[0]);
|
|
67
67
|
(0, unknown_replacement_1.handleReplacementOperator)({
|
|
68
68
|
operator: name.content,
|
|
69
69
|
target: firstArg?.lexeme,
|
|
@@ -80,7 +80,7 @@ args, rootId, data, config) {
|
|
|
80
80
|
res.graph.addEdge(rootId, ref, edge_1.EdgeType.Reads);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
const fa = (0, unpack_argument_1.
|
|
83
|
+
const fa = (0, unpack_argument_1.unpackNonameArg)(args[0]);
|
|
84
84
|
if (!data.ctx.config.solver.pointerTracking && fa) {
|
|
85
85
|
res = {
|
|
86
86
|
...res,
|
|
@@ -4,7 +4,6 @@ exports.processRm = processRm;
|
|
|
4
4
|
const known_call_handling_1 = require("../known-call-handling");
|
|
5
5
|
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
6
6
|
const logger_1 = require("../../../../../logger");
|
|
7
|
-
const remove_1 = require("../../../../../environments/remove");
|
|
8
7
|
const type_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/type");
|
|
9
8
|
/**
|
|
10
9
|
*
|
|
@@ -32,13 +31,16 @@ function processRm(name, args, rootId, data) {
|
|
|
32
31
|
names.push(unpacked.content.str);
|
|
33
32
|
}
|
|
34
33
|
}
|
|
35
|
-
let env = res.environment;
|
|
34
|
+
let env = res.environment.current;
|
|
36
35
|
for (const name of names) {
|
|
37
|
-
env =
|
|
36
|
+
env = env.remove(name);
|
|
38
37
|
}
|
|
39
38
|
return {
|
|
40
39
|
...res,
|
|
41
|
-
environment:
|
|
40
|
+
environment: {
|
|
41
|
+
current: env,
|
|
42
|
+
level: res.environment.level
|
|
43
|
+
}
|
|
42
44
|
};
|
|
43
45
|
}
|
|
44
46
|
//# sourceMappingURL=built-in-rm.js.map
|
|
@@ -148,7 +148,7 @@ function processSourceCall(name, args, rootId, data, config) {
|
|
|
148
148
|
sourceFile = [(0, retriever_1.removeRQuotes)(sourceFileArgument.lexeme)];
|
|
149
149
|
}
|
|
150
150
|
else if (sourceFileArgument !== r_function_call_1.EmptyArgument) {
|
|
151
|
-
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(sourceFileArgument.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.ctx.config.solver.variables }));
|
|
151
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(sourceFileArgument.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.ctx.config.solver.variables, ctx: data.ctx }));
|
|
152
152
|
sourceFile = resolved?.elements.map(r => r.type === 'string' && (0, r_value_1.isValue)(r.value) ? r.value.str : undefined).filter(assert_1.isNotUndefined);
|
|
153
153
|
}
|
|
154
154
|
if (sourceFile && sourceFile.length === 1) {
|
|
@@ -8,11 +8,11 @@ const assert_1 = require("../../../../../../util/assert");
|
|
|
8
8
|
const unpack_argument_1 = require("../argument/unpack-argument");
|
|
9
9
|
const r_function_call_1 = require("../../../../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
10
10
|
const logger_1 = require("../../../../../logger");
|
|
11
|
-
const environment_1 = require("../../../../../environments/environment");
|
|
12
11
|
const edge_1 = require("../../../../../graph/edge");
|
|
13
12
|
const identifier_1 = require("../../../../../environments/identifier");
|
|
14
13
|
const general_1 = require("../../../../../eval/values/general");
|
|
15
14
|
const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
|
|
15
|
+
const reference_to_maybe_1 = require("../../../../../environments/reference-to-maybe");
|
|
16
16
|
/**
|
|
17
17
|
*
|
|
18
18
|
*/
|
|
@@ -21,13 +21,13 @@ function processWhileLoop(name, args, rootId, data) {
|
|
|
21
21
|
logger_1.dataflowLogger.warn(`While-Loop ${name.content} does not have 2 arguments, skipping`);
|
|
22
22
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
23
23
|
}
|
|
24
|
-
const unpackedArgs = args.map(e => (0, unpack_argument_1.
|
|
24
|
+
const unpackedArgs = args.map(e => (0, unpack_argument_1.unpackNonameArg)(e));
|
|
25
25
|
if (unpackedArgs.some(assert_1.isUndefined)) {
|
|
26
26
|
logger_1.dataflowLogger.warn(`While-Loop ${name.content} has empty arguments in ${JSON.stringify(args)}, skipping`);
|
|
27
27
|
return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, origin: 'default' }).information;
|
|
28
28
|
}
|
|
29
29
|
// we should defer this to the abstract interpretation
|
|
30
|
-
const values = (0, alias_tracking_1.resolveIdToValue)(unpackedArgs[0]?.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.ctx.config.solver.variables });
|
|
30
|
+
const values = (0, alias_tracking_1.resolveIdToValue)(unpackedArgs[0]?.info.id, { environment: data.environment, idMap: data.completeAst.idMap, resolve: data.ctx.config.solver.variables, ctx: data.ctx });
|
|
31
31
|
const conditionIsAlwaysFalse = (0, general_1.valueSetGuard)(values)?.elements.every(d => d.type === 'logical' && d.value === false) ?? false;
|
|
32
32
|
//We don't care about the body if it never executes
|
|
33
33
|
if (conditionIsAlwaysFalse) {
|
|
@@ -69,7 +69,7 @@ function processWhileLoop(name, args, rootId, data) {
|
|
|
69
69
|
return condition;
|
|
70
70
|
}
|
|
71
71
|
const cdTrue = { id: name.info.id, when: true };
|
|
72
|
-
const remainingInputs = (0, linker_1.linkInputs)((0,
|
|
72
|
+
const remainingInputs = (0, linker_1.linkInputs)((0, reference_to_maybe_1.makeAllMaybe)(body.unknownReferences, information.graph, information.environment, false, cdTrue).concat((0, reference_to_maybe_1.makeAllMaybe)(body.in, information.graph, information.environment, false, cdTrue)), information.environment, condition.in.concat(condition.unknownReferences), information.graph, true);
|
|
73
73
|
(0, linker_1.linkCircularRedefinitionsWithinALoop)(information.graph, (0, linker_1.produceNameSharedIdMap)((0, linker_1.findNonLocalReads)(information.graph, condition.in)), body.out);
|
|
74
74
|
(0, linker_1.reapplyLoopExitPoints)(body.exitPoints, body.in.concat(body.out, body.unknownReferences));
|
|
75
75
|
// as the while-loop always evaluates its condition
|
|
@@ -77,7 +77,7 @@ function processWhileLoop(name, args, rootId, data) {
|
|
|
77
77
|
return {
|
|
78
78
|
unknownReferences: [],
|
|
79
79
|
in: [{ nodeId: name.info.id, name: name.lexeme, controlDependencies: originalDependency, type: identifier_1.ReferenceType.Function }, ...remainingInputs],
|
|
80
|
-
out: condition.out.concat((0,
|
|
80
|
+
out: condition.out.concat((0, reference_to_maybe_1.makeAllMaybe)(body.out, information.graph, information.environment, true, cdTrue)),
|
|
81
81
|
entryPoint: name.info.id,
|
|
82
82
|
exitPoints: (0, info_1.filterOutLoopExitPoints)(body.exitPoints),
|
|
83
83
|
graph: information.graph,
|
|
@@ -29,8 +29,7 @@ function forceVertexArgumentValueReferences(rootId, value, graph, env) {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
|
-
const containedSubflowIn = graph.
|
|
33
|
-
.filter(([, info]) => (0, vertex_1.isFunctionDefinitionVertex)(info))
|
|
32
|
+
const containedSubflowIn = graph.verticesOfType(vertex_1.VertexType.FunctionDefinition)
|
|
34
33
|
.flatMap(([, info]) => info.subflow.in)
|
|
35
34
|
.toArray();
|
|
36
35
|
// try to resolve them against the current environment
|
|
@@ -122,7 +121,7 @@ function patchFunctionCall({ nextGraph, rootId, name, data, argumentProcessResul
|
|
|
122
121
|
args: argumentProcessResult.map(arg => arg === undefined ? r_function_call_1.EmptyArgument : { nodeId: arg.entryPoint, controlDependencies: undefined, call: undefined, type: identifier_1.ReferenceType.Argument }),
|
|
123
122
|
origin: [origin],
|
|
124
123
|
link
|
|
125
|
-
}, !nextGraph.hasVertex(rootId) || nextGraph.isRoot(rootId), true);
|
|
124
|
+
}, data.ctx.env.makeCleanEnv(), !nextGraph.hasVertex(rootId) || nextGraph.isRoot(rootId), true);
|
|
126
125
|
for (const arg of argumentProcessResult) {
|
|
127
126
|
if (arg) {
|
|
128
127
|
nextGraph.addEdge(rootId, arg.entryPoint, edge_1.EdgeType.Argument);
|
|
@@ -52,7 +52,7 @@ function processKnownFunctionCall({ name, args, rootId, data, reverseOrder = fal
|
|
|
52
52
|
args: reverseOrder ? callArgs.reverse() : callArgs,
|
|
53
53
|
indicesCollection: indicesCollection,
|
|
54
54
|
origin: origin === 'default' ? ['function'] : [origin]
|
|
55
|
-
});
|
|
55
|
+
}, data.ctx.env.makeCleanEnv());
|
|
56
56
|
if (hasUnknownSideEffect) {
|
|
57
57
|
(0, unknown_side_effect_1.handleUnknownSideEffect)(finalGraph, data.environment, rootId);
|
|
58
58
|
}
|
|
@@ -45,7 +45,7 @@ function processUnnamedFunctionCall(functionCall, data) {
|
|
|
45
45
|
cds: data.controlDependencies,
|
|
46
46
|
args: callArgs, // same reference
|
|
47
47
|
origin: [exports.UnnamedFunctionCallOrigin]
|
|
48
|
-
});
|
|
48
|
+
}, data.ctx.env.makeCleanEnv());
|
|
49
49
|
let inIds = remainingReadInArgs;
|
|
50
50
|
inIds.push({ nodeId: functionRootId, name: functionCallName, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function });
|
|
51
51
|
if (functionCall.calledFunction.type === type_1.RType.FunctionDefinition) {
|
|
@@ -34,7 +34,7 @@ function processFunctionArgument(argument, data) {
|
|
|
34
34
|
tag: vertex_1.VertexType.Use,
|
|
35
35
|
id: argument.info.id,
|
|
36
36
|
cds: data.controlDependencies
|
|
37
|
-
});
|
|
37
|
+
}, data.ctx.env.makeCleanEnv());
|
|
38
38
|
entryPoint = argument.info.id;
|
|
39
39
|
}
|
|
40
40
|
const ingoingRefs = [...value?.unknownReferences ?? [], ...value?.in ?? [], ...(name === undefined ? [] : [...name.in])];
|
|
@@ -22,7 +22,7 @@ function processSymbol(symbol, data) {
|
|
|
22
22
|
tag: vertex_1.VertexType.Use,
|
|
23
23
|
id: symbol.info.id,
|
|
24
24
|
cds: data.controlDependencies
|
|
25
|
-
}),
|
|
25
|
+
}, data.ctx.env.makeCleanEnv()),
|
|
26
26
|
entryPoint: symbol.info.id,
|
|
27
27
|
exitPoints: [{ nodeId: symbol.info.id, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }]
|
|
28
28
|
};
|
|
@@ -4,4 +4,4 @@ import type { RNodeWithParent } from '../../../r-bridge/lang-4.x/ast/model/proce
|
|
|
4
4
|
/**
|
|
5
5
|
*
|
|
6
6
|
*/
|
|
7
|
-
export declare function processValue<OtherInfo>({ info: { id } }: RNodeWithParent,
|
|
7
|
+
export declare function processValue<OtherInfo>({ info: { id } }: RNodeWithParent, { controlDependencies, completeAst: { idMap }, ctx: { env }, environment }: DataflowProcessorInformation<OtherInfo>): DataflowInformation;
|
|
@@ -7,18 +7,18 @@ const identifier_1 = require("../../environments/identifier");
|
|
|
7
7
|
/**
|
|
8
8
|
*
|
|
9
9
|
*/
|
|
10
|
-
function processValue({ info: { id } },
|
|
10
|
+
function processValue({ info: { id } }, { controlDependencies, completeAst: { idMap }, ctx: { env }, environment }) {
|
|
11
11
|
return {
|
|
12
12
|
unknownReferences: [],
|
|
13
|
-
in: [{ nodeId: id, name: undefined, controlDependencies
|
|
13
|
+
in: [{ nodeId: id, name: undefined, controlDependencies, type: identifier_1.ReferenceType.Constant }],
|
|
14
14
|
out: [],
|
|
15
|
-
environment
|
|
16
|
-
graph: new graph_1.DataflowGraph(
|
|
15
|
+
environment,
|
|
16
|
+
graph: new graph_1.DataflowGraph(idMap).addVertex({
|
|
17
17
|
tag: vertex_1.VertexType.Value,
|
|
18
18
|
id: id,
|
|
19
|
-
cds:
|
|
20
|
-
}),
|
|
21
|
-
exitPoints: [{ nodeId: id, type: 0 /* ExitPointType.Default */, controlDependencies
|
|
19
|
+
cds: controlDependencies
|
|
20
|
+
}, env.makeCleanEnv()),
|
|
21
|
+
exitPoints: [{ nodeId: id, type: 0 /* ExitPointType.Default */, controlDependencies }],
|
|
22
22
|
entryPoint: id
|
|
23
23
|
};
|
|
24
24
|
}
|
package/dataflow/processor.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { ControlDependency, DataflowInformation } from './info';
|
|
5
5
|
import type { NormalizedAst, ParentInformation, RNodeWithParent } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
6
|
-
import type {
|
|
6
|
+
import type { REnvironmentInformation } from './environments/environment';
|
|
7
7
|
import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
|
|
8
8
|
import type { KnownParserType, Parser } from '../r-bridge/parser';
|
|
9
9
|
import type { FlowrAnalyzerContext } from '../project/context/flowr-analyzer-context';
|
|
@@ -31,10 +31,6 @@ export interface DataflowProcessorInformation<OtherInfo> {
|
|
|
31
31
|
* The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
|
|
32
32
|
*/
|
|
33
33
|
readonly controlDependencies: ControlDependency[] | undefined;
|
|
34
|
-
/**
|
|
35
|
-
* The built-in environment
|
|
36
|
-
*/
|
|
37
|
-
readonly builtInEnvironment: IEnvironment;
|
|
38
34
|
/**
|
|
39
35
|
* The flowr context used for environment seeding, files, and precision control, ...
|
|
40
36
|
*/
|
|
@@ -82,13 +82,14 @@ ${switchCodeAndGraph ? dfGraph : codeText}
|
|
|
82
82
|
}
|
|
83
83
|
/** returns resolved expected df graph */
|
|
84
84
|
async function verifyExpectedSubgraph(parser, code, expectedSubgraph) {
|
|
85
|
+
const context = (0, flowr_analyzer_context_1.contextFromInput)(code);
|
|
85
86
|
/* we verify that we get what we want first! */
|
|
86
87
|
const info = await (0, default_pipelines_1.createDataflowPipeline)(parser, {
|
|
87
|
-
context:
|
|
88
|
+
context: context,
|
|
88
89
|
getId: (0, decorate_1.deterministicCountingIdGenerator)(0)
|
|
89
90
|
}).allRemainingSteps();
|
|
90
91
|
expectedSubgraph.setIdMap(info.normalize.idMap);
|
|
91
|
-
expectedSubgraph = (0, resolve_graph_1.resolveDataflowGraph)(expectedSubgraph);
|
|
92
|
+
expectedSubgraph = (0, resolve_graph_1.resolveDataflowGraph)(expectedSubgraph, context);
|
|
92
93
|
const report = (0, diff_dataflow_graph_1.diffOfDataflowGraphs)({ name: 'expected', graph: expectedSubgraph }, { name: 'got', graph: info.dataflow.graph }, {
|
|
93
94
|
leftIsSubgraph: true
|
|
94
95
|
});
|
|
@@ -64,12 +64,13 @@ ${(0, ast_1.normalizedAstToMermaid)(result.normalize.ast, prefix)}
|
|
|
64
64
|
*/
|
|
65
65
|
async function verifyExpectedSubgraph(shell, code, expectedSubgraph) {
|
|
66
66
|
/* we verify that we get what we want first! */
|
|
67
|
+
const context = (0, flowr_analyzer_context_1.contextFromInput)(code);
|
|
67
68
|
const info = await (0, default_pipelines_1.createDataflowPipeline)(shell, {
|
|
68
|
-
context:
|
|
69
|
+
context: context,
|
|
69
70
|
getId: (0, decorate_1.deterministicCountingIdGenerator)(0)
|
|
70
71
|
}).allRemainingSteps();
|
|
71
72
|
expectedSubgraph.setIdMap(info.normalize.idMap);
|
|
72
|
-
expectedSubgraph = (0, resolve_graph_1.resolveDataflowGraph)(expectedSubgraph);
|
|
73
|
+
expectedSubgraph = (0, resolve_graph_1.resolveDataflowGraph)(expectedSubgraph, context);
|
|
73
74
|
const report = (0, diff_dataflow_graph_1.diffOfDataflowGraphs)({ name: 'expected', graph: expectedSubgraph }, { name: 'got', graph: info.dataflow.graph }, {
|
|
74
75
|
leftIsSubgraph: true
|
|
75
76
|
});
|
|
@@ -133,7 +133,7 @@ export interface FnElementInfo {
|
|
|
133
133
|
export declare function printCodeOfElement({ program, info, dropLinesEnd, dropLinesStart, doNotAutoGobble, hideDefinedAt }: FnElementInfo, name: string): string;
|
|
134
134
|
/**
|
|
135
135
|
* Create a short link to a type in the documentation.
|
|
136
|
-
* If you create a wiki, please refer to the functions provided by the {@link
|
|
136
|
+
* If you create a wiki, please refer to the functions provided by the {@link GeneralDocContext}.
|
|
137
137
|
* @param name - The name of the type, e.g. `MyType`, may include a container, e.g.,`MyContainer::MyType` (this works with function nestings too)
|
|
138
138
|
* Use `:::` if you want to access a scoped function, but the name should be displayed without the scope
|
|
139
139
|
* @param hierarchy - The hierarchy of types to search in
|
|
@@ -477,7 +477,7 @@ function printCodeOfElement({ program, info, dropLinesEnd = 0, dropLinesStart =
|
|
|
477
477
|
const lines = code.replaceAll('\t', ' ').split(/\n/g);
|
|
478
478
|
let gobble = Number.POSITIVE_INFINITY;
|
|
479
479
|
for (const line of lines) {
|
|
480
|
-
const match = line.match(/^(\s
|
|
480
|
+
const match = line.match(/^(\s*)\S+/);
|
|
481
481
|
if (match) {
|
|
482
482
|
gobble = Math.min(gobble, match[1].length);
|
|
483
483
|
}
|
|
@@ -523,7 +523,7 @@ function retrieveNode(name, hierarchy, fuzzy = false, type = undefined) {
|
|
|
523
523
|
}
|
|
524
524
|
/**
|
|
525
525
|
* Create a short link to a type in the documentation.
|
|
526
|
-
* If you create a wiki, please refer to the functions provided by the {@link
|
|
526
|
+
* If you create a wiki, please refer to the functions provided by the {@link GeneralDocContext}.
|
|
527
527
|
* @param name - The name of the type, e.g. `MyType`, may include a container, e.g.,`MyContainer::MyType` (this works with function nestings too)
|
|
528
528
|
* Use `:::` if you want to access a scoped function, but the name should be displayed without the scope
|
|
529
529
|
* @param hierarchy - The hierarchy of types to search in
|
|
@@ -26,6 +26,7 @@ const flowr_analyzer_plugin_defaults_1 = require("../project/plugins/flowr-analy
|
|
|
26
26
|
const doc_maker_1 = require("./wiki-mk/doc-maker");
|
|
27
27
|
const flowr_analyzer_rmd_file_plugin_1 = require("../project/plugins/file-plugins/notebooks/flowr-analyzer-rmd-file-plugin");
|
|
28
28
|
const flowr_analyzer_plugin_1 = require("../project/plugins/flowr-analyzer-plugin");
|
|
29
|
+
const flowr_analyzer_environment_context_1 = require("../project/context/flowr-analyzer-environment-context");
|
|
29
30
|
async function analyzerQuickExample() {
|
|
30
31
|
const analyzer = await new flowr_analyzer_builder_1.FlowrAnalyzerBuilder()
|
|
31
32
|
.setEngine('tree-sitter')
|
|
@@ -78,7 +79,8 @@ ${(0, doc_structure_1.collapsibleToc)({
|
|
|
78
79
|
'Context Information': {
|
|
79
80
|
'Files Context': undefined,
|
|
80
81
|
'Loading Order Context': undefined,
|
|
81
|
-
'Dependencies Context': undefined
|
|
82
|
+
'Dependencies Context': undefined,
|
|
83
|
+
'Environment Context': undefined
|
|
82
84
|
},
|
|
83
85
|
'Caching': undefined
|
|
84
86
|
})}
|
|
@@ -396,6 +398,17 @@ Probably the most important method is
|
|
|
396
398
|
${ctx.linkM(flowr_analyzer_dependencies_context_1.FlowrAnalyzerDependenciesContext, 'getDependency', { codeFont: true, realNameWrapper: 'i' })}
|
|
397
399
|
that allows you to query for a specific dependency by name.
|
|
398
400
|
|
|
401
|
+
${(0, doc_structure_1.section)('Environment Context', 3)}
|
|
402
|
+
|
|
403
|
+
Here is the structure of the ${ctx.link(flowr_analyzer_environment_context_1.FlowrAnalyzerEnvironmentContext)} that provides access to the built-in environment:
|
|
404
|
+
|
|
405
|
+
${ctx.hierarchy(flowr_analyzer_environment_context_1.FlowrAnalyzerEnvironmentContext, { showImplSnippet: false })}
|
|
406
|
+
|
|
407
|
+
The environment context provides access to the built-in environment via
|
|
408
|
+
${ctx.linkM(flowr_analyzer_environment_context_1.FlowrAnalyzerEnvironmentContext, 'makeCleanEnv', { codeFont: true, realNameWrapper: 'i' })}.
|
|
409
|
+
It also provides the empty built-in environment, which only contains primitives, via
|
|
410
|
+
${ctx.linkM(flowr_analyzer_environment_context_1.FlowrAnalyzerEnvironmentContext, 'makeCleanEnvWithEmptyBuiltIns', { codeFont: true, realNameWrapper: 'i' })}.
|
|
411
|
+
|
|
399
412
|
${(0, doc_structure_1.section)('Caching', 2)}
|
|
400
413
|
|
|
401
414
|
To speed up analyses, flowR provides a caching mechanism that stores intermediate results of the analysis.
|
|
@@ -195,7 +195,7 @@ However, in general, flowR may use any fitting handler as an origin. For example
|
|
|
195
195
|
${(0, doc_structure_1.details)('Example: Simple Function Call (unresolved)', await (async () => {
|
|
196
196
|
const code = 'foo(x,3,y=3,)';
|
|
197
197
|
const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(parser, code, { mark: new Set([8]), exposeResult: true });
|
|
198
|
-
const callInfo =
|
|
198
|
+
const callInfo = info.dataflow.graph.vertices(true).find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionCall && vertex.name === 'foo');
|
|
199
199
|
(0, assert_1.guard)(callInfo !== undefined, () => `Could not find call vertex for ${code}`);
|
|
200
200
|
const [callId, callVert] = callInfo;
|
|
201
201
|
const inverseMapReferenceTypes = Object.fromEntries(Object.entries(identifier_1.ReferenceType).map(([k, v]) => [v, k]));
|
|
@@ -308,7 +308,7 @@ Consider a case in which you have a built-in function (like the assignment opera
|
|
|
308
308
|
|
|
309
309
|
${await (async () => {
|
|
310
310
|
const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(parser, 'x <- 2\nif(u) `<-` <- `*`\nx <- 3', { switchCodeAndGraph: true, mark: new Set([9, '9->0', '9->10']), exposeResult: true });
|
|
311
|
-
const interestingUseOfAssignment =
|
|
311
|
+
const interestingUseOfAssignment = info.dataflow.graph.vertices(true).find(([, vertex]) => vertex.id === 11);
|
|
312
312
|
(0, assert_1.guard)(interestingUseOfAssignment !== undefined, () => 'Could not find interesting assignment vertex for the code');
|
|
313
313
|
const [id, interestingVertex] = interestingUseOfAssignment;
|
|
314
314
|
const env = interestingVertex.environment;
|
|
@@ -333,7 +333,7 @@ Hence, trying to re-resolve the call using ${ctx.link(linker_1.getAllFunctionCal
|
|
|
333
333
|
the following target ids: { \`${[...(0, linker_1.getAllFunctionCallTargets)(id, info.dataflow.graph)].join('`, `')}\` }.
|
|
334
334
|
This way we know that the call may refer to the built-in assignment operator or to the multiplication.
|
|
335
335
|
Similarly, trying to resolve the name with ${ctx.link(resolve_by_name_1.resolveByName)}\` using the environment attached to the call vertex (filtering for any reference type) returns (in a similar fashion):
|
|
336
|
-
{ \`${(0, resolve_by_name_1.
|
|
336
|
+
{ \`${(0, resolve_by_name_1.resolveByNameAnyType)(name, env)?.map(d => d.nodeId).join('`, `')}\` } (however, the latter will not trace aliases).
|
|
337
337
|
|
|
338
338
|
`;
|
|
339
339
|
})()}
|
|
@@ -449,8 +449,7 @@ vertices of function definitions or not (e.g., \`${new graph_1.DataflowGraph(und
|
|
|
449
449
|
|
|
450
450
|
${(0, doc_structure_1.details)('Example: Nested Function Definitions', await (async () => {
|
|
451
451
|
const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(parser, 'f <- function() { g <- function() 3 }', { mark: new Set([9, 6]), exposeResult: true });
|
|
452
|
-
const definitions = info.dataflow.graph.
|
|
453
|
-
.filter(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionDefinition)
|
|
452
|
+
const definitions = info.dataflow.graph.verticesOfType(vertex_1.VertexType.FunctionDefinition)
|
|
454
453
|
.map(([id, vertex]) => `| \`${id}\` | { \`${[...vertex.subflow.graph].join('`, `')}\` } |`)
|
|
455
454
|
.toArray();
|
|
456
455
|
return `
|
|
@@ -144,7 +144,7 @@ df[6, "value"]
|
|
|
144
144
|
const certaintyText = `\`${(0, html_hover_over_1.textWithTooltip)(rule.info.certainty, certaintyDoc)}\``;
|
|
145
145
|
if (format === 'short') {
|
|
146
146
|
ruleExplanations.set(name, () => Promise.resolve(`
|
|
147
|
-
**[${rule.info.name}](${doc_files_1.FlowrWikiBaseRef}/${getPageNameForLintingRule(name)}):** ${rule.info.description} [see ${(0, doc_types_1.shortLinkFile)(ruleType, types)}]\\
|
|
147
|
+
**[${rule.info.name}](${doc_files_1.FlowrWikiBaseRef}/${encodeURIComponent(getPageNameForLintingRule(name))}):** ${rule.info.description} [see ${(0, doc_types_1.shortLinkFile)(ruleType, types)}]\\
|
|
148
148
|
${tags}
|
|
149
149
|
|
|
150
150
|
`.trim()));
|
|
@@ -16,8 +16,9 @@ const DefaultReplacementPatterns = [
|
|
|
16
16
|
[/%%\s*\d*-+/g, ''],
|
|
17
17
|
[/"[rR]": "\d+\.\d+\.\d+.*?"/g, ''],
|
|
18
18
|
[/R\s*\d+\.\d+\.\d+/g, ''],
|
|
19
|
+
[/v\d+\.\d+\.\d+/g, ''],
|
|
19
20
|
// async wrapper depends on whether the promise got forfilled already
|
|
20
|
-
[
|
|
21
|
+
[/async|%20/g, '']
|
|
21
22
|
];
|
|
22
23
|
/**
|
|
23
24
|
* Abstract base class for generating wiki files.
|
package/linter/linter-rules.d.ts
CHANGED
|
@@ -57,7 +57,7 @@ export declare const LintingRules: {
|
|
|
57
57
|
};
|
|
58
58
|
readonly 'seeded-randomness': {
|
|
59
59
|
readonly createSearch: (config: import("./rules/seeded-randomness").SeededRandomnessConfig) => import("../search/flowr-search-builder").FlowrSearchBuilder<"all", ["with", "filter", "with"], import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, Promise<import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>>;
|
|
60
|
-
readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: import("./rules/seeded-randomness").SeededRandomnessConfig, { dataflow }: {
|
|
60
|
+
readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: import("./rules/seeded-randomness").SeededRandomnessConfig, { dataflow, analyzer }: {
|
|
61
61
|
normalize: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
62
62
|
dataflow: import("../dataflow/info").DataflowInformation;
|
|
63
63
|
cfg: import("../control-flow/control-flow-graph").ControlFlowInformation;
|
|
@@ -231,7 +231,7 @@ export declare const LintingRules: {
|
|
|
231
231
|
readonly name: "Dataframe Access Validation";
|
|
232
232
|
readonly tags: readonly [import("./linter-tags").LintingRuleTag.Bug, import("./linter-tags").LintingRuleTag.Usability, import("./linter-tags").LintingRuleTag.Reproducibility];
|
|
233
233
|
readonly certainty: import("./linter-format").LintingRuleCertainty.BestEffort;
|
|
234
|
-
readonly description: "Validates the
|
|
234
|
+
readonly description: "Validates the existence of accessed columns and rows of dataframes.";
|
|
235
235
|
readonly defaultConfig: {
|
|
236
236
|
readonly readLoadedData: false;
|
|
237
237
|
};
|