@eagleoutice/flowr 2.6.0 → 2.6.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 +36 -40
- package/abstract-interpretation/data-frame/absint-visitor.d.ts +1 -1
- package/abstract-interpretation/data-frame/absint-visitor.js +1 -1
- package/cli/flowr.js +8 -4
- package/cli/repl/commands/repl-cfg.js +4 -4
- package/cli/repl/commands/repl-commands.js +2 -2
- package/cli/repl/commands/repl-dataflow.js +4 -4
- package/cli/repl/commands/repl-execute.d.ts +1 -1
- package/cli/repl/commands/repl-execute.js +8 -8
- package/cli/repl/commands/repl-lineage.d.ts +2 -2
- package/cli/repl/commands/repl-lineage.js +11 -12
- package/cli/repl/commands/repl-main.d.ts +4 -7
- package/cli/repl/commands/repl-normalize.js +2 -2
- package/cli/repl/commands/repl-parse.js +3 -2
- package/cli/repl/commands/repl-query.js +3 -3
- package/cli/repl/commands/repl-quit.js +1 -1
- package/cli/repl/commands/repl-version.d.ts +1 -16
- package/cli/repl/commands/repl-version.js +2 -19
- package/cli/repl/core.d.ts +9 -9
- package/cli/repl/core.js +14 -20
- package/cli/repl/print-version.js +2 -2
- package/cli/repl/server/connection.js +6 -2
- package/cli/repl/server/messages/message-hello.d.ts +1 -1
- package/cli/repl/server/server.js +2 -2
- package/core/steps/all/core/20-dataflow.d.ts +3 -1
- package/core/steps/pipeline/default-pipelines.d.ts +66 -50
- package/dataflow/environments/default-builtin-config.js +8 -0
- package/dataflow/eval/resolve/alias-tracking.js +2 -0
- package/dataflow/eval/resolve/resolve.js +3 -0
- package/dataflow/eval/values/r-value.d.ts +4 -1
- package/dataflow/eval/values/r-value.js +2 -0
- package/dataflow/extractor.d.ts +4 -1
- package/dataflow/extractor.js +7 -5
- package/dataflow/fn/higher-order-function.d.ts +9 -0
- package/dataflow/fn/higher-order-function.js +75 -0
- package/documentation/doc-util/doc-repl.js +5 -2
- package/documentation/print-dataflow-graph-wiki.js +2 -2
- package/documentation/print-query-wiki.js +20 -0
- package/documentation/print-readme.js +1 -1
- package/package.json +1 -1
- package/project/cache/flowr-analyzer-cache.d.ts +6 -5
- package/project/cache/flowr-analyzer-cache.js +21 -13
- package/project/cfg-kind.d.ts +17 -0
- package/project/cfg-kind.js +22 -0
- package/project/context/abstract-flowr-analyzer-context.d.ts +4 -0
- package/project/context/flowr-analyzer-context.d.ts +6 -0
- package/project/context/flowr-analyzer-context.js +11 -0
- package/project/context/flowr-analyzer-dependencies-context.d.ts +1 -0
- package/project/context/flowr-analyzer-dependencies-context.js +4 -0
- package/project/context/flowr-analyzer-files-context.d.ts +1 -0
- package/project/context/flowr-analyzer-files-context.js +4 -0
- package/project/context/flowr-analyzer-loading-order-context.d.ts +1 -0
- package/project/context/flowr-analyzer-loading-order-context.js +6 -0
- package/project/flowr-analyzer.d.ts +19 -18
- package/project/flowr-analyzer.js +15 -8
- package/queries/catalog/call-context-query/call-context-query-executor.js +2 -1
- package/queries/catalog/config-query/config-query-format.d.ts +1 -1
- package/queries/catalog/control-flow-query/control-flow-query-executor.js +2 -1
- package/queries/catalog/df-shape-query/df-shape-query-executor.js +1 -1
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.d.ts +3 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +45 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +22 -0
- package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.js +32 -0
- package/queries/query.d.ts +10 -2
- package/queries/query.js +2 -0
- package/r-bridge/parser.d.ts +7 -0
- package/search/search-executor/search-enrichers.js +2 -1
- package/util/r-value.d.ts +1 -1
- package/util/r-value.js +2 -0
- package/util/version.d.ts +17 -0
- package/util/version.js +28 -1
|
@@ -1,30 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.versionCommand = void 0;
|
|
4
|
-
exports.retrieveVersionInformation = retrieveVersionInformation;
|
|
5
|
-
exports.printVersionInformation = printVersionInformation;
|
|
6
4
|
const version_1 = require("../../../util/version");
|
|
7
|
-
const assert_1 = require("../../../util/assert");
|
|
8
|
-
const versionRegex = /^\d+\.\d+\.\d+/m;
|
|
9
|
-
async function retrieveVersionInformation(parser) {
|
|
10
|
-
const flowr = (0, version_1.flowrVersion)().toString();
|
|
11
|
-
const r = await parser.rVersion();
|
|
12
|
-
(0, assert_1.guard)(versionRegex.test(flowr), `flowR version ${flowr} does not match the expected format!`);
|
|
13
|
-
(0, assert_1.guard)(r === 'unknown' || r === 'none' || versionRegex.test(r), `R version ${r} does not match the expected format!`);
|
|
14
|
-
return { flowr: flowr, r: r, engine: parser.name };
|
|
15
|
-
}
|
|
16
|
-
async function printVersionInformation(output, parser) {
|
|
17
|
-
const { flowr, r, engine } = await retrieveVersionInformation(parser);
|
|
18
|
-
output.stdout(`Engine: ${engine}`);
|
|
19
|
-
output.stdout(` flowR: ${flowr}`);
|
|
20
|
-
output.stdout(` R: ${r}`);
|
|
21
|
-
}
|
|
22
5
|
exports.versionCommand = {
|
|
23
6
|
description: 'Prints the version of flowR as well as the current version of R',
|
|
24
|
-
|
|
7
|
+
isCodeCommand: false,
|
|
25
8
|
aliases: [],
|
|
26
9
|
usageExample: ':version',
|
|
27
10
|
script: false,
|
|
28
|
-
fn: ({ output,
|
|
11
|
+
fn: ({ output, analyzer }) => (0, version_1.printVersionInformation)(output, analyzer)
|
|
29
12
|
};
|
|
30
13
|
//# sourceMappingURL=repl-version.js.map
|
package/cli/repl/core.d.ts
CHANGED
|
@@ -1,33 +1,34 @@
|
|
|
1
1
|
import * as readline from 'readline';
|
|
2
2
|
import type { ReplOutput } from './commands/repl-main';
|
|
3
3
|
import type { MergeableRecord } from '../../util/objects';
|
|
4
|
-
import type { KnownParser } from '../../r-bridge/parser';
|
|
5
4
|
import type { FlowrConfigOptions } from '../../config';
|
|
5
|
+
import type { FlowrAnalyzer } from '../../project/flowr-analyzer';
|
|
6
6
|
/**
|
|
7
7
|
* Used by the repl to provide automatic completions for a given (partial) input line
|
|
8
8
|
*/
|
|
9
9
|
export declare function replCompleter(line: string, config: FlowrConfigOptions): [string[], string];
|
|
10
10
|
export declare function makeDefaultReplReadline(config: FlowrConfigOptions): readline.ReadLineOptions;
|
|
11
11
|
export declare function handleString(code: string): {
|
|
12
|
-
input: string;
|
|
12
|
+
input: string | undefined;
|
|
13
13
|
remaining: never[];
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
16
|
* This function interprets the given `expr` as a REPL command (see {@link repl} for more on the semantics).
|
|
17
17
|
*
|
|
18
|
-
* @param
|
|
18
|
+
* @param analyzer - The flowR analyzer to use.
|
|
19
19
|
* @param output - Defines two methods that every function in the repl uses to output its data.
|
|
20
20
|
* @param expr - The expression to process.
|
|
21
|
-
* @param parser - The {@link RShell} or {@link TreeSitterExecutor} to use (see {@link repl}).
|
|
22
21
|
* @param allowRSessionAccess - If true, allows the execution of arbitrary R code.
|
|
23
22
|
*/
|
|
24
|
-
export declare function replProcessAnswer(
|
|
23
|
+
export declare function replProcessAnswer(analyzer: FlowrAnalyzer, output: ReplOutput, expr: string, allowRSessionAccess: boolean): Promise<void>;
|
|
25
24
|
/**
|
|
26
25
|
* Options for the {@link repl} function.
|
|
27
26
|
*/
|
|
28
27
|
export interface FlowrReplOptions extends MergeableRecord {
|
|
29
|
-
/**
|
|
30
|
-
|
|
28
|
+
/**
|
|
29
|
+
* The flowR analyzer to use.
|
|
30
|
+
*/
|
|
31
|
+
readonly analyzer: FlowrAnalyzer;
|
|
31
32
|
/**
|
|
32
33
|
* A potentially customized readline interface to be used for the repl to *read* from the user, we write the output with the {@link ReplOutput | `output` } interface.
|
|
33
34
|
* If you want to provide a custom one but use the same `completer`, refer to {@link replCompleter}.
|
|
@@ -48,10 +49,9 @@ export interface FlowrReplOptions extends MergeableRecord {
|
|
|
48
49
|
* - Starting with anything else, indicating default R code to be directly executed. If you kill the underlying shell, that is on you! </li>
|
|
49
50
|
*
|
|
50
51
|
* @param options - The options for the repl. See {@link FlowrReplOptions} for more information.
|
|
51
|
-
* @param config - The flowr config
|
|
52
52
|
*
|
|
53
53
|
* For the execution, this function makes use of {@link replProcessAnswer}.
|
|
54
54
|
*
|
|
55
55
|
*/
|
|
56
|
-
export declare function repl(
|
|
56
|
+
export declare function repl({ analyzer, rl, output, historyFile, allowRSessionAccess }: FlowrReplOptions): Promise<void>;
|
|
57
57
|
export declare function loadReplHistory(historyFile: string): string[] | undefined;
|
package/cli/repl/core.js
CHANGED
|
@@ -58,11 +58,8 @@ const repl_commands_1 = require("./commands/repl-commands");
|
|
|
58
58
|
const scripts_info_1 = require("../common/scripts-info");
|
|
59
59
|
const retriever_1 = require("../../r-bridge/retriever");
|
|
60
60
|
const repl_main_1 = require("./commands/repl-main");
|
|
61
|
-
const shell_1 = require("../../r-bridge/shell");
|
|
62
61
|
const log_1 = require("../../util/log");
|
|
63
|
-
const config_1 = require("../../config");
|
|
64
62
|
const query_1 = require("../../queries/query");
|
|
65
|
-
const flowr_analyzer_builder_1 = require("../../project/flowr-analyzer-builder");
|
|
66
63
|
let _replCompleterKeywords = undefined;
|
|
67
64
|
function replCompleterKeywords() {
|
|
68
65
|
if (_replCompleterKeywords === undefined) {
|
|
@@ -133,11 +130,11 @@ function makeDefaultReplReadline(config) {
|
|
|
133
130
|
}
|
|
134
131
|
function handleString(code) {
|
|
135
132
|
return {
|
|
136
|
-
input: code.startsWith('"') ? JSON.parse(code) : code,
|
|
133
|
+
input: code.length == 0 ? undefined : code.startsWith('"') ? JSON.parse(code) : code,
|
|
137
134
|
remaining: []
|
|
138
135
|
};
|
|
139
136
|
}
|
|
140
|
-
async function replProcessStatement(output, statement,
|
|
137
|
+
async function replProcessStatement(output, statement, analyzer, allowRSessionAccess) {
|
|
141
138
|
if (statement.startsWith(':')) {
|
|
142
139
|
const command = statement.slice(1).split(' ')[0].toLowerCase();
|
|
143
140
|
const processor = (0, repl_commands_1.getCommand)(command);
|
|
@@ -145,17 +142,16 @@ async function replProcessStatement(output, statement, parser, allowRSessionAcce
|
|
|
145
142
|
if (processor) {
|
|
146
143
|
try {
|
|
147
144
|
const remainingLine = statement.slice(command.length + 2).trim();
|
|
148
|
-
if (processor.
|
|
145
|
+
if (processor.isCodeCommand) {
|
|
149
146
|
const args = processor.argsParser(remainingLine);
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
.
|
|
153
|
-
|
|
154
|
-
.build();
|
|
147
|
+
if (args.input) {
|
|
148
|
+
analyzer.reset();
|
|
149
|
+
analyzer.context().addRequest((0, retriever_1.requestFromInput)(args.input));
|
|
150
|
+
}
|
|
155
151
|
await processor.fn({ output, analyzer, remainingArgs: args.remaining });
|
|
156
152
|
}
|
|
157
153
|
else {
|
|
158
|
-
await processor.fn({ output,
|
|
154
|
+
await processor.fn({ output, analyzer, remainingLine, allowRSessionAccess });
|
|
159
155
|
}
|
|
160
156
|
}
|
|
161
157
|
catch (e) {
|
|
@@ -170,22 +166,21 @@ async function replProcessStatement(output, statement, parser, allowRSessionAcce
|
|
|
170
166
|
}
|
|
171
167
|
}
|
|
172
168
|
else {
|
|
173
|
-
await (0, repl_execute_1.tryExecuteRShellCommand)({ output,
|
|
169
|
+
await (0, repl_execute_1.tryExecuteRShellCommand)({ output, analyzer, remainingLine: statement, allowRSessionAccess });
|
|
174
170
|
}
|
|
175
171
|
}
|
|
176
172
|
/**
|
|
177
173
|
* This function interprets the given `expr` as a REPL command (see {@link repl} for more on the semantics).
|
|
178
174
|
*
|
|
179
|
-
* @param
|
|
175
|
+
* @param analyzer - The flowR analyzer to use.
|
|
180
176
|
* @param output - Defines two methods that every function in the repl uses to output its data.
|
|
181
177
|
* @param expr - The expression to process.
|
|
182
|
-
* @param parser - The {@link RShell} or {@link TreeSitterExecutor} to use (see {@link repl}).
|
|
183
178
|
* @param allowRSessionAccess - If true, allows the execution of arbitrary R code.
|
|
184
179
|
*/
|
|
185
|
-
async function replProcessAnswer(
|
|
180
|
+
async function replProcessAnswer(analyzer, output, expr, allowRSessionAccess) {
|
|
186
181
|
const statements = (0, args_1.splitAtEscapeSensitive)(expr, false, ';');
|
|
187
182
|
for (const statement of statements) {
|
|
188
|
-
await replProcessStatement(output, statement,
|
|
183
|
+
await replProcessStatement(output, statement, analyzer, allowRSessionAccess);
|
|
189
184
|
}
|
|
190
185
|
}
|
|
191
186
|
/**
|
|
@@ -196,12 +191,11 @@ async function replProcessAnswer(config, output, expr, parser, allowRSessionAcce
|
|
|
196
191
|
* - Starting with anything else, indicating default R code to be directly executed. If you kill the underlying shell, that is on you! </li>
|
|
197
192
|
*
|
|
198
193
|
* @param options - The options for the repl. See {@link FlowrReplOptions} for more information.
|
|
199
|
-
* @param config - The flowr config
|
|
200
194
|
*
|
|
201
195
|
* For the execution, this function makes use of {@link replProcessAnswer}.
|
|
202
196
|
*
|
|
203
197
|
*/
|
|
204
|
-
async function repl(
|
|
198
|
+
async function repl({ analyzer, rl = readline.createInterface(makeDefaultReplReadline(analyzer.flowrConfig)), output = repl_main_1.standardReplOutput, historyFile = defaultHistoryFile, allowRSessionAccess = false }) {
|
|
205
199
|
if (historyFile) {
|
|
206
200
|
rl.on('history', h => fs_1.default.writeFileSync(historyFile, h.join('\n'), { encoding: 'utf-8' }));
|
|
207
201
|
}
|
|
@@ -210,7 +204,7 @@ async function repl(config, { parser = new shell_1.RShell((0, config_1.getEngine
|
|
|
210
204
|
await new Promise((resolve, reject) => {
|
|
211
205
|
rl.question((0, prompt_1.prompt)(), answer => {
|
|
212
206
|
rl.pause();
|
|
213
|
-
replProcessAnswer(
|
|
207
|
+
replProcessAnswer(analyzer, output, answer, allowRSessionAccess).then(() => {
|
|
214
208
|
rl.resume();
|
|
215
209
|
resolve();
|
|
216
210
|
}).catch(reject);
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.versionReplString = versionReplString;
|
|
4
4
|
exports.printVersionRepl = printVersionRepl;
|
|
5
|
-
const
|
|
5
|
+
const version_1 = require("../../util/version");
|
|
6
6
|
async function versionReplString(parser) {
|
|
7
|
-
const version = await (0,
|
|
7
|
+
const version = await (0, version_1.retrieveVersionInformation)(parser);
|
|
8
8
|
const rVersion = version.r === 'none' ? '' : version.r === 'unknown' ? ', R version unknown' : `, R v${version.r}`;
|
|
9
9
|
const treeSitterVer = parser.name === 'tree-sitter' ? `, R grammar v${parser.treeSitterVersion()}` : '';
|
|
10
10
|
return `flowR repl using flowR v${version.flowr}${rVersion}${treeSitterVer} (${version.engine} engine)`;
|
|
@@ -287,11 +287,15 @@ class FlowRServerConnection {
|
|
|
287
287
|
stream
|
|
288
288
|
});
|
|
289
289
|
};
|
|
290
|
-
|
|
290
|
+
const analyzer = new flowr_analyzer_builder_1.FlowrAnalyzerBuilder()
|
|
291
|
+
.setConfig(this.config)
|
|
292
|
+
.setParser(this.parser)
|
|
293
|
+
.buildSync();
|
|
294
|
+
void (0, core_1.replProcessAnswer)(analyzer, {
|
|
291
295
|
formatter: request.ansi ? ansi_1.ansiFormatter : ansi_1.voidFormatter,
|
|
292
296
|
stdout: msg => out('stdout', msg),
|
|
293
297
|
stderr: msg => out('stderr', msg)
|
|
294
|
-
}, request.expression, this.
|
|
298
|
+
}, request.expression, this.allowRSessionAccess).then(() => {
|
|
295
299
|
(0, send_1.sendMessage)(this.socket, {
|
|
296
300
|
type: 'end-repl-execution',
|
|
297
301
|
id: request.id
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { VersionInformation } from '../../commands/repl-version';
|
|
2
1
|
import type { IdMessageBase, MessageDefinition } from './all-messages';
|
|
2
|
+
import type { VersionInformation } from '../../../../util/version';
|
|
3
3
|
/**
|
|
4
4
|
* The hello message is automatically sent by the sever upon connection.
|
|
5
5
|
*/
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FlowRServer = exports.serverLog = void 0;
|
|
4
|
-
const repl_version_1 = require("../commands/repl-version");
|
|
5
4
|
const connection_1 = require("./connection");
|
|
6
5
|
const send_1 = require("./send");
|
|
7
6
|
const net_1 = require("./net");
|
|
8
7
|
const log_1 = require("../../../util/log");
|
|
8
|
+
const version_1 = require("../../../util/version");
|
|
9
9
|
// we detach from the main logger so that it can have its own switch
|
|
10
10
|
exports.serverLog = new log_1.FlowrLogger({ name: 'server' });
|
|
11
11
|
/**
|
|
@@ -32,7 +32,7 @@ class FlowRServer {
|
|
|
32
32
|
this.config = config;
|
|
33
33
|
}
|
|
34
34
|
async start(port) {
|
|
35
|
-
this.versionInformation = await (0,
|
|
35
|
+
this.versionInformation = await (0, version_1.retrieveVersionInformation)(this.engines[this.defaultEngine]);
|
|
36
36
|
this.server.start(port);
|
|
37
37
|
exports.serverLog.info(`Server listening on port ${port}`);
|
|
38
38
|
}
|
|
@@ -10,7 +10,9 @@ declare function processor(results: {
|
|
|
10
10
|
}, input: {
|
|
11
11
|
request?: RParseRequests;
|
|
12
12
|
parser?: Parser<KnownParserType>;
|
|
13
|
-
}, config: FlowrConfigOptions): import("../../../../dataflow/info").DataflowInformation
|
|
13
|
+
}, config: FlowrConfigOptions): import("../../../../dataflow/info").DataflowInformation & {
|
|
14
|
+
cfgQuick: import("../../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
15
|
+
};
|
|
14
16
|
export declare const STATIC_DATAFLOW: {
|
|
15
17
|
readonly humanReadableName: "dataflow";
|
|
16
18
|
readonly processor: typeof processor;
|
|
@@ -8,6 +8,20 @@ import type { RShell } from '../../../r-bridge/shell';
|
|
|
8
8
|
import type { TreeSitterExecutor } from '../../../r-bridge/lang-4.x/tree-sitter/tree-sitter-executor';
|
|
9
9
|
import type { FlowrConfigOptions } from '../../../config';
|
|
10
10
|
export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
|
|
11
|
+
readonly name: "slice";
|
|
12
|
+
readonly humanReadableName: "static slice";
|
|
13
|
+
readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
|
|
14
|
+
readonly processor: (results: {
|
|
15
|
+
dataflow?: import("../../../dataflow/info").DataflowInformation;
|
|
16
|
+
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
17
|
+
}, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
|
|
18
|
+
readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
|
|
19
|
+
readonly printer: {
|
|
20
|
+
readonly 0: typeof import("../../print/print").internalPrinter;
|
|
21
|
+
};
|
|
22
|
+
readonly dependencies: readonly ["dataflow"];
|
|
23
|
+
readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
|
|
24
|
+
} | {
|
|
11
25
|
readonly name: "parse";
|
|
12
26
|
readonly humanReadableName: "parse with R shell";
|
|
13
27
|
readonly description: "Parse the given R code into an AST";
|
|
@@ -40,20 +54,6 @@ export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
|
|
|
40
54
|
};
|
|
41
55
|
readonly dependencies: readonly ["parse"];
|
|
42
56
|
readonly requiredInput: import("../all/core/10-normalize").NormalizeRequiredInput;
|
|
43
|
-
} | {
|
|
44
|
-
readonly name: "slice";
|
|
45
|
-
readonly humanReadableName: "static slice";
|
|
46
|
-
readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
|
|
47
|
-
readonly processor: (results: {
|
|
48
|
-
dataflow?: import("../../../dataflow/info").DataflowInformation;
|
|
49
|
-
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
50
|
-
}, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
|
|
51
|
-
readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
|
|
52
|
-
readonly printer: {
|
|
53
|
-
readonly 0: typeof import("../../print/print").internalPrinter;
|
|
54
|
-
};
|
|
55
|
-
readonly dependencies: readonly ["dataflow"];
|
|
56
|
-
readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
|
|
57
57
|
} | {
|
|
58
58
|
readonly humanReadableName: "dataflow";
|
|
59
59
|
readonly processor: (results: {
|
|
@@ -61,7 +61,9 @@ export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
|
|
|
61
61
|
}, input: {
|
|
62
62
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
63
63
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
64
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
64
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
65
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
66
|
+
};
|
|
65
67
|
readonly requiredInput: {};
|
|
66
68
|
readonly name: "dataflow";
|
|
67
69
|
readonly description: "Construct the dataflow graph";
|
|
@@ -90,6 +92,20 @@ export declare const DEFAULT_SLICING_PIPELINE: import("./pipeline").Pipeline<{
|
|
|
90
92
|
readonly requiredInput: import("../all/static-slicing/10-reconstruct").ReconstructRequiredInput;
|
|
91
93
|
}>;
|
|
92
94
|
export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline").Pipeline<{
|
|
95
|
+
readonly name: "slice";
|
|
96
|
+
readonly humanReadableName: "static slice";
|
|
97
|
+
readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
|
|
98
|
+
readonly processor: (results: {
|
|
99
|
+
dataflow?: import("../../../dataflow/info").DataflowInformation;
|
|
100
|
+
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
101
|
+
}, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
|
|
102
|
+
readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
|
|
103
|
+
readonly printer: {
|
|
104
|
+
readonly 0: typeof import("../../print/print").internalPrinter;
|
|
105
|
+
};
|
|
106
|
+
readonly dependencies: readonly ["dataflow"];
|
|
107
|
+
readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
|
|
108
|
+
} | {
|
|
93
109
|
readonly name: "parse";
|
|
94
110
|
readonly humanReadableName: "parse with R shell";
|
|
95
111
|
readonly description: "Parse the given R code into an AST";
|
|
@@ -122,20 +138,6 @@ export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline"
|
|
|
122
138
|
};
|
|
123
139
|
readonly dependencies: readonly ["parse"];
|
|
124
140
|
readonly requiredInput: import("../all/core/10-normalize").NormalizeRequiredInput;
|
|
125
|
-
} | {
|
|
126
|
-
readonly name: "slice";
|
|
127
|
-
readonly humanReadableName: "static slice";
|
|
128
|
-
readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
|
|
129
|
-
readonly processor: (results: {
|
|
130
|
-
dataflow?: import("../../../dataflow/info").DataflowInformation;
|
|
131
|
-
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
132
|
-
}, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
|
|
133
|
-
readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
|
|
134
|
-
readonly printer: {
|
|
135
|
-
readonly 0: typeof import("../../print/print").internalPrinter;
|
|
136
|
-
};
|
|
137
|
-
readonly dependencies: readonly ["dataflow"];
|
|
138
|
-
readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
|
|
139
141
|
} | {
|
|
140
142
|
readonly humanReadableName: "dataflow";
|
|
141
143
|
readonly processor: (results: {
|
|
@@ -143,7 +145,9 @@ export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline"
|
|
|
143
145
|
}, input: {
|
|
144
146
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
145
147
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
146
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
148
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
149
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
150
|
+
};
|
|
147
151
|
readonly requiredInput: {};
|
|
148
152
|
readonly name: "dataflow";
|
|
149
153
|
readonly description: "Construct the dataflow graph";
|
|
@@ -172,6 +176,20 @@ export declare const DEFAULT_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipeline"
|
|
|
172
176
|
readonly requiredInput: import("../all/static-slicing/10-reconstruct").ReconstructRequiredInput;
|
|
173
177
|
}>;
|
|
174
178
|
export declare const DEFAULT_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipeline").Pipeline<{
|
|
179
|
+
readonly name: "slice";
|
|
180
|
+
readonly humanReadableName: "static slice";
|
|
181
|
+
readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
|
|
182
|
+
readonly processor: (results: {
|
|
183
|
+
dataflow?: import("../../../dataflow/info").DataflowInformation;
|
|
184
|
+
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
185
|
+
}, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
|
|
186
|
+
readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
|
|
187
|
+
readonly printer: {
|
|
188
|
+
readonly 0: typeof import("../../print/print").internalPrinter;
|
|
189
|
+
};
|
|
190
|
+
readonly dependencies: readonly ["dataflow"];
|
|
191
|
+
readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
|
|
192
|
+
} | {
|
|
175
193
|
readonly name: "parse";
|
|
176
194
|
readonly humanReadableName: "parse with R shell";
|
|
177
195
|
readonly description: "Parse the given R code into an AST";
|
|
@@ -204,20 +222,6 @@ export declare const DEFAULT_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipel
|
|
|
204
222
|
};
|
|
205
223
|
readonly dependencies: readonly ["parse"];
|
|
206
224
|
readonly requiredInput: import("../all/core/10-normalize").NormalizeRequiredInput;
|
|
207
|
-
} | {
|
|
208
|
-
readonly name: "slice";
|
|
209
|
-
readonly humanReadableName: "static slice";
|
|
210
|
-
readonly description: "Calculate the actual static slice from the dataflow graph and the given slicing criteria";
|
|
211
|
-
readonly processor: (results: {
|
|
212
|
-
dataflow?: import("../../../dataflow/info").DataflowInformation;
|
|
213
|
-
normalize?: import("../../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
|
|
214
|
-
}, input: Partial<import("../all/static-slicing/00-slice").SliceRequiredInput>, _config: FlowrConfigOptions) => Readonly<import("../../../slicing/static/slicer-types").SliceResult>;
|
|
215
|
-
readonly executed: import("../pipeline-step").PipelineStepStage.OncePerRequest;
|
|
216
|
-
readonly printer: {
|
|
217
|
-
readonly 0: typeof import("../../print/print").internalPrinter;
|
|
218
|
-
};
|
|
219
|
-
readonly dependencies: readonly ["dataflow"];
|
|
220
|
-
readonly requiredInput: import("../all/static-slicing/00-slice").SliceRequiredInput;
|
|
221
225
|
} | {
|
|
222
226
|
readonly humanReadableName: "dataflow";
|
|
223
227
|
readonly processor: (results: {
|
|
@@ -225,7 +229,9 @@ export declare const DEFAULT_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./pipel
|
|
|
225
229
|
}, input: {
|
|
226
230
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
227
231
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
228
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
232
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
233
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
234
|
+
};
|
|
229
235
|
readonly requiredInput: {};
|
|
230
236
|
readonly name: "dataflow";
|
|
231
237
|
readonly description: "Construct the dataflow graph";
|
|
@@ -260,7 +266,9 @@ export declare const TREE_SITTER_SLICING_PIPELINE: import("./pipeline").Pipeline
|
|
|
260
266
|
}, input: {
|
|
261
267
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
262
268
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
263
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
269
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
270
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
271
|
+
};
|
|
264
272
|
readonly requiredInput: {};
|
|
265
273
|
readonly name: "dataflow";
|
|
266
274
|
readonly description: "Construct the dataflow graph";
|
|
@@ -341,7 +349,9 @@ export declare const TREE_SITTER_SLICE_AND_RECONSTRUCT_PIPELINE: import("./pipel
|
|
|
341
349
|
}, input: {
|
|
342
350
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
343
351
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
344
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
352
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
353
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
354
|
+
};
|
|
345
355
|
readonly requiredInput: {};
|
|
346
356
|
readonly name: "dataflow";
|
|
347
357
|
readonly description: "Construct the dataflow graph";
|
|
@@ -422,7 +432,9 @@ export declare const TREE_SITTER_SLICE_WITHOUT_RECONSTRUCT_PIPELINE: import("./p
|
|
|
422
432
|
}, input: {
|
|
423
433
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
424
434
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
425
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
435
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
436
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
437
|
+
};
|
|
426
438
|
readonly requiredInput: {};
|
|
427
439
|
readonly name: "dataflow";
|
|
428
440
|
readonly description: "Construct the dataflow graph";
|
|
@@ -513,7 +525,9 @@ export declare const DEFAULT_DATAFLOW_PIPELINE: import("./pipeline").Pipeline<{
|
|
|
513
525
|
}, input: {
|
|
514
526
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
515
527
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
516
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
528
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
529
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
530
|
+
};
|
|
517
531
|
readonly requiredInput: {};
|
|
518
532
|
readonly name: "dataflow";
|
|
519
533
|
readonly description: "Construct the dataflow graph";
|
|
@@ -534,7 +548,9 @@ export declare const TREE_SITTER_DATAFLOW_PIPELINE: import("./pipeline").Pipelin
|
|
|
534
548
|
}, input: {
|
|
535
549
|
request?: import("../../../r-bridge/retriever").RParseRequests;
|
|
536
550
|
parser?: Parser<import("../../../r-bridge/parser").KnownParserType>;
|
|
537
|
-
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation
|
|
551
|
+
}, config: FlowrConfigOptions) => import("../../../dataflow/info").DataflowInformation & {
|
|
552
|
+
cfgQuick: import("../../../control-flow/control-flow-graph").ControlFlowInformation | undefined;
|
|
553
|
+
};
|
|
538
554
|
readonly requiredInput: {};
|
|
539
555
|
readonly name: "dataflow";
|
|
540
556
|
readonly description: "Construct the dataflow graph";
|
|
@@ -212,6 +212,14 @@ exports.DefaultBuiltinConfig = [
|
|
|
212
212
|
{ type: 'function', names: ['('], processor: 'builtin:default', config: { returnsNthArgument: 0 }, assumePrimitive: true },
|
|
213
213
|
{ type: 'function', names: ['load', 'load_all', 'setwd', 'set.seed'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true] }, assumePrimitive: false },
|
|
214
214
|
{ type: 'function', names: ['body', 'formals', 'environment'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true] }, assumePrimitive: true },
|
|
215
|
+
{ type: 'function', names: ['.Call', '.External', '.C', '.Fortran'], processor: 'builtin:default', config: { hasUnknownSideEffects: true, forceArgs: [true],
|
|
216
|
+
treatAsFnCall: {
|
|
217
|
+
'.Call': ['.NAME'],
|
|
218
|
+
'.External': ['.NAME'],
|
|
219
|
+
'.C': ['.NAME'],
|
|
220
|
+
'.Fortran': ['.NAME']
|
|
221
|
+
}
|
|
222
|
+
}, assumePrimitive: true },
|
|
215
223
|
{ type: 'function', names: ['eval'], processor: 'builtin:eval', config: { includeFunctionCall: true }, assumePrimitive: true },
|
|
216
224
|
{ type: 'function', names: ['cat'], processor: 'builtin:default', config: { forceArgs: 'all', hasUnknownSideEffects: { type: 'link-to-last-call', callName: /^sink$/ } }, assumePrimitive: false },
|
|
217
225
|
{ type: 'function', names: ['switch'], processor: 'builtin:default', config: { forceArgs: [true] }, assumePrimitive: false },
|
|
@@ -138,6 +138,8 @@ function resolveIdToValue(id, { environment, graph, idMap, full = true, resolve
|
|
|
138
138
|
else {
|
|
139
139
|
return r_value_1.Top;
|
|
140
140
|
}
|
|
141
|
+
case type_1.RType.FunctionDefinition:
|
|
142
|
+
return (0, set_constants_1.setFrom)({ type: 'function-definition' });
|
|
141
143
|
case type_1.RType.FunctionCall:
|
|
142
144
|
case type_1.RType.BinaryOp:
|
|
143
145
|
case type_1.RType.UnaryOp:
|
|
@@ -41,6 +41,9 @@ function resolveNode(resolve, a, env, graph, map) {
|
|
|
41
41
|
else if (a.type === type_1.RType.Logical) {
|
|
42
42
|
return a.content.valueOf() ? logical_constants_1.ValueLogicalTrue : logical_constants_1.ValueLogicalFalse;
|
|
43
43
|
}
|
|
44
|
+
else if (a.type === type_1.RType.FunctionDefinition) {
|
|
45
|
+
return { type: 'function-definition' };
|
|
46
|
+
}
|
|
44
47
|
else if ((a.type === type_1.RType.FunctionCall || a.type === type_1.RType.BinaryOp || a.type === type_1.RType.UnaryOp) && graph) {
|
|
45
48
|
const origin = (0, dfg_get_origin_1.getOriginInDfg)(graph, a.info.id)?.[0];
|
|
46
49
|
if (origin === undefined || origin.type !== 3 /* OriginType.BuiltInFunctionOrigin */) {
|
|
@@ -37,6 +37,9 @@ export interface ValueString<Str extends Lift<RStringValue> = Lift<RStringValue>
|
|
|
37
37
|
type: 'string';
|
|
38
38
|
value: Str;
|
|
39
39
|
}
|
|
40
|
+
export interface ValueFunctionDefinition {
|
|
41
|
+
type: 'function-definition';
|
|
42
|
+
}
|
|
40
43
|
export interface ValueMissing {
|
|
41
44
|
type: 'missing';
|
|
42
45
|
}
|
|
@@ -45,7 +48,7 @@ export interface ValueLogical {
|
|
|
45
48
|
type: 'logical';
|
|
46
49
|
value: Lift<TernaryLogical>;
|
|
47
50
|
}
|
|
48
|
-
export type Value = Lift<ValueInterval | ValueVector | ValueSet | ValueNumber | ValueString | ValueLogical | ValueMissing>;
|
|
51
|
+
export type Value = Lift<ValueInterval | ValueVector | ValueSet | ValueNumber | ValueString | ValueLogical | ValueMissing | ValueFunctionDefinition>;
|
|
49
52
|
export type ValueType<V> = V extends {
|
|
50
53
|
type: infer T;
|
|
51
54
|
} ? T : never;
|
|
@@ -82,6 +82,8 @@ function stringifyValue(value) {
|
|
|
82
82
|
return tryStringifyBoTop(v.value, l => l === 'maybe' ? 'maybe' : l ? 'TRUE' : 'FALSE', () => '⊤ (logical)', () => '⊥ (logical)');
|
|
83
83
|
case 'missing':
|
|
84
84
|
return '(missing)';
|
|
85
|
+
case 'function-definition':
|
|
86
|
+
return 'fn-def';
|
|
85
87
|
default:
|
|
86
88
|
(0, assert_1.assertUnreachable)(t);
|
|
87
89
|
}
|
package/dataflow/extractor.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type { DataflowProcessors } from './processor';
|
|
|
3
3
|
import type { NormalizedAst, ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
4
|
import type { RParseRequests } from '../r-bridge/retriever';
|
|
5
5
|
import type { KnownParserType, Parser } from '../r-bridge/parser';
|
|
6
|
+
import type { ControlFlowInformation } from '../control-flow/control-flow-graph';
|
|
6
7
|
import type { FlowrConfigOptions } from '../config';
|
|
7
8
|
/**
|
|
8
9
|
* The best friend of {@link produceDataFlowGraph} and {@link processDataflowFor}.
|
|
@@ -15,4 +16,6 @@ export declare const processors: DataflowProcessors<ParentInformation>;
|
|
|
15
16
|
* (e.g., in the event of a `source` call).
|
|
16
17
|
* For the actual, canonical fold entry point, see {@link processDataflowFor}.
|
|
17
18
|
*/
|
|
18
|
-
export declare function produceDataFlowGraph<OtherInfo>(parser: Parser<KnownParserType>, request: RParseRequests, completeAst: NormalizedAst<OtherInfo & ParentInformation>, config: FlowrConfigOptions): DataflowInformation
|
|
19
|
+
export declare function produceDataFlowGraph<OtherInfo>(parser: Parser<KnownParserType>, request: RParseRequests, completeAst: NormalizedAst<OtherInfo & ParentInformation>, config: FlowrConfigOptions): DataflowInformation & {
|
|
20
|
+
cfgQuick: ControlFlowInformation | undefined;
|
|
21
|
+
};
|
package/dataflow/extractor.js
CHANGED
|
@@ -59,14 +59,14 @@ exports.processors = {
|
|
|
59
59
|
}
|
|
60
60
|
};
|
|
61
61
|
function resolveLinkToSideEffects(ast, graph) {
|
|
62
|
-
let
|
|
62
|
+
let cf = undefined;
|
|
63
63
|
for (const s of graph.unknownSideEffects) {
|
|
64
64
|
if (typeof s !== 'object') {
|
|
65
65
|
continue;
|
|
66
66
|
}
|
|
67
|
-
|
|
67
|
+
cf ??= (0, extract_cfg_1.extractCfgQuick)(ast);
|
|
68
68
|
/* this has to change whenever we add a new link to relations because we currently offer no abstraction for the type */
|
|
69
|
-
const potentials = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(s.id,
|
|
69
|
+
const potentials = (0, identify_link_to_last_call_relation_1.identifyLinkToLastCallRelation)(s.id, cf?.graph, graph, s.linkTo);
|
|
70
70
|
for (const pot of potentials) {
|
|
71
71
|
graph.addEdge(s.id, pot, edge_1.EdgeType.Reads);
|
|
72
72
|
}
|
|
@@ -74,6 +74,7 @@ function resolveLinkToSideEffects(ast, graph) {
|
|
|
74
74
|
graph.unknownSideEffects.delete(s);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
|
+
return cf;
|
|
77
78
|
}
|
|
78
79
|
/**
|
|
79
80
|
* This is the main function to produce the dataflow graph from a given request and normalized AST.
|
|
@@ -114,7 +115,8 @@ function produceDataFlowGraph(parser, request, completeAst, config) {
|
|
|
114
115
|
}
|
|
115
116
|
// finally, resolve linkages
|
|
116
117
|
(0, built_in_function_definition_1.updateNestedFunctionCalls)(df.graph, df.environment);
|
|
117
|
-
resolveLinkToSideEffects(completeAst, df.graph);
|
|
118
|
-
return
|
|
118
|
+
const cfgQuick = resolveLinkToSideEffects(completeAst, df.graph);
|
|
119
|
+
// performance optimization: return cfgQuick as part of the result to avoid recomputation
|
|
120
|
+
return { ...df, cfgQuick };
|
|
119
121
|
}
|
|
120
122
|
//# sourceMappingURL=extractor.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
|
+
import type { DataflowGraph } from '../graph/graph';
|
|
3
|
+
/**
|
|
4
|
+
* Determines whether the function with the given id is a higher-order function, i.e.,
|
|
5
|
+
* either takes a function as an argument or (may) returns a function.
|
|
6
|
+
* If the return is an identity, e.g., `function(x) x`, this is not considered higher-order,
|
|
7
|
+
* if no function is passed as an argument.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isHigherOrder(id: NodeId, graph: DataflowGraph): boolean;
|