@eagleoutice/flowr 2.1.8 → 2.1.10
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 +3 -0
- package/benchmark/summarizer/first-phase/process.js +6 -5
- package/cli/repl/commands/repl-dataflow.js +5 -2
- package/cli/repl/commands/repl-normalize.js +5 -2
- package/cli/repl/commands/repl-query.js +2 -2
- package/cli/repl/server/messages/message-query.js +1 -1
- package/config.d.ts +21 -0
- package/config.js +19 -2
- package/dataflow/environments/built-in.d.ts +2 -0
- package/dataflow/environments/built-in.js +2 -0
- package/dataflow/environments/default-builtin-config.js +48 -8
- package/dataflow/environments/define.js +78 -0
- package/dataflow/environments/environment.d.ts +46 -8
- package/dataflow/environments/environment.js +24 -1
- package/dataflow/environments/identifier.d.ts +60 -10
- package/dataflow/environments/identifier.js +11 -2
- package/dataflow/environments/resolve-by-name.d.ts +10 -5
- package/dataflow/environments/resolve-by-name.js +103 -5
- package/dataflow/extractor.js +5 -4
- package/dataflow/graph/dataflowgraph-builder.d.ts +6 -0
- package/dataflow/graph/dataflowgraph-builder.js +8 -0
- package/dataflow/graph/edge.d.ts +10 -4
- package/dataflow/graph/edge.js +12 -5
- package/dataflow/graph/graph.d.ts +41 -3
- package/dataflow/graph/graph.js +39 -34
- package/dataflow/graph/vertex.d.ts +122 -8
- package/dataflow/graph/vertex.js +19 -0
- package/dataflow/info.d.ts +79 -11
- package/dataflow/info.js +20 -0
- package/dataflow/internal/linker.d.ts +4 -2
- package/dataflow/internal/linker.js +12 -5
- package/dataflow/internal/process/functions/call/built-in/built-in-access.d.ts +11 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-access.js +141 -49
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +8 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +40 -11
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.d.ts +16 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +83 -6
- package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +3 -3
- package/dataflow/internal/process/functions/call/built-in/built-in-list.d.ts +15 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-list.js +50 -0
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +1 -1
- package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +29 -1
- package/dataflow/internal/process/functions/call/common.js +16 -2
- package/dataflow/internal/process/functions/call/known-call-handling.d.ts +2 -1
- package/dataflow/internal/process/functions/call/known-call-handling.js +3 -2
- package/documentation/doc-util/doc-dfg.d.ts +0 -1
- package/documentation/doc-util/doc-dfg.js +1 -14
- package/documentation/print-capabilities-markdown.js +1 -1
- package/documentation/print-dataflow-graph-wiki.js +26 -7
- package/documentation/print-interface-wiki.js +6 -1
- package/documentation/print-linting-and-testing-wiki.js +60 -26
- package/documentation/print-query-wiki.js +1 -1
- package/package.json +17 -3
- package/queries/catalog/call-context-query/call-context-query-executor.js +1 -1
- package/queries/catalog/call-context-query/call-context-query-format.d.ts +13 -0
- package/queries/catalog/call-context-query/call-context-query-format.js +3 -1
- package/queries/catalog/call-context-query/cascade-action.d.ts +8 -0
- package/queries/catalog/call-context-query/cascade-action.js +13 -0
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +11 -1
- package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +41 -4
- package/queries/catalog/dependencies-query/dependencies-query-format.js +4 -0
- package/queries/query.d.ts +4 -4
- package/queries/query.js +17 -5
- package/r-bridge/lang-4.x/ast/model/model.d.ts +3 -0
- package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +5 -1
- package/r-bridge/lang-4.x/ast/model/processing/node-id.d.ts +6 -1
- package/r-bridge/lang-4.x/ast/model/processing/node-id.js +6 -1
- package/slicing/static/slice-call.d.ts +7 -2
- package/slicing/static/slice-call.js +33 -44
- package/slicing/static/static-slicer.d.ts +5 -1
- package/slicing/static/static-slicer.js +22 -8
- package/slicing/static/visiting-queue.d.ts +4 -4
- package/slicing/static/visiting-queue.js +5 -3
- package/statistics/output/print-stats.js +2 -1
- package/statistics/summarizer/post-process/histogram.js +2 -1
- package/statistics/summarizer/post-process/post-process-output.js +2 -1
- package/statistics/summarizer/second-phase/process.js +3 -3
- package/util/arrays.d.ts +1 -1
- package/util/arrays.js +3 -3
- package/util/cfg/cfg.js +4 -2
- package/util/list-access.d.ts +48 -0
- package/util/list-access.js +115 -0
- package/util/mermaid/cfg.js +1 -1
- package/util/summarizer.js +2 -2
- package/util/version.js +1 -1
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CallTargets = void 0;
|
|
4
4
|
exports.satisfiesCallTargets = satisfiesCallTargets;
|
|
5
|
+
exports.getValueOfArgument = getValueOfArgument;
|
|
5
6
|
exports.identifyLinkToLastCallRelation = identifyLinkToLastCallRelation;
|
|
7
|
+
const graph_1 = require("../../../dataflow/graph/graph");
|
|
6
8
|
const visitor_1 = require("../../../util/cfg/visitor");
|
|
7
9
|
const vertex_1 = require("../../../dataflow/graph/vertex");
|
|
8
10
|
const edge_1 = require("../../../dataflow/graph/edge");
|
|
@@ -10,6 +12,9 @@ const resolve_by_name_1 = require("../../../dataflow/environments/resolve-by-nam
|
|
|
10
12
|
const identifier_1 = require("../../../dataflow/environments/identifier");
|
|
11
13
|
const built_in_1 = require("../../../dataflow/environments/built-in");
|
|
12
14
|
const assert_1 = require("../../../util/assert");
|
|
15
|
+
const type_1 = require("../../../r-bridge/lang-4.x/ast/model/type");
|
|
16
|
+
const r_function_call_1 = require("../../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
|
|
17
|
+
const cascade_action_1 = require("./cascade-action");
|
|
13
18
|
var CallTargets;
|
|
14
19
|
(function (CallTargets) {
|
|
15
20
|
/** call targets a function that is not defined locally (e.g., the call targets a library function) */
|
|
@@ -74,8 +79,36 @@ function satisfiesCallTargets(id, graph, callTarget) {
|
|
|
74
79
|
(0, assert_1.assertUnreachable)(callTarget);
|
|
75
80
|
}
|
|
76
81
|
}
|
|
77
|
-
function
|
|
82
|
+
function getValueOfArgument(graph, call, argument, additionalAllowedTypes) {
|
|
83
|
+
if (!call) {
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
const totalIndex = argument.name ? call.args.findIndex(arg => arg !== r_function_call_1.EmptyArgument && arg.name === argument.name) : -1;
|
|
87
|
+
let refAtIndex;
|
|
88
|
+
if (totalIndex < 0) {
|
|
89
|
+
const references = call.args.filter(arg => arg !== r_function_call_1.EmptyArgument && !arg.name).map(graph_1.getReferenceOfArgument);
|
|
90
|
+
refAtIndex = references[argument.index];
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
const arg = call.args[totalIndex];
|
|
94
|
+
refAtIndex = (0, graph_1.getReferenceOfArgument)(arg);
|
|
95
|
+
}
|
|
96
|
+
if (refAtIndex === undefined) {
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
let valueNode = graph.idMap?.get(refAtIndex);
|
|
100
|
+
if (valueNode?.type === type_1.RType.Argument) {
|
|
101
|
+
valueNode = valueNode.value;
|
|
102
|
+
}
|
|
103
|
+
if (valueNode) {
|
|
104
|
+
return !additionalAllowedTypes || additionalAllowedTypes.includes(valueNode.type) ? valueNode : undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function identifyLinkToLastCallRelation(from, cfg, graph, { callName, ignoreIf, cascadeIf }) {
|
|
78
108
|
const found = [];
|
|
109
|
+
if (ignoreIf && ignoreIf(from, graph)) {
|
|
110
|
+
return found;
|
|
111
|
+
}
|
|
79
112
|
(0, visitor_1.visitInReverseOrder)(cfg, from, node => {
|
|
80
113
|
/* we ignore the start id as it cannot be the last call */
|
|
81
114
|
if (node === from) {
|
|
@@ -85,13 +118,17 @@ function identifyLinkToLastCallRelation(from, cfg, graph, linkTo) {
|
|
|
85
118
|
if (vertex === undefined || vertex[0].tag !== vertex_1.VertexType.FunctionCall) {
|
|
86
119
|
return;
|
|
87
120
|
}
|
|
88
|
-
if (
|
|
121
|
+
if (callName.test(vertex[0].name)) {
|
|
122
|
+
const act = cascadeIf ? cascadeIf(vertex[0], from, graph) : cascade_action_1.CascadeAction.Stop;
|
|
123
|
+
if (act === cascade_action_1.CascadeAction.Skip) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
89
126
|
const tar = satisfiesCallTargets(vertex[0].id, graph, CallTargets.MustIncludeGlobal);
|
|
90
127
|
if (tar === 'no') {
|
|
91
|
-
return
|
|
128
|
+
return act === cascade_action_1.CascadeAction.Stop;
|
|
92
129
|
}
|
|
93
130
|
found.push(node);
|
|
94
|
-
return
|
|
131
|
+
return act === cascade_action_1.CascadeAction.Stop;
|
|
95
132
|
}
|
|
96
133
|
});
|
|
97
134
|
return found;
|
|
@@ -83,6 +83,8 @@ exports.ReadFunctions = [
|
|
|
83
83
|
{ name: 'read.ssd', argIdx: 0, argName: 'file' },
|
|
84
84
|
{ name: 'read.systat', argIdx: 0, argName: 'file' },
|
|
85
85
|
{ name: 'read.xport', argIdx: 0, argName: 'file' },
|
|
86
|
+
// car
|
|
87
|
+
{ name: 'Import', argIdx: 0, argName: 'file' },
|
|
86
88
|
];
|
|
87
89
|
exports.WriteFunctions = [
|
|
88
90
|
{ name: 'save', argIdx: 0, argName: '...' },
|
|
@@ -138,6 +140,8 @@ exports.WriteFunctions = [
|
|
|
138
140
|
{ name: 'tiff', argIdx: 0, argName: 'file' },
|
|
139
141
|
{ name: 'X11', argIdx: 0, argName: 'file' },
|
|
140
142
|
{ name: 'quartz', argIdx: 0, argName: 'file' },
|
|
143
|
+
// car
|
|
144
|
+
{ name: 'Export', argIdx: 0, argName: 'file' },
|
|
141
145
|
];
|
|
142
146
|
function printResultSection(title, infos, result, sectionSpecifics) {
|
|
143
147
|
if (infos.length <= 0) {
|
package/queries/query.d.ts
CHANGED
|
@@ -450,9 +450,9 @@ type OmitFromValues<T, K extends string | number | symbol> = {
|
|
|
450
450
|
export type QueryResultsWithoutMeta<Queries extends Query> = OmitFromValues<Omit<QueryResults<Queries['type']>, '.meta'>, '.meta'>;
|
|
451
451
|
export type Queries<Base extends SupportedQueryTypes, VirtualArguments extends VirtualCompoundConstraint<Base> = VirtualCompoundConstraint<Base>> = readonly (QueryArgumentsWithType<Base> | VirtualQueryArgumentsWithType<Base, VirtualArguments>)[];
|
|
452
452
|
export declare function executeQueries<Base extends SupportedQueryTypes, VirtualArguments extends VirtualCompoundConstraint<Base> = VirtualCompoundConstraint<Base>>(data: BasicQueryData, queries: Queries<Base, VirtualArguments>): QueryResults<Base>;
|
|
453
|
-
export declare
|
|
453
|
+
export declare function SupportedQueriesSchema(): Joi.AlternativesSchema<any>;
|
|
454
454
|
export declare const CompoundQuerySchema: Joi.ObjectSchema<any>;
|
|
455
|
-
export declare
|
|
456
|
-
export declare
|
|
457
|
-
export declare
|
|
455
|
+
export declare function VirtualQuerySchema(): Joi.AlternativesSchema<any>;
|
|
456
|
+
export declare function AnyQuerySchema(): Joi.AlternativesSchema<any>;
|
|
457
|
+
export declare function QueriesSchema(): Joi.ArraySchema<any[]>;
|
|
458
458
|
export {};
|
package/queries/query.js
CHANGED
|
@@ -3,9 +3,13 @@ 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.
|
|
6
|
+
exports.CompoundQuerySchema = exports.SupportedQueries = void 0;
|
|
7
7
|
exports.executeQueriesOfSameType = executeQueriesOfSameType;
|
|
8
8
|
exports.executeQueries = executeQueries;
|
|
9
|
+
exports.SupportedQueriesSchema = SupportedQueriesSchema;
|
|
10
|
+
exports.VirtualQuerySchema = VirtualQuerySchema;
|
|
11
|
+
exports.AnyQuerySchema = AnyQuerySchema;
|
|
12
|
+
exports.QueriesSchema = QueriesSchema;
|
|
9
13
|
const call_context_query_format_1 = require("./catalog/call-context-query/call-context-query-format");
|
|
10
14
|
const assert_1 = require("../util/assert");
|
|
11
15
|
const virtual_queries_1 = require("./virtual-query/virtual-queries");
|
|
@@ -74,14 +78,22 @@ function executeQueries(data, queries) {
|
|
|
74
78
|
};
|
|
75
79
|
return results;
|
|
76
80
|
}
|
|
77
|
-
|
|
81
|
+
function SupportedQueriesSchema() {
|
|
82
|
+
return joi_1.default.alternatives(Object.values(exports.SupportedQueries).map(q => q.schema)).description('Supported queries');
|
|
83
|
+
}
|
|
78
84
|
exports.CompoundQuerySchema = joi_1.default.object({
|
|
79
85
|
type: joi_1.default.string().valid('compound').required().description('The type of the query.'),
|
|
80
86
|
query: joi_1.default.string().required().description('The query to run on the file analysis information.'),
|
|
81
87
|
commonArguments: joi_1.default.object().required().description('Common arguments for all queries.'),
|
|
82
88
|
arguments: joi_1.default.array().items(joi_1.default.object()).required().description('Arguments for each query.')
|
|
83
89
|
}).description('Compound query used to combine queries of the same type');
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
function VirtualQuerySchema() {
|
|
91
|
+
return joi_1.default.alternatives(exports.CompoundQuerySchema).description('Virtual queries (used for structure)');
|
|
92
|
+
}
|
|
93
|
+
function AnyQuerySchema() {
|
|
94
|
+
return joi_1.default.alternatives(SupportedQueriesSchema(), VirtualQuerySchema()).description('Any query');
|
|
95
|
+
}
|
|
96
|
+
function QueriesSchema() {
|
|
97
|
+
return joi_1.default.array().items(AnyQuerySchema()).description('Queries to run on the file analysis information (in the form of an array)');
|
|
98
|
+
}
|
|
87
99
|
//# sourceMappingURL=query.js.map
|
|
@@ -145,6 +145,9 @@ export type ROther<Info> = RComment<Info> | RLineDirective<Info>;
|
|
|
145
145
|
* All other subtypes (like {@link RLoopConstructs}) listed above
|
|
146
146
|
* can be used to restrict the kind of node. They do not have to be
|
|
147
147
|
* exclusive, some nodes can appear in multiple subtypes.
|
|
148
|
+
*
|
|
149
|
+
* @see {@link recoverName} - to receive the name/lexeme from such a node
|
|
150
|
+
* @see {@link recoverContent} - for a more rigorous approach to get the content of a node within a {@link DataflowGraph|dataflow graph}
|
|
148
151
|
*/
|
|
149
152
|
export type RNode<Info = NoInfo> = RExpressionList<Info> | RFunctions<Info> | ROther<Info> | RConstructs<Info> | RNamedAccess<Info> | RIndexAccess<Info> | RUnaryOp<Info> | RBinaryOp<Info> | RSingleNode<Info> | RPipe<Info>;
|
|
150
153
|
export type OtherInfoNode = RNode | RDelimiter;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import type { Leaf, Location, NoInfo } from '../model';
|
|
2
2
|
import type { RType } from '../type';
|
|
3
3
|
import type { RNumberValue } from '../../../convert-values';
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* A number like `3`, `-2.14`, `1L`, or `2i`.
|
|
6
|
+
* Includes numeric, integer, and complex.
|
|
7
|
+
* See {@link RNumberValue} for more information.
|
|
8
|
+
*/
|
|
5
9
|
export interface RNumber<Info = NoInfo> extends Leaf<Info>, Location {
|
|
6
10
|
readonly type: RType.Number;
|
|
7
11
|
content: RNumberValue;
|
|
@@ -7,7 +7,12 @@ export type NodeId<T extends string | number = string | number> = T & {
|
|
|
7
7
|
/** used so that we do not have to store strings for the default numeric ids */
|
|
8
8
|
export declare function normalizeIdToNumberIfPossible(id: NodeId): NodeId;
|
|
9
9
|
/**
|
|
10
|
-
* Recovers the lexeme of a node from its id in the
|
|
10
|
+
* Recovers the lexeme of a {@link RNode|node} from its id in the {@link AstIdMap|id map}.
|
|
11
|
+
*
|
|
12
|
+
* @see {@link recoverContent} - to recover the content of a node
|
|
11
13
|
*/
|
|
12
14
|
export declare function recoverName(id: NodeId, idMap?: AstIdMap): string | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Recovers the content of a {@link RNode|node} from its id in the {@link DataflowGraph|dataflow graph}.
|
|
17
|
+
*/
|
|
13
18
|
export declare function recoverContent(id: NodeId, graph: DataflowGraph): string | undefined;
|
|
@@ -15,11 +15,16 @@ function normalizeIdToNumberIfPossible(id) {
|
|
|
15
15
|
return id;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* Recovers the lexeme of a node from its id in the
|
|
18
|
+
* Recovers the lexeme of a {@link RNode|node} from its id in the {@link AstIdMap|id map}.
|
|
19
|
+
*
|
|
20
|
+
* @see {@link recoverContent} - to recover the content of a node
|
|
19
21
|
*/
|
|
20
22
|
function recoverName(id, idMap) {
|
|
21
23
|
return idMap?.get(id)?.lexeme;
|
|
22
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* Recovers the content of a {@link RNode|node} from its id in the {@link DataflowGraph|dataflow graph}.
|
|
27
|
+
*/
|
|
23
28
|
function recoverContent(id, graph) {
|
|
24
29
|
const vertex = graph.getVertex(id);
|
|
25
30
|
if (vertex === undefined) {
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import type { NodeToSlice } from './slicer-types';
|
|
2
2
|
import type { VisitingQueue } from './visiting-queue';
|
|
3
3
|
import type { Fingerprint } from './fingerprint';
|
|
4
|
-
import type { DataflowGraphVertexFunctionCall } from '../../dataflow/graph/vertex';
|
|
4
|
+
import type { DataflowGraphVertexFunctionCall, DataflowGraphVertexInfo } from '../../dataflow/graph/vertex';
|
|
5
5
|
import type { REnvironmentInformation } from '../../dataflow/environments/environment';
|
|
6
6
|
import type { DataflowGraph, OutgoingEdges } from '../../dataflow/graph/graph';
|
|
7
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
8
|
+
/**
|
|
9
|
+
* Returns the function call targets (definitions) by the given caller
|
|
10
|
+
*/
|
|
11
|
+
export declare function getAllFunctionCallTargets(dataflowGraph: DataflowGraph, callerInfo: DataflowGraphVertexFunctionCall, baseEnvironment: REnvironmentInformation): [Set<DataflowGraphVertexInfo>, REnvironmentInformation];
|
|
7
12
|
/** returns the new threshold hit count */
|
|
8
13
|
export declare function sliceForCall(current: NodeToSlice, callerInfo: DataflowGraphVertexFunctionCall, dataflowGraph: DataflowGraph, queue: VisitingQueue): void;
|
|
9
14
|
/** Returns true if we found at least one return edge */
|
|
10
|
-
export declare function handleReturns(queue: VisitingQueue, currentEdges: OutgoingEdges, baseEnvFingerprint: Fingerprint, baseEnvironment: REnvironmentInformation): boolean;
|
|
15
|
+
export declare function handleReturns(from: NodeId, queue: VisitingQueue, currentEdges: OutgoingEdges, baseEnvFingerprint: Fingerprint, baseEnvironment: REnvironmentInformation): boolean;
|
|
@@ -1,31 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getAllFunctionCallTargets = getAllFunctionCallTargets;
|
|
3
4
|
exports.sliceForCall = sliceForCall;
|
|
4
5
|
exports.handleReturns = handleReturns;
|
|
5
6
|
const assert_1 = require("../../util/assert");
|
|
6
7
|
const fingerprint_1 = require("./fingerprint");
|
|
7
8
|
const linker_1 = require("../../dataflow/internal/linker");
|
|
8
|
-
const environment_1 = require("../../dataflow/environments/environment");
|
|
9
|
-
const scoping_1 = require("../../dataflow/environments/scoping");
|
|
10
|
-
const overwrite_1 = require("../../dataflow/environments/overwrite");
|
|
11
9
|
const graph_1 = require("../../dataflow/graph/graph");
|
|
12
10
|
const built_in_1 = require("../../dataflow/environments/built-in");
|
|
13
11
|
const resolve_by_name_1 = require("../../dataflow/environments/resolve-by-name");
|
|
14
12
|
const edge_1 = require("../../dataflow/graph/edge");
|
|
15
13
|
const identifier_1 = require("../../dataflow/environments/identifier");
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
const built_in_function_definition_1 = require("../../dataflow/internal/process/functions/call/built-in/built-in-function-definition");
|
|
15
|
+
const static_slicer_1 = require("./static-slicer");
|
|
16
|
+
/**
|
|
17
|
+
* Returns the function call targets (definitions) by the given caller
|
|
18
|
+
*/
|
|
19
|
+
function getAllFunctionCallTargets(dataflowGraph, callerInfo, baseEnvironment) {
|
|
20
|
+
// bind with call-local environments during slicing
|
|
21
|
+
const outgoingEdges = dataflowGraph.get(callerInfo.id, true);
|
|
22
|
+
(0, assert_1.guard)(outgoingEdges !== undefined, () => `outgoing edges of id: ${callerInfo.id} must be in graph but can not be found, keep in slice to be sure`);
|
|
23
|
+
// lift baseEnv on the same level
|
|
24
|
+
const activeEnvironment = (0, built_in_function_definition_1.retrieveActiveEnvironment)(callerInfo.environment, baseEnvironment);
|
|
25
|
+
const name = callerInfo.name;
|
|
26
|
+
(0, assert_1.guard)(name !== undefined, () => `name of id: ${callerInfo.id} can not be found in id map`);
|
|
27
|
+
const functionCallDefs = (0, resolve_by_name_1.resolveByName)(name, activeEnvironment, identifier_1.ReferenceType.Unknown)?.filter(d => d.definedAt !== built_in_1.BuiltIn)?.map(d => d.nodeId) ?? [];
|
|
28
|
+
for (const [target, outgoingEdge] of outgoingEdges[1].entries()) {
|
|
29
|
+
if ((0, edge_1.edgeIncludesType)(outgoingEdge.types, edge_1.EdgeType.Calls)) {
|
|
30
|
+
functionCallDefs.push(target);
|
|
26
31
|
}
|
|
27
32
|
}
|
|
28
|
-
|
|
33
|
+
const functionCallTargets = (0, linker_1.getAllLinkedFunctionDefinitions)(new Set(functionCallDefs), dataflowGraph);
|
|
34
|
+
return [functionCallTargets, activeEnvironment];
|
|
29
35
|
}
|
|
30
36
|
function includeArgumentFunctionCallClosure(arg, baseEnvironment, activeEnvironment, queue, dataflowGraph) {
|
|
31
37
|
const valueRoot = (0, graph_1.getReferenceOfArgument)(arg);
|
|
@@ -33,20 +39,21 @@ function includeArgumentFunctionCallClosure(arg, baseEnvironment, activeEnvironm
|
|
|
33
39
|
return;
|
|
34
40
|
}
|
|
35
41
|
const callTargets = (0, linker_1.getAllLinkedFunctionDefinitions)(new Set([valueRoot]), dataflowGraph);
|
|
36
|
-
linkCallTargets(false, callTargets,
|
|
42
|
+
linkCallTargets(false, callTargets, activeEnvironment, (0, fingerprint_1.envFingerprint)(activeEnvironment), queue);
|
|
37
43
|
}
|
|
38
|
-
function linkCallTargets(onlyForSideEffects, functionCallTargets,
|
|
44
|
+
function linkCallTargets(onlyForSideEffects, functionCallTargets, activeEnvironment, activeEnvironmentFingerprint, queue) {
|
|
39
45
|
for (const functionCallTarget of functionCallTargets) {
|
|
40
46
|
// all those linked within the scopes of other functions are already linked when exiting a function definition
|
|
41
|
-
for
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
/* for(const openIn of (functionCallTarget as DataflowGraphVertexFunctionDefinition).subflow.in) {
|
|
48
|
+
// only if the outgoing path does not already have a defined by linkage
|
|
49
|
+
const defs = openIn.name ? resolveByName(openIn.name, activeEnvironment, openIn.type) : undefined;
|
|
50
|
+
if(defs === undefined) {
|
|
44
51
|
continue;
|
|
45
52
|
}
|
|
46
|
-
for
|
|
53
|
+
for(const def of defs.filter(d => d.nodeId !== BuiltIn)) {
|
|
47
54
|
queue.add(def.nodeId, baseEnvironment, baseEnvPrint, onlyForSideEffects);
|
|
48
55
|
}
|
|
49
|
-
}
|
|
56
|
+
}*/
|
|
50
57
|
for (const exitPoint of functionCallTarget.exitPoints) {
|
|
51
58
|
queue.add(exitPoint, activeEnvironment, activeEnvironmentFingerprint, onlyForSideEffects);
|
|
52
59
|
}
|
|
@@ -54,23 +61,9 @@ function linkCallTargets(onlyForSideEffects, functionCallTargets, baseEnvironmen
|
|
|
54
61
|
}
|
|
55
62
|
/** returns the new threshold hit count */
|
|
56
63
|
function sliceForCall(current, callerInfo, dataflowGraph, queue) {
|
|
57
|
-
// bind with call-local environments during slicing
|
|
58
|
-
const outgoingEdges = dataflowGraph.get(callerInfo.id, true);
|
|
59
|
-
(0, assert_1.guard)(outgoingEdges !== undefined, () => `outgoing edges of id: ${callerInfo.id} must be in graph but can not be found, keep in slice to be sure`);
|
|
60
|
-
// lift baseEnv on the same level
|
|
61
64
|
const baseEnvironment = current.baseEnvironment;
|
|
62
|
-
const
|
|
63
|
-
const activeEnvironment = retrieveActiveEnvironment(callerInfo, baseEnvironment);
|
|
65
|
+
const [functionCallTargets, activeEnvironment] = getAllFunctionCallTargets(dataflowGraph, callerInfo, current.baseEnvironment);
|
|
64
66
|
const activeEnvironmentFingerprint = (0, fingerprint_1.envFingerprint)(activeEnvironment);
|
|
65
|
-
const name = callerInfo.name;
|
|
66
|
-
(0, assert_1.guard)(name !== undefined, () => `name of id: ${callerInfo.id} can not be found in id map`);
|
|
67
|
-
const functionCallDefs = (0, resolve_by_name_1.resolveByName)(name, activeEnvironment, identifier_1.ReferenceType.Unknown)?.filter(d => d.definedAt !== built_in_1.BuiltIn)?.map(d => d.nodeId) ?? [];
|
|
68
|
-
for (const [target, outgoingEdge] of outgoingEdges[1].entries()) {
|
|
69
|
-
if ((0, edge_1.edgeIncludesType)(outgoingEdge.types, edge_1.EdgeType.Calls)) {
|
|
70
|
-
functionCallDefs.push(target);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const functionCallTargets = (0, linker_1.getAllLinkedFunctionDefinitions)(new Set(functionCallDefs), dataflowGraph);
|
|
74
67
|
if (functionCallTargets.size === 0) {
|
|
75
68
|
/*
|
|
76
69
|
* if we do not have any call to resolve this function, we have to assume that every function passed is actually called!
|
|
@@ -81,10 +74,10 @@ function sliceForCall(current, callerInfo, dataflowGraph, queue) {
|
|
|
81
74
|
}
|
|
82
75
|
return;
|
|
83
76
|
}
|
|
84
|
-
linkCallTargets(current.onlyForSideEffects, functionCallTargets,
|
|
77
|
+
linkCallTargets(current.onlyForSideEffects, functionCallTargets, activeEnvironment, activeEnvironmentFingerprint, queue);
|
|
85
78
|
}
|
|
86
79
|
/** Returns true if we found at least one return edge */
|
|
87
|
-
function handleReturns(queue, currentEdges, baseEnvFingerprint, baseEnvironment) {
|
|
80
|
+
function handleReturns(from, queue, currentEdges, baseEnvFingerprint, baseEnvironment) {
|
|
88
81
|
const e = [...currentEdges.entries()];
|
|
89
82
|
const found = e.filter(([_, edge]) => (0, edge_1.edgeIncludesType)(edge.types, edge_1.EdgeType.Returns));
|
|
90
83
|
if (found.length === 0) {
|
|
@@ -97,12 +90,8 @@ function handleReturns(queue, currentEdges, baseEnvFingerprint, baseEnvironment)
|
|
|
97
90
|
if ((0, edge_1.edgeIncludesType)(edge.types, edge_1.EdgeType.Reads)) {
|
|
98
91
|
queue.add(target, baseEnvironment, baseEnvFingerprint, false);
|
|
99
92
|
}
|
|
100
|
-
else if ((0, edge_1.edgeIncludesType)(edge.types, edge_1.EdgeType.Argument)) {
|
|
101
|
-
|
|
102
|
-
id: target,
|
|
103
|
-
baseEnvironment,
|
|
104
|
-
onlyForSideEffects: false
|
|
105
|
-
});
|
|
93
|
+
else if ((0, edge_1.edgeIncludesType)(edge.types, edge_1.EdgeType.DefinesOnCall | edge_1.EdgeType.DefinedByOnCall | edge_1.EdgeType.Argument)) {
|
|
94
|
+
(0, static_slicer_1.updatePotentialAddition)(queue, from, target, baseEnvironment);
|
|
106
95
|
}
|
|
107
96
|
}
|
|
108
97
|
return true;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { SliceResult } from './slicer-types';
|
|
2
|
+
import { VisitingQueue } from './visiting-queue';
|
|
2
3
|
import type { DataflowGraph } from '../../dataflow/graph/graph';
|
|
3
4
|
import type { NormalizedAst } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
|
|
4
5
|
import type { SlicingCriteria } from '../criterion/parse';
|
|
6
|
+
import type { REnvironmentInformation } from '../../dataflow/environments/environment';
|
|
7
|
+
import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
|
|
5
8
|
export declare const slicerLogger: import("tslog").Logger<import("tslog").ILogObj>;
|
|
6
9
|
/**
|
|
7
10
|
* This returns the ids to include in the static backward slice, when slicing with the given seed id's (must be at least one).
|
|
@@ -10,7 +13,8 @@ export declare const slicerLogger: import("tslog").Logger<import("tslog").ILogOb
|
|
|
10
13
|
*
|
|
11
14
|
* @param graph - The dataflow graph to conduct the slicing on.
|
|
12
15
|
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
13
|
-
* @param criteria - The
|
|
16
|
+
* @param criteria - The criterias to slice on.
|
|
14
17
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
15
18
|
*/
|
|
16
19
|
export declare function staticSlicing(graph: DataflowGraph, { idMap }: NormalizedAst, criteria: SlicingCriteria, threshold?: number): Readonly<SliceResult>;
|
|
20
|
+
export declare function updatePotentialAddition(queue: VisitingQueue, id: NodeId, target: NodeId, baseEnvironment: REnvironmentInformation): void;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.slicerLogger = void 0;
|
|
4
4
|
exports.staticSlicing = staticSlicing;
|
|
5
|
+
exports.updatePotentialAddition = updatePotentialAddition;
|
|
5
6
|
const assert_1 = require("../../util/assert");
|
|
6
7
|
const log_1 = require("../../util/log");
|
|
7
8
|
const fingerprint_1 = require("./fingerprint");
|
|
@@ -19,7 +20,7 @@ exports.slicerLogger = log_1.log.getSubLogger({ name: 'slicer' });
|
|
|
19
20
|
*
|
|
20
21
|
* @param graph - The dataflow graph to conduct the slicing on.
|
|
21
22
|
* @param ast - The normalized AST of the code (used to get static nesting information of the lexemes in case of control flow dependencies that may have no effect on the slicing scope).
|
|
22
|
-
* @param criteria - The
|
|
23
|
+
* @param criteria - The criterias to slice on.
|
|
23
24
|
* @param threshold - The maximum number of nodes to visit in the graph. If the threshold is reached, the slice will side with inclusion and drop its minimal guarantee. The limit ensures that the algorithm halts.
|
|
24
25
|
*/
|
|
25
26
|
function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
@@ -71,7 +72,7 @@ function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
|
71
72
|
if (currentVertex.tag === vertex_1.VertexType.FunctionCall && !currentVertex.onlyBuiltin) {
|
|
72
73
|
(0, slice_call_1.sliceForCall)(current, currentVertex, graph, queue);
|
|
73
74
|
}
|
|
74
|
-
const ret = (0, slice_call_1.handleReturns)(queue, currentEdges, baseEnvFingerprint, baseEnvironment);
|
|
75
|
+
const ret = (0, slice_call_1.handleReturns)(id, queue, currentEdges, baseEnvFingerprint, baseEnvironment);
|
|
75
76
|
if (ret) {
|
|
76
77
|
continue;
|
|
77
78
|
}
|
|
@@ -84,12 +85,8 @@ function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
|
84
85
|
if (t === 3 /* TraverseEdge.Always */) {
|
|
85
86
|
queue.add(target, baseEnvironment, baseEnvFingerprint, false);
|
|
86
87
|
}
|
|
87
|
-
else if (t === 2 /* TraverseEdge.
|
|
88
|
-
|
|
89
|
-
if (n) {
|
|
90
|
-
queue.add(target, n.baseEnvironment, (0, fingerprint_1.envFingerprint)(n.baseEnvironment), n.onlyForSideEffects);
|
|
91
|
-
queue.potentialArguments.delete(target);
|
|
92
|
-
}
|
|
88
|
+
else if (t === 2 /* TraverseEdge.OnlyIfBoth */) {
|
|
89
|
+
updatePotentialAddition(queue, id, target, baseEnvironment);
|
|
93
90
|
}
|
|
94
91
|
else if (t === 1 /* TraverseEdge.SideEffect */) {
|
|
95
92
|
queue.add(target, baseEnvironment, baseEnvFingerprint, true);
|
|
@@ -98,4 +95,21 @@ function staticSlicing(graph, { idMap }, criteria, threshold = 75) {
|
|
|
98
95
|
}
|
|
99
96
|
return { ...queue.status(), decodedCriteria };
|
|
100
97
|
}
|
|
98
|
+
function updatePotentialAddition(queue, id, target, baseEnvironment) {
|
|
99
|
+
const n = queue.potentialAdditions.get(target);
|
|
100
|
+
if (n) {
|
|
101
|
+
const [addedBy, { baseEnvironment, onlyForSideEffects }] = n;
|
|
102
|
+
if (addedBy !== id) {
|
|
103
|
+
queue.add(target, baseEnvironment, (0, fingerprint_1.envFingerprint)(baseEnvironment), onlyForSideEffects);
|
|
104
|
+
queue.potentialAdditions.delete(target);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
queue.potentialAdditions.set(target, [id, {
|
|
109
|
+
id: target,
|
|
110
|
+
baseEnvironment,
|
|
111
|
+
onlyForSideEffects: false
|
|
112
|
+
}]);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
101
115
|
//# sourceMappingURL=static-slicer.js.map
|
|
@@ -4,10 +4,10 @@ import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-i
|
|
|
4
4
|
export declare class VisitingQueue {
|
|
5
5
|
private readonly threshold;
|
|
6
6
|
private timesHitThreshold;
|
|
7
|
-
private seen;
|
|
8
|
-
private idThreshold;
|
|
9
|
-
private queue;
|
|
10
|
-
|
|
7
|
+
private readonly seen;
|
|
8
|
+
private readonly idThreshold;
|
|
9
|
+
private readonly queue;
|
|
10
|
+
potentialAdditions: Map<NodeId, [NodeId, NodeToSlice]>;
|
|
11
11
|
constructor(threshold: number);
|
|
12
12
|
/**
|
|
13
13
|
* Adds a node to the queue if it has not been seen before.
|
|
@@ -3,14 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.VisitingQueue = void 0;
|
|
4
4
|
const fingerprint_1 = require("./fingerprint");
|
|
5
5
|
const static_slicer_1 = require("./static-slicer");
|
|
6
|
+
const assert_1 = require("../../util/assert");
|
|
6
7
|
class VisitingQueue {
|
|
7
8
|
threshold;
|
|
8
9
|
timesHitThreshold = 0;
|
|
9
10
|
seen = new Map();
|
|
10
11
|
idThreshold = new Map();
|
|
11
12
|
queue = [];
|
|
12
|
-
// the set of potential
|
|
13
|
-
|
|
13
|
+
// the set of potential additions holds nodes which may be added if a second edge deems them relevant (e.g., found with the `defined-by-on-call` edge)
|
|
14
|
+
// additionally it holds which node id added the addition so we can separate their inclusion on the structure
|
|
15
|
+
potentialAdditions = new Map();
|
|
14
16
|
constructor(threshold) {
|
|
15
17
|
this.threshold = threshold;
|
|
16
18
|
}
|
|
@@ -48,7 +50,7 @@ class VisitingQueue {
|
|
|
48
50
|
status() {
|
|
49
51
|
return {
|
|
50
52
|
timesHitThreshold: this.timesHitThreshold,
|
|
51
|
-
result: new Set(this.seen.values())
|
|
53
|
+
result: new Set([...this.seen.values()].filter(assert_1.isNotUndefined))
|
|
52
54
|
};
|
|
53
55
|
}
|
|
54
56
|
}
|
|
@@ -7,9 +7,10 @@ exports.printFeatureStatisticsEntry = printFeatureStatisticsEntry;
|
|
|
7
7
|
const ansi_1 = require("../../util/ansi");
|
|
8
8
|
const json_1 = require("../../util/json");
|
|
9
9
|
const feature_1 = require("../features/feature");
|
|
10
|
+
const arrays_1 = require("../../util/arrays");
|
|
10
11
|
function minMaxAvgAndMedian(data) {
|
|
11
12
|
data = data.sort((a, b) => a - b);
|
|
12
|
-
const sum =
|
|
13
|
+
const sum = (0, arrays_1.arraySum)(data);
|
|
13
14
|
return {
|
|
14
15
|
sum,
|
|
15
16
|
min: data[0],
|
|
@@ -11,6 +11,7 @@ const bimap_1 = require("../../../util/bimap");
|
|
|
11
11
|
const defaultmap_1 = require("../../../util/defaultmap");
|
|
12
12
|
const assert_1 = require("../../../util/assert");
|
|
13
13
|
const summarizer_1 = require("../../../util/summarizer");
|
|
14
|
+
const arrays_1 = require("../../../util/arrays");
|
|
14
15
|
/**
|
|
15
16
|
* Produces column-wise histogram-information based on a {@link ClusterReport}.
|
|
16
17
|
*
|
|
@@ -79,7 +80,7 @@ function histograms2table(histograms, countAsDensity = false) {
|
|
|
79
80
|
(0, assert_1.guard)(histograms.length > 0, 'there must be at least one histogram to convert to a table');
|
|
80
81
|
const mostBins = guardForLargestBinSize(histograms);
|
|
81
82
|
const header = ['bin', 'from', 'to', ...histograms.map(h => JSON.stringify(h.name))];
|
|
82
|
-
const sums = histograms.map(h =>
|
|
83
|
+
const sums = histograms.map(h => (0, arrays_1.arraySum)(h.bins));
|
|
83
84
|
const rows = [];
|
|
84
85
|
for (let binIndex = 0; binIndex < mostBins; binIndex++) {
|
|
85
86
|
const row = new Array(histograms.length + 3);
|
|
@@ -14,6 +14,7 @@ const ansi_1 = require("../../../util/ansi");
|
|
|
14
14
|
const feature_1 = require("../../features/feature");
|
|
15
15
|
const decorate_1 = require("../../../r-bridge/lang-4.x/ast/model/processing/decorate");
|
|
16
16
|
const file_provider_1 = require("../../output/file-provider");
|
|
17
|
+
const arrays_1 = require("../../../util/arrays");
|
|
17
18
|
/**
|
|
18
19
|
* Post process the collections in a given folder, reducing them in a memory preserving way.
|
|
19
20
|
*
|
|
@@ -79,7 +80,7 @@ function printClusterReport(report, limit = 1000) {
|
|
|
79
80
|
const shortStats = [...report.valueInfoMap.entries()].map(([name, values]) => {
|
|
80
81
|
return {
|
|
81
82
|
name,
|
|
82
|
-
count: [...values.values()]
|
|
83
|
+
count: (0, arrays_1.arraySum)([...values.values()]),
|
|
83
84
|
unique: values.size()
|
|
84
85
|
};
|
|
85
86
|
}).sort((a, b) => b.count - a.count).slice(0, limit);
|
|
@@ -50,7 +50,7 @@ function postProcessMeta(config, filepath, outputPath, logger, metaFeatureInform
|
|
|
50
50
|
out.write(`file,successfulParsed,${(0, summarizer_1.summarizedMeasurement2CsvHeader)('processing')},failedRequests,${(0, summarizer_1.summarizedMeasurement2CsvHeader)('line-length')},${(0, summarizer_1.summarizedMeasurement2CsvHeader)('lines')},${(0, summarizer_1.summarizedMeasurement2CsvHeader)('characters')},numberOfNormalizedNodes\n`);
|
|
51
51
|
for (const [file, info] of metaFeatureInformation) {
|
|
52
52
|
// we could retrieve these by summing later as well :thinking: however, this makes it more explicit
|
|
53
|
-
const characters = (0, arrays_1.
|
|
53
|
+
const characters = (0, arrays_1.arraySum)(info.stats.lines[0]);
|
|
54
54
|
out.write(`${JSON.stringify(file)},${info.stats.successfulParsed},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)(info.stats.processingTimeMs))},`
|
|
55
55
|
+ `${info.stats.failedRequests.length},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)(info.stats.lines[0]))},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)([info.stats.lines[0].length]))},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)([characters]))},${info.stats.numberOfNormalizedNodes[0]}\n`);
|
|
56
56
|
fileStatisticsSummary.successfulParsed.push(info.stats.successfulParsed);
|
|
@@ -60,8 +60,8 @@ function postProcessMeta(config, filepath, outputPath, logger, metaFeatureInform
|
|
|
60
60
|
fileStatisticsSummary.characters.push(characters);
|
|
61
61
|
fileStatisticsSummary.numberOfNormalizedNodes.push(info.stats.numberOfNormalizedNodes[0]);
|
|
62
62
|
}
|
|
63
|
-
out.write(`all,${(0, arrays_1.
|
|
64
|
-
+ `${(0, arrays_1.
|
|
63
|
+
out.write(`all,${(0, arrays_1.arraySum)(fileStatisticsSummary.successfulParsed)},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)(fileStatisticsSummary.processingTimeMs))},`
|
|
64
|
+
+ `${(0, arrays_1.arraySum)(fileStatisticsSummary.failedRequests)},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)(fileStatisticsSummary.lines.flat()))},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)(fileStatisticsSummary.lines.map(l => l.length)))},${(0, summarizer_1.summarizedMeasurement2Csv)((0, summarizer_1.summarizeMeasurement)(fileStatisticsSummary.characters))},${(0, arrays_1.arraySum)(fileStatisticsSummary.numberOfNormalizedNodes)}\n`);
|
|
65
65
|
out.close();
|
|
66
66
|
}
|
|
67
67
|
/**
|
package/util/arrays.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export declare function getUniqueCombinationsOfSize<T>(array: T[], minSize?: num
|
|
|
46
46
|
/**
|
|
47
47
|
* Returns the sum of all elements in the given array
|
|
48
48
|
*/
|
|
49
|
-
export declare function
|
|
49
|
+
export declare function arraySum(arr: readonly number[]): number;
|
|
50
50
|
/**
|
|
51
51
|
* Converts an array into a bag data-structure (in the form of a map mapping the entries/keys to their counts)
|
|
52
52
|
*/
|
package/util/arrays.js
CHANGED
|
@@ -5,7 +5,7 @@ exports.partitionArray = partitionArray;
|
|
|
5
5
|
exports.allPermutations = allPermutations;
|
|
6
6
|
exports.partition = partition;
|
|
7
7
|
exports.getUniqueCombinationsOfSize = getUniqueCombinationsOfSize;
|
|
8
|
-
exports.
|
|
8
|
+
exports.arraySum = arraySum;
|
|
9
9
|
exports.array2bag = array2bag;
|
|
10
10
|
exports.arrayEqual = arrayEqual;
|
|
11
11
|
const assert_1 = require("./assert");
|
|
@@ -143,7 +143,7 @@ function* getUniqueCombinationsOfSize(array, minSize = 0, maxSize = array.length
|
|
|
143
143
|
/**
|
|
144
144
|
* Returns the sum of all elements in the given array
|
|
145
145
|
*/
|
|
146
|
-
function
|
|
146
|
+
function arraySum(arr) {
|
|
147
147
|
let sum = 0;
|
|
148
148
|
for (const elem of arr) {
|
|
149
149
|
sum += elem;
|
|
@@ -167,7 +167,7 @@ function arrayEqual(a, b) {
|
|
|
167
167
|
if (a.length !== b.length) {
|
|
168
168
|
return false;
|
|
169
169
|
}
|
|
170
|
-
for (let i = 0; i < a.length; ++
|
|
170
|
+
for (let i = 0; i < a.length; i++) {
|
|
171
171
|
if (a[i] !== b[i]) {
|
|
172
172
|
return false;
|
|
173
173
|
}
|
package/util/cfg/cfg.js
CHANGED
|
@@ -381,9 +381,11 @@ function cfgAccess(access, name, accessors) {
|
|
|
381
381
|
}
|
|
382
382
|
function cfgUnaryOp(unary, operand) {
|
|
383
383
|
const graph = operand.graph;
|
|
384
|
-
const result = { ...operand, graph, exitPoints: [unary.info.id] };
|
|
385
384
|
graph.addVertex({ id: unary.info.id, name: unary.type, type: "end-marker" /* CfgVertexType.EndMarker */ });
|
|
386
|
-
|
|
385
|
+
for (const entry of operand.exitPoints) {
|
|
386
|
+
graph.addEdge(unary.info.id, entry, { label: 'FD' });
|
|
387
|
+
}
|
|
388
|
+
return { ...operand, graph, exitPoints: [unary.info.id] };
|
|
387
389
|
}
|
|
388
390
|
function cfgExprList(_node, _grouping, expressions) {
|
|
389
391
|
const result = { graph: new ControlFlowGraph(), breaks: [], nexts: [], returns: [], exitPoints: [], entryPoints: [] };
|