@eagleoutice/flowr 2.1.12 → 2.2.0
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/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/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/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-format.d.ts +5 -4
- package/queries/catalog/static-slice-query/static-slice-query-format.d.ts +5 -4
- package/queries/query.d.ts +40 -32
- 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/version.js +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.queryStarCommand = exports.queryCommand = void 0;
|
|
4
|
-
const pipeline_executor_1 = require("../../../core/pipeline-executor");
|
|
5
4
|
const default_pipelines_1 = require("../../../core/steps/pipeline/default-pipelines");
|
|
6
5
|
const retriever_1 = require("../../../r-bridge/retriever");
|
|
7
6
|
const args_1 = require("../../../util/args");
|
|
@@ -10,9 +9,8 @@ const schema_1 = require("../../../util/schema");
|
|
|
10
9
|
const query_1 = require("../../../queries/query");
|
|
11
10
|
const json_1 = require("../../../util/json");
|
|
12
11
|
const query_print_1 = require("../../../queries/query-print");
|
|
13
|
-
async function getDataflow(
|
|
14
|
-
return await
|
|
15
|
-
shell,
|
|
12
|
+
async function getDataflow(parser, remainingLine) {
|
|
13
|
+
return await (0, default_pipelines_1.createDataflowPipeline)(parser, {
|
|
16
14
|
request: (0, retriever_1.requestFromInput)(remainingLine.trim())
|
|
17
15
|
}).allRemainingSteps();
|
|
18
16
|
}
|
|
@@ -26,7 +24,7 @@ function printHelp(output) {
|
|
|
26
24
|
output.stdout(`Similarly, '@<type>' is interpreted as a query of the given type.`);
|
|
27
25
|
output.stdout(`With this, ${(0, ansi_1.italic)(':query @config', output.formatter)} prints the result of the config query.`);
|
|
28
26
|
}
|
|
29
|
-
async function processQueryArgs(line,
|
|
27
|
+
async function processQueryArgs(line, parser, output) {
|
|
30
28
|
const args = (0, args_1.splitAtEscapeSensitive)(line);
|
|
31
29
|
const query = args.shift();
|
|
32
30
|
if (!query) {
|
|
@@ -59,7 +57,7 @@ async function processQueryArgs(line, shell, output) {
|
|
|
59
57
|
else {
|
|
60
58
|
parsedQuery = [{ type: 'call-context', callName: query }];
|
|
61
59
|
}
|
|
62
|
-
const processed = await getDataflow(
|
|
60
|
+
const processed = await getDataflow(parser, args.join(' '));
|
|
63
61
|
return {
|
|
64
62
|
query: (0, query_1.executeQueries)({ dataflow: processed.dataflow, ast: processed.normalize }, parsedQuery),
|
|
65
63
|
processed
|
|
@@ -70,9 +68,9 @@ exports.queryCommand = {
|
|
|
70
68
|
usageExample: ':query "<query>" <code>',
|
|
71
69
|
aliases: [],
|
|
72
70
|
script: false,
|
|
73
|
-
fn: async (output,
|
|
71
|
+
fn: async (output, parser, remainingLine) => {
|
|
74
72
|
const totalStart = Date.now();
|
|
75
|
-
const results = await processQueryArgs(remainingLine,
|
|
73
|
+
const results = await processQueryArgs(remainingLine, parser, output);
|
|
76
74
|
const totalEnd = Date.now();
|
|
77
75
|
if (results) {
|
|
78
76
|
output.stdout((0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.ansiFormatter, totalEnd - totalStart, results.query, results.processed));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReplCommand, ReplOutput } from './repl-main';
|
|
2
|
-
import type {
|
|
2
|
+
import type { KnownParser } from '../../../r-bridge/parser';
|
|
3
3
|
type Version = `${number}.${number}.${number}`;
|
|
4
4
|
/**
|
|
5
5
|
* Describes the version of flowR and the used R interpreter.
|
|
@@ -8,9 +8,10 @@ export interface VersionInformation {
|
|
|
8
8
|
/** The version of flowR */
|
|
9
9
|
flowr: Version;
|
|
10
10
|
/** The version of R identified by the underlying {@link RShell} */
|
|
11
|
-
r: Version | 'unknown';
|
|
11
|
+
r: Version | 'unknown' | 'none';
|
|
12
|
+
engine: string;
|
|
12
13
|
}
|
|
13
|
-
export declare function retrieveVersionInformation(
|
|
14
|
-
export declare function printVersionInformation(output: ReplOutput,
|
|
14
|
+
export declare function retrieveVersionInformation(parser: KnownParser): Promise<VersionInformation>;
|
|
15
|
+
export declare function printVersionInformation(output: ReplOutput, parser: KnownParser): Promise<void>;
|
|
15
16
|
export declare const versionCommand: ReplCommand;
|
|
16
17
|
export {};
|
|
@@ -6,23 +6,24 @@ exports.printVersionInformation = printVersionInformation;
|
|
|
6
6
|
const version_1 = require("../../../util/version");
|
|
7
7
|
const assert_1 = require("../../../util/assert");
|
|
8
8
|
const versionRegex = /^\d+\.\d+\.\d+/m;
|
|
9
|
-
async function retrieveVersionInformation(
|
|
9
|
+
async function retrieveVersionInformation(parser) {
|
|
10
10
|
const flowr = (0, version_1.flowrVersion)().toString();
|
|
11
|
-
const r =
|
|
11
|
+
const r = await parser.rVersion();
|
|
12
12
|
(0, assert_1.guard)(versionRegex.test(flowr), `flowR version ${flowr} does not match the expected format!`);
|
|
13
|
-
(0, assert_1.guard)(r === 'unknown' || versionRegex.test(r), `R version ${r} does not match the expected format!`);
|
|
14
|
-
return { flowr: flowr, r: r };
|
|
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
15
|
}
|
|
16
|
-
async function printVersionInformation(output,
|
|
17
|
-
const { flowr, r } = await retrieveVersionInformation(
|
|
18
|
-
output.stdout(`
|
|
19
|
-
output.stdout(`
|
|
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}`);
|
|
20
21
|
}
|
|
21
22
|
exports.versionCommand = {
|
|
22
23
|
description: 'Prints the version of flowR as well as the current version of R',
|
|
23
24
|
aliases: [],
|
|
24
25
|
usageExample: ':version',
|
|
25
26
|
script: false,
|
|
26
|
-
fn: (output,
|
|
27
|
+
fn: (output, parser) => printVersionInformation(output, parser)
|
|
27
28
|
};
|
|
28
29
|
//# sourceMappingURL=repl-version.js.map
|
package/cli/repl/core.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as readline from 'readline';
|
|
2
2
|
import type { ReplOutput } from './commands/repl-main';
|
|
3
|
-
import { RShell } from '../../r-bridge/shell';
|
|
4
3
|
import type { MergeableRecord } from '../../util/objects';
|
|
4
|
+
import type { KnownParser } from '../../r-bridge/parser';
|
|
5
5
|
/**
|
|
6
6
|
* Used by the repl to provide automatic completions for a given (partial) input line
|
|
7
7
|
*/
|
|
@@ -12,16 +12,16 @@ export declare const DEFAULT_REPL_READLINE_CONFIGURATION: readline.ReadLineOptio
|
|
|
12
12
|
*
|
|
13
13
|
* @param output - Defines two methods that every function in the repl uses to output its data.
|
|
14
14
|
* @param expr - The expression to process.
|
|
15
|
-
* @param
|
|
15
|
+
* @param parser - The {@link RShell} or {@link TreeSitterExecutor} to use (see {@link repl}).
|
|
16
16
|
* @param allowRSessionAccess - If true, allows the execution of arbitrary R code.
|
|
17
17
|
*/
|
|
18
|
-
export declare function replProcessAnswer(output: ReplOutput, expr: string,
|
|
18
|
+
export declare function replProcessAnswer(output: ReplOutput, expr: string, parser: KnownParser, allowRSessionAccess: boolean): Promise<void>;
|
|
19
19
|
/**
|
|
20
20
|
* Options for the {@link repl} function.
|
|
21
21
|
*/
|
|
22
22
|
export interface FlowrReplOptions extends MergeableRecord {
|
|
23
23
|
/** The shell to use, if you do not pass one it will automatically create a new one with the `revive` option set to 'always'. */
|
|
24
|
-
readonly
|
|
24
|
+
readonly parser?: KnownParser;
|
|
25
25
|
/**
|
|
26
26
|
* 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.
|
|
27
27
|
* If you want to provide a custom one but use the same `completer`, refer to {@link replCompleter}.
|
|
@@ -47,5 +47,5 @@ export interface FlowrReplOptions extends MergeableRecord {
|
|
|
47
47
|
* For the execution, this function makes use of {@link replProcessAnswer}.
|
|
48
48
|
*
|
|
49
49
|
*/
|
|
50
|
-
export declare function repl({
|
|
50
|
+
export declare function repl({ parser, rl, output, historyFile, allowRSessionAccess }: FlowrReplOptions): Promise<void>;
|
|
51
51
|
export declare function loadReplHistory(historyFile: string): string[] | undefined;
|
package/cli/repl/core.js
CHANGED
|
@@ -43,7 +43,6 @@ const os_1 = __importDefault(require("os"));
|
|
|
43
43
|
const path_1 = __importDefault(require("path"));
|
|
44
44
|
const fs_1 = __importDefault(require("fs"));
|
|
45
45
|
const args_1 = require("../../util/args");
|
|
46
|
-
const ansi_1 = require("../../util/ansi");
|
|
47
46
|
const repl_commands_1 = require("./commands/repl-commands");
|
|
48
47
|
const scripts_info_1 = require("../common/scripts-info");
|
|
49
48
|
const retriever_1 = require("../../r-bridge/retriever");
|
|
@@ -97,14 +96,14 @@ exports.DEFAULT_REPL_READLINE_CONFIGURATION = {
|
|
|
97
96
|
removeHistoryDuplicates: true,
|
|
98
97
|
completer: replCompleter
|
|
99
98
|
};
|
|
100
|
-
async function replProcessStatement(output, statement,
|
|
99
|
+
async function replProcessStatement(output, statement, parser, allowRSessionAccess) {
|
|
101
100
|
if (statement.startsWith(':')) {
|
|
102
101
|
const command = statement.slice(1).split(' ')[0].toLowerCase();
|
|
103
102
|
const processor = (0, repl_commands_1.getCommand)(command);
|
|
104
103
|
const bold = (s) => output.formatter.format(s, { style: 1 /* FontStyles.Bold */ });
|
|
105
104
|
if (processor) {
|
|
106
105
|
try {
|
|
107
|
-
await processor.fn(output,
|
|
106
|
+
await processor.fn(output, parser, statement.slice(command.length + 2).trim(), allowRSessionAccess);
|
|
108
107
|
}
|
|
109
108
|
catch (e) {
|
|
110
109
|
output.stdout(`${bold(`Failed to execute command ${command}`)}: ${e?.message}. Using the ${bold('--verbose')} flag on startup may provide additional information.\n`);
|
|
@@ -114,11 +113,8 @@ async function replProcessStatement(output, statement, shell, allowRSessionAcces
|
|
|
114
113
|
output.stdout(`the command '${command}' is unknown, try ${bold(':help')} for more information\n`);
|
|
115
114
|
}
|
|
116
115
|
}
|
|
117
|
-
else if (allowRSessionAccess) {
|
|
118
|
-
await (0, repl_execute_1.executeRShellCommand)(output, shell, statement);
|
|
119
|
-
}
|
|
120
116
|
else {
|
|
121
|
-
|
|
117
|
+
await (0, repl_execute_1.tryExecuteRShellCommand)(output, parser, statement, allowRSessionAccess);
|
|
122
118
|
}
|
|
123
119
|
}
|
|
124
120
|
/**
|
|
@@ -126,13 +122,13 @@ async function replProcessStatement(output, statement, shell, allowRSessionAcces
|
|
|
126
122
|
*
|
|
127
123
|
* @param output - Defines two methods that every function in the repl uses to output its data.
|
|
128
124
|
* @param expr - The expression to process.
|
|
129
|
-
* @param
|
|
125
|
+
* @param parser - The {@link RShell} or {@link TreeSitterExecutor} to use (see {@link repl}).
|
|
130
126
|
* @param allowRSessionAccess - If true, allows the execution of arbitrary R code.
|
|
131
127
|
*/
|
|
132
|
-
async function replProcessAnswer(output, expr,
|
|
128
|
+
async function replProcessAnswer(output, expr, parser, allowRSessionAccess) {
|
|
133
129
|
const statements = (0, args_1.splitAtEscapeSensitive)(expr, false, ';');
|
|
134
130
|
for (const statement of statements) {
|
|
135
|
-
await replProcessStatement(output, statement,
|
|
131
|
+
await replProcessStatement(output, statement, parser, allowRSessionAccess);
|
|
136
132
|
}
|
|
137
133
|
}
|
|
138
134
|
/**
|
|
@@ -147,7 +143,7 @@ async function replProcessAnswer(output, expr, shell, allowRSessionAccess) {
|
|
|
147
143
|
* For the execution, this function makes use of {@link replProcessAnswer}.
|
|
148
144
|
*
|
|
149
145
|
*/
|
|
150
|
-
async function repl({
|
|
146
|
+
async function repl({ parser = new shell_1.RShell({ revive: 2 /* RShellReviveOptions.Always */ }), rl = readline.createInterface(exports.DEFAULT_REPL_READLINE_CONFIGURATION), output = repl_main_1.standardReplOutput, historyFile = defaultHistoryFile, allowRSessionAccess = false }) {
|
|
151
147
|
if (historyFile) {
|
|
152
148
|
rl.on('history', h => fs_1.default.writeFileSync(historyFile, h.join('\n'), { encoding: 'utf-8' }));
|
|
153
149
|
}
|
|
@@ -157,7 +153,7 @@ async function repl({ shell = new shell_1.RShell({ revive: 2 /* RShellReviveOpti
|
|
|
157
153
|
await new Promise((resolve, reject) => {
|
|
158
154
|
rl.question((0, prompt_1.prompt)(), answer => {
|
|
159
155
|
rl.pause();
|
|
160
|
-
replProcessAnswer(output, answer,
|
|
156
|
+
replProcessAnswer(output, answer, parser, allowRSessionAccess).then(() => {
|
|
161
157
|
rl.resume();
|
|
162
158
|
resolve();
|
|
163
159
|
}).catch(reject);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function printVersionRepl(
|
|
1
|
+
import type { KnownParser } from '../../r-bridge/parser';
|
|
2
|
+
export declare function printVersionRepl(parser: KnownParser): Promise<void>;
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.printVersionRepl = printVersionRepl;
|
|
4
4
|
const repl_version_1 = require("./commands/repl-version");
|
|
5
|
-
async function printVersionRepl(
|
|
6
|
-
const version = await (0, repl_version_1.retrieveVersionInformation)(
|
|
7
|
-
console.log(`flowR repl using flowR ${version.flowr}, R ${version.r}`);
|
|
5
|
+
async function printVersionRepl(parser) {
|
|
6
|
+
const version = await (0, repl_version_1.retrieveVersionInformation)(parser);
|
|
7
|
+
console.log(`flowR repl using flowR ${version.flowr}, R ${version.r}, engine ${version.engine}`);
|
|
8
8
|
}
|
|
9
9
|
//# sourceMappingURL=print-version.js.map
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import type { Socket } from './net';
|
|
2
2
|
import { DEFAULT_SLICING_PIPELINE } from '../../../core/steps/pipeline/default-pipelines';
|
|
3
|
-
import type { RShell } from '../../../r-bridge/shell';
|
|
4
3
|
import type { PipelineOutput } from '../../../core/steps/pipeline/pipeline';
|
|
5
4
|
import type { DeepPartial } from 'ts-essentials';
|
|
5
|
+
import type { KnownParser } from '../../../r-bridge/parser';
|
|
6
6
|
/**
|
|
7
7
|
* Each connection handles a single client, answering to its requests.
|
|
8
8
|
* There is no need to construct this class manually, {@link FlowRServer} will do it for you.
|
|
9
9
|
*/
|
|
10
10
|
export declare class FlowRServerConnection {
|
|
11
11
|
private readonly socket;
|
|
12
|
-
private readonly
|
|
12
|
+
private readonly parser;
|
|
13
13
|
private readonly name;
|
|
14
14
|
private readonly logger;
|
|
15
15
|
private readonly allowRSessionAccess;
|
|
16
16
|
private readonly fileMap;
|
|
17
|
-
constructor(socket: Socket, name: string,
|
|
17
|
+
constructor(socket: Socket, name: string, parser: KnownParser, allowRSessionAccess: boolean);
|
|
18
18
|
private currentMessageBuffer;
|
|
19
19
|
private handleData;
|
|
20
20
|
private handleFileAnalysisRequest;
|
|
@@ -35,7 +35,6 @@ const message_slice_1 = require("./messages/message-slice");
|
|
|
35
35
|
const server_1 = require("./server");
|
|
36
36
|
const message_repl_1 = require("./messages/message-repl");
|
|
37
37
|
const core_1 = require("../core");
|
|
38
|
-
const pipeline_executor_1 = require("../../../core/pipeline-executor");
|
|
39
38
|
const cfg_1 = require("../../../util/cfg/cfg");
|
|
40
39
|
const quads_1 = require("../../../util/quads");
|
|
41
40
|
const print_1 = require("../../../core/print/print");
|
|
@@ -60,16 +59,16 @@ const query_1 = require("../../../queries/query");
|
|
|
60
59
|
*/
|
|
61
60
|
class FlowRServerConnection {
|
|
62
61
|
socket;
|
|
63
|
-
|
|
62
|
+
parser;
|
|
64
63
|
name;
|
|
65
64
|
logger;
|
|
66
65
|
allowRSessionAccess;
|
|
67
66
|
// maps token to information
|
|
68
67
|
fileMap = new Map();
|
|
69
68
|
// we do not have to ensure synchronized shell-access as we are always running synchronized
|
|
70
|
-
constructor(socket, name,
|
|
69
|
+
constructor(socket, name, parser, allowRSessionAccess) {
|
|
71
70
|
this.socket = socket;
|
|
72
|
-
this.
|
|
71
|
+
this.parser = parser;
|
|
73
72
|
this.name = name;
|
|
74
73
|
this.logger = server_1.serverLog.getSubLogger({ name });
|
|
75
74
|
this.socket.on('data', data => this.handleData(String(data)));
|
|
@@ -198,8 +197,7 @@ class FlowRServerConnection {
|
|
|
198
197
|
else {
|
|
199
198
|
throw new Error('Either content or filepath must be defined.');
|
|
200
199
|
}
|
|
201
|
-
const slicer =
|
|
202
|
-
shell: this.shell,
|
|
200
|
+
const slicer = (0, default_pipelines_1.createSlicePipeline)(this.parser, {
|
|
203
201
|
request,
|
|
204
202
|
criterion: [] // currently unknown
|
|
205
203
|
});
|
|
@@ -270,7 +268,7 @@ class FlowRServerConnection {
|
|
|
270
268
|
formatter: request.ansi ? ansi_1.ansiFormatter : ansi_1.voidFormatter,
|
|
271
269
|
stdout: msg => out('stdout', msg),
|
|
272
270
|
stderr: msg => out('stderr', msg)
|
|
273
|
-
}, request.expression, this.
|
|
271
|
+
}, request.expression, this.parser, this.allowRSessionAccess).then(() => {
|
|
274
272
|
(0, send_1.sendMessage)(this.socket, {
|
|
275
273
|
type: 'end-repl-execution',
|
|
276
274
|
id: request.id
|
|
@@ -13,7 +13,8 @@ exports.helloMessageDefinition = {
|
|
|
13
13
|
clientName: joi_1.default.string().required().description('A unique name that is assigned to each client. It has no semantic meaning and is only used/useful for debugging.'),
|
|
14
14
|
versions: joi_1.default.object({
|
|
15
15
|
flowr: joi_1.default.string().required().description('The version of the flowr server running in semver format.'),
|
|
16
|
-
r: joi_1.default.string().required().description('The version of the underlying R shell running in semver format.')
|
|
16
|
+
r: joi_1.default.string().required().description('The version of the underlying R shell running in semver format.'),
|
|
17
|
+
engine: joi_1.default.string().required().description('The parser backend that is used to parse the R code.')
|
|
17
18
|
}).required()
|
|
18
19
|
}).required()
|
|
19
20
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Server } from './net';
|
|
2
2
|
import { FlowrLogger } from '../../../util/log';
|
|
3
|
-
import type {
|
|
3
|
+
import type { 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}.
|
|
@@ -9,13 +9,14 @@ export declare const serverLog: FlowrLogger;
|
|
|
9
9
|
*/
|
|
10
10
|
export declare class FlowRServer {
|
|
11
11
|
private readonly server;
|
|
12
|
-
private readonly
|
|
12
|
+
private readonly engines;
|
|
13
|
+
private readonly defaultEngine;
|
|
13
14
|
private versionInformation;
|
|
14
15
|
private readonly allowRSessionAccess;
|
|
15
16
|
/** maps names to the respective connection */
|
|
16
17
|
private readonly connections;
|
|
17
18
|
private nameCounter;
|
|
18
|
-
constructor(
|
|
19
|
+
constructor(engines: KnownEngines, defaultEngine: keyof KnownEngines, allowRSessionAccess: boolean, server?: Server);
|
|
19
20
|
start(port: number): Promise<void>;
|
|
20
21
|
private onConnect;
|
|
21
22
|
}
|
|
@@ -15,20 +15,22 @@ exports.serverLog = new log_1.FlowrLogger({ name: 'server' });
|
|
|
15
15
|
*/
|
|
16
16
|
class FlowRServer {
|
|
17
17
|
server;
|
|
18
|
-
|
|
18
|
+
engines;
|
|
19
|
+
defaultEngine;
|
|
19
20
|
versionInformation;
|
|
20
21
|
allowRSessionAccess;
|
|
21
22
|
/** maps names to the respective connection */
|
|
22
23
|
connections = new Map();
|
|
23
24
|
nameCounter = 0;
|
|
24
|
-
constructor(
|
|
25
|
+
constructor(engines, defaultEngine, allowRSessionAccess, server = new net_1.NetServer()) {
|
|
25
26
|
this.server = server;
|
|
26
27
|
this.server.onConnect(c => this.onConnect(c));
|
|
27
|
-
this.
|
|
28
|
+
this.engines = engines;
|
|
29
|
+
this.defaultEngine = defaultEngine;
|
|
28
30
|
this.allowRSessionAccess = allowRSessionAccess;
|
|
29
31
|
}
|
|
30
32
|
async start(port) {
|
|
31
|
-
this.versionInformation = await (0, repl_version_1.retrieveVersionInformation)(this.
|
|
33
|
+
this.versionInformation = await (0, repl_version_1.retrieveVersionInformation)(this.engines[this.defaultEngine]);
|
|
32
34
|
this.server.start(port);
|
|
33
35
|
exports.serverLog.info(`Server listening on port ${port}`);
|
|
34
36
|
}
|
|
@@ -39,7 +41,7 @@ class FlowRServer {
|
|
|
39
41
|
}
|
|
40
42
|
const name = `client-${this.nameCounter++}`;
|
|
41
43
|
exports.serverLog.info(`Client connected: ${(0, send_1.getUnnamedSocketName)(c)} as "${name}"`);
|
|
42
|
-
this.connections.set(name, new connection_1.FlowRServerConnection(c, name, this.
|
|
44
|
+
this.connections.set(name, new connection_1.FlowRServerConnection(c, name, this.engines[this.defaultEngine], this.allowRSessionAccess));
|
|
43
45
|
helloClient(c, name, this.versionInformation);
|
|
44
46
|
c.on('close', () => {
|
|
45
47
|
this.connections.delete(name);
|
package/cli/slicer-app.js
CHANGED
|
@@ -25,7 +25,7 @@ const options = (0, script_1.processCommandLineArgs)('slicer', ['input', 'criter
|
|
|
25
25
|
]
|
|
26
26
|
});
|
|
27
27
|
async function getSlice() {
|
|
28
|
-
const slicer = new slicer_1.BenchmarkSlicer();
|
|
28
|
+
const slicer = new slicer_1.BenchmarkSlicer('r-shell');
|
|
29
29
|
(0, assert_1.guard)(options.input !== undefined, 'input must be given');
|
|
30
30
|
(0, assert_1.guard)(options.criterion !== undefined, 'a slicing criterion must be given');
|
|
31
31
|
await slicer.init(options['input-is-text']
|
package/config.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MergeableRecord } from './util/objects';
|
|
2
2
|
import Joi from 'joi';
|
|
3
3
|
import type { BuiltInDefinitions } from './dataflow/environments/built-in-config';
|
|
4
|
+
import type { KnownParser } from './r-bridge/parser';
|
|
4
5
|
export declare enum VariableResolve {
|
|
5
6
|
/** Don't resolve constants at all */
|
|
6
7
|
Disabled = "disabled",
|
|
@@ -14,10 +15,6 @@ export interface FlowrConfigOptions extends MergeableRecord {
|
|
|
14
15
|
* Whether source calls should be ignored, causing {@link processSourceCall}'s behavior to be skipped
|
|
15
16
|
*/
|
|
16
17
|
readonly ignoreSourceCalls: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* The path to the R executable to use. If this is undefined, {@link DEFAULT_R_PATH} will be used.
|
|
19
|
-
*/
|
|
20
|
-
readonly rPath: string | undefined;
|
|
21
18
|
/** Configure language semantics and how flowR handles them */
|
|
22
19
|
readonly semantics: {
|
|
23
20
|
/** Semantics regarding the handlings of the environment */
|
|
@@ -31,6 +28,15 @@ export interface FlowrConfigOptions extends MergeableRecord {
|
|
|
31
28
|
};
|
|
32
29
|
};
|
|
33
30
|
};
|
|
31
|
+
/**
|
|
32
|
+
* The engines to use for interacting with R code. Currently supports {@link TreeSitterEngineConfig} and {@link RShellEngineConfig}.
|
|
33
|
+
* An empty array means all available engines will be used.
|
|
34
|
+
*/
|
|
35
|
+
readonly engines: readonly EngineConfig[];
|
|
36
|
+
/**
|
|
37
|
+
* The default engine to use for interacting with R code. If this is undefined, an arbitrary engine from {@link engines} will be used.
|
|
38
|
+
*/
|
|
39
|
+
readonly defaultEngine?: EngineConfig['type'];
|
|
34
40
|
/** How to resolve constants, constraints, cells, ... */
|
|
35
41
|
readonly solver: {
|
|
36
42
|
/**
|
|
@@ -45,9 +51,35 @@ export interface FlowrConfigOptions extends MergeableRecord {
|
|
|
45
51
|
readonly pointerTracking: boolean;
|
|
46
52
|
};
|
|
47
53
|
}
|
|
54
|
+
export interface TreeSitterEngineConfig extends MergeableRecord {
|
|
55
|
+
readonly type: 'tree-sitter';
|
|
56
|
+
/**
|
|
57
|
+
* The path to the tree-sitter-r WASM binary to use. If this is undefined, {@link DEFAULT_TREE_SITTER_R_WASM_PATH} will be used.
|
|
58
|
+
*/
|
|
59
|
+
readonly wasmPath?: string;
|
|
60
|
+
/**
|
|
61
|
+
* The path to the tree-sitter WASM binary to use. If this is undefined, the path specified by the tree-sitter package will be used.
|
|
62
|
+
*/
|
|
63
|
+
readonly treeSitterWasmPath?: string;
|
|
64
|
+
}
|
|
65
|
+
export interface RShellEngineConfig extends MergeableRecord {
|
|
66
|
+
readonly type: 'r-shell';
|
|
67
|
+
/**
|
|
68
|
+
* The path to the R executable to use. If this is undefined, {@link DEFAULT_R_PATH} will be used.
|
|
69
|
+
*/
|
|
70
|
+
readonly rPath?: string;
|
|
71
|
+
}
|
|
72
|
+
export type EngineConfig = TreeSitterEngineConfig | RShellEngineConfig;
|
|
73
|
+
export type KnownEngines = {
|
|
74
|
+
[T in EngineConfig['type']]?: KnownParser;
|
|
75
|
+
};
|
|
48
76
|
export declare const defaultConfigOptions: FlowrConfigOptions;
|
|
49
77
|
export declare const flowrConfigFileSchema: Joi.ObjectSchema<any>;
|
|
50
78
|
export declare function setConfigFile(file: string | undefined, workingDirectory?: string, forceLoad?: boolean): void;
|
|
51
79
|
export declare function parseConfig(jsonString: string): FlowrConfigOptions | undefined;
|
|
52
80
|
export declare function setConfig(config: FlowrConfigOptions): void;
|
|
81
|
+
export declare function amendConfig(amendment: Partial<FlowrConfigOptions>): void;
|
|
53
82
|
export declare function getConfig(): FlowrConfigOptions;
|
|
83
|
+
export declare function getEngineConfig<T extends EngineConfig['type']>(engine: T): EngineConfig & {
|
|
84
|
+
type: T;
|
|
85
|
+
} | undefined;
|
package/config.js
CHANGED
|
@@ -7,7 +7,9 @@ exports.flowrConfigFileSchema = exports.defaultConfigOptions = exports.VariableR
|
|
|
7
7
|
exports.setConfigFile = setConfigFile;
|
|
8
8
|
exports.parseConfig = parseConfig;
|
|
9
9
|
exports.setConfig = setConfig;
|
|
10
|
+
exports.amendConfig = amendConfig;
|
|
10
11
|
exports.getConfig = getConfig;
|
|
12
|
+
exports.getEngineConfig = getEngineConfig;
|
|
11
13
|
const objects_1 = require("./util/objects");
|
|
12
14
|
const path_1 = __importDefault(require("path"));
|
|
13
15
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -23,6 +25,10 @@ var VariableResolve;
|
|
|
23
25
|
/** Only resolve directly assigned builtin constants */
|
|
24
26
|
VariableResolve["Builtin"] = "builtin";
|
|
25
27
|
})(VariableResolve || (exports.VariableResolve = VariableResolve = {}));
|
|
28
|
+
const defaultEngineConfigs = {
|
|
29
|
+
'tree-sitter': { type: 'tree-sitter' },
|
|
30
|
+
'r-shell': { type: 'r-shell' }
|
|
31
|
+
};
|
|
26
32
|
exports.defaultConfigOptions = {
|
|
27
33
|
ignoreSourceCalls: false,
|
|
28
34
|
rPath: undefined,
|
|
@@ -34,6 +40,8 @@ exports.defaultConfigOptions = {
|
|
|
34
40
|
}
|
|
35
41
|
}
|
|
36
42
|
},
|
|
43
|
+
engines: [],
|
|
44
|
+
defaultEngine: 'r-shell',
|
|
37
45
|
solver: {
|
|
38
46
|
variables: VariableResolve.Alias,
|
|
39
47
|
pointerTracking: true
|
|
@@ -41,7 +49,6 @@ exports.defaultConfigOptions = {
|
|
|
41
49
|
};
|
|
42
50
|
exports.flowrConfigFileSchema = joi_1.default.object({
|
|
43
51
|
ignoreSourceCalls: joi_1.default.boolean().optional().description('Whether source calls should be ignored, causing {@link processSourceCall}\'s behavior to be skipped.'),
|
|
44
|
-
rPath: joi_1.default.string().optional().description('The path to the R executable to use. If this is undefined, this uses the default path.'),
|
|
45
52
|
semantics: joi_1.default.object({
|
|
46
53
|
environment: joi_1.default.object({
|
|
47
54
|
overwriteBuiltIns: joi_1.default.object({
|
|
@@ -50,6 +57,15 @@ exports.flowrConfigFileSchema = joi_1.default.object({
|
|
|
50
57
|
}).optional().description('Do you want to overwrite (parts) of the builtin definition?')
|
|
51
58
|
}).optional().description('Semantics regarding the handlings of the environment.')
|
|
52
59
|
}).description('Configure language semantics and how flowR handles them.'),
|
|
60
|
+
engines: joi_1.default.array().items(joi_1.default.alternatives(joi_1.default.object({
|
|
61
|
+
type: joi_1.default.string().required().valid('tree-sitter').description('Use the tree sitter engine.'),
|
|
62
|
+
wasmPath: joi_1.default.string().optional().description('The path to the tree-sitter-r WASM binary to use. If this is undefined, this uses the default path.'),
|
|
63
|
+
treeSitterWasmPath: joi_1.default.string().optional().description('The path to the tree-sitter WASM binary to use. If this is undefined, this uses the default path.')
|
|
64
|
+
}).description('The configuration for the tree sitter engine.'), joi_1.default.object({
|
|
65
|
+
type: joi_1.default.string().required().valid('r-shell').description('Use the R shell engine.'),
|
|
66
|
+
rPath: joi_1.default.string().optional().description('The path to the R executable to use. If this is undefined, this uses the default path.')
|
|
67
|
+
}).description('The configuration for the R shell engine.'))).min(1).description('The engine or set of engines to use for interacting with R code. An empty array means all available engines will be used.'),
|
|
68
|
+
defaultEngine: joi_1.default.string().optional().valid('tree-sitter', 'r-shell').description('The default engine to use for interacting with R code. If this is undefined, an arbitrary engine from the specified list will be used.'),
|
|
53
69
|
solver: joi_1.default.object({
|
|
54
70
|
variables: joi_1.default.string().valid(...Object.values(VariableResolve)).description('How to resolve variables and their values.'),
|
|
55
71
|
pointerTracking: joi_1.default.boolean().description('Whether to track pointers in the dataflow graph, if not, the graph will be over-approximated wrt. containers and accesses.')
|
|
@@ -88,6 +104,10 @@ function parseConfig(jsonString) {
|
|
|
88
104
|
function setConfig(config) {
|
|
89
105
|
currentConfig = config;
|
|
90
106
|
}
|
|
107
|
+
function amendConfig(amendment) {
|
|
108
|
+
setConfig((0, objects_1.deepMergeObject)(getConfig(), amendment));
|
|
109
|
+
log_1.log.trace(`Amending config with ${JSON.stringify(amendment)}, resulting in ${JSON.stringify(getConfig())}}`);
|
|
110
|
+
}
|
|
91
111
|
function getConfig() {
|
|
92
112
|
// lazy-load the config based on the current settings
|
|
93
113
|
if (currentConfig === undefined) {
|
|
@@ -95,6 +115,15 @@ function getConfig() {
|
|
|
95
115
|
}
|
|
96
116
|
return currentConfig;
|
|
97
117
|
}
|
|
118
|
+
function getEngineConfig(engine) {
|
|
119
|
+
const config = getConfig().engines;
|
|
120
|
+
if (!config.length) {
|
|
121
|
+
return defaultEngineConfigs[engine];
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
return config.find(e => e.type == engine);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
98
127
|
function loadConfigFromFile(configFile, workingDirectory) {
|
|
99
128
|
if (configFile !== undefined) {
|
|
100
129
|
let searchPath = path_1.default.resolve(workingDirectory);
|
|
@@ -61,7 +61,7 @@ import type { Pipeline, PipelineInput, PipelineOutput, PipelinePerRequestInput,
|
|
|
61
61
|
*
|
|
62
62
|
* ```ts
|
|
63
63
|
* const slicer = new PipelineExecutor(DEFAULT_SLICING_PIPELINE, {
|
|
64
|
-
*
|
|
64
|
+
* parser: new RShell(),
|
|
65
65
|
* // of course, the criterion and request given here are just examples, you can use whatever you want to slice!
|
|
66
66
|
* criterion: ['2@b'],
|
|
67
67
|
* request: requestFromInput('b <- 3; x <- 5\ncat(b)'),
|
|
@@ -65,7 +65,7 @@ const built_in_config_1 = require("../dataflow/environments/built-in-config");
|
|
|
65
65
|
*
|
|
66
66
|
* ```ts
|
|
67
67
|
* const slicer = new PipelineExecutor(DEFAULT_SLICING_PIPELINE, {
|
|
68
|
-
*
|
|
68
|
+
* parser: new RShell(),
|
|
69
69
|
* // of course, the criterion and request given here are just examples, you can use whatever you want to slice!
|
|
70
70
|
* criterion: ['2@b'],
|
|
71
71
|
* request: requestFromInput('b <- 3; x <- 5\ncat(b)'),
|
|
@@ -1,25 +1,12 @@
|
|
|
1
1
|
import { internalPrinter } from '../../../print/print';
|
|
2
2
|
import { PipelineStepStage } from '../../pipeline-step';
|
|
3
|
-
import type { RShellExecutor } from '../../../../r-bridge/shell-executor';
|
|
4
|
-
import type { RShell } from '../../../../r-bridge/shell';
|
|
5
|
-
import type { RParseRequests } from '../../../../r-bridge/retriever';
|
|
6
3
|
import type { QuadSerializationConfiguration } from '../../../../util/quads';
|
|
7
|
-
|
|
8
|
-
/** This is the {@link RShell} or {@link RShellExecutor} connection to be used to obtain the original parses AST of the R code */
|
|
9
|
-
readonly shell: RShell | RShellExecutor;
|
|
10
|
-
/** The request which essentially indicates the input to extract the AST from */
|
|
11
|
-
readonly request: RParseRequests;
|
|
12
|
-
}
|
|
13
|
-
export interface ParseStepOutput {
|
|
14
|
-
/** The parsed AST of the R code as given by the R parse side */
|
|
15
|
-
readonly parsed: string;
|
|
16
|
-
}
|
|
17
|
-
declare function processor(_results: unknown, input: Partial<ParseRequiredInput>): Promise<ParseStepOutput>;
|
|
4
|
+
import type { ParseRequiredInput } from '../../../../r-bridge/parser';
|
|
18
5
|
export declare const PARSE_WITH_R_SHELL_STEP: {
|
|
19
6
|
readonly name: "parse";
|
|
20
7
|
readonly humanReadableName: "parse with R shell";
|
|
21
8
|
readonly description: "Parse the given R code into an AST";
|
|
22
|
-
readonly processor:
|
|
9
|
+
readonly processor: (_results: unknown, input: Partial<ParseRequiredInput<string>>) => Promise<import("../../../../r-bridge/parser").ParseStepOutput<string>>;
|
|
23
10
|
readonly executed: PipelineStepStage.OncePerFile;
|
|
24
11
|
readonly printer: {
|
|
25
12
|
readonly 0: typeof internalPrinter;
|
|
@@ -27,9 +14,8 @@ export declare const PARSE_WITH_R_SHELL_STEP: {
|
|
|
27
14
|
(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
28
15
|
(value: any, replacer?: (number | string)[] | null, space?: string | number): string;
|
|
29
16
|
};
|
|
30
|
-
readonly 5: ({ parsed }: ParseStepOutput
|
|
17
|
+
readonly 5: ({ parsed }: import("../../../../r-bridge/parser").ParseStepOutput<string>, config: QuadSerializationConfiguration) => string;
|
|
31
18
|
};
|
|
32
19
|
readonly dependencies: readonly [];
|
|
33
|
-
readonly requiredInput: ParseRequiredInput
|
|
20
|
+
readonly requiredInput: ParseRequiredInput<string>;
|
|
34
21
|
};
|
|
35
|
-
export {};
|
|
@@ -3,21 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PARSE_WITH_R_SHELL_STEP = void 0;
|
|
4
4
|
const print_1 = require("../../../print/print");
|
|
5
5
|
const parse_printer_1 = require("../../../print/parse-printer");
|
|
6
|
-
const
|
|
7
|
-
async function processor(_results, input) {
|
|
8
|
-
/* in the future, we want to expose all cases */
|
|
9
|
-
if (Array.isArray(input.request)) {
|
|
10
|
-
return { parsed: await (0, retriever_1.retrieveParseDataFromRCode)(input.request[0], input.shell) };
|
|
11
|
-
}
|
|
12
|
-
else {
|
|
13
|
-
return { parsed: await (0, retriever_1.retrieveParseDataFromRCode)(input.request, input.shell) };
|
|
14
|
-
}
|
|
15
|
-
}
|
|
6
|
+
const parser_1 = require("../../../../r-bridge/parser");
|
|
16
7
|
exports.PARSE_WITH_R_SHELL_STEP = {
|
|
17
8
|
name: 'parse',
|
|
18
9
|
humanReadableName: 'parse with R shell',
|
|
19
10
|
description: 'Parse the given R code into an AST',
|
|
20
|
-
processor,
|
|
11
|
+
processor: (parser_1.parseRequests),
|
|
21
12
|
executed: 0 /* PipelineStepStage.OncePerFile */,
|
|
22
13
|
printer: {
|
|
23
14
|
[0 /* StepOutputFormat.Internal */]: print_1.internalPrinter,
|