@eagleoutice/flowr 1.4.1 → 1.4.2
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 +3 -3
- package/abstract-interpretation/processor.js +9 -3
- package/benchmark/slicer.d.ts +0 -3
- package/benchmark/slicer.js +4 -16
- package/benchmark/stats/print.js +0 -2
- package/benchmark/stats/stats.d.ts +2 -3
- package/benchmark/stats/stats.js +1 -1
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +21 -6
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +15 -6
- package/cli/common/options.js +4 -1
- package/cli/common/scripts-info.d.ts +1 -0
- package/cli/common/scripts-info.js +15 -1
- package/cli/export-quads-app.js +1 -5
- package/cli/repl/commands/cfg.js +2 -2
- package/cli/repl/commands/commands.d.ts +3 -1
- package/cli/repl/commands/commands.js +67 -28
- package/cli/repl/commands/dataflow.js +2 -2
- package/cli/repl/commands/normalize.js +2 -2
- package/cli/repl/commands/parse.js +12 -12
- package/cli/repl/commands/quit.js +4 -1
- package/cli/repl/core.d.ts +4 -2
- package/cli/repl/core.js +63 -7
- package/cli/repl/execute.d.ts +1 -1
- package/cli/repl/execute.js +3 -3
- package/cli/repl/server/connection.js +3 -8
- package/cli/repl/server/net.js +2 -2
- package/cli/statistics-helper-app.js +0 -1
- package/cli/summarizer-app.js +1 -2
- package/config.d.ts +16 -0
- package/config.js +75 -0
- package/core/input.d.ts +1 -1
- package/core/output.d.ts +1 -2
- package/core/print/parse-printer.d.ts +1 -2
- package/core/print/parse-printer.js +6 -4
- package/core/slicer.js +4 -8
- package/core/steps.d.ts +7 -24
- package/core/steps.js +5 -12
- package/dataflow/environments/environment.js +8 -0
- package/dataflow/environments/register.js +1 -0
- package/dataflow/extractor.d.ts +2 -2
- package/dataflow/extractor.js +10 -2
- package/dataflow/internal/process/functions/function-call.js +7 -1
- package/dataflow/internal/process/functions/source.d.ts +8 -0
- package/dataflow/internal/process/functions/source.js +81 -0
- package/dataflow/processor.d.ts +10 -1
- package/flowr.d.ts +2 -0
- package/flowr.js +14 -9
- package/package.json +41 -18
- package/r-bridge/lang-4.x/ast/index.d.ts +1 -0
- package/r-bridge/lang-4.x/ast/index.js +3 -0
- package/r-bridge/lang-4.x/ast/model/processing/decorate.d.ts +2 -0
- package/r-bridge/lang-4.x/ast/model/processing/decorate.js +6 -1
- package/r-bridge/lang-4.x/ast/parser/json/format.d.ts +14 -0
- package/r-bridge/lang-4.x/ast/parser/json/format.js +26 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +7 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +57 -0
- package/r-bridge/lang-4.x/ast/parser/xml/data.d.ts +0 -3
- package/r-bridge/lang-4.x/ast/parser/xml/index.d.ts +0 -2
- package/r-bridge/lang-4.x/ast/parser/xml/index.js +0 -2
- package/r-bridge/lang-4.x/ast/parser/xml/input-format.d.ts +5 -1
- package/r-bridge/lang-4.x/ast/parser/xml/input-format.js +7 -10
- package/r-bridge/lang-4.x/ast/parser/xml/internal/access.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/control/if-then-else.js +1 -1
- package/r-bridge/lang-4.x/ast/parser/xml/internal/control/if-then.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/expression/expression.js +4 -4
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/argument.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/call.js +4 -4
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/definition.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/functions/parameter.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/index.d.ts +0 -1
- package/r-bridge/lang-4.x/ast/parser/xml/internal/index.js +0 -1
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/break.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/for.js +3 -6
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/next.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/repeat.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/loops/while.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/meta.d.ts +6 -11
- package/r-bridge/lang-4.x/ast/parser/xml/internal/meta.js +15 -23
- package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/binary.js +6 -6
- package/r-bridge/lang-4.x/ast/parser/xml/internal/operators/unary.js +3 -3
- package/r-bridge/lang-4.x/ast/parser/xml/internal/other/comment.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/other/line-directive.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/elements.js +3 -3
- package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/root.js +3 -4
- package/r-bridge/lang-4.x/ast/parser/xml/internal/structure/single-element.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/values/number.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/values/string.js +2 -2
- package/r-bridge/lang-4.x/ast/parser/xml/internal/values/symbol.js +4 -4
- package/r-bridge/lang-4.x/values.d.ts +0 -1
- package/r-bridge/lang-4.x/values.js +14 -6
- package/r-bridge/retriever.d.ts +25 -21
- package/r-bridge/retriever.js +73 -23
- package/r-bridge/shell-executor.d.ts +3 -17
- package/r-bridge/shell-executor.js +9 -78
- package/r-bridge/shell.d.ts +5 -27
- package/r-bridge/shell.js +31 -92
- package/statistics/features/supported/assignments/post-process.js +6 -6
- package/statistics/features/supported/comments/post-process.js +2 -2
- package/statistics/features/supported/data-access/post-process.js +4 -4
- package/statistics/features/supported/defined-functions/post-process.js +4 -4
- package/statistics/features/supported/expression-list/post-process.js +3 -3
- package/statistics/features/supported/loops/post-process.js +3 -3
- package/statistics/features/supported/used-functions/post-process.js +5 -5
- package/statistics/features/supported/used-packages/post-process.js +5 -5
- package/statistics/features/supported/values/post-process.js +3 -3
- package/statistics/features/supported/variables/post-process.js +3 -3
- package/statistics/output/ansi.js +1 -1
- package/statistics/statistics.js +7 -8
- package/util/args.d.ts +8 -4
- package/util/args.js +11 -4
- package/util/cfg/visitor.js +1 -1
- package/util/files.d.ts +6 -0
- package/util/files.js +11 -1
- package/util/log.js +3 -0
- package/util/summarizer/benchmark/first-phase/input.d.ts +2 -1
- package/util/summarizer/benchmark/first-phase/input.js +20 -4
- package/util/summarizer/benchmark/first-phase/process.d.ts +2 -1
- package/util/summarizer/benchmark/first-phase/process.js +14 -5
- package/util/summarizer/benchmark/second-phase/graph.js +1 -1
- package/util/summarizer/benchmark/second-phase/process.d.ts +2 -0
- package/util/summarizer/benchmark/second-phase/process.js +48 -11
- package/util/summarizer/benchmark/summarizer.d.ts +0 -4
- package/util/summarizer/benchmark/summarizer.js +16 -7
- package/util/summarizer/statistics/first-phase/process.js +8 -8
- package/util/summarizer/statistics/post-process/post-process-output.js +4 -5
- package/r-bridge/lang-4.x/ast/parser/xml/config.d.ts +0 -25
- package/r-bridge/lang-4.x/ast/parser/xml/config.js +0 -16
- package/r-bridge/lang-4.x/ast/parser/xml/internal/xml-to-json.d.ts +0 -9
- package/r-bridge/lang-4.x/ast/parser/xml/internal/xml-to-json.js +0 -51
- package/r-bridge/lang-4.x/ast/parser/xml/parser.d.ts +0 -17
- package/r-bridge/lang-4.x/ast/parser/xml/parser.js +0 -30
package/dataflow/extractor.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.processBinaryOp = exports.produceDataFlowGraph = void 0;
|
|
4
|
+
const r_bridge_1 = require("../r-bridge");
|
|
4
5
|
const processor_1 = require("./processor");
|
|
5
6
|
const uninteresting_leaf_1 = require("./internal/process/uninteresting-leaf");
|
|
6
7
|
const symbol_1 = require("./internal/process/symbol");
|
|
@@ -44,8 +45,15 @@ const processors = {
|
|
|
44
45
|
["RArgument" /* RType.Argument */]: argument_1.processFunctionArgument,
|
|
45
46
|
["RExpressionList" /* RType.ExpressionList */]: expression_list_1.processExpressionList,
|
|
46
47
|
};
|
|
47
|
-
function produceDataFlowGraph(ast, initialScope = scopes_1.LocalScope) {
|
|
48
|
-
return (0, processor_1.processDataflowFor)(ast.ast, {
|
|
48
|
+
function produceDataFlowGraph(request, ast, initialScope = scopes_1.LocalScope) {
|
|
49
|
+
return (0, processor_1.processDataflowFor)(ast.ast, {
|
|
50
|
+
completeAst: ast,
|
|
51
|
+
activeScope: initialScope,
|
|
52
|
+
environments: (0, environments_1.initializeCleanEnvironments)(),
|
|
53
|
+
processors: processors,
|
|
54
|
+
currentRequest: request,
|
|
55
|
+
referenceChain: [(0, r_bridge_1.requestFingerprint)(request)]
|
|
56
|
+
});
|
|
49
57
|
}
|
|
50
58
|
exports.produceDataFlowGraph = produceDataFlowGraph;
|
|
51
59
|
function processBinaryOp(node, data) {
|
|
@@ -7,6 +7,7 @@ const assert_1 = require("../../../../util/assert");
|
|
|
7
7
|
const index_1 = require("../../../index");
|
|
8
8
|
const linker_1 = require("../../linker");
|
|
9
9
|
const scopes_1 = require("../../../environments/scopes");
|
|
10
|
+
const source_1 = require("./source");
|
|
10
11
|
exports.UnnamedFunctionCallPrefix = 'unnamed-function-call-';
|
|
11
12
|
function processFunctionCall(functionCall, data) {
|
|
12
13
|
const named = functionCall.flavor === 'named';
|
|
@@ -86,7 +87,7 @@ function processFunctionCall(functionCall, data) {
|
|
|
86
87
|
// push the called function to the ids:
|
|
87
88
|
inIds.push(...functionName.in, ...functionName.unknownReferences);
|
|
88
89
|
}
|
|
89
|
-
|
|
90
|
+
let info = {
|
|
90
91
|
unknownReferences: [],
|
|
91
92
|
in: inIds,
|
|
92
93
|
out: functionName.out, // we do not keep argument out as it has been linked by the function
|
|
@@ -94,6 +95,11 @@ function processFunctionCall(functionCall, data) {
|
|
|
94
95
|
environments: finalEnv,
|
|
95
96
|
scope: data.activeScope
|
|
96
97
|
};
|
|
98
|
+
// parse a source call and analyze the referenced code
|
|
99
|
+
if ((0, source_1.isSourceCall)(functionCallName, data.activeScope, finalEnv)) {
|
|
100
|
+
info = (0, source_1.processSourceCall)(functionCall, data, info);
|
|
101
|
+
}
|
|
102
|
+
return info;
|
|
97
103
|
}
|
|
98
104
|
exports.processFunctionCall = processFunctionCall;
|
|
99
105
|
//# sourceMappingURL=function-call.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { IdGenerator, NoInfo, RParseRequest, RParseRequestProvider, ParentInformation, RFunctionCall } from '../../../../r-bridge';
|
|
2
|
+
import { type DataflowProcessorInformation } from '../../../processor';
|
|
3
|
+
import { type DataflowScopeName, type Identifier, type REnvironmentInformation } from '../../../environments';
|
|
4
|
+
import type { DataflowInformation } from '../../info';
|
|
5
|
+
export declare function setSourceProvider(provider: RParseRequestProvider): void;
|
|
6
|
+
export declare function isSourceCall(name: Identifier, scope: DataflowScopeName, environments: REnvironmentInformation): boolean;
|
|
7
|
+
export declare function processSourceCall<OtherInfo>(functionCall: RFunctionCall<OtherInfo & ParentInformation>, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, information: DataflowInformation): DataflowInformation;
|
|
8
|
+
export declare function sourceRequest<OtherInfo>(request: RParseRequest, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, information: DataflowInformation, getId: IdGenerator<NoInfo>): DataflowInformation;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sourceRequest = exports.processSourceCall = exports.isSourceCall = exports.setSourceProvider = void 0;
|
|
4
|
+
const r_bridge_1 = require("../../../../r-bridge");
|
|
5
|
+
const shell_executor_1 = require("../../../../r-bridge/shell-executor");
|
|
6
|
+
const core_1 = require("../../../../core");
|
|
7
|
+
const processor_1 = require("../../../processor");
|
|
8
|
+
const environments_1 = require("../../../environments");
|
|
9
|
+
const index_1 = require("../../../index");
|
|
10
|
+
const config_1 = require("../../../../config");
|
|
11
|
+
let sourceProvider = (0, r_bridge_1.requestProviderFromFile)();
|
|
12
|
+
function setSourceProvider(provider) {
|
|
13
|
+
sourceProvider = provider;
|
|
14
|
+
}
|
|
15
|
+
exports.setSourceProvider = setSourceProvider;
|
|
16
|
+
function isSourceCall(name, scope, environments) {
|
|
17
|
+
const definitions = (0, environments_1.resolveByName)(name, scope, environments);
|
|
18
|
+
if (definitions === undefined) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// fail if there are multiple definitions because then we must treat the complete import as a maybe because it might do something different
|
|
22
|
+
if (definitions.length !== 1) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
const def = definitions[0];
|
|
26
|
+
return def.name == 'source' && def.kind == 'built-in-function';
|
|
27
|
+
}
|
|
28
|
+
exports.isSourceCall = isSourceCall;
|
|
29
|
+
function processSourceCall(functionCall, data, information) {
|
|
30
|
+
const sourceFile = functionCall.arguments[0];
|
|
31
|
+
if ((0, config_1.getConfig)().ignoreSourceCalls) {
|
|
32
|
+
index_1.dataflowLogger.info(`Skipping source call ${JSON.stringify(sourceFile)} (disabled in config file)`);
|
|
33
|
+
return information;
|
|
34
|
+
}
|
|
35
|
+
if (sourceFile?.value?.type == "RString" /* RType.String */) {
|
|
36
|
+
const path = (0, r_bridge_1.removeRQuotes)(sourceFile.lexeme);
|
|
37
|
+
const request = sourceProvider.createRequest(path);
|
|
38
|
+
// check if the sourced file has already been dataflow analyzed, and if so, skip it
|
|
39
|
+
if (data.referenceChain.includes((0, r_bridge_1.requestFingerprint)(request))) {
|
|
40
|
+
index_1.dataflowLogger.info(`Found loop in dataflow analysis for ${JSON.stringify(request)}: ${JSON.stringify(data.referenceChain)}, skipping further dataflow analysis`);
|
|
41
|
+
return information;
|
|
42
|
+
}
|
|
43
|
+
return sourceRequest(request, data, information, (0, r_bridge_1.sourcedDeterministicCountingIdGenerator)(path, functionCall.location));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
index_1.dataflowLogger.info(`Non-constant argument ${JSON.stringify(sourceFile)} for source is currently not supported, skipping`);
|
|
47
|
+
return information;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
exports.processSourceCall = processSourceCall;
|
|
51
|
+
function sourceRequest(request, data, information, getId) {
|
|
52
|
+
const executor = new shell_executor_1.RShellExecutor();
|
|
53
|
+
// parse, normalize and dataflow the sourced file
|
|
54
|
+
let normalized;
|
|
55
|
+
let dataflow;
|
|
56
|
+
try {
|
|
57
|
+
const parsed = (0, core_1.executeSingleSubStep)('parse', request, executor);
|
|
58
|
+
normalized = (0, core_1.executeSingleSubStep)('normalize', parsed, undefined, getId);
|
|
59
|
+
dataflow = (0, processor_1.processDataflowFor)(normalized.ast, {
|
|
60
|
+
...data,
|
|
61
|
+
currentRequest: request,
|
|
62
|
+
environments: information.environments,
|
|
63
|
+
referenceChain: [...data.referenceChain, (0, r_bridge_1.requestFingerprint)(request)]
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
index_1.dataflowLogger.warn(`Failed to analyze sourced file ${JSON.stringify(request)}, skipping: ${e.message}`);
|
|
68
|
+
return information;
|
|
69
|
+
}
|
|
70
|
+
// update our graph with the sourced file's information
|
|
71
|
+
const newInformation = { ...information };
|
|
72
|
+
newInformation.environments = (0, environments_1.overwriteEnvironments)(information.environments, dataflow.environments);
|
|
73
|
+
newInformation.graph.mergeWith(dataflow.graph);
|
|
74
|
+
// this can be improved, see issue #628
|
|
75
|
+
for (const [k, v] of normalized.idMap) {
|
|
76
|
+
data.completeAst.idMap.set(k, v);
|
|
77
|
+
}
|
|
78
|
+
return newInformation;
|
|
79
|
+
}
|
|
80
|
+
exports.sourceRequest = sourceRequest;
|
|
81
|
+
//# sourceMappingURL=source.js.map
|
package/dataflow/processor.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Based on a two-way fold, this processor will automatically supply scope information
|
|
3
3
|
*/
|
|
4
|
-
import type { NormalizedAst, ParentInformation, RNode, RNodeWithParent } from '../r-bridge';
|
|
4
|
+
import type { NormalizedAst, ParentInformation, RNode, RNodeWithParent, RParseRequest } from '../r-bridge';
|
|
5
5
|
import type { DataflowInformation } from './internal/info';
|
|
6
6
|
import type { DataflowScopeName, REnvironmentInformation } from './environments';
|
|
7
7
|
export interface DataflowProcessorInformation<OtherInfo> {
|
|
@@ -22,6 +22,15 @@ export interface DataflowProcessorInformation<OtherInfo> {
|
|
|
22
22
|
* Other processors to be called by the given functions
|
|
23
23
|
*/
|
|
24
24
|
readonly processors: DataflowProcessors<OtherInfo>;
|
|
25
|
+
/**
|
|
26
|
+
* The {@link RParseRequest} that is currently being parsed
|
|
27
|
+
*/
|
|
28
|
+
readonly currentRequest: RParseRequest;
|
|
29
|
+
/**
|
|
30
|
+
* The chain of {@link RParseRequest} fingerprints ({@link requestFingerprint}) that lead to the {@link currentRequest}.
|
|
31
|
+
* The most recent (last) entry is expected to always be the {@link currentRequest}.
|
|
32
|
+
*/
|
|
33
|
+
readonly referenceChain: string[];
|
|
25
34
|
}
|
|
26
35
|
export type DataflowProcessor<OtherInfo, NodeType extends RNodeWithParent<OtherInfo>> = (node: NodeType, data: DataflowProcessorInformation<OtherInfo>) => DataflowInformation;
|
|
27
36
|
type NodeWithKey<OtherInfo, Node extends RNode<OtherInfo & ParentInformation>, TypeKey> = Node['type'] extends TypeKey ? Node : never;
|
package/flowr.d.ts
CHANGED
package/flowr.js
CHANGED
|
@@ -23,6 +23,7 @@ const version_1 = require("./cli/repl/commands/version");
|
|
|
23
23
|
const server_1 = require("./cli/repl/server/server");
|
|
24
24
|
const commands_1 = require("./cli/repl/commands");
|
|
25
25
|
const net_1 = require("./cli/repl/server/net");
|
|
26
|
+
const config_1 = require("./config");
|
|
26
27
|
const scriptsText = Array.from(Object.entries(common_1.scripts).filter(([, { type }]) => type === 'master script'), ([k,]) => k).join(', ');
|
|
27
28
|
exports.toolName = 'flowr';
|
|
28
29
|
exports.optionDefinitions = [
|
|
@@ -35,6 +36,8 @@ exports.optionDefinitions = [
|
|
|
35
36
|
{ name: 'execute', alias: 'e', type: String, description: 'Execute the given command and exit. Use a semicolon ";" to separate multiple commands.', typeLabel: '{underline command}', multiple: false },
|
|
36
37
|
{ name: 'no-ansi', type: Boolean, description: 'Disable ansi-escape-sequences in the output. Useful, if you want to redirect the output to a file.' },
|
|
37
38
|
{ name: 'script', alias: 's', type: String, description: `The sub-script to run (${scriptsText})`, multiple: false, defaultOption: true, typeLabel: '{underline files}', defaultValue: undefined },
|
|
39
|
+
{ name: 'config-file', type: String, description: 'The name of the configuration file to use', multiple: false },
|
|
40
|
+
{ name: 'r-path', type: String, description: 'The path to the R executable to use. Defaults to your PATH.', multiple: false }
|
|
38
41
|
];
|
|
39
42
|
exports.optionHelp = [
|
|
40
43
|
{
|
|
@@ -63,19 +66,21 @@ if (options['no-ansi']) {
|
|
|
63
66
|
log_1.log.info('disabling ansi colors');
|
|
64
67
|
(0, statistics_1.setFormatter)(statistics_1.voidFormatter);
|
|
65
68
|
}
|
|
66
|
-
|
|
69
|
+
(0, config_1.setConfigFile)(undefined, options['config-file'] ?? config_1.defaultConfigFile, true);
|
|
70
|
+
function retrieveShell() {
|
|
67
71
|
// we keep an active shell session to allow other parse investigations :)
|
|
68
|
-
|
|
72
|
+
let opts = {
|
|
69
73
|
revive: 'always',
|
|
70
74
|
onRevive: (code, signal) => {
|
|
71
75
|
const signalText = signal == null ? '' : ` and signal ${signal}`;
|
|
72
76
|
console.log(statistics_1.formatter.format(`R process exited with code ${code}${signalText}. Restarting...`, { color: 5 /* Colors.Magenta */, effect: statistics_1.ColorEffect.Foreground }));
|
|
73
77
|
console.log((0, statistics_1.italic)(`If you want to exit, press either Ctrl+C twice, or enter ${(0, statistics_1.bold)(':quit')}`));
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
if (options['r-path']) {
|
|
81
|
+
opts = { ...opts, pathToRExecutable: options['r-path'] };
|
|
82
|
+
}
|
|
83
|
+
return new r_bridge_1.RShell(opts);
|
|
79
84
|
}
|
|
80
85
|
async function mainRepl() {
|
|
81
86
|
if (options.script) {
|
|
@@ -95,7 +100,7 @@ async function mainRepl() {
|
|
|
95
100
|
await (0, version_1.printVersionInformation)(commands_1.standardReplOutput);
|
|
96
101
|
process.exit(0);
|
|
97
102
|
}
|
|
98
|
-
const shell =
|
|
103
|
+
const shell = retrieveShell();
|
|
99
104
|
const end = () => {
|
|
100
105
|
if (options.execute === undefined) {
|
|
101
106
|
console.log(`\n${(0, statistics_1.italic)('Exiting...')}`);
|
|
@@ -115,7 +120,7 @@ async function mainRepl() {
|
|
|
115
120
|
process.exit(0);
|
|
116
121
|
}
|
|
117
122
|
async function mainServer(backend = new net_1.NetServer()) {
|
|
118
|
-
const shell =
|
|
123
|
+
const shell = retrieveShell();
|
|
119
124
|
const end = () => {
|
|
120
125
|
if (options.execute === undefined) {
|
|
121
126
|
console.log(`\n${(0, statistics_1.italic)('Exiting...')}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eagleoutice/flowr",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
|
|
5
5
|
"types": "dist/src/index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"slicer": "ts-node src/cli/slicer-app.ts",
|
|
20
20
|
"release": "release-it --ci",
|
|
21
21
|
"benchmark-helper": "ts-node src/cli/benchmark-helper-app.ts",
|
|
22
|
-
"benchmark": "
|
|
22
|
+
"benchmark": "npm run build && node dist/src/cli/benchmark-app.js",
|
|
23
23
|
"summarizer": "ts-node src/cli/summarizer-app.ts",
|
|
24
24
|
"export-quads": "ts-node src/cli/export-quads-app.ts",
|
|
25
25
|
"build": "tsc --project .",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"lint": "npm run license-compat -- --summary && eslint src/ test/",
|
|
28
28
|
"license-compat": "license-checker --onlyAllow 'MIT;MIT OR X11;GPLv2;LGPL;GNUGPL;ISC;Apache-2.0;FreeBSD;BSD-2-Clause;clearbsd;ModifiedBSD;BSD-3-Clause;Python-2.0;Unlicense;WTFPL;CC-BY-4.0;CC-BY-3.0;CC0-1.0;0BSD'",
|
|
29
29
|
"doc": "typedoc",
|
|
30
|
-
"test": "nyc --no-clean mocha
|
|
31
|
-
"performance-test": "func() { cd test/performance/ && bash run-all-suites.sh $1 $2; cd ../../; }; func",
|
|
30
|
+
"test": "nyc --no-clean mocha",
|
|
31
|
+
"performance-test": "func() { cd test/performance/ && bash run-all-suites.sh $1 $2 $3; cd ../../; }; func",
|
|
32
32
|
"test-full": "npm run test -- --test-installation"
|
|
33
33
|
},
|
|
34
34
|
"keywords": [
|
|
@@ -41,6 +41,11 @@
|
|
|
41
41
|
],
|
|
42
42
|
"author": "Florian Sihler",
|
|
43
43
|
"license": "ISC",
|
|
44
|
+
"mocha": {
|
|
45
|
+
"require": "ts-node/register",
|
|
46
|
+
"timeout": 60000,
|
|
47
|
+
"spec": "test/**/*.spec.ts"
|
|
48
|
+
},
|
|
44
49
|
"nyc": {
|
|
45
50
|
"all": true,
|
|
46
51
|
"per-file": true,
|
|
@@ -132,11 +137,18 @@
|
|
|
132
137
|
"plugins": [
|
|
133
138
|
"@typescript-eslint",
|
|
134
139
|
"eslint-plugin-tsdoc",
|
|
135
|
-
"check-file"
|
|
140
|
+
"check-file",
|
|
141
|
+
"@stylistic",
|
|
142
|
+
"@stylistic/js",
|
|
143
|
+
"@stylistic/ts",
|
|
144
|
+
"import"
|
|
136
145
|
],
|
|
137
146
|
"rules": {
|
|
138
|
-
"
|
|
139
|
-
|
|
147
|
+
"@stylistic/js/object-curly-spacing": [
|
|
148
|
+
"error",
|
|
149
|
+
"always"
|
|
150
|
+
],
|
|
151
|
+
"@stylistic/js/indent": [
|
|
140
152
|
"error",
|
|
141
153
|
"tab",
|
|
142
154
|
{
|
|
@@ -147,14 +159,14 @@
|
|
|
147
159
|
"SwitchCase": 1
|
|
148
160
|
}
|
|
149
161
|
],
|
|
150
|
-
"quotes": [
|
|
162
|
+
"@stylistic/js/quotes": [
|
|
151
163
|
"error",
|
|
152
164
|
"single",
|
|
153
165
|
{
|
|
154
166
|
"avoidEscape": true
|
|
155
167
|
}
|
|
156
168
|
],
|
|
157
|
-
"no-mixed-spaces-and-tabs": [
|
|
169
|
+
"@stylistic/no-mixed-spaces-and-tabs": [
|
|
158
170
|
"error",
|
|
159
171
|
"smart-tabs"
|
|
160
172
|
],
|
|
@@ -178,21 +190,21 @@
|
|
|
178
190
|
"assertionStyle": "as"
|
|
179
191
|
}
|
|
180
192
|
],
|
|
181
|
-
"@
|
|
193
|
+
"@stylistic/ts/key-spacing": [
|
|
182
194
|
"error",
|
|
183
195
|
{
|
|
184
196
|
"align": "value"
|
|
185
197
|
}
|
|
186
198
|
],
|
|
187
|
-
"semi": [
|
|
199
|
+
"@stylistic/js/semi": [
|
|
188
200
|
"error",
|
|
189
201
|
"never"
|
|
190
202
|
],
|
|
191
|
-
"space-before-function-paren": [
|
|
203
|
+
"@stylistic/js/space-before-function-paren": [
|
|
192
204
|
"error",
|
|
193
205
|
"never"
|
|
194
206
|
],
|
|
195
|
-
"keyword-spacing": "off",
|
|
207
|
+
"@stylistic/js/keyword-spacing": "off",
|
|
196
208
|
"check-file/filename-naming-convention": [
|
|
197
209
|
"error",
|
|
198
210
|
{
|
|
@@ -205,7 +217,7 @@
|
|
|
205
217
|
"*.spec.{js,jsx,ts,tsx}": "test/**"
|
|
206
218
|
}
|
|
207
219
|
],
|
|
208
|
-
"@
|
|
220
|
+
"@stylistic/ts/keyword-spacing": [
|
|
209
221
|
"error",
|
|
210
222
|
{
|
|
211
223
|
"before": true,
|
|
@@ -238,7 +250,7 @@
|
|
|
238
250
|
}
|
|
239
251
|
}
|
|
240
252
|
],
|
|
241
|
-
"@
|
|
253
|
+
"@stylistic/ts/space-before-function-paren": [
|
|
242
254
|
"error",
|
|
243
255
|
"never"
|
|
244
256
|
],
|
|
@@ -295,7 +307,14 @@
|
|
|
295
307
|
]
|
|
296
308
|
}
|
|
297
309
|
],
|
|
298
|
-
"@typescript-eslint/consistent-type-imports": "error"
|
|
310
|
+
"@typescript-eslint/consistent-type-imports": "error",
|
|
311
|
+
"curly": "error",
|
|
312
|
+
"@stylistic/js/brace-style": [
|
|
313
|
+
"error",
|
|
314
|
+
"1tbs"
|
|
315
|
+
],
|
|
316
|
+
"@stylistic/js/new-parens": "error",
|
|
317
|
+
"import/no-duplicates": "error"
|
|
299
318
|
}
|
|
300
319
|
},
|
|
301
320
|
"release-it": {
|
|
@@ -332,9 +351,15 @@
|
|
|
332
351
|
"after:release": "echo Successfully released ${name} v${version} to ${repo.repository}."
|
|
333
352
|
}
|
|
334
353
|
},
|
|
354
|
+
"engines": {
|
|
355
|
+
"node": ">=16.0.0"
|
|
356
|
+
},
|
|
335
357
|
"devDependencies": {
|
|
336
358
|
"@commitlint/cli": "^18.4.3",
|
|
337
359
|
"@commitlint/config-angular": "^18.4.3",
|
|
360
|
+
"@stylistic/eslint-plugin": "^1.6.2",
|
|
361
|
+
"@stylistic/eslint-plugin-plus": "^1.6.2",
|
|
362
|
+
"@stylistic/eslint-plugin-ts": "^1.6.2",
|
|
338
363
|
"@types/chai": "^4.3.11",
|
|
339
364
|
"@types/chai-as-promised": "^7.1.8",
|
|
340
365
|
"@types/command-line-args": "^5.2.3",
|
|
@@ -344,7 +369,6 @@
|
|
|
344
369
|
"@types/n3": "^1.16.4",
|
|
345
370
|
"@types/object-hash": "^3.0.6",
|
|
346
371
|
"@types/tmp": "^0.2.6",
|
|
347
|
-
"@types/xml2js": "^0.4.14",
|
|
348
372
|
"@typescript-eslint/eslint-plugin": "^6.13.2",
|
|
349
373
|
"chai": "^4.3.10",
|
|
350
374
|
"chai-as-promised": "^7.1.1",
|
|
@@ -386,7 +410,6 @@
|
|
|
386
410
|
"ts-essentials": "^9.4.1",
|
|
387
411
|
"tslog": "^4.9.2",
|
|
388
412
|
"ws": "^8.16.0",
|
|
389
|
-
"xml2js": "^0.6.2",
|
|
390
413
|
"xpath-ts2": "^1.4.2"
|
|
391
414
|
}
|
|
392
415
|
}
|
|
@@ -14,6 +14,9 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.parseLog = void 0;
|
|
17
18
|
__exportStar(require("./model"), exports);
|
|
18
19
|
__exportStar(require("./parser/xml"), exports);
|
|
20
|
+
var parser_1 = require("./parser/json/parser");
|
|
21
|
+
Object.defineProperty(exports, "parseLog", { enumerable: true, get: function () { return parser_1.parseLog; } });
|
|
19
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
11
|
import type { NoInfo, RNode } from '../model';
|
|
12
|
+
import type { SourceRange } from '../../../../../util/range';
|
|
12
13
|
import { BiMap } from '../../../../../util/bimap';
|
|
13
14
|
import type { MergeableRecord } from '../../../../../util/objects';
|
|
14
15
|
import { RoleInParent } from './role';
|
|
@@ -27,6 +28,7 @@ export type IdGenerator<OtherInfo> = (data: RNode<OtherInfo>) => NodeId;
|
|
|
27
28
|
* The simplest id generator which just increments a number on each call.
|
|
28
29
|
*/
|
|
29
30
|
export declare function deterministicCountingIdGenerator(start?: number): () => NodeId;
|
|
31
|
+
export declare function sourcedDeterministicCountingIdGenerator(path: string, location: SourceRange, start?: number): () => NodeId;
|
|
30
32
|
/**
|
|
31
33
|
* Generates the location id, used by {@link deterministicLocationIdGenerator}.
|
|
32
34
|
*
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* @module
|
|
11
11
|
*/
|
|
12
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.decorateAst = exports.deterministicLocationIdGenerator = exports.nodeToLocationId = exports.deterministicCountingIdGenerator = void 0;
|
|
13
|
+
exports.decorateAst = exports.deterministicLocationIdGenerator = exports.nodeToLocationId = exports.sourcedDeterministicCountingIdGenerator = exports.deterministicCountingIdGenerator = void 0;
|
|
14
14
|
const assert_1 = require("../../../../../util/assert");
|
|
15
15
|
const bimap_1 = require("../../../../../util/bimap");
|
|
16
16
|
const fold_1 = require("./fold");
|
|
@@ -22,6 +22,11 @@ function deterministicCountingIdGenerator(start = 0) {
|
|
|
22
22
|
return () => `${id++}`;
|
|
23
23
|
}
|
|
24
24
|
exports.deterministicCountingIdGenerator = deterministicCountingIdGenerator;
|
|
25
|
+
function sourcedDeterministicCountingIdGenerator(path, location, start = 0) {
|
|
26
|
+
let id = start;
|
|
27
|
+
return () => `${path}-${loc2Id(location)}-${id++}`;
|
|
28
|
+
}
|
|
29
|
+
exports.sourcedDeterministicCountingIdGenerator = sourcedDeterministicCountingIdGenerator;
|
|
25
30
|
function loc2Id(loc) {
|
|
26
31
|
return `${loc.start.line}:${loc.start.column}-${loc.end.line}:${loc.end.column}`;
|
|
27
32
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const RootId = 0;
|
|
2
|
+
export interface Entry extends Record<string, unknown> {
|
|
3
|
+
line1: number;
|
|
4
|
+
col1: number;
|
|
5
|
+
line2: number;
|
|
6
|
+
col2: number;
|
|
7
|
+
id: number;
|
|
8
|
+
parent: number;
|
|
9
|
+
token: string;
|
|
10
|
+
terminal: boolean;
|
|
11
|
+
text: string;
|
|
12
|
+
children?: Entry[];
|
|
13
|
+
}
|
|
14
|
+
export declare function prepareParsedData(data: string): Map<number, Entry>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.prepareParsedData = exports.RootId = void 0;
|
|
4
|
+
const retriever_1 = require("../../../../retriever");
|
|
5
|
+
const assert_1 = require("../../../../../util/assert");
|
|
6
|
+
exports.RootId = 0;
|
|
7
|
+
function prepareParsedData(data) {
|
|
8
|
+
const json = JSON.parse(data);
|
|
9
|
+
(0, assert_1.guard)(Array.isArray(json), () => `Expected ${data} to be an array but was not`);
|
|
10
|
+
const ret = new Map(json.map(([line1, col1, line2, col2, id, parent, token, terminal, text]) => {
|
|
11
|
+
return [id, { line1, col1, line2, col2, id, parent, token: (0, retriever_1.removeRQuotes)(token), terminal, text }];
|
|
12
|
+
}));
|
|
13
|
+
// iterate a second time to set parent-child relations (since they may be out of order in the csv)
|
|
14
|
+
for (const entry of ret.values()) {
|
|
15
|
+
if (entry.parent != exports.RootId) {
|
|
16
|
+
const parent = ret.get(entry.parent);
|
|
17
|
+
if (parent) {
|
|
18
|
+
parent.children ??= [];
|
|
19
|
+
parent.children.push(entry);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return ret;
|
|
24
|
+
}
|
|
25
|
+
exports.prepareParsedData = prepareParsedData;
|
|
26
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DeepPartial } from 'ts-essentials';
|
|
2
|
+
import type { XmlBasedJson, XmlParserHooks } from '../xml';
|
|
3
|
+
import type { IdGenerator, NoInfo, NormalizedAst } from '../../model';
|
|
4
|
+
import type { Entry } from './format';
|
|
5
|
+
export declare const parseLog: import("tslog").Logger<import("tslog").ILogObj>;
|
|
6
|
+
export declare function normalize(jsonString: string, hooks?: DeepPartial<XmlParserHooks>, getId?: IdGenerator<NoInfo>): NormalizedAst;
|
|
7
|
+
export declare function convertPreparedParsedData(valueMapping: Map<number, Entry>): XmlBasedJson;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.convertPreparedParsedData = exports.normalize = exports.parseLog = void 0;
|
|
4
|
+
const xml_1 = require("../xml");
|
|
5
|
+
const model_1 = require("../../model");
|
|
6
|
+
const objects_1 = require("../../../../../util/objects");
|
|
7
|
+
const format_1 = require("./format");
|
|
8
|
+
const internal_1 = require("../xml/internal");
|
|
9
|
+
const log_1 = require("../../../../../util/log");
|
|
10
|
+
exports.parseLog = log_1.log.getSubLogger({ name: 'ast-parser' });
|
|
11
|
+
function normalize(jsonString, hooks, getId = (0, model_1.deterministicCountingIdGenerator)(0)) {
|
|
12
|
+
const hooksWithDefaults = (0, objects_1.deepMergeObject)(xml_1.DEFAULT_PARSER_HOOKS, hooks);
|
|
13
|
+
const data = { hooks: hooksWithDefaults, currentRange: undefined, currentLexeme: undefined };
|
|
14
|
+
const object = convertPreparedParsedData((0, format_1.prepareParsedData)(jsonString));
|
|
15
|
+
return (0, model_1.decorateAst)((0, internal_1.parseRootObjToAst)(data, object), getId);
|
|
16
|
+
}
|
|
17
|
+
exports.normalize = normalize;
|
|
18
|
+
function convertPreparedParsedData(valueMapping) {
|
|
19
|
+
const exprlist = {};
|
|
20
|
+
exprlist[xml_1.nameKey] = 'exprlist';
|
|
21
|
+
const children = [];
|
|
22
|
+
for (const entry of valueMapping.values()) {
|
|
23
|
+
if (entry.parent == format_1.RootId) {
|
|
24
|
+
children.push(convertEntry(entry));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exprlist[xml_1.childrenKey] = children;
|
|
28
|
+
return { 'exprlist': exprlist };
|
|
29
|
+
}
|
|
30
|
+
exports.convertPreparedParsedData = convertPreparedParsedData;
|
|
31
|
+
function convertEntry(csvEntry) {
|
|
32
|
+
const xmlEntry = {};
|
|
33
|
+
xmlEntry[xml_1.attributesKey] = {
|
|
34
|
+
'line1': csvEntry.line1,
|
|
35
|
+
'col1': csvEntry.col1,
|
|
36
|
+
'line2': csvEntry.line2,
|
|
37
|
+
'col2': csvEntry.col2
|
|
38
|
+
};
|
|
39
|
+
xmlEntry[xml_1.nameKey] = csvEntry.token;
|
|
40
|
+
if (csvEntry.text) {
|
|
41
|
+
xmlEntry[xml_1.contentKey] = csvEntry.text;
|
|
42
|
+
}
|
|
43
|
+
// check and recursively iterate children
|
|
44
|
+
if (csvEntry.children && csvEntry.children.length > 0) {
|
|
45
|
+
xmlEntry[xml_1.childrenKey] = csvEntry.children
|
|
46
|
+
// we sort children the same way xmlparsedata does (by line, by column, by inverse end line, by inverse end column, by terminal state, by combined "start" tiebreaker value)
|
|
47
|
+
// (https://github.com/r-lib/xmlparsedata/blob/main/R/package.R#L153C72-L153C78)
|
|
48
|
+
.sort((c1, c2) => c1.line1 - c2.line1 || c1.col1 - c2.col1 || c2.line2 - c1.line2 || c2.col2 - c1.col2 || Number(c1.terminal) - Number(c2.terminal) || sortTiebreak(c1) - sortTiebreak(c2))
|
|
49
|
+
.map(convertEntry);
|
|
50
|
+
}
|
|
51
|
+
return xmlEntry;
|
|
52
|
+
}
|
|
53
|
+
function sortTiebreak(entry) {
|
|
54
|
+
// see https://github.com/r-lib/xmlparsedata/blob/main/R/package.R#L110C5-L110C11
|
|
55
|
+
return entry.line1 * (Math.max(entry.col1, entry.col2) + 1) + entry.col1;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import type { MergeableRecord } from '../../../../../util/objects';
|
|
2
2
|
import type { DeepReadonly } from 'ts-essentials';
|
|
3
|
-
import type { XmlParserConfig } from './config';
|
|
4
3
|
import type { XmlParserHooks } from './hooks';
|
|
5
4
|
import type { SourceRange } from '../../../../../util/range';
|
|
6
5
|
/**
|
|
7
6
|
* Contains all information populated and present during parsing and normalization of the R AST.
|
|
8
7
|
*/
|
|
9
8
|
export interface ParserData extends MergeableRecord {
|
|
10
|
-
/** @see XmlParserConfig */
|
|
11
|
-
readonly config: DeepReadonly<XmlParserConfig>;
|
|
12
9
|
/** @see XmlParserHooks */
|
|
13
10
|
readonly hooks: DeepReadonly<XmlParserHooks>;
|
|
14
11
|
/**
|
|
@@ -16,7 +16,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./data"), exports);
|
|
18
18
|
__exportStar(require("./hooks"), exports);
|
|
19
|
-
__exportStar(require("./config"), exports);
|
|
20
|
-
__exportStar(require("./parser"), exports);
|
|
21
19
|
__exportStar(require("./input-format"), exports);
|
|
22
20
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import type { RawRType } from '../../model';
|
|
2
|
+
export declare const attributesKey = "a";
|
|
3
|
+
export declare const childrenKey = "c";
|
|
4
|
+
export declare const contentKey = "@";
|
|
5
|
+
export declare const nameKey = "#";
|
|
2
6
|
/**
|
|
3
7
|
* Thrown if the given input xml is not valid/contains unexpected elements.
|
|
4
8
|
*/
|
|
@@ -29,4 +33,4 @@ export interface NamedXmlBasedJson {
|
|
|
29
33
|
* @typeParam T - the type of the values to retrieve. Note, that this type is not checked at runtime.
|
|
30
34
|
*/
|
|
31
35
|
export declare function getKeysGuarded<T extends XmlBasedJsonValue>(obj: XmlBasedJson, key: string): T;
|
|
32
|
-
export declare function getKeysGuarded<T extends XmlBasedJsonValue>(obj: XmlBasedJson, ...key: string[]): Record<string, T>;
|
|
36
|
+
export declare function getKeysGuarded<T extends XmlBasedJsonValue>(obj: XmlBasedJson, ...key: readonly string[]): Record<string, T>;
|