@eagleoutice/flowr 2.2.14 → 2.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -6
- package/benchmark/slicer.d.ts +3 -1
- package/benchmark/slicer.js +8 -5
- package/benchmark/summarizer/first-phase/process.d.ts +2 -1
- package/benchmark/summarizer/first-phase/process.js +2 -2
- package/cli/benchmark-app.d.ts +1 -0
- package/cli/benchmark-app.js +4 -1
- package/cli/benchmark-helper-app.d.ts +1 -0
- package/cli/benchmark-helper-app.js +7 -8
- package/cli/common/options.js +2 -0
- package/cli/export-quads-app.js +2 -1
- package/cli/flowr.js +58 -57
- package/cli/repl/commands/repl-cfg.js +13 -13
- package/cli/repl/commands/repl-commands.js +3 -3
- package/cli/repl/commands/repl-dataflow.js +10 -10
- package/cli/repl/commands/repl-execute.d.ts +2 -3
- package/cli/repl/commands/repl-execute.js +5 -4
- package/cli/repl/commands/repl-lineage.js +4 -4
- package/cli/repl/commands/repl-main.d.ts +12 -1
- package/cli/repl/commands/repl-normalize.js +6 -6
- package/cli/repl/commands/repl-parse.js +2 -2
- package/cli/repl/commands/repl-query.js +9 -9
- package/cli/repl/commands/repl-version.js +1 -1
- package/cli/repl/core.d.ts +5 -2
- package/cli/repl/core.js +10 -8
- package/cli/repl/server/connection.d.ts +3 -1
- package/cli/repl/server/connection.js +7 -5
- package/cli/repl/server/server.d.ts +3 -2
- package/cli/repl/server/server.js +4 -2
- package/cli/script-core/statistics-core.d.ts +2 -1
- package/cli/script-core/statistics-core.js +2 -2
- package/cli/script-core/statistics-helper-core.d.ts +2 -1
- package/cli/script-core/statistics-helper-core.js +5 -4
- package/cli/slicer-app.js +4 -2
- package/cli/statistics-app.js +2 -1
- package/cli/statistics-helper-app.js +2 -1
- package/config.d.ts +12 -10
- package/config.js +27 -43
- package/control-flow/basic-cfg-guided-visitor.d.ts +3 -3
- package/control-flow/cfg-dead-code.d.ts +4 -0
- package/control-flow/cfg-dead-code.js +124 -0
- package/control-flow/cfg-simplification.d.ts +19 -6
- package/control-flow/cfg-simplification.js +23 -19
- package/control-flow/control-flow-graph.d.ts +3 -1
- package/control-flow/control-flow-graph.js +5 -0
- package/control-flow/dfg-cfg-guided-visitor.d.ts +9 -7
- package/control-flow/dfg-cfg-guided-visitor.js +16 -5
- package/control-flow/extract-cfg.d.ts +4 -2
- package/control-flow/extract-cfg.js +63 -59
- package/control-flow/semantic-cfg-guided-visitor.d.ts +36 -9
- package/control-flow/semantic-cfg-guided-visitor.js +73 -20
- package/control-flow/simple-visitor.d.ts +4 -0
- package/control-flow/simple-visitor.js +14 -0
- package/control-flow/syntax-cfg-guided-visitor.d.ts +2 -2
- package/core/pipeline-executor.d.ts +4 -1
- package/core/pipeline-executor.js +6 -5
- package/core/steps/all/core/10-normalize.d.ts +2 -0
- package/core/steps/all/core/10-normalize.js +1 -1
- package/core/steps/all/core/11-normalize-tree-sitter.d.ts +2 -1
- package/core/steps/all/core/11-normalize-tree-sitter.js +2 -2
- package/core/steps/all/core/20-dataflow.d.ts +2 -1
- package/core/steps/all/core/20-dataflow.js +2 -2
- package/core/steps/all/static-slicing/00-slice.d.ts +2 -1
- package/core/steps/all/static-slicing/00-slice.js +2 -2
- package/core/steps/pipeline/default-pipelines.d.ts +32 -31
- package/core/steps/pipeline/default-pipelines.js +8 -8
- package/core/steps/pipeline-step.d.ts +2 -1
- package/dataflow/environments/built-in-config.d.ts +4 -3
- package/dataflow/environments/built-in.d.ts +16 -1
- package/dataflow/environments/built-in.js +11 -5
- package/dataflow/environments/default-builtin-config.js +5 -3
- package/dataflow/environments/define.d.ts +2 -1
- package/dataflow/environments/define.js +4 -5
- package/dataflow/environments/remove.d.ts +6 -0
- package/dataflow/environments/remove.js +29 -0
- package/dataflow/environments/resolve-by-name.d.ts +0 -36
- package/dataflow/environments/resolve-by-name.js +0 -240
- package/dataflow/eval/resolve/alias-tracking.d.ts +92 -0
- package/dataflow/eval/resolve/alias-tracking.js +352 -0
- package/dataflow/eval/resolve/resolve-argument.d.ts +8 -0
- package/dataflow/eval/resolve/resolve-argument.js +118 -0
- package/dataflow/eval/resolve/resolve.d.ts +37 -0
- package/dataflow/eval/resolve/resolve.js +95 -0
- package/dataflow/eval/values/general.d.ts +27 -0
- package/dataflow/eval/values/general.js +73 -0
- package/dataflow/eval/values/intervals/interval-constants.d.ts +4 -0
- package/dataflow/eval/values/intervals/interval-constants.js +27 -0
- package/dataflow/eval/values/logical/logical-constants.d.ts +7 -0
- package/dataflow/eval/values/logical/logical-constants.js +31 -0
- package/dataflow/eval/values/r-value.d.ts +58 -0
- package/dataflow/eval/values/r-value.js +90 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.d.ts +15 -0
- package/dataflow/eval/values/scalar/scalar-consatnts.js +35 -0
- package/dataflow/eval/values/sets/set-constants.d.ts +7 -0
- package/dataflow/eval/values/sets/set-constants.js +34 -0
- package/dataflow/eval/values/string/string-constants.d.ts +8 -0
- package/dataflow/eval/values/string/string-constants.js +45 -0
- package/dataflow/eval/values/vectors/vector-constants.d.ts +14 -0
- package/dataflow/eval/values/vectors/vector-constants.js +35 -0
- package/dataflow/extractor.d.ts +2 -1
- package/dataflow/extractor.js +2 -1
- package/dataflow/graph/unknown-replacement.d.ts +11 -0
- package/dataflow/graph/unknown-replacement.js +12 -0
- package/dataflow/graph/unknown-side-effect.d.ts +7 -0
- package/dataflow/graph/unknown-side-effect.js +13 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +5 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +8 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +4 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +15 -13
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +20 -18
- package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +7 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +2 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -4
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +11 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-source.d.ts +5 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-source.js +26 -29
- package/dataflow/internal/process/functions/call/built-in/built-in-vector.js +2 -2
- package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +23 -0
- package/dataflow/internal/process/functions/call/common.js +1 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +2 -1
- package/dataflow/internal/process/functions/process-parameter.js +1 -1
- package/dataflow/origin/dfg-get-symbol-refs.d.ts +21 -0
- package/dataflow/origin/dfg-get-symbol-refs.js +50 -0
- package/dataflow/processor.d.ts +5 -0
- package/documentation/doc-util/doc-cfg.js +4 -3
- package/documentation/doc-util/doc-code.d.ts +1 -1
- package/documentation/doc-util/doc-dfg.js +3 -2
- package/documentation/doc-util/doc-functions.d.ts +24 -0
- package/documentation/doc-util/doc-functions.js +65 -0
- package/documentation/doc-util/doc-normalized-ast.js +3 -2
- package/documentation/doc-util/doc-print.d.ts +5 -0
- package/documentation/doc-util/doc-print.js +36 -0
- package/documentation/doc-util/doc-query.d.ts +6 -3
- package/documentation/doc-util/doc-query.js +6 -3
- package/documentation/doc-util/doc-repl.js +2 -1
- package/documentation/doc-util/doc-search.js +3 -2
- package/documentation/doc-util/doc-types.d.ts +28 -6
- package/documentation/doc-util/doc-types.js +89 -45
- package/documentation/print-cfg-wiki.js +10 -11
- package/documentation/print-core-wiki.js +5 -5
- package/documentation/print-dataflow-graph-wiki.js +14 -13
- package/documentation/print-engines-wiki.js +2 -3
- package/documentation/print-faq-wiki.js +8 -2
- package/documentation/print-interface-wiki.js +1 -2
- package/documentation/print-linter-issue.d.ts +1 -0
- package/documentation/print-linter-issue.js +71 -0
- package/documentation/print-linter-wiki.js +219 -34
- package/documentation/print-linting-and-testing-wiki.js +2 -4
- package/documentation/print-normalized-ast-wiki.js +3 -3
- package/documentation/print-query-wiki.js +81 -2
- package/documentation/print-readme.js +24 -1
- package/documentation/print-search-wiki.js +1 -2
- package/linter/linter-executor.d.ts +3 -1
- package/linter/linter-executor.js +3 -2
- package/linter/linter-format.d.ts +67 -7
- package/linter/linter-format.js +12 -1
- package/linter/linter-rules.d.ts +155 -16
- package/linter/linter-rules.js +12 -4
- package/linter/linter-tags.d.ts +80 -0
- package/linter/linter-tags.js +85 -0
- package/linter/rules/absolute-path.d.ts +71 -0
- package/linter/rules/absolute-path.js +177 -0
- package/linter/rules/deprecated-functions.d.ts +43 -0
- package/linter/rules/deprecated-functions.js +58 -0
- package/linter/rules/{2-file-path-validity.d.ts → file-path-validity.d.ts} +16 -6
- package/linter/rules/{2-file-path-validity.js → file-path-validity.js} +21 -13
- package/linter/rules/naming-convention.d.ts +71 -0
- package/linter/rules/naming-convention.js +164 -0
- package/linter/rules/seeded-randomness.d.ts +65 -0
- package/linter/rules/seeded-randomness.js +122 -0
- package/linter/rules/unused-definition.d.ts +41 -0
- package/linter/rules/unused-definition.js +105 -0
- package/package.json +4 -1
- package/queries/base-query-format.d.ts +2 -0
- package/queries/catalog/call-context-query/call-context-query-executor.d.ts +1 -1
- package/queries/catalog/call-context-query/call-context-query-executor.js +2 -2
- package/queries/catalog/cluster-query/cluster-query-format.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.d.ts +1 -1
- package/queries/catalog/config-query/config-query-executor.js +2 -3
- package/queries/catalog/control-flow-query/control-flow-query-executor.d.ts +3 -0
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +20 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.d.ts +81 -0
- package/queries/catalog/control-flow-query/control-flow-query-format.js +34 -0
- package/queries/catalog/dataflow-lens-query/dataflow-lens-query-format.d.ts +1 -1
- package/queries/catalog/dataflow-query/dataflow-query-format.d.ts +1 -1
- package/queries/catalog/dependencies-query/dependencies-query-executor.js +4 -115
- package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +1 -1
- package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +1 -1
- package/queries/catalog/id-map-query/id-map-query-format.d.ts +1 -1
- package/queries/catalog/lineage-query/lineage-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-executor.js +2 -2
- package/queries/catalog/linter-query/linter-query-format.d.ts +1 -1
- package/queries/catalog/linter-query/linter-query-format.js +17 -12
- package/queries/catalog/normalized-ast-query/normalized-ast-query-format.d.ts +1 -1
- package/queries/catalog/origin-query/origin-query-format.d.ts +1 -1
- package/queries/catalog/project-query/project-query-format.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.d.ts +1 -1
- package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +4 -4
- package/queries/catalog/resolve-value-query/resolve-value-query-format.d.ts +3 -2
- package/queries/catalog/resolve-value-query/resolve-value-query-format.js +2 -22
- package/queries/catalog/search-query/search-query-executor.d.ts +1 -1
- package/queries/catalog/search-query/search-query-executor.js +2 -2
- package/queries/catalog/search-query/search-query-format.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.d.ts +1 -1
- package/queries/catalog/static-slice-query/static-slice-query-executor.js +2 -2
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +1 -1
- package/queries/query.d.ts +75 -15
- package/queries/query.js +2 -0
- package/r-bridge/lang-4.x/ast/parser/json/parser.d.ts +2 -1
- package/r-bridge/lang-4.x/ast/parser/json/parser.js +4 -2
- package/r-bridge/lang-4.x/convert-values.js +2 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.d.ts +3 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-executor.js +4 -4
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.d.ts +1 -1
- package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +18 -9
- package/r-bridge/shell.d.ts +3 -2
- package/r-bridge/shell.js +4 -5
- package/search/flowr-search-builder.d.ts +6 -2
- package/search/flowr-search-builder.js +7 -0
- package/search/flowr-search-filters.d.ts +32 -8
- package/search/flowr-search-filters.js +42 -15
- package/search/flowr-search.d.ts +4 -0
- package/search/search-executor/search-enrichers.d.ts +7 -3
- package/search/search-executor/search-enrichers.js +32 -20
- package/search/search-executor/search-generators.js +1 -1
- package/search/search-executor/search-transformer.d.ts +2 -0
- package/search/search-executor/search-transformer.js +10 -1
- package/slicing/criterion/parse.d.ts +8 -0
- package/slicing/criterion/parse.js +20 -0
- package/slicing/static/static-slicer.d.ts +1 -1
- package/slicing/static/static-slicer.js +2 -3
- package/statistics/statistics.d.ts +3 -1
- package/statistics/statistics.js +5 -4
- package/util/containers.d.ts +12 -9
- package/util/containers.js +12 -9
- package/util/objects.d.ts +5 -4
- package/util/range.d.ts +5 -1
- package/util/range.js +11 -3
- package/util/text/strings.d.ts +6 -0
- package/util/text/strings.js +35 -0
- package/util/version.js +1 -1
- package/linter/rules/1-deprecated-functions.d.ts +0 -34
- package/linter/rules/1-deprecated-functions.js +0 -54
|
@@ -3,6 +3,7 @@ import { DEFAULT_SLICING_PIPELINE } from '../../../core/steps/pipeline/default-p
|
|
|
3
3
|
import type { PipelineOutput } from '../../../core/steps/pipeline/pipeline';
|
|
4
4
|
import type { DeepPartial } from 'ts-essentials';
|
|
5
5
|
import type { KnownParser } from '../../../r-bridge/parser';
|
|
6
|
+
import type { FlowrConfigOptions } from '../../../config';
|
|
6
7
|
/**
|
|
7
8
|
* Each connection handles a single client, answering to its requests.
|
|
8
9
|
* There is no need to construct this class manually, {@link FlowRServer} will do it for you.
|
|
@@ -13,8 +14,9 @@ export declare class FlowRServerConnection {
|
|
|
13
14
|
private readonly name;
|
|
14
15
|
private readonly logger;
|
|
15
16
|
private readonly allowRSessionAccess;
|
|
17
|
+
private readonly config;
|
|
16
18
|
private readonly fileMap;
|
|
17
|
-
constructor(socket: Socket, name: string, parser: KnownParser, allowRSessionAccess: boolean);
|
|
19
|
+
constructor(socket: Socket, name: string, parser: KnownParser, allowRSessionAccess: boolean, config: FlowrConfigOptions);
|
|
18
20
|
private currentMessageBuffer;
|
|
19
21
|
private handleData;
|
|
20
22
|
private handleFileAnalysisRequest;
|
|
@@ -71,10 +71,12 @@ class FlowRServerConnection {
|
|
|
71
71
|
name;
|
|
72
72
|
logger;
|
|
73
73
|
allowRSessionAccess;
|
|
74
|
+
config;
|
|
74
75
|
// maps token to information
|
|
75
76
|
fileMap = new Map();
|
|
76
77
|
// we do not have to ensure synchronized shell-access as we are always running synchronized
|
|
77
|
-
constructor(socket, name, parser, allowRSessionAccess) {
|
|
78
|
+
constructor(socket, name, parser, allowRSessionAccess, config) {
|
|
79
|
+
this.config = config;
|
|
78
80
|
this.socket = socket;
|
|
79
81
|
this.parser = parser;
|
|
80
82
|
this.name = name;
|
|
@@ -160,7 +162,7 @@ class FlowRServerConnection {
|
|
|
160
162
|
async sendFileAnalysisResponse(slicer, results, message) {
|
|
161
163
|
let cfg = undefined;
|
|
162
164
|
if (message.cfg) {
|
|
163
|
-
cfg = (0, extract_cfg_1.extractCfg)(results.normalize, results.dataflow?.graph);
|
|
165
|
+
cfg = (0, extract_cfg_1.extractCfg)(results.normalize, this.config, results.dataflow?.graph);
|
|
164
166
|
}
|
|
165
167
|
const config = () => ({ context: message.filename ?? 'unknown', getId: (0, quads_1.defaultQuadIdGenerator)() });
|
|
166
168
|
const sanitizedResults = sanitizeAnalysisResults(results);
|
|
@@ -222,7 +224,7 @@ class FlowRServerConnection {
|
|
|
222
224
|
const slicer = (0, default_pipelines_1.createSlicePipeline)(this.parser, {
|
|
223
225
|
request,
|
|
224
226
|
criterion: [] // currently unknown
|
|
225
|
-
});
|
|
227
|
+
}, this.config);
|
|
226
228
|
if (message.filetoken) {
|
|
227
229
|
this.logger.info(`Storing file token ${message.filetoken}`);
|
|
228
230
|
this.fileMap.set(message.filetoken, {
|
|
@@ -286,7 +288,7 @@ class FlowRServerConnection {
|
|
|
286
288
|
stream
|
|
287
289
|
});
|
|
288
290
|
};
|
|
289
|
-
void (0, core_1.replProcessAnswer)({
|
|
291
|
+
void (0, core_1.replProcessAnswer)(this.config, {
|
|
290
292
|
formatter: request.ansi ? ansi_1.ansiFormatter : ansi_1.voidFormatter,
|
|
291
293
|
stdout: msg => out('stdout', msg),
|
|
292
294
|
stderr: msg => out('stderr', msg)
|
|
@@ -346,7 +348,7 @@ class FlowRServerConnection {
|
|
|
346
348
|
const { dataflow: dfg, normalize: ast } = fileInformation.pipeline.getResults(true);
|
|
347
349
|
(0, assert_1.guard)(dfg !== undefined, `Dataflow graph must be present (request: ${request.filetoken})`);
|
|
348
350
|
(0, assert_1.guard)(ast !== undefined, `AST must be present (request: ${request.filetoken})`);
|
|
349
|
-
const results = (0, query_1.executeQueries)({ dataflow: dfg, ast }, request.query);
|
|
351
|
+
const results = (0, query_1.executeQueries)({ dataflow: dfg, ast, config: this.config }, request.query);
|
|
350
352
|
(0, send_1.sendMessage)(this.socket, {
|
|
351
353
|
type: 'response-query',
|
|
352
354
|
id: request.id,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Server } from './net';
|
|
2
2
|
import { FlowrLogger } from '../../../util/log';
|
|
3
|
-
import type { KnownEngines } from '../../../config';
|
|
3
|
+
import type { FlowrConfigOptions, KnownEngines } from '../../../config';
|
|
4
4
|
export declare const serverLog: FlowrLogger;
|
|
5
5
|
/**
|
|
6
6
|
* This class controls the TCP server, which can be started by calling {@link start}.
|
|
@@ -13,10 +13,11 @@ export declare class FlowRServer {
|
|
|
13
13
|
private readonly defaultEngine;
|
|
14
14
|
private versionInformation;
|
|
15
15
|
private readonly allowRSessionAccess;
|
|
16
|
+
private readonly config;
|
|
16
17
|
/** maps names to the respective connection */
|
|
17
18
|
private readonly connections;
|
|
18
19
|
private nameCounter;
|
|
19
|
-
constructor(engines: KnownEngines, defaultEngine: keyof KnownEngines, allowRSessionAccess: boolean, server?: Server);
|
|
20
|
+
constructor(engines: KnownEngines, defaultEngine: keyof KnownEngines, allowRSessionAccess: boolean, config: FlowrConfigOptions, server?: Server);
|
|
20
21
|
start(port: number): Promise<void>;
|
|
21
22
|
private onConnect;
|
|
22
23
|
}
|
|
@@ -19,15 +19,17 @@ class FlowRServer {
|
|
|
19
19
|
defaultEngine;
|
|
20
20
|
versionInformation;
|
|
21
21
|
allowRSessionAccess;
|
|
22
|
+
config;
|
|
22
23
|
/** maps names to the respective connection */
|
|
23
24
|
connections = new Map();
|
|
24
25
|
nameCounter = 0;
|
|
25
|
-
constructor(engines, defaultEngine, allowRSessionAccess, server = new net_1.NetServer()) {
|
|
26
|
+
constructor(engines, defaultEngine, allowRSessionAccess, config, server = new net_1.NetServer()) {
|
|
26
27
|
this.server = server;
|
|
27
28
|
this.server.onConnect(c => this.onConnect(c));
|
|
28
29
|
this.engines = engines;
|
|
29
30
|
this.defaultEngine = defaultEngine;
|
|
30
31
|
this.allowRSessionAccess = allowRSessionAccess;
|
|
32
|
+
this.config = config;
|
|
31
33
|
}
|
|
32
34
|
async start(port) {
|
|
33
35
|
this.versionInformation = await (0, repl_version_1.retrieveVersionInformation)(this.engines[this.defaultEngine]);
|
|
@@ -41,7 +43,7 @@ class FlowRServer {
|
|
|
41
43
|
}
|
|
42
44
|
const name = `client-${this.nameCounter++}`;
|
|
43
45
|
exports.serverLog.info(`Client connected: ${(0, send_1.getUnnamedSocketName)(c)} as "${name}"`);
|
|
44
|
-
this.connections.set(name, new connection_1.FlowRServerConnection(c, name, this.engines[this.defaultEngine], this.allowRSessionAccess));
|
|
46
|
+
this.connections.set(name, new connection_1.FlowRServerConnection(c, name, this.engines[this.defaultEngine], this.allowRSessionAccess, this.config));
|
|
45
47
|
helloClient(c, name, this.versionInformation);
|
|
46
48
|
c.on('close', () => {
|
|
47
49
|
this.connections.delete(name);
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { StatsCliOptions } from '../statistics-app';
|
|
2
|
-
|
|
2
|
+
import type { FlowrConfigOptions } from '../../config';
|
|
3
|
+
export declare function flowrScriptGetStats(options: StatsCliOptions, config: FlowrConfigOptions): Promise<void>;
|
|
@@ -57,7 +57,7 @@ async function collectFileArguments(options, verboseAdd, dumpJson, features) {
|
|
|
57
57
|
console.log(`Total: ${counter} files (${skipped} skipped with archive existing)`);
|
|
58
58
|
return files;
|
|
59
59
|
}
|
|
60
|
-
async function flowrScriptGetStats(options) {
|
|
60
|
+
async function flowrScriptGetStats(options, config) {
|
|
61
61
|
if (options.input.length === 0) {
|
|
62
62
|
console.error('No input files given. Nothing to do. See \'--help\' if this is an error.');
|
|
63
63
|
process.exit(0);
|
|
@@ -93,7 +93,7 @@ async function flowrScriptGetStats(options) {
|
|
|
93
93
|
else {
|
|
94
94
|
console.log('Run Sequentially as parallel <= 0...');
|
|
95
95
|
for (const arg of args) {
|
|
96
|
-
await (0, statistics_helper_core_1.getStatsForSingleFile)((0, command_line_args_1.default)(scripts_info_1.scripts['stats-helper'].options, { argv: arg }));
|
|
96
|
+
await (0, statistics_helper_core_1.getStatsForSingleFile)((0, command_line_args_1.default)(scripts_info_1.scripts['stats-helper'].options, { argv: arg }), config);
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { StatsHelperCliOptions } from '../statistics-helper-app';
|
|
2
|
-
|
|
2
|
+
import type { FlowrConfigOptions } from '../../config';
|
|
3
|
+
export declare function getStatsForSingleFile(options: StatsHelperCliOptions, config: FlowrConfigOptions): Promise<void>;
|
|
@@ -20,6 +20,7 @@ const assert_1 = require("../../util/assert");
|
|
|
20
20
|
const time_1 = require("../../util/text/time");
|
|
21
21
|
const tar_1 = require("tar");
|
|
22
22
|
const ansi_1 = require("../../util/text/ansi");
|
|
23
|
+
const config_1 = require("../../config");
|
|
23
24
|
function compressFolder(folder, target) {
|
|
24
25
|
return (0, tar_1.create)({
|
|
25
26
|
gzip: true,
|
|
@@ -35,7 +36,7 @@ function compressFolder(folder, target) {
|
|
|
35
36
|
console.error('Error during compression:', e);
|
|
36
37
|
});
|
|
37
38
|
}
|
|
38
|
-
async function getStatsForSingleFile(options) {
|
|
39
|
+
async function getStatsForSingleFile(options, config) {
|
|
39
40
|
if (options['no-ansi']) {
|
|
40
41
|
log_1.log.info('disabling ansi colors');
|
|
41
42
|
(0, ansi_1.setFormatter)(ansi_1.voidFormatter);
|
|
@@ -50,15 +51,15 @@ async function getStatsForSingleFile(options) {
|
|
|
50
51
|
}
|
|
51
52
|
// assume correct
|
|
52
53
|
const processedFeatures = new Set(options.features);
|
|
53
|
-
const shell = new shell_1.RShell();
|
|
54
|
+
const shell = new shell_1.RShell((0, config_1.getEngineConfig)(config, 'r-shell'));
|
|
54
55
|
(0, statistics_file_1.initFileProvider)(options['output-dir']);
|
|
55
56
|
await shell.obtainTmpDir();
|
|
56
|
-
const stats = await (0, statistics_1.extractUsageStatistics)(shell, () => { }, processedFeatures, (0, statistics_1.staticRequests)({ request: 'file', content: options.input }), options['root-dir']);
|
|
57
|
+
const stats = await (0, statistics_1.extractUsageStatistics)(shell, config, () => { }, processedFeatures, (0, statistics_1.staticRequests)({ request: 'file', content: options.input }), options['root-dir']);
|
|
57
58
|
// console.warn(`skipped ${stats.meta.failedRequests.length} requests due to errors (run with logs to get more info)`)
|
|
58
59
|
if (stats.outputs.size === 1) {
|
|
59
60
|
if (options['dump-json']) {
|
|
60
61
|
const [, output] = [...stats.outputs.entries()][0];
|
|
61
|
-
const cfg = (0, extract_cfg_1.extractCfg)(output.normalize, output.dataflow.graph);
|
|
62
|
+
const cfg = (0, extract_cfg_1.extractCfg)(output.normalize, config, output.dataflow.graph);
|
|
62
63
|
statistics_file_1.statisticsFileProvider.append('output-json', 'parse', await (0, print_1.printStepResult)(_00_parse_1.PARSE_WITH_R_SHELL_STEP, output.parse, 2 /* StepOutputFormat.Json */));
|
|
63
64
|
statistics_file_1.statisticsFileProvider.append('output-json', 'normalize', await (0, print_1.printStepResult)(_10_normalize_1.NORMALIZE, output.normalize, 2 /* StepOutputFormat.Json */));
|
|
64
65
|
statistics_file_1.statisticsFileProvider.append('output-json', 'dataflow', await (0, print_1.printStepResult)(_20_dataflow_1.STATIC_DATAFLOW, output.dataflow, 2 /* StepOutputFormat.Json */));
|
package/cli/slicer-app.js
CHANGED
|
@@ -14,6 +14,7 @@ const slicer_1 = require("../benchmark/slicer");
|
|
|
14
14
|
const print_1 = require("../benchmark/stats/print");
|
|
15
15
|
const magic_comments_1 = require("../reconstruct/auto-select/magic-comments");
|
|
16
16
|
const auto_select_defaults_1 = require("../reconstruct/auto-select/auto-select-defaults");
|
|
17
|
+
const config_1 = require("../config");
|
|
17
18
|
const options = (0, script_1.processCommandLineArgs)('slicer', ['input', 'criterion'], {
|
|
18
19
|
subtitle: 'Slice R code based on a given slicing criterion',
|
|
19
20
|
examples: [
|
|
@@ -28,9 +29,10 @@ async function getSlice() {
|
|
|
28
29
|
const slicer = new slicer_1.BenchmarkSlicer('r-shell');
|
|
29
30
|
(0, assert_1.guard)(options.input !== undefined, 'input must be given');
|
|
30
31
|
(0, assert_1.guard)(options.criterion !== undefined, 'a slicing criterion must be given');
|
|
32
|
+
const config = (0, config_1.getConfig)();
|
|
31
33
|
await slicer.init(options['input-is-text']
|
|
32
34
|
? { request: 'text', content: options.input.replaceAll('\\n', '\n') }
|
|
33
|
-
: { request: 'file', content: options.input }, options['no-magic-comments'] ? auto_select_defaults_1.doNotAutoSelect : (0, magic_comments_1.makeMagicCommentHandler)(auto_select_defaults_1.doNotAutoSelect));
|
|
35
|
+
: { request: 'file', content: options.input }, config, options['no-magic-comments'] ? auto_select_defaults_1.doNotAutoSelect : (0, magic_comments_1.makeMagicCommentHandler)(auto_select_defaults_1.doNotAutoSelect));
|
|
34
36
|
let mappedSlices = [];
|
|
35
37
|
let reconstruct = undefined;
|
|
36
38
|
const doSlicing = options.criterion.trim() !== '';
|
|
@@ -58,7 +60,7 @@ async function getSlice() {
|
|
|
58
60
|
const { stats, normalize, parse, tokenMap, dataflow } = slicer.finish();
|
|
59
61
|
const mappedCriteria = mappedSlices.map(c => ` ${c.criterion} => ${c.id} (${JSON.stringify(normalize.idMap.get(c.id)?.location)})`).join('\n');
|
|
60
62
|
log_1.log.info(`Mapped criteria:\n${mappedCriteria}`);
|
|
61
|
-
const sliceStatsAsString = (0, print_1.stats2string)(await (0, process_1.summarizeSlicerStats)(stats));
|
|
63
|
+
const sliceStatsAsString = (0, print_1.stats2string)(await (0, process_1.summarizeSlicerStats)(stats, undefined, (0, config_1.getEngineConfig)(config, 'r-shell')));
|
|
62
64
|
if (options.api) {
|
|
63
65
|
const output = {
|
|
64
66
|
tokenMap,
|
package/cli/statistics-app.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const script_1 = require("./common/script");
|
|
4
4
|
const statistics_core_1 = require("./script-core/statistics-core");
|
|
5
|
+
const config_1 = require("../config");
|
|
5
6
|
const scriptOptions = (0, script_1.processCommandLineArgs)('stats', [], {
|
|
6
7
|
subtitle: 'Given input files or folders, this will collect usage statistics for the given features and write them to a file',
|
|
7
8
|
examples: [
|
|
@@ -11,5 +12,5 @@ const scriptOptions = (0, script_1.processCommandLineArgs)('stats', [], {
|
|
|
11
12
|
'{bold --help}'
|
|
12
13
|
]
|
|
13
14
|
});
|
|
14
|
-
void (0, statistics_core_1.flowrScriptGetStats)(scriptOptions);
|
|
15
|
+
void (0, statistics_core_1.flowrScriptGetStats)(scriptOptions, (0, config_1.getConfig)());
|
|
15
16
|
//# sourceMappingURL=statistics-app.js.map
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const script_1 = require("./common/script");
|
|
4
4
|
const statistics_helper_core_1 = require("./script-core/statistics-helper-core");
|
|
5
|
+
const config_1 = require("../config");
|
|
5
6
|
const scriptOptions = (0, script_1.processCommandLineArgs)('stats-helper', [], {
|
|
6
7
|
subtitle: 'Given a single input file, this will collect usage statistics for the given features and write them to a file',
|
|
7
8
|
examples: [
|
|
@@ -9,5 +10,5 @@ const scriptOptions = (0, script_1.processCommandLineArgs)('stats-helper', [], {
|
|
|
9
10
|
'{bold --help}'
|
|
10
11
|
]
|
|
11
12
|
});
|
|
12
|
-
void (0, statistics_helper_core_1.getStatsForSingleFile)(scriptOptions);
|
|
13
|
+
void (0, statistics_helper_core_1.getStatsForSingleFile)(scriptOptions, (0, config_1.getConfig)());
|
|
13
14
|
//# sourceMappingURL=statistics-helper-app.js.map
|
package/config.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { MergeableRecord } from './util/objects';
|
|
|
2
2
|
import Joi from 'joi';
|
|
3
3
|
import type { BuiltInDefinitions } from './dataflow/environments/built-in-config';
|
|
4
4
|
import type { KnownParser } from './r-bridge/parser';
|
|
5
|
-
import type {
|
|
5
|
+
import type { DeepWritable } from 'ts-essentials';
|
|
6
6
|
export declare enum VariableResolve {
|
|
7
7
|
/** Don't resolve constants at all */
|
|
8
8
|
Disabled = "disabled",
|
|
@@ -47,7 +47,7 @@ export interface FlowrLaxSourcingOptions extends MergeableRecord {
|
|
|
47
47
|
/**
|
|
48
48
|
* Additionally search in these paths
|
|
49
49
|
*/
|
|
50
|
-
readonly searchPath:
|
|
50
|
+
readonly searchPath: string[];
|
|
51
51
|
/**
|
|
52
52
|
* Allow to drop the first or all parts of the sourced path,
|
|
53
53
|
* if it is relative.
|
|
@@ -77,7 +77,7 @@ export interface FlowrLaxSourcingOptions extends MergeableRecord {
|
|
|
77
77
|
* - `foo bar.R` (original name)
|
|
78
78
|
* - `main.R` (replaced with main.R)
|
|
79
79
|
* - `foo_bar.R` (replaced spaces)
|
|
80
|
-
* - `
|
|
80
|
+
* - `faa-bar.R` (replaced spaces and oo)
|
|
81
81
|
*/
|
|
82
82
|
readonly applyReplacements?: Record<string, string>[];
|
|
83
83
|
}
|
|
@@ -103,7 +103,7 @@ export interface FlowrConfigOptions extends MergeableRecord {
|
|
|
103
103
|
* The engines to use for interacting with R code. Currently, supports {@link TreeSitterEngineConfig} and {@link RShellEngineConfig}.
|
|
104
104
|
* An empty array means all available engines will be used.
|
|
105
105
|
*/
|
|
106
|
-
readonly engines:
|
|
106
|
+
readonly engines: EngineConfig[];
|
|
107
107
|
/**
|
|
108
108
|
* The default engine to use for interacting with R code. If this is undefined, an arbitrary engine from {@link engines} will be used.
|
|
109
109
|
*/
|
|
@@ -174,12 +174,14 @@ export type KnownEngines = {
|
|
|
174
174
|
};
|
|
175
175
|
export declare const defaultConfigOptions: FlowrConfigOptions;
|
|
176
176
|
export declare const flowrConfigFileSchema: Joi.ObjectSchema<any>;
|
|
177
|
-
export declare function setConfigFile(file: string | undefined, workingDirectory?: string, forceLoad?: boolean): void;
|
|
178
177
|
export declare function parseConfig(jsonString: string): FlowrConfigOptions | undefined;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
export declare function
|
|
178
|
+
/**
|
|
179
|
+
* Creates a new flowr config that has the updated values.
|
|
180
|
+
*/
|
|
181
|
+
export declare function amendConfig(config: FlowrConfigOptions, amendmentFunc: (config: DeepWritable<FlowrConfigOptions>) => FlowrConfigOptions): FlowrConfigOptions;
|
|
182
|
+
export declare function cloneConfig(config: FlowrConfigOptions): FlowrConfigOptions;
|
|
183
|
+
export declare function getConfig(configFile?: string, configWorkingDirectory?: string): FlowrConfigOptions;
|
|
184
|
+
export declare function getEngineConfig<T extends EngineConfig['type']>(config: FlowrConfigOptions, engine: T): EngineConfig & {
|
|
183
185
|
type: T;
|
|
184
186
|
} | undefined;
|
|
185
|
-
export declare function isOverPointerAnalysisThreshold(count: number): boolean;
|
|
187
|
+
export declare function isOverPointerAnalysisThreshold(config: FlowrConfigOptions, count: number): boolean;
|
package/config.js
CHANGED
|
@@ -4,10 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.flowrConfigFileSchema = exports.defaultConfigOptions = exports.DropPathsOption = exports.InferWorkingDirectory = exports.VariableResolve = void 0;
|
|
7
|
-
exports.setConfigFile = setConfigFile;
|
|
8
7
|
exports.parseConfig = parseConfig;
|
|
9
|
-
exports.setConfig = setConfig;
|
|
10
8
|
exports.amendConfig = amendConfig;
|
|
9
|
+
exports.cloneConfig = cloneConfig;
|
|
11
10
|
exports.getConfig = getConfig;
|
|
12
11
|
exports.getEngineConfig = getEngineConfig;
|
|
13
12
|
exports.isOverPointerAnalysisThreshold = isOverPointerAnalysisThreshold;
|
|
@@ -67,7 +66,7 @@ exports.defaultConfigOptions = {
|
|
|
67
66
|
}
|
|
68
67
|
},
|
|
69
68
|
engines: [],
|
|
70
|
-
defaultEngine: '
|
|
69
|
+
defaultEngine: 'tree-sitter',
|
|
71
70
|
solver: {
|
|
72
71
|
variables: VariableResolve.Alias,
|
|
73
72
|
evalStrings: true,
|
|
@@ -123,19 +122,6 @@ exports.flowrConfigFileSchema = joi_1.default.object({
|
|
|
123
122
|
}).optional().description('The configuration for the slicer.')
|
|
124
123
|
}).description('How to resolve constants, constraints, cells, ...')
|
|
125
124
|
}).description('The configuration file format for flowR.');
|
|
126
|
-
// we don't load from a config file at all by default unless setConfigFile is called
|
|
127
|
-
let configFile = undefined;
|
|
128
|
-
let configWorkingDirectory = process.cwd();
|
|
129
|
-
let currentConfig = undefined;
|
|
130
|
-
function setConfigFile(file, workingDirectory = process.cwd(), forceLoad = false) {
|
|
131
|
-
configFile = file;
|
|
132
|
-
configWorkingDirectory = workingDirectory;
|
|
133
|
-
// reset the config so it gets reloaded
|
|
134
|
-
currentConfig = undefined;
|
|
135
|
-
if (forceLoad) {
|
|
136
|
-
getConfig();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
125
|
function parseConfig(jsonString) {
|
|
140
126
|
try {
|
|
141
127
|
const parsed = JSON.parse(jsonString);
|
|
@@ -153,46 +139,44 @@ function parseConfig(jsonString) {
|
|
|
153
139
|
log_1.log.error(`Failed to parse config ${jsonString}: ${e.message}`);
|
|
154
140
|
}
|
|
155
141
|
}
|
|
156
|
-
|
|
157
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Creates a new flowr config that has the updated values.
|
|
144
|
+
*/
|
|
145
|
+
function amendConfig(config, amendmentFunc) {
|
|
146
|
+
return amendmentFunc(cloneConfig(config));
|
|
158
147
|
}
|
|
159
|
-
function
|
|
160
|
-
|
|
161
|
-
log_1.log.trace(`Amending config with ${JSON.stringify(amendment)}, resulting in ${JSON.stringify(getConfig())}}`);
|
|
148
|
+
function cloneConfig(config) {
|
|
149
|
+
return JSON.parse(JSON.stringify(config));
|
|
162
150
|
}
|
|
163
|
-
function getConfig() {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
log_1.log.error(`Failed to load config: ${e.message}`);
|
|
171
|
-
setConfig(exports.defaultConfigOptions);
|
|
172
|
-
}
|
|
151
|
+
function getConfig(configFile, configWorkingDirectory = process.cwd()) {
|
|
152
|
+
try {
|
|
153
|
+
return loadConfigFromFile(configFile, configWorkingDirectory);
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
log_1.log.error(`Failed to load config: ${e.message}`);
|
|
157
|
+
return exports.defaultConfigOptions;
|
|
173
158
|
}
|
|
174
|
-
return currentConfig;
|
|
175
159
|
}
|
|
176
|
-
function getEngineConfig(engine) {
|
|
177
|
-
const
|
|
178
|
-
if (!
|
|
160
|
+
function getEngineConfig(config, engine) {
|
|
161
|
+
const engines = config.engines;
|
|
162
|
+
if (!engines.length) {
|
|
179
163
|
return defaultEngineConfigs[engine];
|
|
180
164
|
}
|
|
181
165
|
else {
|
|
182
|
-
return
|
|
166
|
+
return engines.find(e => e.type == engine);
|
|
183
167
|
}
|
|
184
168
|
}
|
|
185
|
-
function getPointerAnalysisThreshold() {
|
|
186
|
-
const
|
|
187
|
-
if (typeof
|
|
188
|
-
return
|
|
169
|
+
function getPointerAnalysisThreshold(config) {
|
|
170
|
+
const pointerTracking = config.solver.pointerTracking;
|
|
171
|
+
if (typeof pointerTracking === 'object') {
|
|
172
|
+
return pointerTracking.maxIndexCount;
|
|
189
173
|
}
|
|
190
174
|
else {
|
|
191
|
-
return
|
|
175
|
+
return pointerTracking ? 'unlimited' : 'disabled';
|
|
192
176
|
}
|
|
193
177
|
}
|
|
194
|
-
function isOverPointerAnalysisThreshold(count) {
|
|
195
|
-
const threshold = getPointerAnalysisThreshold();
|
|
178
|
+
function isOverPointerAnalysisThreshold(config, count) {
|
|
179
|
+
const threshold = getPointerAnalysisThreshold(config);
|
|
196
180
|
return threshold !== 'unlimited' && (threshold === 'disabled' || count > threshold);
|
|
197
181
|
}
|
|
198
182
|
function loadConfigFromFile(configFile, workingDirectory) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CfgBasicBlockVertex, CfgEndMarkerVertex, CfgExpressionVertex, CfgMidMarkerVertex, CfgSimpleVertex, CfgStatementVertex, ControlFlowInformation } from './control-flow-graph';
|
|
2
2
|
import type { NodeId } from '../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
3
|
-
export interface BasicCfgGuidedVisitorConfiguration<
|
|
4
|
-
readonly controlFlow:
|
|
3
|
+
export interface BasicCfgGuidedVisitorConfiguration<ControlFlow extends ControlFlowInformation = ControlFlowInformation> {
|
|
4
|
+
readonly controlFlow: ControlFlow;
|
|
5
5
|
readonly defaultVisitingOrder: 'forward' | 'backward';
|
|
6
6
|
}
|
|
7
7
|
/**
|
|
@@ -11,7 +11,7 @@ export interface BasicCfgGuidedVisitorConfiguration<Cfg extends ControlFlowInfor
|
|
|
11
11
|
*
|
|
12
12
|
* Use {@link BasicCfgGuidedVisitor#start} to start the traversal.
|
|
13
13
|
*/
|
|
14
|
-
export declare class BasicCfgGuidedVisitor<
|
|
14
|
+
export declare class BasicCfgGuidedVisitor<ControlFlow extends ControlFlowInformation = ControlFlowInformation, Config extends BasicCfgGuidedVisitorConfiguration<ControlFlow> = BasicCfgGuidedVisitorConfiguration<ControlFlow>> {
|
|
15
15
|
protected readonly config: Config;
|
|
16
16
|
protected readonly visited: Map<NodeId, number>;
|
|
17
17
|
constructor(config: Config);
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ControlFlowInformation } from './control-flow-graph';
|
|
2
|
+
import type { CfgPassInfo } from './cfg-simplification';
|
|
3
|
+
/** Breaks unsatisfiable control dependencies */
|
|
4
|
+
export declare function cfgAnalyzeDeadCode(cfg: ControlFlowInformation, info: CfgPassInfo): ControlFlowInformation;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cfgAnalyzeDeadCode = cfgAnalyzeDeadCode;
|
|
4
|
+
const logic_1 = require("../util/logic");
|
|
5
|
+
const semantic_cfg_guided_visitor_1 = require("./semantic-cfg-guided-visitor");
|
|
6
|
+
const alias_tracking_1 = require("../dataflow/eval/resolve/alias-tracking");
|
|
7
|
+
const log_1 = require("../util/log");
|
|
8
|
+
const r_function_call_1 = require("../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
9
|
+
const general_1 = require("../dataflow/eval/values/general");
|
|
10
|
+
const r_value_1 = require("../dataflow/eval/values/r-value");
|
|
11
|
+
class CfgConditionalDeadCodeRemoval extends semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor {
|
|
12
|
+
cachedConditions = new Map();
|
|
13
|
+
cachedStatements = new Map();
|
|
14
|
+
getValue(id) {
|
|
15
|
+
const has = this.cachedConditions.get(id);
|
|
16
|
+
if (has) {
|
|
17
|
+
return has;
|
|
18
|
+
}
|
|
19
|
+
this.visitNode(id);
|
|
20
|
+
return this.cachedConditions.get(id) ?? logic_1.Ternary.Maybe;
|
|
21
|
+
}
|
|
22
|
+
isUnconditionalJump(id) {
|
|
23
|
+
const has = this.cachedStatements.get(id);
|
|
24
|
+
if (has) {
|
|
25
|
+
return has;
|
|
26
|
+
}
|
|
27
|
+
this.visitNode(id);
|
|
28
|
+
return this.cachedStatements.get(id) ?? false;
|
|
29
|
+
}
|
|
30
|
+
unableToCalculateValue(id) {
|
|
31
|
+
this.cachedConditions.set(id, logic_1.Ternary.Maybe);
|
|
32
|
+
}
|
|
33
|
+
storeDefiniteValue(id, value) {
|
|
34
|
+
this.cachedConditions.set(id, value ? logic_1.Ternary.Always : logic_1.Ternary.Never);
|
|
35
|
+
}
|
|
36
|
+
startVisitor() {
|
|
37
|
+
for (const [from, targets] of this.config.controlFlow.graph.edges()) {
|
|
38
|
+
for (const [target, edge] of targets) {
|
|
39
|
+
if (edge.label === 1 /* CfgEdgeType.Cd */) {
|
|
40
|
+
const og = this.getValue(edge.caused);
|
|
41
|
+
if (og === logic_1.Ternary.Always && edge.when === 'FALSE') {
|
|
42
|
+
this.config.controlFlow.graph.removeEdge(from, target);
|
|
43
|
+
}
|
|
44
|
+
else if (og === logic_1.Ternary.Never && edge.when === 'TRUE') {
|
|
45
|
+
this.config.controlFlow.graph.removeEdge(from, target);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else if (edge.label === 0 /* CfgEdgeType.Fd */) {
|
|
49
|
+
if (this.isUnconditionalJump(target)) {
|
|
50
|
+
this.config.controlFlow.graph.removeEdge(from, target);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
handleValuesFor(id, valueId) {
|
|
57
|
+
const values = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(valueId, { graph: this.config.dfg, full: true, idMap: this.config.normalizedAst.idMap, resolve: this.config.flowrConfig.solver.variables }));
|
|
58
|
+
if (values === undefined || values.elements.length !== 1 || values.elements[0].type != 'logical' || !(0, r_value_1.isValue)(values.elements[0].value)) {
|
|
59
|
+
this.unableToCalculateValue(id);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
/* we should translate this to truthy later */
|
|
63
|
+
this.storeDefiniteValue(id, Boolean(values.elements[0].value));
|
|
64
|
+
}
|
|
65
|
+
handleWithCondition(data) {
|
|
66
|
+
const id = data.call.id;
|
|
67
|
+
if (data.condition === undefined || data.condition === r_function_call_1.EmptyArgument) {
|
|
68
|
+
this.unableToCalculateValue(id);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.handleValuesFor(id, typeof data.condition === 'object' ? data.condition.nodeId : data.condition);
|
|
72
|
+
}
|
|
73
|
+
getBoolArgValue(data) {
|
|
74
|
+
if (data.call.args.length !== 1 || data.call.args[0] === r_function_call_1.EmptyArgument) {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
const values = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(data.call.args[0].nodeId, { graph: this.config.dfg, full: true, idMap: this.config.normalizedAst.idMap, resolve: this.config.flowrConfig.solver.variables }));
|
|
78
|
+
if (values === undefined || values.elements.length !== 1 || values.elements[0].type != 'logical' || !(0, r_value_1.isValue)(values.elements[0].value)) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return Boolean(values.elements[0].value);
|
|
82
|
+
}
|
|
83
|
+
handleFunctionCall(data) {
|
|
84
|
+
switch (data.call.origin[0]) {
|
|
85
|
+
case 'builtin:return':
|
|
86
|
+
case 'builtin:stop':
|
|
87
|
+
this.cachedStatements.set(data.call.id, true);
|
|
88
|
+
break;
|
|
89
|
+
case 'builtin:stopifnot': {
|
|
90
|
+
const arg = this.getBoolArgValue(data);
|
|
91
|
+
if (arg !== undefined) {
|
|
92
|
+
this.cachedStatements.set(data.call.id, !arg);
|
|
93
|
+
}
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
onIfThenElseCall(data) {
|
|
99
|
+
this.handleWithCondition(data);
|
|
100
|
+
}
|
|
101
|
+
onWhileLoopCall(data) {
|
|
102
|
+
this.handleWithCondition(data);
|
|
103
|
+
}
|
|
104
|
+
onDefaultFunctionCall(data) {
|
|
105
|
+
this.handleFunctionCall(data);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/** Breaks unsatisfiable control dependencies */
|
|
109
|
+
function cfgAnalyzeDeadCode(cfg, info) {
|
|
110
|
+
if (!info.ast || !info.dfg) {
|
|
111
|
+
log_1.log.warn('cfgAnalyzeDeadCode called without ast or dfg, skipping dead code analysis');
|
|
112
|
+
return cfg;
|
|
113
|
+
}
|
|
114
|
+
const visitor = new CfgConditionalDeadCodeRemoval({
|
|
115
|
+
controlFlow: cfg,
|
|
116
|
+
normalizedAst: info.ast,
|
|
117
|
+
dfg: info.dfg,
|
|
118
|
+
flowrConfig: info.config,
|
|
119
|
+
defaultVisitingOrder: 'forward',
|
|
120
|
+
});
|
|
121
|
+
visitor.start();
|
|
122
|
+
return cfg;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=cfg-dead-code.js.map
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { ControlFlowInformation } from './control-flow-graph';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type { NormalizedAst } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
3
|
+
import type { DataflowGraph } from '../dataflow/graph/graph';
|
|
4
|
+
import { cfgAnalyzeDeadCode } from './cfg-dead-code';
|
|
5
|
+
import type { FlowrConfigOptions } from '../config';
|
|
6
|
+
export interface CfgPassInfo {
|
|
7
|
+
ast?: NormalizedAst;
|
|
8
|
+
dfg?: DataflowGraph;
|
|
9
|
+
config: FlowrConfigOptions;
|
|
10
|
+
}
|
|
11
|
+
export type CfgSimplificationPass = (cfg: ControlFlowInformation, info: CfgPassInfo) => ControlFlowInformation;
|
|
12
|
+
export declare const CfgSimplificationPasses: {
|
|
4
13
|
readonly 'unique-cf-sets': typeof uniqueControlFlowSets;
|
|
14
|
+
readonly 'analyze-dead-code': typeof cfgAnalyzeDeadCode;
|
|
5
15
|
readonly 'remove-dead-code': typeof cfgRemoveDeadCode;
|
|
6
16
|
readonly 'to-basic-blocks': typeof toBasicBlocks;
|
|
7
17
|
};
|
|
@@ -11,8 +21,11 @@ export declare const DefaultCfgSimplificationOrder: ["unique-cf-sets"];
|
|
|
11
21
|
* Simplify the control flow information by applying the given passes.
|
|
12
22
|
* This may reduce the vertex count, in- and outgoing edges, entry and exit points, etc.
|
|
13
23
|
*/
|
|
14
|
-
export declare function simplifyControlFlowInformation(cfg: ControlFlowInformation, passes?: readonly CfgSimplificationPassName[]): ControlFlowInformation;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
export declare function simplifyControlFlowInformation(cfg: ControlFlowInformation, info: CfgPassInfo, passes?: readonly CfgSimplificationPassName[]): ControlFlowInformation;
|
|
25
|
+
/**
|
|
26
|
+
* removes dead vertices and edges from the control flow graph.
|
|
27
|
+
*/
|
|
28
|
+
declare function cfgRemoveDeadCode(cfg: ControlFlowInformation, _info?: CfgPassInfo): ControlFlowInformation;
|
|
29
|
+
declare function uniqueControlFlowSets(cfg: ControlFlowInformation, _info?: CfgPassInfo): ControlFlowInformation;
|
|
30
|
+
declare function toBasicBlocks(cfg: ControlFlowInformation, _info?: CfgPassInfo): ControlFlowInformation;
|
|
18
31
|
export {};
|