@eagleoutice/flowr 2.1.12 → 2.2.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 +0 -1
- package/benchmark/slicer.d.ts +5 -12
- package/benchmark/slicer.js +46 -28
- package/cli/benchmark-app.d.ts +2 -0
- package/cli/benchmark-app.js +2 -1
- package/cli/benchmark-helper-app.d.ts +2 -0
- package/cli/benchmark-helper-app.js +2 -2
- package/cli/common/options.js +3 -1
- package/cli/flowr-main-options.js +36 -2
- package/cli/flowr.d.ts +6 -0
- package/cli/flowr.js +51 -24
- package/cli/repl/commands/repl-cfg.js +2 -4
- package/cli/repl/commands/repl-dataflow.js +2 -4
- package/cli/repl/commands/repl-execute.d.ts +2 -2
- package/cli/repl/commands/repl-execute.js +15 -5
- package/cli/repl/commands/repl-lineage.js +2 -4
- package/cli/repl/commands/repl-main.d.ts +2 -2
- package/cli/repl/commands/repl-normalize.js +2 -4
- package/cli/repl/commands/repl-parse.js +2 -4
- package/cli/repl/commands/repl-query.js +6 -8
- package/cli/repl/commands/repl-version.d.ts +5 -4
- package/cli/repl/commands/repl-version.js +10 -9
- package/cli/repl/core.d.ts +5 -5
- package/cli/repl/core.js +8 -12
- package/cli/repl/print-version.d.ts +2 -2
- package/cli/repl/print-version.js +3 -3
- package/cli/repl/server/connection.d.ts +3 -3
- package/cli/repl/server/connection.js +5 -7
- package/cli/repl/server/messages/message-hello.js +2 -1
- package/cli/repl/server/server.d.ts +4 -3
- package/cli/repl/server/server.js +7 -5
- package/cli/slicer-app.js +1 -1
- package/config.d.ts +36 -4
- package/config.js +30 -1
- package/core/pipeline-executor.d.ts +1 -1
- package/core/pipeline-executor.js +1 -1
- package/core/steps/all/core/00-parse.d.ts +4 -18
- package/core/steps/all/core/00-parse.js +2 -11
- package/core/steps/all/core/01-parse-tree-sitter.d.ts +23 -0
- package/core/steps/all/core/01-parse-tree-sitter.js +19 -0
- package/core/steps/all/core/10-normalize.d.ts +3 -2
- package/core/steps/all/core/10-normalize.js +1 -0
- package/core/steps/all/core/11-normalize-tree-sitter.d.ts +25 -0
- package/core/steps/all/core/11-normalize-tree-sitter.js +27 -0
- package/core/steps/all/core/20-dataflow.d.ts +2 -0
- package/core/steps/all/core/20-dataflow.js +1 -1
- package/core/steps/pipeline/default-pipelines.d.ts +368 -23
- package/core/steps/pipeline/default-pipelines.js +42 -4
- package/dataflow/environments/resolve-by-name.js +5 -4
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +6 -5
- package/dataflow/processor.d.ts +2 -0
- package/documentation/doc-util/doc-auto-gen.js +2 -1
- package/documentation/doc-util/doc-cfg.js +1 -1
- package/documentation/doc-util/doc-dfg.js +2 -2
- package/documentation/doc-util/doc-files.d.ts +1 -0
- package/documentation/doc-util/doc-files.js +4 -0
- package/documentation/doc-util/doc-normalized-ast.js +2 -3
- package/documentation/doc-util/doc-query.js +1 -1
- package/documentation/doc-util/doc-search.js +1 -1
- package/documentation/doc-util/doc-types.js +2 -2
- package/documentation/print-dataflow-graph-wiki.js +15 -15
- package/documentation/print-engines-wiki.d.ts +1 -0
- package/documentation/print-engines-wiki.js +82 -0
- package/documentation/print-interface-wiki.js +6 -7
- package/documentation/print-normalized-ast-wiki.js +1 -1
- package/documentation/print-query-wiki.js +24 -0
- package/package.json +9 -5
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +5 -4
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +5 -4
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +5 -4
- package/queries/catalog/happens-before-query/happens-before-query-executor.d.ts +3 -0
- package/queries/catalog/happens-before-query/happens-before-query-executor.js +36 -0
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +71 -0
- package/queries/catalog/happens-before-query/happens-before-query-format.js +27 -0
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +5 -4
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +5 -4
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +5 -4
- package/queries/catalog/search-query/search-query-executor.js +0 -4
- package/queries/catalog/search-query/search-query-format.d.ts +5 -4
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +5 -4
- package/queries/query.d.ts +100 -33
- package/queries/query.js +3 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +4 -2
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +5 -0
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +18 -0
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +57 -0
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +3 -0
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +541 -0
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.d.ts +35 -0
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-types.js +40 -0
- package/r-bridge/parser.d.ts +32 -0
- package/r-bridge/parser.js +14 -0
- package/r-bridge/shell-executor.d.ts +37 -1
- package/r-bridge/shell-executor.js +39 -0
- package/r-bridge/shell.d.ts +12 -6
- package/r-bridge/shell.js +15 -6
- package/search/search-optimizer/search-optimizer.js +1 -1
- package/statistics/statistics.js +1 -1
- package/util/cfg/cfg.d.ts +2 -0
- package/util/cfg/cfg.js +8 -8
- package/util/cfg/happens-before.d.ts +7 -0
- package/util/cfg/happens-before.js +32 -0
- package/util/logic.d.ts +4 -4
- package/util/logic.js +8 -0
- package/util/version.js +1 -1
|
@@ -1,10 +1,46 @@
|
|
|
1
1
|
import type { RShellExecutionOptions } from './shell';
|
|
2
2
|
import type { SemVer } from 'semver';
|
|
3
|
-
|
|
3
|
+
import type { SyncParser } from './parser';
|
|
4
|
+
import { type RParseRequest } from './retriever';
|
|
5
|
+
/**
|
|
6
|
+
* This is a synchronous alternative to the {@link RShell}.
|
|
7
|
+
* Please be aware that using this is expensive.
|
|
8
|
+
* Every request effectively causes a new initialization of the R interpreter.
|
|
9
|
+
*
|
|
10
|
+
* With this class you can {@link RShellExecutor#run|run(command)} commands,
|
|
11
|
+
* that are potentially decorated with {@link RShellExecutor#addPrerequisites|prerequisites}.
|
|
12
|
+
* For compatibility,
|
|
13
|
+
* we provide {@link RShellExecutor#parse|parse(request)} and {@link RShellExecutor#rVersion|rVersion()}.
|
|
14
|
+
*/
|
|
15
|
+
export declare class RShellExecutor implements SyncParser<string> {
|
|
16
|
+
readonly name = "r-shell";
|
|
4
17
|
readonly options: Readonly<RShellExecutionOptions>;
|
|
5
18
|
private readonly prerequisites;
|
|
6
19
|
constructor(options?: Partial<RShellExecutionOptions>);
|
|
20
|
+
/**
|
|
21
|
+
* Adds commands that should be executed for every {@link RShellExecutor#run|run}.
|
|
22
|
+
*/
|
|
7
23
|
addPrerequisites(commands: string | string[]): this;
|
|
24
|
+
/**
|
|
25
|
+
* @returns the version of the R interpreter available to this executor.
|
|
26
|
+
*
|
|
27
|
+
* @see {@link RShellExecutor#usedRVersion}
|
|
28
|
+
* @see {@link RShell#rVersion}
|
|
29
|
+
* @see {@link RShell#usedRVersion}
|
|
30
|
+
*/
|
|
31
|
+
rVersion(): Promise<string | 'unknown' | 'none'>;
|
|
32
|
+
/**
|
|
33
|
+
* Instead of returning a promise, this method returns the version of the R interpreter available to this executor,
|
|
34
|
+
* in the SemVer format.
|
|
35
|
+
*/
|
|
8
36
|
usedRVersion(): SemVer | null;
|
|
37
|
+
/**
|
|
38
|
+
* Runs the given command in the R interpreter.
|
|
39
|
+
*/
|
|
9
40
|
run(command: string, returnErr?: boolean): string;
|
|
41
|
+
/**
|
|
42
|
+
* Parses the given request and returns the result.
|
|
43
|
+
*/
|
|
44
|
+
parse(request: RParseRequest): string;
|
|
45
|
+
close(): void;
|
|
10
46
|
}
|
|
@@ -11,23 +11,55 @@ const preload_1 = __importDefault(require("semver/preload"));
|
|
|
11
11
|
const log_1 = require("../util/log");
|
|
12
12
|
const init_1 = require("./init");
|
|
13
13
|
const convert_values_1 = require("./lang-4.x/convert-values");
|
|
14
|
+
const retriever_1 = require("./retriever");
|
|
14
15
|
const executorLog = log_1.log.getSubLogger({ name: 'RShellExecutor' });
|
|
16
|
+
/**
|
|
17
|
+
* This is a synchronous alternative to the {@link RShell}.
|
|
18
|
+
* Please be aware that using this is expensive.
|
|
19
|
+
* Every request effectively causes a new initialization of the R interpreter.
|
|
20
|
+
*
|
|
21
|
+
* With this class you can {@link RShellExecutor#run|run(command)} commands,
|
|
22
|
+
* that are potentially decorated with {@link RShellExecutor#addPrerequisites|prerequisites}.
|
|
23
|
+
* For compatibility,
|
|
24
|
+
* we provide {@link RShellExecutor#parse|parse(request)} and {@link RShellExecutor#rVersion|rVersion()}.
|
|
25
|
+
*/
|
|
15
26
|
class RShellExecutor {
|
|
27
|
+
name = 'r-shell';
|
|
16
28
|
options;
|
|
17
29
|
prerequisites;
|
|
18
30
|
constructor(options) {
|
|
19
31
|
this.options = (0, objects_1.deepMergeObject)((0, shell_1.getDefaultRShellOptions)(), options);
|
|
20
32
|
this.prerequisites = [(0, init_1.initCommand)(this.options.eol)];
|
|
21
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Adds commands that should be executed for every {@link RShellExecutor#run|run}.
|
|
36
|
+
*/
|
|
22
37
|
addPrerequisites(commands) {
|
|
23
38
|
this.prerequisites.push(...(typeof commands == 'string' ? [commands] : commands));
|
|
24
39
|
return this;
|
|
25
40
|
}
|
|
41
|
+
/**
|
|
42
|
+
* @returns the version of the R interpreter available to this executor.
|
|
43
|
+
*
|
|
44
|
+
* @see {@link RShellExecutor#usedRVersion}
|
|
45
|
+
* @see {@link RShell#rVersion}
|
|
46
|
+
* @see {@link RShell#usedRVersion}
|
|
47
|
+
*/
|
|
48
|
+
rVersion() {
|
|
49
|
+
return Promise.resolve(this.usedRVersion()?.format() ?? 'unknown');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Instead of returning a promise, this method returns the version of the R interpreter available to this executor,
|
|
53
|
+
* in the SemVer format.
|
|
54
|
+
*/
|
|
26
55
|
usedRVersion() {
|
|
27
56
|
const version = this.run(`cat(paste0(R.version$major,".",R.version$minor), ${(0, convert_values_1.ts2r)(this.options.eol)})`);
|
|
28
57
|
(0, log_1.expensiveTrace)(executorLog, () => `raw version: ${JSON.stringify(version)}`);
|
|
29
58
|
return preload_1.default.coerce(version);
|
|
30
59
|
}
|
|
60
|
+
/**
|
|
61
|
+
* Runs the given command in the R interpreter.
|
|
62
|
+
*/
|
|
31
63
|
run(command, returnErr = false) {
|
|
32
64
|
command += ';base::quit()';
|
|
33
65
|
(0, log_1.expensiveTrace)(executorLog, () => `> ${JSON.stringify(command)}`);
|
|
@@ -40,6 +72,13 @@ class RShellExecutor {
|
|
|
40
72
|
});
|
|
41
73
|
return (returnErr ? returns.stderr : returns.stdout).trim();
|
|
42
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Parses the given request and returns the result.
|
|
77
|
+
*/
|
|
78
|
+
parse(request) {
|
|
79
|
+
return (0, retriever_1.retrieveParseDataFromRCode)(request, this);
|
|
80
|
+
}
|
|
81
|
+
close() { }
|
|
43
82
|
}
|
|
44
83
|
exports.RShellExecutor = RShellExecutor;
|
|
45
84
|
//# sourceMappingURL=shell-executor.js.map
|
package/r-bridge/shell.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type MergeableRecord } from '../util/objects';
|
|
2
2
|
import type { SemVer } from 'semver';
|
|
3
3
|
import type { AsyncOrSync } from 'ts-essentials';
|
|
4
|
+
import type { AsyncParser } from './parser';
|
|
5
|
+
import type { RParseRequest } from './retriever';
|
|
4
6
|
export type OutputStreamSelector = 'stdout' | 'stderr' | 'both';
|
|
5
7
|
export interface CollectorTimeout extends MergeableRecord {
|
|
6
8
|
/**
|
|
@@ -72,22 +74,26 @@ export declare function getDefaultRShellOptions(): RShellOptions;
|
|
|
72
74
|
* You can configure it by {@link RShellOptions}.
|
|
73
75
|
*
|
|
74
76
|
* At the moment we are using a live R session (and not networking etc.) to communicate with R easily,
|
|
75
|
-
* which allows us to install packages etc. However, this might and probably will change in the future
|
|
76
|
-
* as a legacy mode :D)
|
|
77
|
+
* which allows us to install packages etc. However, this might and probably will change in the future
|
|
78
|
+
* (leaving this as a legacy mode :D)
|
|
77
79
|
*/
|
|
78
|
-
export declare class RShell {
|
|
80
|
+
export declare class RShell implements AsyncParser<string> {
|
|
81
|
+
readonly name = "r-shell";
|
|
82
|
+
readonly async = true;
|
|
79
83
|
readonly options: Readonly<RShellOptions>;
|
|
80
84
|
private session;
|
|
81
85
|
private readonly log;
|
|
82
86
|
private versionCache;
|
|
83
87
|
private tempDirs;
|
|
84
88
|
constructor(options?: Partial<RShellOptions>);
|
|
89
|
+
parse(request: RParseRequest): Promise<string>;
|
|
85
90
|
private revive;
|
|
86
91
|
/**
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
* sends the given command directly to the current R session
|
|
93
|
+
* will not do anything to alter input markers!
|
|
94
|
+
*/
|
|
90
95
|
sendCommand(command: string): void;
|
|
96
|
+
rVersion(): Promise<string | 'unknown' | 'none'>;
|
|
91
97
|
usedRVersion(): Promise<SemVer | null>;
|
|
92
98
|
injectLibPaths(...paths: readonly string[]): void;
|
|
93
99
|
tryToInjectHomeLibPath(): void;
|
package/r-bridge/shell.js
CHANGED
|
@@ -38,6 +38,7 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
38
38
|
const init_1 = require("./init");
|
|
39
39
|
const config_1 = require("../config");
|
|
40
40
|
const convert_values_1 = require("./lang-4.x/convert-values");
|
|
41
|
+
const retriever_1 = require("./retriever");
|
|
41
42
|
exports.DEFAULT_OUTPUT_COLLECTOR_CONFIGURATION = {
|
|
42
43
|
from: 'stdout',
|
|
43
44
|
postamble: `🐧${'-'.repeat(5)}🐧`,
|
|
@@ -54,7 +55,7 @@ let DEFAULT_R_SHELL_OPTIONS = undefined;
|
|
|
54
55
|
function getDefaultRShellOptions() {
|
|
55
56
|
if (!DEFAULT_R_SHELL_OPTIONS) {
|
|
56
57
|
DEFAULT_R_SHELL_OPTIONS = {
|
|
57
|
-
pathToRExecutable: (0, config_1.
|
|
58
|
+
pathToRExecutable: (0, config_1.getEngineConfig)('r-shell')?.rPath ?? exports.DEFAULT_R_PATH,
|
|
58
59
|
// -s is a short form of --no-echo (and the old version --slave), but this one works in R 3 and 4
|
|
59
60
|
// (see https://github.com/wch/r-source/commit/f1ff49e74593341c74c20de9517f31a22c8bcb04)
|
|
60
61
|
commandLineOptions: ['--vanilla', '--quiet', '--no-save', '-s'],
|
|
@@ -74,10 +75,12 @@ function getDefaultRShellOptions() {
|
|
|
74
75
|
* You can configure it by {@link RShellOptions}.
|
|
75
76
|
*
|
|
76
77
|
* At the moment we are using a live R session (and not networking etc.) to communicate with R easily,
|
|
77
|
-
* which allows us to install packages etc. However, this might and probably will change in the future
|
|
78
|
-
* as a legacy mode :D)
|
|
78
|
+
* which allows us to install packages etc. However, this might and probably will change in the future
|
|
79
|
+
* (leaving this as a legacy mode :D)
|
|
79
80
|
*/
|
|
80
81
|
class RShell {
|
|
82
|
+
name = 'r-shell';
|
|
83
|
+
async = true;
|
|
81
84
|
options;
|
|
82
85
|
session;
|
|
83
86
|
log;
|
|
@@ -90,6 +93,9 @@ class RShell {
|
|
|
90
93
|
this.session = new RShellSession(this.options, this.log);
|
|
91
94
|
this.revive();
|
|
92
95
|
}
|
|
96
|
+
parse(request) {
|
|
97
|
+
return (0, retriever_1.retrieveParseDataFromRCode)(request, this);
|
|
98
|
+
}
|
|
93
99
|
revive() {
|
|
94
100
|
if (this.options.revive === 0 /* RShellReviveOptions.Never */) {
|
|
95
101
|
return;
|
|
@@ -104,15 +110,18 @@ class RShell {
|
|
|
104
110
|
});
|
|
105
111
|
}
|
|
106
112
|
/**
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
113
|
+
* sends the given command directly to the current R session
|
|
114
|
+
* will not do anything to alter input markers!
|
|
115
|
+
*/
|
|
110
116
|
sendCommand(command) {
|
|
111
117
|
if (this.log.settings.minLevel <= 1 /* LogLevel.Trace */) {
|
|
112
118
|
this.log.trace(`> ${JSON.stringify(command)}`);
|
|
113
119
|
}
|
|
114
120
|
this._sendCommand(command);
|
|
115
121
|
}
|
|
122
|
+
async rVersion() {
|
|
123
|
+
return (await this.usedRVersion())?.format() ?? 'unknown';
|
|
124
|
+
}
|
|
116
125
|
async usedRVersion() {
|
|
117
126
|
if (this.versionCache !== null) {
|
|
118
127
|
return this.versionCache;
|
|
@@ -71,7 +71,7 @@ function dropAnyNameRegex(generator) {
|
|
|
71
71
|
if (generator.name !== 'get' || !generator.args.filter.nameIsRegex) {
|
|
72
72
|
return generator;
|
|
73
73
|
}
|
|
74
|
-
if (generator.args.filter.name === '
|
|
74
|
+
if (generator.args.filter.name === '.*') {
|
|
75
75
|
return {
|
|
76
76
|
...generator,
|
|
77
77
|
args: {
|
package/statistics/statistics.js
CHANGED
|
@@ -82,7 +82,7 @@ function processMetaOnSuccessful(meta, request) {
|
|
|
82
82
|
const parser = new xmldom_1.DOMParser();
|
|
83
83
|
async function extractSingle(result, shell, request, features, suffixFilePath) {
|
|
84
84
|
const slicerOutput = await new pipeline_executor_1.PipelineExecutor(default_pipelines_1.DEFAULT_DATAFLOW_PIPELINE, {
|
|
85
|
-
request, shell
|
|
85
|
+
request, parser: shell
|
|
86
86
|
}).allRemainingSteps();
|
|
87
87
|
// retrieve parsed xml through (legacy) xmlparsedata
|
|
88
88
|
const suffix = request.request === 'file' ? ', encoding="utf-8"' : '';
|
package/util/cfg/cfg.d.ts
CHANGED
|
@@ -25,6 +25,8 @@ interface CfgFlowDependencyEdge extends MergeableRecord {
|
|
|
25
25
|
}
|
|
26
26
|
interface CfgControlDependencyEdge extends MergeableRecord {
|
|
27
27
|
label: 'CD';
|
|
28
|
+
/** the id which caused the control dependency */
|
|
29
|
+
caused: NodeId;
|
|
28
30
|
when: typeof RTrue | typeof RFalse;
|
|
29
31
|
}
|
|
30
32
|
export type CfgEdge = CfgFlowDependencyEdge | CfgControlDependencyEdge;
|
package/util/cfg/cfg.js
CHANGED
|
@@ -134,10 +134,10 @@ function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
|
134
134
|
}
|
|
135
135
|
for (const exitPoint of condition.exitPoints) {
|
|
136
136
|
for (const entryPoint of then.entryPoints) {
|
|
137
|
-
graph.addEdge(entryPoint, exitPoint, { label: 'CD', when: convert_values_1.RTrue });
|
|
137
|
+
graph.addEdge(entryPoint, exitPoint, { label: 'CD', when: convert_values_1.RTrue, caused: ifNode.info.id });
|
|
138
138
|
}
|
|
139
139
|
for (const entryPoint of otherwise?.entryPoints ?? []) {
|
|
140
|
-
graph.addEdge(entryPoint, exitPoint, { label: 'CD', when: convert_values_1.RFalse });
|
|
140
|
+
graph.addEdge(entryPoint, exitPoint, { label: 'CD', when: convert_values_1.RFalse, caused: ifNode.info.id });
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
for (const entryPoint of condition.entryPoints) {
|
|
@@ -148,7 +148,7 @@ function cfgIfThenElse(ifNode, condition, then, otherwise) {
|
|
|
148
148
|
}
|
|
149
149
|
if (!otherwise) {
|
|
150
150
|
for (const exitPoint of condition.exitPoints) {
|
|
151
|
-
graph.addEdge(ifNode.info.id + '-exit', exitPoint, { label: 'CD', when: convert_values_1.RFalse });
|
|
151
|
+
graph.addEdge(ifNode.info.id + '-exit', exitPoint, { label: 'CD', when: convert_values_1.RFalse, caused: ifNode.info.id });
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
return {
|
|
@@ -165,7 +165,7 @@ function cfgRepeat(repeat, body) {
|
|
|
165
165
|
graph.addVertex({ id: repeat.info.id, name: repeat.type, type: identifyMayStatementType(repeat) });
|
|
166
166
|
graph.addVertex({ id: repeat.info.id + '-exit', name: 'repeat-exit', type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
167
167
|
for (const entryPoint of body.entryPoints) {
|
|
168
|
-
graph.addEdge(repeat.info.id,
|
|
168
|
+
graph.addEdge(entryPoint, repeat.info.id, { label: 'FD' });
|
|
169
169
|
}
|
|
170
170
|
// loops automatically
|
|
171
171
|
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
@@ -186,7 +186,7 @@ function cfgWhile(whileLoop, condition, body) {
|
|
|
186
186
|
}
|
|
187
187
|
for (const exit of condition.exitPoints) {
|
|
188
188
|
for (const entry of body.entryPoints) {
|
|
189
|
-
graph.addEdge(entry, exit, { label: 'CD', when: convert_values_1.RTrue });
|
|
189
|
+
graph.addEdge(entry, exit, { label: 'CD', when: convert_values_1.RTrue, caused: whileLoop.info.id });
|
|
190
190
|
}
|
|
191
191
|
}
|
|
192
192
|
for (const entryPoint of body.entryPoints) {
|
|
@@ -200,7 +200,7 @@ function cfgWhile(whileLoop, condition, body) {
|
|
|
200
200
|
}
|
|
201
201
|
// while can break on the condition as well
|
|
202
202
|
for (const exit of condition.exitPoints) {
|
|
203
|
-
graph.addEdge(whileLoop.info.id + '-exit', exit, { label: 'CD', when: convert_values_1.RFalse });
|
|
203
|
+
graph.addEdge(whileLoop.info.id + '-exit', exit, { label: 'CD', when: convert_values_1.RFalse, caused: whileLoop.info.id });
|
|
204
204
|
}
|
|
205
205
|
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [whileLoop.info.id + '-exit'], entryPoints: [whileLoop.info.id] };
|
|
206
206
|
}
|
|
@@ -220,7 +220,7 @@ function cfgFor(forLoop, variable, vector, body) {
|
|
|
220
220
|
}
|
|
221
221
|
for (const exit of variable.exitPoints) {
|
|
222
222
|
for (const entry of body.entryPoints) {
|
|
223
|
-
graph.addEdge(entry, exit, { label: 'CD', when: convert_values_1.RTrue });
|
|
223
|
+
graph.addEdge(entry, exit, { label: 'CD', when: convert_values_1.RTrue, caused: forLoop.info.id });
|
|
224
224
|
}
|
|
225
225
|
}
|
|
226
226
|
for (const next of [...body.nexts, ...body.exitPoints]) {
|
|
@@ -231,7 +231,7 @@ function cfgFor(forLoop, variable, vector, body) {
|
|
|
231
231
|
}
|
|
232
232
|
// while can break on the condition as well
|
|
233
233
|
for (const exit of variable.exitPoints) {
|
|
234
|
-
graph.addEdge(forLoop.info.id + '-exit', exit, { label: 'CD', when: convert_values_1.RFalse });
|
|
234
|
+
graph.addEdge(forLoop.info.id + '-exit', exit, { label: 'CD', when: convert_values_1.RFalse, caused: forLoop.info.id });
|
|
235
235
|
}
|
|
236
236
|
return { graph, breaks: [], nexts: [], returns: body.returns, exitPoints: [forLoop.info.id + '-exit'], entryPoints: [forLoop.info.id] };
|
|
237
237
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ControlFlowGraph } from './cfg';
|
|
2
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
|
+
import { Ternary } from '../logic';
|
|
4
|
+
/**
|
|
5
|
+
* Determines if node `a` happens before node `b` in the control flow graph.
|
|
6
|
+
*/
|
|
7
|
+
export declare function happensBefore(cfg: ControlFlowGraph, a: NodeId, b: NodeId): Ternary;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.happensBefore = happensBefore;
|
|
4
|
+
const logic_1 = require("../logic");
|
|
5
|
+
/**
|
|
6
|
+
* Determines if node `a` happens before node `b` in the control flow graph.
|
|
7
|
+
*/
|
|
8
|
+
function happensBefore(cfg, a, b) {
|
|
9
|
+
const visited = new Set();
|
|
10
|
+
/* the first is the id we are currently at, the second one the exit marker of the current largest cd scope */
|
|
11
|
+
const stack = [[b, undefined]];
|
|
12
|
+
while (stack.length > 0) {
|
|
13
|
+
const [current, cd] = stack.pop();
|
|
14
|
+
let useCd = cd;
|
|
15
|
+
if (current === a) {
|
|
16
|
+
return cd ? logic_1.Ternary.Maybe : logic_1.Ternary.Always;
|
|
17
|
+
}
|
|
18
|
+
else if (visited.has(current)) {
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
else if (cd && (current === cd || visited.has(cd))) {
|
|
22
|
+
useCd = undefined;
|
|
23
|
+
}
|
|
24
|
+
visited.add(current);
|
|
25
|
+
for (const [id, t] of cfg.outgoing(current) ?? []) {
|
|
26
|
+
const marker = t.label === 'CD' ? `${t.caused}-exit` : useCd;
|
|
27
|
+
stack.push([id, useCd ?? marker]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return logic_1.Ternary.Never;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=happens-before.js.map
|
package/util/logic.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare
|
|
2
|
-
Always =
|
|
3
|
-
Maybe =
|
|
4
|
-
Never =
|
|
1
|
+
export declare enum Ternary {
|
|
2
|
+
Always = "always",
|
|
3
|
+
Maybe = "maybe",
|
|
4
|
+
Never = "never"
|
|
5
5
|
}
|
package/util/logic.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Ternary = void 0;
|
|
4
|
+
// diverging from boolean | maybe requires explicit handling
|
|
5
|
+
var Ternary;
|
|
6
|
+
(function (Ternary) {
|
|
7
|
+
Ternary["Always"] = "always";
|
|
8
|
+
Ternary["Maybe"] = "maybe";
|
|
9
|
+
Ternary["Never"] = "never";
|
|
10
|
+
})(Ternary || (exports.Ternary = Ternary = {}));
|
|
3
11
|
//# sourceMappingURL=logic.js.map
|
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.1
|
|
6
|
+
const version = '2.2.1';
|
|
7
7
|
function flowrVersion() {
|
|
8
8
|
return new semver_1.SemVer(version);
|
|
9
9
|
}
|