@eagleoutice/flowr 2.10.4 → 2.10.5
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 +37 -20
- package/abstract-interpretation/absint-visitor.d.ts +17 -21
- package/abstract-interpretation/absint-visitor.js +47 -48
- package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -3
- package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -1
- package/abstract-interpretation/data-frame/shape-inference.js +5 -4
- package/abstract-interpretation/domains/abstract-domain.d.ts +17 -16
- package/abstract-interpretation/domains/abstract-domain.js +25 -27
- package/abstract-interpretation/domains/bounded-set-domain.js +1 -1
- package/abstract-interpretation/domains/multi-value-state-domain.d.ts +32 -0
- package/abstract-interpretation/domains/multi-value-state-domain.js +60 -0
- package/abstract-interpretation/domains/partial-product-domain.d.ts +43 -0
- package/abstract-interpretation/domains/partial-product-domain.js +163 -0
- package/abstract-interpretation/domains/product-domain.d.ts +2 -29
- package/abstract-interpretation/domains/product-domain.js +6 -123
- package/abstract-interpretation/domains/set-range-domain.js +3 -3
- package/abstract-interpretation/domains/set-upper-bound-domain.js +1 -1
- package/abstract-interpretation/domains/singleton-domain.js +1 -1
- package/abstract-interpretation/domains/state-abstract-domain.d.ts +13 -28
- package/abstract-interpretation/domains/state-abstract-domain.js +16 -38
- package/abstract-interpretation/domains/state-domain-like.d.ts +36 -0
- package/abstract-interpretation/domains/state-domain-like.js +3 -0
- package/cli/flowr.js +11 -1
- package/config.d.ts +7 -0
- package/config.js +22 -3
- package/control-flow/semantic-cfg-guided-visitor.d.ts +4 -0
- package/control-flow/semantic-cfg-guided-visitor.js +20 -32
- package/dataflow/environments/default-builtin-config.d.ts +10 -0
- package/dataflow/environments/default-builtin-config.js +2 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +2 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +38 -21
- package/documentation/doc-readme.js +13 -2
- package/documentation/wiki-absint.d.ts +1 -2
- package/documentation/wiki-absint.js +34 -10
- package/documentation/wiki-analyzer.js +3 -4
- package/documentation/wiki-interface.js +21 -16
- package/linter/linter-rules.d.ts +2 -2
- package/linter/rules/problematic-inputs.d.ts +4 -3
- package/linter/rules/problematic-inputs.js +3 -4
- package/package.json +3 -3
- package/project/flowr-analyzer-builder.d.ts +6 -3
- package/project/flowr-analyzer-builder.js +12 -5
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.d.ts +4 -3
- package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +17 -4
- package/project/plugins/flowr-analyzer-plugin.d.ts +1 -1
- package/project/plugins/flowr-analyzer-plugin.js +1 -1
- package/queries/catalog/input-sources-query/input-source-functions.d.ts +6 -0
- package/queries/catalog/input-sources-query/input-source-functions.js +50 -0
- package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +1 -1
- package/queries/catalog/input-sources-query/input-sources-query-executor.js +19 -53
- package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +2 -1
- package/queries/catalog/input-sources-query/input-sources-query-format.js +26 -11
- package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +18 -41
- package/queries/catalog/input-sources-query/simple-input-classifier.js +165 -103
- package/r-bridge/lang-4.x/ast/model/model.d.ts +4 -4
- package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +3 -3
- package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +3 -3
- package/util/record.d.ts +18 -3
- package/util/record.js +22 -1
- package/util/version.js +1 -1
- package/project/plugins/flowr-analyzer-plugin-defaults.d.ts +0 -5
- package/project/plugins/flowr-analyzer-plugin-defaults.js +0 -37
|
@@ -1,32 +1,33 @@
|
|
|
1
1
|
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
2
|
import { AbstractDomain, type AnyAbstractDomain, type ConcreteDomain } from './abstract-domain';
|
|
3
3
|
import { Bottom, Top } from './lattice';
|
|
4
|
+
import type { StateDomainLike } from './state-domain-like';
|
|
4
5
|
/** The type of the concrete state of the concrete domain of a state abstract domain that maps keys to a concrete value in the concrete domain */
|
|
5
6
|
export type ConcreteState<Domain extends AnyAbstractDomain> = ReadonlyMap<NodeId, ConcreteDomain<Domain>>;
|
|
6
7
|
/** The type of the actual values of the state abstract domain as map of keys to domain values */
|
|
7
|
-
type StateDomainValue<Domain extends AnyAbstractDomain> = ReadonlyMap<NodeId, Domain>;
|
|
8
|
+
export type StateDomainValue<Domain extends AnyAbstractDomain> = ReadonlyMap<NodeId, Domain>;
|
|
8
9
|
/** The type of the Top element of the state abstract domain as (empty) map of keys to domain values */
|
|
9
|
-
type StateDomainTop = ReadonlyMap<NodeId, never>;
|
|
10
|
+
export type StateDomainTop = ReadonlyMap<NodeId, never>;
|
|
10
11
|
/** The type of the Bottom element of the state abstract domain as {@link Bottom} symbol */
|
|
11
|
-
type StateDomainBottom = typeof Bottom;
|
|
12
|
+
export type StateDomainBottom = typeof Bottom;
|
|
12
13
|
/** The type of the abstract values of the state abstract domain that are Top, Bottom, or actual values */
|
|
13
|
-
type StateDomainLift<Domain extends AnyAbstractDomain> = StateDomainValue<Domain> | StateDomainBottom;
|
|
14
|
+
export type StateDomainLift<Domain extends AnyAbstractDomain> = StateDomainValue<Domain> | StateDomainBottom;
|
|
14
15
|
/**
|
|
15
16
|
* A state abstract domain that maps AST node IDs of a program to abstract values of an abstract domain.
|
|
16
17
|
* The Bottom element is defined as {@link Bottom} symbol and the Top element as empty mapping.
|
|
17
18
|
* @template Domain - Type of the value abstract domain to map the AST node IDs to
|
|
18
19
|
* @see {@link NodeId} for the node IDs of the AST nodes
|
|
19
20
|
*/
|
|
20
|
-
export declare class StateAbstractDomain<Domain extends AnyAbstractDomain, Value extends StateDomainLift<Domain> = StateDomainLift<Domain>> extends AbstractDomain<ConcreteState<Domain>, StateDomainValue<Domain>, StateDomainTop, StateDomainBottom, Value> {
|
|
21
|
-
|
|
21
|
+
export declare class StateAbstractDomain<Domain extends AnyAbstractDomain, Value extends StateDomainLift<Domain> = StateDomainLift<Domain>> extends AbstractDomain<ConcreteState<Domain>, StateDomainValue<Domain>, StateDomainTop, StateDomainBottom, Value> implements StateDomainLike<Domain> {
|
|
22
|
+
readonly domain: Domain;
|
|
22
23
|
constructor(value: Value, domain: Domain);
|
|
23
24
|
create(value: StateDomainLift<Domain>): this;
|
|
24
|
-
static top<Domain extends AnyAbstractDomain
|
|
25
|
-
static bottom<Domain extends AnyAbstractDomain
|
|
26
|
-
get(
|
|
27
|
-
has(
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
static top<Domain extends AnyAbstractDomain, StateDomain extends StateAbstractDomain<Domain, StateDomainTop>>(this: new (value: StateDomainTop, domain: Domain) => StateDomain, domain: Domain): StateDomain;
|
|
26
|
+
static bottom<Domain extends AnyAbstractDomain, StateDomain extends StateAbstractDomain<Domain, StateDomainBottom>>(this: new (value: StateDomainBottom, domain: Domain) => StateDomain, domain: Domain): StateDomain;
|
|
27
|
+
get(node: NodeId): Domain | undefined;
|
|
28
|
+
has(node: NodeId): boolean;
|
|
29
|
+
set(node: NodeId, value: Domain): void;
|
|
30
|
+
remove(node: NodeId): void;
|
|
30
31
|
top(): this & StateAbstractDomain<Domain, StateDomainTop>;
|
|
31
32
|
bottom(): this & StateAbstractDomain<Domain, StateDomainBottom>;
|
|
32
33
|
equals(other: this): boolean;
|
|
@@ -43,19 +44,3 @@ export declare class StateAbstractDomain<Domain extends AnyAbstractDomain, Value
|
|
|
43
44
|
isBottom(): this is this & StateAbstractDomain<Domain, StateDomainBottom>;
|
|
44
45
|
isValue(): this is this & StateAbstractDomain<Domain, StateDomainValue<Domain>>;
|
|
45
46
|
}
|
|
46
|
-
/**
|
|
47
|
-
* A mutable version of the {@link StateAbstractDomain} with {@link MutableStateAbstractDomain#set|`set`} and {@link MutableStateAbstractDomain#remove|`remove`}.
|
|
48
|
-
*/
|
|
49
|
-
export declare class MutableStateAbstractDomain<Domain extends AnyAbstractDomain, Value extends StateDomainLift<Domain> = StateDomainLift<Domain>> extends StateAbstractDomain<Domain, Value> {
|
|
50
|
-
create(value: StateDomainLift<Domain>): this;
|
|
51
|
-
static top<Domain extends AnyAbstractDomain>(domain: Domain): MutableStateAbstractDomain<Domain, StateDomainTop>;
|
|
52
|
-
static bottom<Domain extends AnyAbstractDomain>(domain: Domain): MutableStateAbstractDomain<Domain, StateDomainBottom>;
|
|
53
|
-
set(key: NodeId, value: Domain): void;
|
|
54
|
-
remove(key: NodeId): void;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* The type of the value abstract domain of a state abstract domain (i.e. the abstract domain a state abstract domain maps to).
|
|
58
|
-
* @template StateDomain - The state abstract domain to get the value abstract domain type for
|
|
59
|
-
*/
|
|
60
|
-
export type ValueAbstractDomain<StateDomain extends StateAbstractDomain<AnyAbstractDomain>> = StateDomain extends StateAbstractDomain<infer Domain> ? Domain : never;
|
|
61
|
-
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.StateAbstractDomain = void 0;
|
|
4
4
|
const abstract_domain_1 = require("./abstract-domain");
|
|
5
5
|
const lattice_1 = require("./lattice");
|
|
6
6
|
/**
|
|
@@ -24,33 +24,32 @@ class StateAbstractDomain extends abstract_domain_1.AbstractDomain {
|
|
|
24
24
|
return new StateAbstractDomain(value, this.domain);
|
|
25
25
|
}
|
|
26
26
|
static top(domain) {
|
|
27
|
-
return new
|
|
27
|
+
return new this(new Map(), domain);
|
|
28
28
|
}
|
|
29
29
|
static bottom(domain) {
|
|
30
|
-
return new
|
|
30
|
+
return new this(lattice_1.Bottom, domain);
|
|
31
31
|
}
|
|
32
|
-
get(
|
|
33
|
-
return this.value === lattice_1.Bottom ? this.domain.bottom() : this.value.get(
|
|
32
|
+
get(node) {
|
|
33
|
+
return this.value === lattice_1.Bottom ? this.domain.bottom() : this.value.get(node);
|
|
34
34
|
}
|
|
35
|
-
has(
|
|
36
|
-
return this.value !== lattice_1.Bottom && this.value.has(
|
|
35
|
+
has(node) {
|
|
36
|
+
return this.value !== lattice_1.Bottom && this.value.has(node);
|
|
37
37
|
}
|
|
38
|
-
set(
|
|
39
|
-
if (this.value
|
|
40
|
-
this._value
|
|
38
|
+
set(node, value) {
|
|
39
|
+
if (this.value !== lattice_1.Bottom) {
|
|
40
|
+
this._value.set(node, value);
|
|
41
41
|
}
|
|
42
|
-
this._value.set(key, value);
|
|
43
42
|
}
|
|
44
|
-
remove(
|
|
43
|
+
remove(node) {
|
|
45
44
|
if (this.value !== lattice_1.Bottom) {
|
|
46
|
-
this._value.delete(
|
|
45
|
+
this._value.delete(node);
|
|
47
46
|
}
|
|
48
47
|
}
|
|
49
48
|
top() {
|
|
50
|
-
return
|
|
49
|
+
return this.create(new Map());
|
|
51
50
|
}
|
|
52
51
|
bottom() {
|
|
53
|
-
return
|
|
52
|
+
return this.create(lattice_1.Bottom);
|
|
54
53
|
}
|
|
55
54
|
equals(other) {
|
|
56
55
|
if (this.value === other.value) {
|
|
@@ -216,38 +215,17 @@ class StateAbstractDomain extends abstract_domain_1.AbstractDomain {
|
|
|
216
215
|
if (this.value === lattice_1.Bottom) {
|
|
217
216
|
return lattice_1.BottomSymbol;
|
|
218
217
|
}
|
|
219
|
-
return '(' + this.value.entries().toArray().map(([key, value]) => `${
|
|
218
|
+
return '(' + this.value.entries().toArray().map(([key, value]) => `${abstract_domain_1.AbstractDomain.toString(key)} -> ${value.toString()}`).join(', ') + ')';
|
|
220
219
|
}
|
|
221
220
|
isTop() {
|
|
222
221
|
return this.value !== lattice_1.Bottom && this.value.size === 0;
|
|
223
222
|
}
|
|
224
223
|
isBottom() {
|
|
225
|
-
return this.value
|
|
224
|
+
return this.value === lattice_1.Bottom;
|
|
226
225
|
}
|
|
227
226
|
isValue() {
|
|
228
227
|
return this.value !== lattice_1.Bottom;
|
|
229
228
|
}
|
|
230
229
|
}
|
|
231
230
|
exports.StateAbstractDomain = StateAbstractDomain;
|
|
232
|
-
/**
|
|
233
|
-
* A mutable version of the {@link StateAbstractDomain} with {@link MutableStateAbstractDomain#set|`set`} and {@link MutableStateAbstractDomain#remove|`remove`}.
|
|
234
|
-
*/
|
|
235
|
-
class MutableStateAbstractDomain extends StateAbstractDomain {
|
|
236
|
-
create(value) {
|
|
237
|
-
return new MutableStateAbstractDomain(value, this.domain);
|
|
238
|
-
}
|
|
239
|
-
static top(domain) {
|
|
240
|
-
return new MutableStateAbstractDomain(new Map(), domain);
|
|
241
|
-
}
|
|
242
|
-
static bottom(domain) {
|
|
243
|
-
return new MutableStateAbstractDomain(lattice_1.Bottom, domain);
|
|
244
|
-
}
|
|
245
|
-
set(key, value) {
|
|
246
|
-
super.set(key, value);
|
|
247
|
-
}
|
|
248
|
-
remove(key) {
|
|
249
|
-
super.remove(key);
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
exports.MutableStateAbstractDomain = MutableStateAbstractDomain;
|
|
253
231
|
//# sourceMappingURL=state-abstract-domain.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
2
|
+
import { type AnyAbstractDomain } from './abstract-domain';
|
|
3
|
+
/**
|
|
4
|
+
* An interface for state-like domains that store abstract values for AST nodes.
|
|
5
|
+
*/
|
|
6
|
+
export interface StateDomainLike<Domain extends AnyAbstractDomain> {
|
|
7
|
+
/**
|
|
8
|
+
* The underlying value domain of the state domain.
|
|
9
|
+
*/
|
|
10
|
+
get domain(): Domain;
|
|
11
|
+
/**
|
|
12
|
+
* Gets the inferred abstract value for an AST node ID.
|
|
13
|
+
*/
|
|
14
|
+
get(node: NodeId): Domain | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Checks whether the state domain has an inferred value for an AST node ID.
|
|
17
|
+
*/
|
|
18
|
+
has(node: NodeId): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Removes the inferred value for an AST node ID from the state domain.
|
|
21
|
+
*/
|
|
22
|
+
remove(node: NodeId): void;
|
|
23
|
+
/**
|
|
24
|
+
* Sets the inferred value for an AST node ID from the state domain.
|
|
25
|
+
*/
|
|
26
|
+
set(node: NodeId, value: Domain): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A type representing any state abstract domain that stores abstract values for AST nodes.
|
|
30
|
+
*/
|
|
31
|
+
export type AnyStateDomain<Domain extends AnyAbstractDomain> = AnyAbstractDomain & StateDomainLike<Domain>;
|
|
32
|
+
/**
|
|
33
|
+
* The type of the value abstract domain of a state abstract domain.
|
|
34
|
+
* @template StateDomain - The state abstract domain to get the value abstract domain type for
|
|
35
|
+
*/
|
|
36
|
+
export type ValueDomain<StateDomain extends AnyStateDomain<AnyAbstractDomain>> = StateDomain extends AnyStateDomain<infer Domain> ? Domain : never;
|
package/cli/flowr.js
CHANGED
|
@@ -102,6 +102,15 @@ function hookSignalHandlers(engines) {
|
|
|
102
102
|
process.on('SIGINT', end);
|
|
103
103
|
process.on('SIGTERM', end);
|
|
104
104
|
}
|
|
105
|
+
function getReplPlugins(config) {
|
|
106
|
+
const plugins = config.repl.plugins.filter(p => p !== 'flowr:default');
|
|
107
|
+
if (plugins.length !== config.repl.plugins.length) {
|
|
108
|
+
return plugins.concat(config.defaultPlugins);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
return plugins;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
105
114
|
async function mainRepl() {
|
|
106
115
|
const config = createConfig();
|
|
107
116
|
if (options.script) {
|
|
@@ -128,9 +137,10 @@ async function mainRepl() {
|
|
|
128
137
|
process.exit(0);
|
|
129
138
|
}
|
|
130
139
|
hookSignalHandlers(engines);
|
|
131
|
-
const analyzer = new flowr_analyzer_builder_1.FlowrAnalyzerBuilder()
|
|
140
|
+
const analyzer = new flowr_analyzer_builder_1.FlowrAnalyzerBuilder(false)
|
|
132
141
|
.setParser(defaultEngine)
|
|
133
142
|
.setConfig(config)
|
|
143
|
+
.registerPlugins(...getReplPlugins(config))
|
|
134
144
|
.buildSync();
|
|
135
145
|
const allowRSessionAccess = options['r-session-access'] ?? false;
|
|
136
146
|
if (options.execute) {
|
package/config.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { DeepWritable, Paths, PathValue } from 'ts-essentials';
|
|
|
6
6
|
import type { DataflowProcessors } from './dataflow/processor';
|
|
7
7
|
import type { ParentInformation } from './r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
8
8
|
import type { FlowrAnalyzerContext } from './project/context/flowr-analyzer-context';
|
|
9
|
+
import type { BuiltInFlowrPluginArgs, BuiltInFlowrPluginName } from './project/plugins/plugin-registry';
|
|
9
10
|
export declare enum VariableResolve {
|
|
10
11
|
/** Don't resolve constants at all */
|
|
11
12
|
Disabled = "disabled",
|
|
@@ -83,6 +84,7 @@ export interface FlowrLaxSourcingOptions extends MergeableRecord {
|
|
|
83
84
|
*/
|
|
84
85
|
readonly applyReplacements?: Record<string, string>[];
|
|
85
86
|
}
|
|
87
|
+
export type ConfigPlugin<T extends BuiltInFlowrPluginName | string> = T | string | (T extends BuiltInFlowrPluginName ? [T, BuiltInFlowrPluginArgs<T>] : [string, unknown[]]);
|
|
86
88
|
/**
|
|
87
89
|
* The configuration file format for flowR.
|
|
88
90
|
* @see {@link FlowrConfig.default} for the default configuration.
|
|
@@ -106,12 +108,16 @@ export interface FlowrConfig extends MergeableRecord {
|
|
|
106
108
|
};
|
|
107
109
|
};
|
|
108
110
|
};
|
|
111
|
+
/** Plugins to load by default when creating a new FlowrAnalyzer */
|
|
112
|
+
readonly defaultPlugins: ConfigPlugin<string>[];
|
|
109
113
|
/** Configuration options for the REPL */
|
|
110
114
|
readonly repl: {
|
|
111
115
|
/** Whether to show quick stats in the REPL after each evaluation */
|
|
112
116
|
quickStats: boolean;
|
|
113
117
|
/** This instruments the dataflow processors to count how often each processor is called */
|
|
114
118
|
dfProcessorHeat: boolean;
|
|
119
|
+
/** Plugins to load in REPL mode */
|
|
120
|
+
plugins: (ConfigPlugin<string> | 'flowr:default')[];
|
|
115
121
|
};
|
|
116
122
|
readonly project: {
|
|
117
123
|
/** Whether to resolve unknown paths loaded by the r project disk when trying to source/analyze files */
|
|
@@ -226,6 +232,7 @@ export type EngineConfig = TreeSitterEngineConfig | RShellEngineConfig;
|
|
|
226
232
|
export type KnownEngines = {
|
|
227
233
|
[T in EngineConfig['type']]?: KnownParser;
|
|
228
234
|
};
|
|
235
|
+
export declare const FlowrDefaultPlugins: string[];
|
|
229
236
|
/**
|
|
230
237
|
* Helper Object to work with {@link FlowrConfig}, provides the default config and the Joi schema for validation.
|
|
231
238
|
*/
|
package/config.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.FlowrConfig = exports.DropPathsOption = exports.InferWorkingDirectory = exports.VariableResolve = void 0;
|
|
6
|
+
exports.FlowrConfig = exports.FlowrDefaultPlugins = exports.DropPathsOption = exports.InferWorkingDirectory = exports.VariableResolve = void 0;
|
|
7
7
|
const objects_1 = require("./util/objects");
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -50,6 +50,21 @@ const defaultEngineConfigs = {
|
|
|
50
50
|
'tree-sitter': { type: 'tree-sitter' },
|
|
51
51
|
'r-shell': { type: 'r-shell' }
|
|
52
52
|
};
|
|
53
|
+
exports.FlowrDefaultPlugins = [
|
|
54
|
+
'file:description',
|
|
55
|
+
'versions:description',
|
|
56
|
+
'loading-order:description',
|
|
57
|
+
'meta:description',
|
|
58
|
+
'files:vignette',
|
|
59
|
+
'files:test',
|
|
60
|
+
'file:rmd',
|
|
61
|
+
'file:qmd',
|
|
62
|
+
'file:rnw',
|
|
63
|
+
'file:ipynb',
|
|
64
|
+
'file:namespace',
|
|
65
|
+
'file:news',
|
|
66
|
+
'file:license',
|
|
67
|
+
];
|
|
53
68
|
/**
|
|
54
69
|
* Helper Object to work with {@link FlowrConfig}, provides the default config and the Joi schema for validation.
|
|
55
70
|
*/
|
|
@@ -70,9 +85,11 @@ exports.FlowrConfig = {
|
|
|
70
85
|
}
|
|
71
86
|
}
|
|
72
87
|
},
|
|
88
|
+
defaultPlugins: exports.FlowrDefaultPlugins,
|
|
73
89
|
repl: {
|
|
74
90
|
quickStats: false,
|
|
75
|
-
dfProcessorHeat: false
|
|
91
|
+
dfProcessorHeat: false,
|
|
92
|
+
plugins: ['flowr:default'],
|
|
76
93
|
},
|
|
77
94
|
project: {
|
|
78
95
|
resolveUnknownPathsOnDisk: true
|
|
@@ -122,9 +139,11 @@ exports.FlowrConfig = {
|
|
|
122
139
|
}).optional().description('Do you want to overwrite (parts) of the builtin definition?')
|
|
123
140
|
}).optional().description('Semantics regarding how to handle the R environment.')
|
|
124
141
|
}).description('Configure language semantics and how flowR handles them.'),
|
|
142
|
+
defaultPlugins: joi_1.default.array().items(joi_1.default.alternatives().try(joi_1.default.string(), joi_1.default.array().ordered(joi_1.default.string(), joi_1.default.array().items(joi_1.default.any())).length(2))).optional().description('The default plugins to load when creating a new instance of FlowrAnalyzer'),
|
|
125
143
|
repl: joi_1.default.object({
|
|
126
144
|
quickStats: joi_1.default.boolean().optional().description('Whether to show quick stats in the REPL after each evaluation.'),
|
|
127
|
-
dfProcessorHeat: joi_1.default.boolean().optional().description('This instruments the dataflow processors to count how often each processor is called.')
|
|
145
|
+
dfProcessorHeat: joi_1.default.boolean().optional().description('This instruments the dataflow processors to count how often each processor is called.'),
|
|
146
|
+
plugins: joi_1.default.array().items(joi_1.default.alternatives().try(joi_1.default.string(), joi_1.default.array().ordered(joi_1.default.string(), joi_1.default.array().items(joi_1.default.any())).length(2))).optional().description('The plugins to load in REPL mode')
|
|
128
147
|
}).description('Configuration options for the REPL.'),
|
|
129
148
|
project: joi_1.default.object({
|
|
130
149
|
resolveUnknownPathsOnDisk: joi_1.default.boolean().optional().description('Whether to resolve unknown paths loaded by the r project disk when trying to source/analyze files.')
|
|
@@ -572,4 +572,8 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, ControlFlow ex
|
|
|
572
572
|
protected onPurrFormulaCall(_data: {
|
|
573
573
|
call: DataflowGraphVertexFunctionCall;
|
|
574
574
|
}): void;
|
|
575
|
+
protected getSourceAndTarget(call: DataflowGraphVertexFunctionCall): {
|
|
576
|
+
target: NodeId | undefined;
|
|
577
|
+
source: NodeId | undefined;
|
|
578
|
+
};
|
|
575
579
|
}
|
|
@@ -200,22 +200,8 @@ class SemanticCfgGuidedVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfg
|
|
|
200
200
|
return this.onVectorCall({ call });
|
|
201
201
|
case built_in_proc_name_1.BuiltInProcName.Assignment:
|
|
202
202
|
case built_in_proc_name_1.BuiltInProcName.AssignmentLike:
|
|
203
|
-
case built_in_proc_name_1.BuiltInProcName.TableAssignment:
|
|
204
|
-
|
|
205
|
-
if (outgoing) {
|
|
206
|
-
const target = outgoing.entries().filter(([, e]) => edge_1.DfEdge.includesType(e, edge_1.EdgeType.Returns)).toArray();
|
|
207
|
-
if (target.length === 1) {
|
|
208
|
-
const targetOut = this.config.dfg.outgoingEdges(target[0][0]);
|
|
209
|
-
if (targetOut) {
|
|
210
|
-
const source = targetOut.entries().filter(([t, e]) => edge_1.DfEdge.includesType(e, edge_1.EdgeType.DefinedBy) && t !== call.id).toArray();
|
|
211
|
-
if (source.length === 1) {
|
|
212
|
-
return this.onAssignmentCall({ call, target: target[0][0], source: source[0][0] });
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
return this.onAssignmentCall({ call, target: undefined, source: undefined });
|
|
218
|
-
}
|
|
203
|
+
case built_in_proc_name_1.BuiltInProcName.TableAssignment:
|
|
204
|
+
return this.onAssignmentCall({ call, ...this.getSourceAndTarget(call) });
|
|
219
205
|
case built_in_proc_name_1.BuiltInProcName.SpecialBinOp:
|
|
220
206
|
if (call.args.length !== 2) {
|
|
221
207
|
return this.onSpecialBinaryOpCall({ call });
|
|
@@ -234,22 +220,8 @@ class SemanticCfgGuidedVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfg
|
|
|
234
220
|
return this.onRepeatLoopCall({ call, body: call.args[0] });
|
|
235
221
|
case built_in_proc_name_1.BuiltInProcName.WhileLoop:
|
|
236
222
|
return this.onWhileLoopCall({ call, condition: call.args[0], body: call.args[1] });
|
|
237
|
-
case built_in_proc_name_1.BuiltInProcName.Replacement:
|
|
238
|
-
|
|
239
|
-
if (outgoing) {
|
|
240
|
-
const target = outgoing.entries().filter(([, e]) => edge_1.DfEdge.includesType(e, edge_1.EdgeType.Returns)).toArray();
|
|
241
|
-
if (target.length === 1) {
|
|
242
|
-
const targetOut = this.config.dfg.outgoingEdges(target[0][0]);
|
|
243
|
-
if (targetOut) {
|
|
244
|
-
const source = targetOut.entries().filter(([t, e]) => edge_1.DfEdge.includesType(e, edge_1.EdgeType.DefinedBy) && t !== call.id).toArray();
|
|
245
|
-
if (source.length === 1) {
|
|
246
|
-
return this.onReplacementCall({ call, target: target[0][0], source: source[0][0] });
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
return this.onReplacementCall({ call, target: undefined, source: undefined });
|
|
252
|
-
}
|
|
223
|
+
case built_in_proc_name_1.BuiltInProcName.Replacement:
|
|
224
|
+
return this.onReplacementCall({ call, ...this.getSourceAndTarget(call) });
|
|
253
225
|
case built_in_proc_name_1.BuiltInProcName.Library:
|
|
254
226
|
return this.onLibraryCall({ call });
|
|
255
227
|
case built_in_proc_name_1.BuiltInProcName.Try:
|
|
@@ -646,6 +618,22 @@ class SemanticCfgGuidedVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfg
|
|
|
646
618
|
* This event triggers for any purr formula as in `map(df, ~ .x + 1)`
|
|
647
619
|
*/
|
|
648
620
|
onPurrFormulaCall(_data) { }
|
|
621
|
+
getSourceAndTarget(call) {
|
|
622
|
+
const outgoing = this.config.dfg.outgoingEdges(call.id);
|
|
623
|
+
if (outgoing !== undefined) {
|
|
624
|
+
const target = outgoing.entries().filter(([, e]) => edge_1.DfEdge.includesType(e, edge_1.EdgeType.Returns)).toArray();
|
|
625
|
+
if (target.length === 1) {
|
|
626
|
+
const targetOut = this.config.dfg.outgoingEdges(target[0][0]);
|
|
627
|
+
if (targetOut !== undefined) {
|
|
628
|
+
const source = targetOut.entries().filter(([t, e]) => edge_1.DfEdge.includesType(e, edge_1.EdgeType.DefinedBy) && t !== call.id).toArray();
|
|
629
|
+
if (source.length === 1) {
|
|
630
|
+
return { target: target[0][0], source: source[0][0] };
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
return { target: undefined, source: undefined };
|
|
636
|
+
}
|
|
649
637
|
}
|
|
650
638
|
exports.SemanticCfgGuidedVisitor = SemanticCfgGuidedVisitor;
|
|
651
639
|
//# sourceMappingURL=semantic-cfg-guided-visitor.js.map
|
|
@@ -234,6 +234,16 @@ export declare const DefaultBuiltinConfig: [{
|
|
|
234
234
|
readonly processor: BuiltInProcName.Eval;
|
|
235
235
|
readonly config: {
|
|
236
236
|
readonly includeFunctionCall: true;
|
|
237
|
+
readonly supportFunctionCall: false;
|
|
238
|
+
};
|
|
239
|
+
readonly assumePrimitive: true;
|
|
240
|
+
}, {
|
|
241
|
+
readonly type: "function";
|
|
242
|
+
readonly names: ["evalText"];
|
|
243
|
+
readonly processor: BuiltInProcName.Eval;
|
|
244
|
+
readonly config: {
|
|
245
|
+
readonly includeFunctionCall: true;
|
|
246
|
+
readonly supportFunctionCall: true;
|
|
237
247
|
};
|
|
238
248
|
readonly assumePrimitive: true;
|
|
239
249
|
}, {
|
|
@@ -231,7 +231,8 @@ exports.DefaultBuiltinConfig = [
|
|
|
231
231
|
'.Fortran': ['.NAME']
|
|
232
232
|
}
|
|
233
233
|
}, assumePrimitive: true },
|
|
234
|
-
{ type: 'function', names: ['eval'], processor: built_in_proc_name_1.BuiltInProcName.Eval, config: { includeFunctionCall: true }, assumePrimitive: true },
|
|
234
|
+
{ type: 'function', names: ['eval'], processor: built_in_proc_name_1.BuiltInProcName.Eval, config: { includeFunctionCall: true, supportFunctionCall: false }, assumePrimitive: true },
|
|
235
|
+
{ type: 'function', names: ['evalText'], processor: built_in_proc_name_1.BuiltInProcName.Eval, config: { includeFunctionCall: true, supportFunctionCall: true }, assumePrimitive: true },
|
|
235
236
|
{ type: 'function', names: ['cat'], processor: built_in_proc_name_1.BuiltInProcName.Default, config: { forceArgs: 'all', hasUnknownSideEffects: { type: 'link-to-last-call', callName: /^sink$/ } }, assumePrimitive: false },
|
|
236
237
|
{ type: 'function', names: ['switch'], processor: built_in_proc_name_1.BuiltInProcName.Default, config: { forceArgs: [true] }, assumePrimitive: false },
|
|
237
238
|
{ type: 'function', names: ['return'], processor: built_in_proc_name_1.BuiltInProcName.Default, config: { returnsNthArgument: 0, cfg: 1 /* ExitPointType.Return */, useAsProcessor: built_in_proc_name_1.BuiltInProcName.Return }, assumePrimitive: true },
|
|
@@ -10,4 +10,6 @@ import type { NodeId } from '../../../../../../r-bridge/lang-4.x/ast/model/proce
|
|
|
10
10
|
export declare function processEvalCall<OtherInfo>(name: RSymbol<OtherInfo & ParentInformation>, args: readonly PotentiallyEmptyRArgument<OtherInfo & ParentInformation>[], rootId: NodeId, data: DataflowProcessorInformation<OtherInfo & ParentInformation>, config: {
|
|
11
11
|
/** should this produce an explicit source function call in the graph? */
|
|
12
12
|
includeFunctionCall?: boolean;
|
|
13
|
+
/** if selected processes evalText function call, else processes eval*/
|
|
14
|
+
supportFunctionCall?: boolean;
|
|
13
15
|
}): DataflowInformation;
|
|
@@ -40,7 +40,7 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
40
40
|
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
41
41
|
return information;
|
|
42
42
|
}
|
|
43
|
-
const code = resolveEvalToCode(evalArgument.value,
|
|
43
|
+
const code = resolveEvalToCode(evalArgument.value, config, data);
|
|
44
44
|
if (code) {
|
|
45
45
|
const idGenerator = (0, decorate_1.sourcedDeterministicCountingIdGenerator)(name.lexeme + '::' + rootId, name.location);
|
|
46
46
|
data = {
|
|
@@ -73,35 +73,52 @@ function processEvalCall(name, args, rootId, data, config) {
|
|
|
73
73
|
(0, unknown_side_effect_1.handleUnknownSideEffect)(information.graph, information.environment, rootId);
|
|
74
74
|
return information;
|
|
75
75
|
}
|
|
76
|
-
function resolveEvalToCode(evalArgument,
|
|
76
|
+
function resolveEvalToCode(evalArgument, config, data) {
|
|
77
|
+
const ctx = data.ctx;
|
|
78
|
+
const env = data.environment;
|
|
79
|
+
const idMap = data.completeAst.idMap;
|
|
77
80
|
const val = evalArgument;
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if (nArg !== undefined || arg === undefined || arg === r_function_call_1.EmptyArgument) {
|
|
82
|
-
return undefined;
|
|
83
|
-
}
|
|
84
|
-
if (arg.value?.type === type_1.RType.String) {
|
|
85
|
-
return [arg.value.content.str];
|
|
81
|
+
if (config.supportFunctionCall) {
|
|
82
|
+
if (val.type === type_1.RType.String) {
|
|
83
|
+
return [val.content.str];
|
|
86
84
|
}
|
|
87
|
-
else if (
|
|
88
|
-
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(
|
|
85
|
+
else if (val.type === type_1.RType.Symbol) {
|
|
86
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(val.info.id, { environment: env, idMap: idMap, resolve: ctx.config.solver.variables, ctx }));
|
|
89
87
|
if (resolved) {
|
|
90
88
|
return (0, string_constants_1.collectStrings)(resolved.elements);
|
|
91
89
|
}
|
|
92
90
|
}
|
|
93
|
-
else if (arg.value?.type === type_1.RType.FunctionCall && arg.value.named && ['paste', 'paste0'].includes(identifier_1.Identifier.getName(arg.value.functionName.content))) {
|
|
94
|
-
return handlePaste(ctx.config, arg.value.arguments, env, idMap, arg.value.functionName.content === 'paste' ? [' '] : [''], ctx);
|
|
95
|
-
}
|
|
96
|
-
return undefined;
|
|
97
|
-
}
|
|
98
|
-
else if (val.type === type_1.RType.Symbol) {
|
|
99
|
-
// const resolved = resolveValueOfVariable(val.content, env);
|
|
100
|
-
// see https://github.com/flowr-analysis/flowr/pull/1467
|
|
101
91
|
return undefined;
|
|
102
92
|
}
|
|
103
93
|
else {
|
|
104
|
-
|
|
94
|
+
if (val.type === type_1.RType.FunctionCall && val.named && val.functionName.content === 'parse') {
|
|
95
|
+
const arg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'text');
|
|
96
|
+
const nArg = val.arguments.find(v => v !== r_function_call_1.EmptyArgument && v.name?.content === 'n');
|
|
97
|
+
if (nArg !== undefined || arg === undefined || arg === r_function_call_1.EmptyArgument) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
if (arg.value?.type === type_1.RType.String) {
|
|
101
|
+
return [arg.value.content.str];
|
|
102
|
+
}
|
|
103
|
+
else if (arg.value?.type === type_1.RType.Symbol) {
|
|
104
|
+
const resolved = (0, general_1.valueSetGuard)((0, alias_tracking_1.resolveIdToValue)(arg.value.info.id, { environment: env, idMap: idMap, resolve: ctx.config.solver.variables, ctx }));
|
|
105
|
+
if (resolved) {
|
|
106
|
+
return (0, string_constants_1.collectStrings)(resolved.elements);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (arg.value?.type === type_1.RType.FunctionCall && arg.value.named && ['paste', 'paste0'].includes(identifier_1.Identifier.getName(arg.value.functionName.content))) {
|
|
110
|
+
return handlePaste(ctx.config, arg.value.arguments, env, idMap, arg.value.functionName.content === 'paste' ? [' '] : [''], ctx);
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
}
|
|
114
|
+
else if (val.type === type_1.RType.Symbol) {
|
|
115
|
+
// const resolved = resolveValueOfVariable(val.content, env);
|
|
116
|
+
// see https://github.com/flowr-analysis/flowr/pull/1467
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
return undefined;
|
|
121
|
+
}
|
|
105
122
|
}
|
|
106
123
|
}
|
|
107
124
|
function getAsString(config, val, env, idMap, ctx) {
|
|
@@ -17,9 +17,20 @@ const doc_issue_1 = require("./doc-util/doc-issue");
|
|
|
17
17
|
const strings_1 = require("../util/text/strings");
|
|
18
18
|
const doc_maker_1 = require("./wiki-mk/doc-maker");
|
|
19
19
|
const PublicationsMain = [
|
|
20
|
+
{
|
|
21
|
+
header: 'Supporting the Comprehension of Data Analysis Scripts (FSE \'25, Tool)',
|
|
22
|
+
description: 'This refers to an updated tool demonstration of the framework. Preprint available at <a href="https://doi.org/10.48550/arXiv.2604.15963" target="_blank">arXiv:2604.15963</a>.',
|
|
23
|
+
doi: 'https://doi.org/10.1145/3803437.3806402',
|
|
24
|
+
bibtex: String.raw `@article{10.1145/3803437.3806402,
|
|
25
|
+
author = {Sihler, Florian and Gerstl, Oliver and Pfrenger, Lars and Schubert, Julian and Tichy, Matthias},
|
|
26
|
+
title = {Supporting the Comprehension of Data Analysis Scripts},
|
|
27
|
+
year = {2026},
|
|
28
|
+
doi = {10.1145/3803437.3806402}
|
|
29
|
+
}`
|
|
30
|
+
},
|
|
20
31
|
{
|
|
21
32
|
header: 'Statically Analyzing the Dataflow of R Programs (OOPSLA \'25)',
|
|
22
|
-
description: 'Please cite this paper if you are using flowR in your research
|
|
33
|
+
description: '**Please cite this paper if you are using flowR in your research.**',
|
|
23
34
|
doi: 'https://doi.org/10.1145/3763087',
|
|
24
35
|
bibtex: String.raw `@article{10.1145/3763087,
|
|
25
36
|
author = {Sihler, Florian and Tichy, Matthias},
|
|
@@ -42,7 +53,7 @@ const PublicationsMain = [
|
|
|
42
53
|
},
|
|
43
54
|
{
|
|
44
55
|
header: 'flowR: A Static Program Slicer for R (ASE \'24, Tool)',
|
|
45
|
-
description: `This refers to the tool-demonstration of the <a href="${doc_files_1.FlowrVsCode}">VS Code Extension</a>.`,
|
|
56
|
+
description: `This refers to the tool-demonstration of the <a href="${doc_files_1.FlowrVsCode}" target="_blank">VS Code Extension</a>.`,
|
|
46
57
|
doi: 'https://doi.org/10.1145/3691620.3695359',
|
|
47
58
|
bibtex: `@inproceedings{DBLP:conf/kbse/SihlerT24,
|
|
48
59
|
author = {Florian Sihler and
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import { DocMaker } from './wiki-mk/doc-maker';
|
|
1
|
+
import { DocMaker, type DocMakerArgs } from './wiki-mk/doc-maker';
|
|
3
2
|
export declare class WikiAbsint extends DocMaker<'wiki/Abstract Interpretation.md'> {
|
|
4
3
|
constructor();
|
|
5
4
|
protected text({ ctx }: DocMakerArgs): Promise<string>;
|