@eagleoutice/flowr 2.4.0 → 2.4.1
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 +23 -23
- package/benchmark/stats/size-of.js +3 -3
- package/cli/repl/commands/repl-query.js +1 -1
- package/core/pipeline-executor.js +0 -8
- package/core/steps/all/static-slicing/00-slice.js +1 -1
- package/dataflow/environments/append.js +1 -1
- package/dataflow/environments/built-in-config.d.ts +12 -4
- package/dataflow/environments/built-in-config.js +23 -82
- package/dataflow/environments/built-in.d.ts +38 -4
- package/dataflow/environments/built-in.js +106 -11
- package/dataflow/environments/clone.d.ts +3 -2
- package/dataflow/environments/clone.js +6 -5
- package/dataflow/environments/define.js +1 -2
- package/dataflow/environments/diff.js +1 -3
- package/dataflow/environments/environment.d.ts +18 -24
- package/dataflow/environments/environment.js +25 -37
- package/dataflow/environments/overwrite.d.ts +1 -1
- package/dataflow/environments/overwrite.js +1 -1
- package/dataflow/environments/remove.d.ts +2 -2
- package/dataflow/environments/remove.js +3 -4
- package/dataflow/environments/resolve-by-name.d.ts +3 -3
- package/dataflow/environments/resolve-by-name.js +4 -5
- package/dataflow/eval/resolve/alias-tracking.d.ts +12 -12
- package/dataflow/eval/resolve/alias-tracking.js +12 -12
- package/dataflow/eval/resolve/resolve.js +1 -1
- package/dataflow/extractor.js +6 -1
- package/dataflow/graph/dataflowgraph-builder.d.ts +3 -1
- package/dataflow/graph/graph.d.ts +2 -1
- package/dataflow/graph/graph.js +5 -1
- package/dataflow/info.d.ts +1 -1
- package/dataflow/internal/linker.js +9 -9
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +5 -5
- 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-function-definition.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-rm.js +1 -1
- package/dataflow/processor.d.ts +5 -1
- package/documentation/doc-util/doc-env.js +1 -2
- package/package.json +1 -1
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +7 -7
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +18 -0
- package/queries/catalog/dependencies-query/function-info/function-info.d.ts +9 -5
- package/queries/catalog/dependencies-query/function-info/read-functions.js +4 -2
- package/queries/catalog/dependencies-query/function-info/write-functions.js +5 -0
- 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/slicing/static/fingerprint.js +1 -2
- package/slicing/static/slice-call.d.ts +2 -1
- package/slicing/static/slice-call.js +3 -3
- package/slicing/static/static-slicer.d.ts +3 -4
- package/slicing/static/static-slicer.js +4 -4
- package/util/containers.d.ts +1 -0
- package/util/containers.js +1 -0
- package/util/json.js +1 -4
- package/util/mermaid/dfg.js +1 -2
- package/util/prefix.d.ts +1 -1
- package/util/version.js +1 -1
|
@@ -10,7 +10,6 @@ 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';
|
|
14
13
|
export interface AssignmentConfiguration extends ForceArguments {
|
|
15
14
|
readonly superAssignment?: boolean;
|
|
16
15
|
readonly swapSourceAndTarget?: boolean;
|
|
@@ -44,10 +43,10 @@ export interface AssignmentToSymbolParameters<OtherInfo> extends AssignmentConfi
|
|
|
44
43
|
* @param nodeToDefine - `x`
|
|
45
44
|
* @param sourceIds - `v`
|
|
46
45
|
* @param rootIdOfAssignment - `<-`
|
|
47
|
-
* @param
|
|
46
|
+
* @param data - The dataflow analysis fold backpack
|
|
48
47
|
* @param assignmentConfig - configuration for the assignment processing
|
|
49
48
|
*/
|
|
50
|
-
export declare function markAsAssignment(information: {
|
|
49
|
+
export declare function markAsAssignment<OtherInfo>(information: {
|
|
51
50
|
environment: REnvironmentInformation;
|
|
52
51
|
graph: DataflowGraph;
|
|
53
|
-
}, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId,
|
|
52
|
+
}, nodeToDefine: InGraphIdentifierDefinition, sourceIds: readonly NodeId[], rootIdOfAssignment: NodeId, data: DataflowProcessorInformation<OtherInfo>, assignmentConfig?: AssignmentConfiguration): void;
|
|
@@ -215,11 +215,11 @@ function checkTargetReferenceType(source, sourceInfo) {
|
|
|
215
215
|
* @param nodeToDefine - `x`
|
|
216
216
|
* @param sourceIds - `v`
|
|
217
217
|
* @param rootIdOfAssignment - `<-`
|
|
218
|
-
* @param
|
|
218
|
+
* @param data - The dataflow analysis fold backpack
|
|
219
219
|
* @param assignmentConfig - configuration for the assignment processing
|
|
220
220
|
*/
|
|
221
|
-
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment,
|
|
222
|
-
if (
|
|
221
|
+
function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignment, data, assignmentConfig) {
|
|
222
|
+
if (data.flowrConfig.solver.pointerTracking) {
|
|
223
223
|
let indicesCollection = undefined;
|
|
224
224
|
if (sourceIds.length === 1) {
|
|
225
225
|
// support for tracking indices.
|
|
@@ -248,7 +248,7 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
|
|
|
248
248
|
}
|
|
249
249
|
nodeToDefine.indicesCollection ??= indicesCollection;
|
|
250
250
|
}
|
|
251
|
-
information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment,
|
|
251
|
+
information.environment = (0, define_1.define)(nodeToDefine, assignmentConfig?.superAssignment, information.environment, data.flowrConfig);
|
|
252
252
|
information.graph.setDefinitionOfVertex(nodeToDefine);
|
|
253
253
|
if (!assignmentConfig?.quoteSource) {
|
|
254
254
|
for (const sourceId of sourceIds) {
|
|
@@ -285,7 +285,7 @@ function processAssignmentToSymbol(config) {
|
|
|
285
285
|
information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
|
|
286
286
|
// install assigned variables in environment
|
|
287
287
|
for (const write of writeNodes) {
|
|
288
|
-
markAsAssignment(information, write, [source.info.id], rootId, data
|
|
288
|
+
markAsAssignment(information, write, [source.info.id], rootId, data, config);
|
|
289
289
|
}
|
|
290
290
|
information.graph.addEdge(rootId, targetArg.entryPoint, edge_1.EdgeType.Returns);
|
|
291
291
|
if (quoteSource) {
|
|
@@ -50,24 +50,24 @@ function linkReadNameToWriteIfPossible(read, environments, listEnvironments, rem
|
|
|
50
50
|
}
|
|
51
51
|
function processNextExpression(currentElement, environment, listEnvironments, remainingRead, nextGraph) {
|
|
52
52
|
// all inputs that have not been written until now are read!
|
|
53
|
-
for (const read of
|
|
53
|
+
for (const read of currentElement.in.concat(currentElement.unknownReferences)) {
|
|
54
54
|
linkReadNameToWriteIfPossible(read, environment, listEnvironments, remainingRead, nextGraph);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextGraph, localDefs) {
|
|
58
58
|
for (const { functionCall, called } of calledEnvs) {
|
|
59
|
-
|
|
59
|
+
let callDependencies = null;
|
|
60
60
|
for (const calledFn of called) {
|
|
61
61
|
(0, assert_1.guard)(calledFn.tag === vertex_1.VertexType.FunctionDefinition, 'called function must be a function definition');
|
|
62
62
|
// only merge the environments they have in common
|
|
63
|
-
let environment = calledFn.environment;
|
|
63
|
+
let environment = calledFn.subflow.environment;
|
|
64
64
|
while (environment.level > inputEnvironment.level) {
|
|
65
65
|
environment = (0, scoping_1.popLocalEnvironment)(environment);
|
|
66
66
|
}
|
|
67
67
|
// update alle definitions to be defined at this function call
|
|
68
68
|
let current = environment.current;
|
|
69
69
|
let hasUpdate = false;
|
|
70
|
-
while (current
|
|
70
|
+
while (!current?.builtInEnv) {
|
|
71
71
|
for (const definitions of current.memory.values()) {
|
|
72
72
|
for (const def of definitions) {
|
|
73
73
|
if (!(0, built_in_1.isBuiltIn)(def.definedAt)) {
|
|
@@ -84,6 +84,9 @@ function updateSideEffectsForCalledFunctions(calledEnvs, inputEnvironment, nextG
|
|
|
84
84
|
if (localDefs.length > 0) {
|
|
85
85
|
environment = (0, remove_1.removeAll)(localDefs, environment);
|
|
86
86
|
}
|
|
87
|
+
if (callDependencies === null) {
|
|
88
|
+
callDependencies = nextGraph.getVertex(functionCall, true)?.cds;
|
|
89
|
+
}
|
|
87
90
|
inputEnvironment = (0, overwrite_1.overwriteEnvironment)(inputEnvironment, environment, callDependencies);
|
|
88
91
|
}
|
|
89
92
|
}
|
|
@@ -110,7 +113,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
110
113
|
continue;
|
|
111
114
|
}
|
|
112
115
|
// use the current environments for processing
|
|
113
|
-
data =
|
|
116
|
+
data.environment = environment;
|
|
114
117
|
const processed = (0, processor_1.processDataflowFor)(expression, data);
|
|
115
118
|
processedExpressions.push(processed);
|
|
116
119
|
nextGraph.mergeWith(processed.graph);
|
|
@@ -140,7 +143,6 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
140
143
|
break;
|
|
141
144
|
}
|
|
142
145
|
}
|
|
143
|
-
logger_1.dataflowLogger.trace(`expression list exits with ${remainingRead.size} remaining read names`);
|
|
144
146
|
if (defaultReturnExpr) {
|
|
145
147
|
exitPoints.push({
|
|
146
148
|
type: 0 /* ExitPointType.Default */,
|
|
@@ -148,7 +150,7 @@ function processExpressionList(name, args, rootId, data) {
|
|
|
148
150
|
controlDependencies: data.controlDependencies
|
|
149
151
|
});
|
|
150
152
|
}
|
|
151
|
-
const ingoing = [...remainingRead.values()
|
|
153
|
+
const ingoing = [...remainingRead.values().flatMap(v => v)];
|
|
152
154
|
const rootNode = data.completeAst.idMap.get(rootId);
|
|
153
155
|
const withGroup = rootNode?.grouping;
|
|
154
156
|
if (withGroup) {
|
|
@@ -107,7 +107,7 @@ function processFunctionDefinition(name, args, rootId, data) {
|
|
|
107
107
|
// this is no longer necessary when we update environments to be back to front (e.g., with a list of environments)
|
|
108
108
|
// this favors the bigger environment
|
|
109
109
|
function retrieveActiveEnvironment(callerEnvironment, baseEnvironment) {
|
|
110
|
-
callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(true);
|
|
110
|
+
callerEnvironment ??= (0, environment_1.initializeCleanEnvironments)(undefined, true);
|
|
111
111
|
let level = callerEnvironment.level ?? 0;
|
|
112
112
|
if (baseEnvironment.level !== level) {
|
|
113
113
|
while (baseEnvironment.level < level) {
|
|
@@ -212,7 +212,7 @@ function updateNestedFunctionCalls(graph, outEnvironment) {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
function prepareFunctionEnvironment(data) {
|
|
215
|
-
let env = (0, environment_1.initializeCleanEnvironments)();
|
|
215
|
+
let env = (0, environment_1.initializeCleanEnvironments)(data.builtInEnvironment.memory);
|
|
216
216
|
for (let i = 0; i < data.environment.level + 1 /* add another env */; i++) {
|
|
217
217
|
env = (0, scoping_1.pushLocalEnvironment)(env);
|
|
218
218
|
}
|
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 { REnvironmentInformation } from './environments/environment';
|
|
6
|
+
import type { IEnvironment, REnvironmentInformation } from './environments/environment';
|
|
7
7
|
import type { RParseRequest } from '../r-bridge/retriever';
|
|
8
8
|
import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
|
|
9
9
|
import type { KnownParserType, Parser } from '../r-bridge/parser';
|
|
@@ -36,6 +36,10 @@ export interface DataflowProcessorInformation<OtherInfo> {
|
|
|
36
36
|
* The chain of control-flow {@link NodeId}s that lead to the current node (e.g., of known ifs).
|
|
37
37
|
*/
|
|
38
38
|
readonly controlDependencies: ControlDependency[] | undefined;
|
|
39
|
+
/**
|
|
40
|
+
* The built-in environment
|
|
41
|
+
*/
|
|
42
|
+
readonly builtInEnvironment: IEnvironment;
|
|
39
43
|
/**
|
|
40
44
|
* The flowr configuration used for environment seeding, and precision control
|
|
41
45
|
*/
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.printEnvironmentToMarkdown = printEnvironmentToMarkdown;
|
|
4
|
-
const environment_1 = require("../../dataflow/environments/environment");
|
|
5
4
|
const dfg_1 = require("../../util/mermaid/dfg");
|
|
6
5
|
function printEnvironmentToMarkdown(env) {
|
|
7
6
|
if (env === undefined) {
|
|
8
7
|
return '?? (error)';
|
|
9
8
|
}
|
|
10
|
-
else if (env.
|
|
9
|
+
else if (env.builtInEnv) {
|
|
11
10
|
return `_Built-in Environment (${env.memory.size} entries)_`;
|
|
12
11
|
}
|
|
13
12
|
const lines = ['| Name | Definitions |', '|------|-------------|'];
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
2
2
|
import type { DataflowInformation } from '../dataflow/info';
|
|
3
3
|
import type { FlowrConfigOptions } from '../config';
|
|
4
|
+
import type { SemVer } from 'semver';
|
|
4
5
|
export interface BaseQueryFormat {
|
|
5
6
|
/** used to select the query type :) */
|
|
6
7
|
readonly type: string;
|
|
@@ -13,6 +14,7 @@ export interface BaseQueryResult {
|
|
|
13
14
|
readonly '.meta': BaseQueryMeta;
|
|
14
15
|
}
|
|
15
16
|
export interface BasicQueryData {
|
|
17
|
+
readonly lib?: Record<string, SemVer>;
|
|
16
18
|
readonly ast: NormalizedAst;
|
|
17
19
|
readonly dataflow: DataflowInformation;
|
|
18
20
|
readonly config: FlowrConfigOptions;
|
|
@@ -41,13 +41,7 @@ function satisfiesCallTargets(id, graph, callTarget) {
|
|
|
41
41
|
.filter(([, { types }]) => (0, edge_1.edgeIncludesType)(types, edge_1.EdgeType.Calls))
|
|
42
42
|
.map(([t]) => t);
|
|
43
43
|
let builtIn = false;
|
|
44
|
-
if (callVertex.environment
|
|
45
|
-
/* if we have a call with an unbound environment,
|
|
46
|
-
* this only happens if we are sure of built-in relations and want to save references
|
|
47
|
-
*/
|
|
48
|
-
builtIn = true;
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
44
|
+
if (callVertex.environment !== undefined) {
|
|
51
45
|
/*
|
|
52
46
|
* for performance and scoping reasons, flowR will not identify the global linkage,
|
|
53
47
|
* including any potential built-in mapping.
|
|
@@ -57,6 +51,12 @@ function satisfiesCallTargets(id, graph, callTarget) {
|
|
|
57
51
|
builtIn = true;
|
|
58
52
|
}
|
|
59
53
|
}
|
|
54
|
+
else {
|
|
55
|
+
/* if we have a call with an unbound environment,
|
|
56
|
+
* this only happens if we are sure of built-in relations and want to save references
|
|
57
|
+
*/
|
|
58
|
+
builtIn = true;
|
|
59
|
+
}
|
|
60
60
|
switch (callTarget) {
|
|
61
61
|
case CallTargets.Any:
|
|
62
62
|
return callTargets;
|
|
@@ -15,6 +15,7 @@ const write_functions_1 = require("./function-info/write-functions");
|
|
|
15
15
|
const function_info_1 = require("./function-info/function-info");
|
|
16
16
|
const identify_link_to_last_call_relation_1 = require("../call-context-query/identify-link-to-last-call-relation");
|
|
17
17
|
const resolve_argument_1 = require("../../../dataflow/eval/resolve/resolve-argument");
|
|
18
|
+
const assert_1 = require("../../../util/assert");
|
|
18
19
|
function collectNamespaceAccesses(data, libraries) {
|
|
19
20
|
/* for libraries, we have to additionally track all uses of `::` and `:::`, for this we currently simply traverse all uses */
|
|
20
21
|
(0, visitor_1.visitAst)(data.ast.ast, n => {
|
|
@@ -113,6 +114,8 @@ function dropInfoOnLinkedIds(linkedIds) {
|
|
|
113
114
|
}
|
|
114
115
|
return linkedIds.map(id => typeof id === 'object' ? id.id : id);
|
|
115
116
|
}
|
|
117
|
+
const readOnlyModes = new Set(['r', 'rt', 'rb']);
|
|
118
|
+
const writeOnlyModes = new Set(['w', 'wt', 'wb', 'a', 'at', 'ab']);
|
|
116
119
|
function getResults(data, results, kind, functions, makeInfo) {
|
|
117
120
|
const kindEntries = Object.entries(results?.kinds[kind]?.subkinds ?? {});
|
|
118
121
|
return kindEntries.flatMap(([name, results]) => results.flatMap(({ id, linkedIds }) => {
|
|
@@ -128,6 +131,21 @@ function getResults(data, results, kind, functions, makeInfo) {
|
|
|
128
131
|
const record = (0, objects_1.compactRecord)(makeInfo(id, vertex, undefined, undefined, dropInfoOnLinkedIds(linkedIds)));
|
|
129
132
|
return record ? [record] : [];
|
|
130
133
|
}
|
|
134
|
+
else if (info.ignoreIf === 'mode-only-read' || info.ignoreIf === 'mode-only-write') {
|
|
135
|
+
(0, assert_1.guard)('mode' in (info.additionalArgs ?? {}), 'Need additional argument mode when checking for mode');
|
|
136
|
+
const margs = info.additionalArgs?.mode;
|
|
137
|
+
(0, assert_1.guard)(margs, 'Need additional argument mode when checking for mode');
|
|
138
|
+
const modeArgs = (0, resolve_argument_1.getArgumentStringValue)(data.config.solver.variables, data.dataflow.graph, vertex, margs.argIdx, margs.argName, margs.resolveValue);
|
|
139
|
+
const modeValues = modeArgs?.values().flatMap(v => [...v]) ?? [];
|
|
140
|
+
if (info.ignoreIf === 'mode-only-read' && modeValues.every(m => m && readOnlyModes.has(m))) {
|
|
141
|
+
// all modes are read-only, so we can ignore this
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
else if (info.ignoreIf === 'mode-only-write' && modeValues.every(m => m && writeOnlyModes.has(m))) {
|
|
145
|
+
// all modes are write-only, so we can ignore this
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
}
|
|
131
149
|
const results = [];
|
|
132
150
|
for (const [arg, values] of foundValues.entries()) {
|
|
133
151
|
for (const value of values) {
|
|
@@ -12,13 +12,17 @@ export type DependencyInfoLink = LinkTo<RegExp | string, Omit<FunctionInfo, 'nam
|
|
|
12
12
|
when: DependencyInfoLinkConstraint;
|
|
13
13
|
} | undefined>;
|
|
14
14
|
export type DependencyInfoLinkAttachedInfo = DependencyInfoLink['attachLinkInfo'];
|
|
15
|
-
export interface
|
|
16
|
-
package?: string;
|
|
17
|
-
name: string;
|
|
15
|
+
export interface FunctionArgInfo {
|
|
18
16
|
/** the index if the argument can be positional, unnamed in case of something like `...`, if the argument must be given with the name, please leave undefined */
|
|
19
17
|
argIdx?: number | 'unnamed';
|
|
20
18
|
argName?: string;
|
|
21
|
-
linkTo?: DependencyInfoLink[];
|
|
22
19
|
resolveValue?: boolean | 'library';
|
|
23
|
-
|
|
20
|
+
}
|
|
21
|
+
export interface FunctionInfo extends FunctionArgInfo {
|
|
22
|
+
package?: string;
|
|
23
|
+
name: string;
|
|
24
|
+
linkTo?: DependencyInfoLink[];
|
|
25
|
+
ignoreIf?: 'arg-missing' | 'mode-only-read' | 'mode-only-write';
|
|
26
|
+
/** additional info on arguments - e.g. for the mode flag */
|
|
27
|
+
additionalArgs?: Record<string, FunctionArgInfo>;
|
|
24
28
|
}
|
|
@@ -10,8 +10,8 @@ exports.ReadFunctions = [
|
|
|
10
10
|
{ package: 'base', name: 'read.dcf', argIdx: 0, argName: 'file', resolveValue: true },
|
|
11
11
|
{ package: 'base', name: 'scan', argIdx: 0, argName: 'file', resolveValue: true },
|
|
12
12
|
{ package: 'utils', name: 'read.fwf', argIdx: 0, argName: 'file', resolveValue: true },
|
|
13
|
-
{ package: 'base', name: 'file', argIdx: 1, argName: 'open', resolveValue: true },
|
|
14
|
-
{ package: 'base', name: 'url', argIdx: 1, argName: 'open', resolveValue: true },
|
|
13
|
+
{ package: 'base', name: 'file', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-write', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
|
|
14
|
+
{ package: 'base', name: 'url', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-write', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
|
|
15
15
|
{ package: 'base', name: 'load', argIdx: 0, argName: 'file', resolveValue: true },
|
|
16
16
|
{ package: 'base', name: 'gzfile', argIdx: 1, argName: 'open', resolveValue: true },
|
|
17
17
|
{ package: 'base', name: 'bzfile', argIdx: 1, argName: 'open', resolveValue: true },
|
|
@@ -22,6 +22,8 @@ exports.ReadFunctions = [
|
|
|
22
22
|
{ package: 'base', name: 'matrix', argIdx: 0, argName: 'data', resolveValue: true },
|
|
23
23
|
{ package: 'base', name: 'readRDS', argIdx: 0, argName: 'file', resolveValue: true },
|
|
24
24
|
{ package: 'base', name: 'readLines', argIdx: 0, argName: 'con', resolveValue: true },
|
|
25
|
+
{ package: 'base', name: 'readChar', argIdx: 0, argName: 'con', resolveValue: true },
|
|
26
|
+
{ package: 'base', name: 'readBin', argIdx: 0, argName: 'con', resolveValue: true },
|
|
25
27
|
{ package: 'base', name: 'readRenviron', argIdx: 0, argName: 'path', resolveValue: true },
|
|
26
28
|
{ package: 'readr', name: 'read_csv', argIdx: 0, argName: 'file', resolveValue: true },
|
|
27
29
|
{ package: 'readr', name: 'read_csv2', argIdx: 0, argName: 'file', resolveValue: true },
|
|
@@ -19,6 +19,11 @@ exports.WriteFunctions = [
|
|
|
19
19
|
{ package: 'base', name: 'cat', linkTo: OutputRedirects, argName: 'file', resolveValue: true },
|
|
20
20
|
{ package: 'base', name: 'message', linkTo: OutputRedirects, resolveValue: true },
|
|
21
21
|
{ package: 'base', name: 'warning', linkTo: OutputRedirects, resolveValue: true },
|
|
22
|
+
{ package: 'base', name: 'writeLines', argIdx: 1, argName: 'con', resolveValue: true },
|
|
23
|
+
{ package: 'base', name: 'writeChar', argIdx: 1, argName: 'con', resolveValue: true },
|
|
24
|
+
{ package: 'base', name: 'writeBin', argIdx: 1, argName: 'con', resolveValue: true },
|
|
25
|
+
{ package: 'base', name: 'file', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-read', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
|
|
26
|
+
{ package: 'base', name: 'url', argIdx: 0, argName: 'description', resolveValue: true, ignoreIf: 'mode-only-read', additionalArgs: { mode: { argIdx: 1, argName: 'open', resolveValue: true } } },
|
|
22
27
|
{ package: 'readr', name: 'write_csv', argIdx: 1, argName: 'file', resolveValue: true },
|
|
23
28
|
{ package: 'readr', name: 'write_csv2', argIdx: 1, argName: 'file', resolveValue: true },
|
|
24
29
|
{ package: 'readr', name: 'write_delim', argIdx: 1, argName: 'file', resolveValue: true },
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { StaticSliceQuery, StaticSliceQueryResult } from './static-slice-query-format';
|
|
2
2
|
import type { BasicQueryData } from '../../base-query-format';
|
|
3
3
|
export declare function fingerPrintOfQuery(query: StaticSliceQuery): string;
|
|
4
|
-
export declare function executeStaticSliceQuery({ dataflow
|
|
4
|
+
export declare function executeStaticSliceQuery({ dataflow, ast, config }: BasicQueryData, queries: readonly StaticSliceQuery[]): StaticSliceQueryResult;
|
|
@@ -11,7 +11,7 @@ const _00_slice_1 = require("../../../core/steps/all/static-slicing/00-slice");
|
|
|
11
11
|
function fingerPrintOfQuery(query) {
|
|
12
12
|
return JSON.stringify(query);
|
|
13
13
|
}
|
|
14
|
-
function executeStaticSliceQuery({ dataflow
|
|
14
|
+
function executeStaticSliceQuery({ dataflow, ast, config }, queries) {
|
|
15
15
|
const start = Date.now();
|
|
16
16
|
const results = {};
|
|
17
17
|
for (const query of queries) {
|
|
@@ -21,7 +21,7 @@ function executeStaticSliceQuery({ dataflow: { graph }, ast, config }, queries)
|
|
|
21
21
|
}
|
|
22
22
|
const { criteria, noReconstruction, noMagicComments } = query;
|
|
23
23
|
const sliceStart = Date.now();
|
|
24
|
-
const slice = (0, static_slicer_1.staticSlice)(
|
|
24
|
+
const slice = (0, static_slicer_1.staticSlice)(dataflow, ast, criteria, query.direction ?? _00_slice_1.SliceDirection.Backward, config.solver.slicer?.threshold);
|
|
25
25
|
const sliceEnd = Date.now();
|
|
26
26
|
if (noReconstruction) {
|
|
27
27
|
results[key] = { slice: { ...slice, '.meta': { timing: sliceEnd - sliceStart } } };
|
|
@@ -7,7 +7,6 @@ exports.envFingerprint = envFingerprint;
|
|
|
7
7
|
exports.fingerprint = fingerprint;
|
|
8
8
|
const object_hash_1 = __importDefault(require("object-hash"));
|
|
9
9
|
const environment_1 = require("../../dataflow/environments/environment");
|
|
10
|
-
const built_in_1 = require("../../dataflow/environments/built-in");
|
|
11
10
|
function envFingerprint(env) {
|
|
12
11
|
return (0, object_hash_1.default)(env, {
|
|
13
12
|
algorithm: 'md5',
|
|
@@ -15,7 +14,7 @@ function envFingerprint(env) {
|
|
|
15
14
|
respectFunctionProperties: false,
|
|
16
15
|
respectFunctionNames: false,
|
|
17
16
|
ignoreUnknown: true,
|
|
18
|
-
replacer: (v) => (
|
|
17
|
+
replacer: (v) => (0, environment_1.isDefaultBuiltInEnvironment)(v) ? undefined : v
|
|
19
18
|
});
|
|
20
19
|
}
|
|
21
20
|
function fingerprint(id, envFingerprint, onlyForSideEffects) {
|
|
@@ -5,11 +5,12 @@ import type { DataflowGraphVertexFunctionCall, DataflowGraphVertexInfo } from '.
|
|
|
5
5
|
import type { REnvironmentInformation } from '../../dataflow/environments/environment';
|
|
6
6
|
import type { DataflowGraph, OutgoingEdges } from '../../dataflow/graph/graph';
|
|
7
7
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
|
+
import type { DataflowInformation } from '../../dataflow/info';
|
|
8
9
|
/**
|
|
9
10
|
* Returns the function call targets (definitions) by the given caller
|
|
10
11
|
*/
|
|
11
12
|
export declare function getAllFunctionCallTargets(dataflowGraph: DataflowGraph, callerInfo: DataflowGraphVertexFunctionCall, baseEnvironment: REnvironmentInformation, queue: VisitingQueue): [Set<DataflowGraphVertexInfo>, REnvironmentInformation];
|
|
12
13
|
/** returns the new threshold hit count */
|
|
13
|
-
export declare function sliceForCall(current: NodeToSlice, callerInfo: DataflowGraphVertexFunctionCall,
|
|
14
|
+
export declare function sliceForCall(current: NodeToSlice, callerInfo: DataflowGraphVertexFunctionCall, dataflowInformation: DataflowInformation, queue: VisitingQueue): void;
|
|
14
15
|
/** Returns true if we found at least one return edge */
|
|
15
16
|
export declare function handleReturns(from: NodeId, queue: VisitingQueue, currentEdges: OutgoingEdges, baseEnvFingerprint: Fingerprint, baseEnvironment: REnvironmentInformation): boolean;
|
|
@@ -59,9 +59,9 @@ function linkCallTargets(onlyForSideEffects, functionCallTargets, activeEnvironm
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
/** returns the new threshold hit count */
|
|
62
|
-
function sliceForCall(current, callerInfo,
|
|
62
|
+
function sliceForCall(current, callerInfo, dataflowInformation, queue) {
|
|
63
63
|
const baseEnvironment = current.baseEnvironment;
|
|
64
|
-
const [functionCallTargets, activeEnvironment] = getAllFunctionCallTargets(
|
|
64
|
+
const [functionCallTargets, activeEnvironment] = getAllFunctionCallTargets(dataflowInformation.graph, callerInfo, current.baseEnvironment, queue);
|
|
65
65
|
const activeEnvironmentFingerprint = (0, fingerprint_1.envFingerprint)(activeEnvironment);
|
|
66
66
|
if (functionCallTargets.size === 0) {
|
|
67
67
|
/*
|
|
@@ -69,7 +69,7 @@ function sliceForCall(current, callerInfo, dataflowGraph, queue) {
|
|
|
69
69
|
* hence, we add a new flag and add all argument values to the queue causing directly
|
|
70
70
|
*/
|
|
71
71
|
for (const arg of callerInfo.args) {
|
|
72
|
-
includeArgumentFunctionCallClosure(arg, baseEnvironment, activeEnvironment, queue,
|
|
72
|
+
includeArgumentFunctionCallClosure(arg, baseEnvironment, activeEnvironment, queue, dataflowInformation.graph);
|
|
73
73
|
}
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
import type { SliceResult } from './slicer-types';
|
|
2
2
|
import type { Fingerprint } from './fingerprint';
|
|
3
3
|
import { VisitingQueue } from './visiting-queue';
|
|
4
|
-
import type { DataflowGraph } from '../../dataflow/graph/graph';
|
|
5
4
|
import type { NormalizedAst } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
6
5
|
import type { SlicingCriteria } from '../criterion/parse';
|
|
7
6
|
import type { REnvironmentInformation } from '../../dataflow/environments/environment';
|
|
8
7
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
9
8
|
import { SliceDirection } from '../../core/steps/all/static-slicing/00-slice';
|
|
9
|
+
import type { DataflowInformation } from '../../dataflow/info';
|
|
10
10
|
export declare const slicerLogger: import("tslog").Logger<import("tslog").ILogObj>;
|
|
11
11
|
/**
|
|
12
12
|
* This returns the ids to include in the static slice of the given type, when slicing with the given seed id's (must be at least one).
|
|
13
13
|
* <p>
|
|
14
14
|
* The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
|
|
15
15
|
*
|
|
16
|
-
* @param
|
|
17
|
-
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
16
|
+
* @param info - The dataflow information used for slicing.
|
|
18
17
|
* @param criteria - The criteria to slice on.
|
|
19
18
|
* @param direction - The direction to slice in.
|
|
20
19
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
21
20
|
* @param cache - A cache to store the results of the slice. If provided, the slice may use this cache to speed up the slicing process.
|
|
22
21
|
*/
|
|
23
|
-
export declare function staticSlice(
|
|
22
|
+
export declare function staticSlice(info: DataflowInformation, { idMap }: NormalizedAst, criteria: SlicingCriteria, direction: SliceDirection, threshold?: number, cache?: Map<Fingerprint, Set<NodeId>>): Readonly<SliceResult>;
|
|
24
23
|
export declare function updatePotentialAddition(queue: VisitingQueue, id: NodeId, target: NodeId, baseEnvironment: REnvironmentInformation, envFingerprint: string): void;
|
|
@@ -20,17 +20,17 @@ exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
|
|
|
20
20
|
* <p>
|
|
21
21
|
* The returned ids can be used to {@link reconstructToCode|reconstruct the slice to R code}.
|
|
22
22
|
*
|
|
23
|
-
* @param
|
|
24
|
-
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
23
|
+
* @param info - The dataflow information used for slicing.
|
|
25
24
|
* @param criteria - The criteria to slice on.
|
|
26
25
|
* @param direction - The direction to slice in.
|
|
27
26
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
28
27
|
* @param cache - A cache to store the results of the slice. If provided, the slice may use this cache to speed up the slicing process.
|
|
29
28
|
*/
|
|
30
|
-
function staticSlice(
|
|
29
|
+
function staticSlice(info, { idMap }, criteria, direction, threshold = 75, cache) {
|
|
31
30
|
(0, assert_1.guard)(criteria.length > 0, 'must have at least one seed id to calculate slice');
|
|
32
31
|
const decodedCriteria = (0, parse_1.convertAllSlicingCriteriaToIds)(criteria, idMap);
|
|
33
32
|
(0, log_1.expensiveTrace)(exports.slicerLogger, () => `calculating ${direction} slice for ${decodedCriteria.length} seed criteria: ${decodedCriteria.map(s => JSON.stringify(s)).join(', ')}`);
|
|
33
|
+
let { graph } = info;
|
|
34
34
|
if (direction === _00_slice_1.SliceDirection.Forward) {
|
|
35
35
|
graph = (0, invert_dfg_1.invertDfg)(graph);
|
|
36
36
|
}
|
|
@@ -77,7 +77,7 @@ function staticSlice(graph, { idMap }, criteria, direction, threshold = 75, cach
|
|
|
77
77
|
}
|
|
78
78
|
if (!onlyForSideEffects) {
|
|
79
79
|
if (currentVertex.tag === vertex_1.VertexType.FunctionCall && !currentVertex.onlyBuiltin) {
|
|
80
|
-
(0, slice_call_1.sliceForCall)(current, currentVertex,
|
|
80
|
+
(0, slice_call_1.sliceForCall)(current, currentVertex, info, queue);
|
|
81
81
|
}
|
|
82
82
|
const ret = (0, slice_call_1.handleReturns)(id, queue, currentEdges, baseEnvFingerprint, baseEnvironment);
|
|
83
83
|
if (ret) {
|
package/util/containers.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export declare function getAccessOperands<OtherInfo>(args: readonly RFunctionArg
|
|
|
17
17
|
*
|
|
18
18
|
* @param name - Name to resolve
|
|
19
19
|
* @param environment - Environment in which name is resolved
|
|
20
|
+
* @param builtInEnvironment - Built-in environment
|
|
20
21
|
* @returns The indicesCollection of the resolved definitions
|
|
21
22
|
*/
|
|
22
23
|
export declare function resolveIndicesByName(name: Identifier, environment: REnvironmentInformation): ContainerIndices[] | undefined;
|
package/util/containers.js
CHANGED
|
@@ -24,6 +24,7 @@ function getAccessOperands(args) {
|
|
|
24
24
|
*
|
|
25
25
|
* @param name - Name to resolve
|
|
26
26
|
* @param environment - Environment in which name is resolved
|
|
27
|
+
* @param builtInEnvironment - Built-in environment
|
|
27
28
|
* @returns The indicesCollection of the resolved definitions
|
|
28
29
|
*/
|
|
29
30
|
function resolveIndicesByName(name, environment) {
|
package/util/json.js
CHANGED
|
@@ -46,12 +46,9 @@ function bigStringify(obj, current, send) {
|
|
|
46
46
|
if (obj === undefined || obj === null) {
|
|
47
47
|
return current + 'null';
|
|
48
48
|
}
|
|
49
|
-
else if (
|
|
49
|
+
else if ((0, environment_1.isDefaultBuiltInEnvironment)(obj)) {
|
|
50
50
|
return current + '<BuiltInEnvironment>';
|
|
51
51
|
}
|
|
52
|
-
else if (obj === environment_1.EmptyBuiltInEnvironment) {
|
|
53
|
-
return current + '<EmptyBuiltInEnvironment>';
|
|
54
|
-
}
|
|
55
52
|
else if (Array.isArray(obj)) {
|
|
56
53
|
let str = current + '[';
|
|
57
54
|
for (let i = 0; i < obj.length; i++) {
|
package/util/mermaid/dfg.js
CHANGED
|
@@ -13,7 +13,6 @@ const identifier_1 = require("../../dataflow/environments/identifier");
|
|
|
13
13
|
const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
14
14
|
const edge_1 = require("../../dataflow/graph/edge");
|
|
15
15
|
const vertex_1 = require("../../dataflow/graph/vertex");
|
|
16
|
-
const environment_1 = require("../../dataflow/environments/environment");
|
|
17
16
|
const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
|
|
18
17
|
const built_in_1 = require("../../dataflow/environments/built-in");
|
|
19
18
|
/**
|
|
@@ -134,7 +133,7 @@ function printEnvironmentToLines(env) {
|
|
|
134
133
|
if (env === undefined) {
|
|
135
134
|
return ['??'];
|
|
136
135
|
}
|
|
137
|
-
else if (env.
|
|
136
|
+
else if (env.builtInEnv) {
|
|
138
137
|
return ['Built-in'];
|
|
139
138
|
}
|
|
140
139
|
const lines = [...printEnvironmentToLines(env.parent), `${env.id}${'-'.repeat(40)}`];
|
package/util/prefix.d.ts
CHANGED
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
* findByPrefixIfUnique('', { 'hello', 'hell' }) // => undefined (empty prefix)
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
|
-
export declare function findByPrefixIfUnique(prefix: string, keys: readonly string[]): string | undefined;
|
|
13
|
+
export declare function findByPrefixIfUnique(prefix: string, keys: readonly string[] | MapIterator<string>): string | undefined;
|
package/util/version.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.flowrVersion = flowrVersion;
|
|
4
4
|
const semver_1 = require("semver");
|
|
5
5
|
// this is automatically replaced with the current version by release-it
|
|
6
|
-
const version = '2.4.
|
|
6
|
+
const version = '2.4.1';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|