@eagleoutice/flowr 2.7.0 → 2.7.3

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.
Files changed (168) hide show
  1. package/README.md +14 -14
  2. package/abstract-interpretation/absint-visitor.d.ts +160 -0
  3. package/abstract-interpretation/absint-visitor.js +279 -0
  4. package/abstract-interpretation/data-frame/dataframe-domain.d.ts +2 -2
  5. package/abstract-interpretation/data-frame/dataframe-domain.js +23 -7
  6. package/abstract-interpretation/data-frame/mappers/access-mapper.d.ts +6 -6
  7. package/abstract-interpretation/data-frame/mappers/access-mapper.js +10 -14
  8. package/abstract-interpretation/data-frame/mappers/arguments.d.ts +15 -9
  9. package/abstract-interpretation/data-frame/mappers/arguments.js +27 -4
  10. package/abstract-interpretation/data-frame/mappers/function-mapper.d.ts +17 -17
  11. package/abstract-interpretation/data-frame/mappers/function-mapper.js +55 -67
  12. package/abstract-interpretation/data-frame/mappers/replacement-mapper.d.ts +7 -7
  13. package/abstract-interpretation/data-frame/mappers/replacement-mapper.js +25 -29
  14. package/abstract-interpretation/data-frame/resolve-args.d.ts +1 -1
  15. package/abstract-interpretation/data-frame/resolve-args.js +1 -1
  16. package/abstract-interpretation/data-frame/semantics.js +5 -6
  17. package/abstract-interpretation/data-frame/shape-inference.d.ts +52 -28
  18. package/abstract-interpretation/data-frame/shape-inference.js +67 -90
  19. package/abstract-interpretation/domains/bounded-set-domain.d.ts +2 -2
  20. package/abstract-interpretation/domains/interval-domain.d.ts +2 -2
  21. package/abstract-interpretation/domains/set-range-domain.d.ts +10 -4
  22. package/abstract-interpretation/domains/set-range-domain.js +7 -1
  23. package/abstract-interpretation/domains/set-upper-bound-domain.d.ts +2 -2
  24. package/abstract-interpretation/domains/singleton-domain.d.ts +2 -2
  25. package/benchmark/slicer.js +13 -14
  26. package/cli/common/options.d.ts +431 -8
  27. package/cli/common/options.js +1 -1
  28. package/cli/common/scripts-info.d.ts +431 -7
  29. package/cli/flowr-main-options.d.ts +102 -2
  30. package/cli/flowr.d.ts +102 -2
  31. package/cli/repl/commands/repl-commands.d.ts +25 -0
  32. package/cli/repl/commands/repl-query.js +17 -5
  33. package/cli/wiki.d.ts +13 -0
  34. package/cli/wiki.js +7 -2
  35. package/config.d.ts +4 -4
  36. package/config.js +1 -1
  37. package/control-flow/basic-cfg-guided-visitor.js +7 -8
  38. package/control-flow/control-flow-graph.d.ts +1 -1
  39. package/control-flow/semantic-cfg-guided-visitor.d.ts +1 -1
  40. package/control-flow/semantic-cfg-guided-visitor.js +1 -1
  41. package/dataflow/eval/resolve/alias-tracking.js +1 -1
  42. package/dataflow/internal/linker.d.ts +2 -0
  43. package/dataflow/internal/linker.js +10 -12
  44. package/documentation/doc-capabilities.d.ts +1 -1
  45. package/documentation/doc-readme.d.ts +1 -1
  46. package/documentation/doc-util/doc-cfg.js +1 -1
  47. package/documentation/doc-util/doc-cli-option.d.ts +6 -6
  48. package/documentation/doc-util/doc-cli-option.js +3 -3
  49. package/documentation/doc-util/doc-dfg.d.ts +1 -1
  50. package/documentation/doc-util/doc-files.d.ts +3 -0
  51. package/documentation/doc-util/doc-files.js +4 -1
  52. package/documentation/doc-util/doc-normalized-ast.js +2 -2
  53. package/documentation/issue-linting-rule.d.ts +1 -1
  54. package/documentation/wiki-analyzer.d.ts +1 -1
  55. package/documentation/wiki-cfg.d.ts +1 -1
  56. package/documentation/wiki-core.d.ts +1 -1
  57. package/documentation/wiki-dataflow-graph.d.ts +1 -1
  58. package/documentation/wiki-dataflow-graph.js +6 -6
  59. package/documentation/wiki-engine.d.ts +1 -1
  60. package/documentation/wiki-engine.js +9 -10
  61. package/documentation/wiki-faq.d.ts +1 -1
  62. package/documentation/wiki-interface.d.ts +1 -1
  63. package/documentation/wiki-interface.js +12 -13
  64. package/documentation/wiki-linter.d.ts +1 -1
  65. package/documentation/wiki-linting-and-testing.d.ts +1 -1
  66. package/documentation/wiki-mk/doc-context.d.ts +54 -1
  67. package/documentation/wiki-mk/doc-context.js +17 -0
  68. package/documentation/wiki-mk/doc-maker.d.ts +5 -5
  69. package/documentation/wiki-mk/doc-maker.js +3 -1
  70. package/documentation/wiki-normalized-ast.d.ts +1 -1
  71. package/documentation/wiki-onboarding.d.ts +1 -1
  72. package/documentation/wiki-overview.d.ts +9 -0
  73. package/documentation/wiki-overview.js +248 -0
  74. package/documentation/wiki-query.d.ts +1 -1
  75. package/documentation/wiki-query.js +17 -1
  76. package/documentation/wiki-search.d.ts +1 -1
  77. package/documentation/wiki-setup.d.ts +9 -0
  78. package/documentation/wiki-setup.js +122 -0
  79. package/linter/rules/dataframe-access-validation.d.ts +1 -1
  80. package/linter/rules/dataframe-access-validation.js +8 -10
  81. package/linter/rules/unused-definition.js +1 -1
  82. package/package.json +1 -1
  83. package/project/context/flowr-analyzer-context.d.ts +4 -0
  84. package/project/context/flowr-analyzer-context.js +3 -1
  85. package/project/context/flowr-analyzer-dependencies-context.d.ts +3 -2
  86. package/project/context/flowr-analyzer-dependencies-context.js +4 -2
  87. package/project/context/flowr-analyzer-files-context.d.ts +9 -1
  88. package/project/context/flowr-analyzer-files-context.js +4 -0
  89. package/project/context/flowr-analyzer-functions-context.d.ts +29 -0
  90. package/project/context/flowr-analyzer-functions-context.js +68 -0
  91. package/project/context/flowr-file.d.ts +2 -0
  92. package/project/context/flowr-file.js +2 -0
  93. package/project/plugins/file-plugins/{flowr-description-file.d.ts → files/flowr-description-file.d.ts} +1 -1
  94. package/project/plugins/file-plugins/files/flowr-description-file.js +75 -0
  95. package/project/plugins/file-plugins/files/flowr-namespace-file.d.ts +32 -0
  96. package/project/plugins/file-plugins/files/flowr-namespace-file.js +102 -0
  97. package/project/plugins/file-plugins/files/flowr-news-file.d.ts +27 -0
  98. package/project/plugins/file-plugins/files/flowr-news-file.js +152 -0
  99. package/project/plugins/file-plugins/flowr-analyzer-description-file-plugin.d.ts +1 -1
  100. package/project/plugins/file-plugins/flowr-analyzer-description-file-plugin.js +1 -1
  101. package/project/plugins/file-plugins/flowr-analyzer-namespace-file-plugin.d.ts +22 -0
  102. package/project/plugins/file-plugins/flowr-analyzer-namespace-file-plugin.js +34 -0
  103. package/project/plugins/file-plugins/flowr-analyzer-news-file-plugin.d.ts +23 -0
  104. package/project/plugins/file-plugins/flowr-analyzer-news-file-plugin.js +35 -0
  105. package/project/plugins/file-plugins/notebooks/flowr-analyzer-jupyter-file-plugin.d.ts +1 -1
  106. package/project/plugins/file-plugins/notebooks/flowr-analyzer-jupyter-file-plugin.js +1 -1
  107. package/project/plugins/file-plugins/notebooks/flowr-analyzer-qmd-file-plugin.d.ts +1 -1
  108. package/project/plugins/file-plugins/notebooks/flowr-analyzer-qmd-file-plugin.js +1 -1
  109. package/project/plugins/file-plugins/notebooks/flowr-analyzer-rmd-file-plugin.d.ts +1 -1
  110. package/project/plugins/file-plugins/notebooks/flowr-analyzer-rmd-file-plugin.js +1 -1
  111. package/project/plugins/flowr-analyzer-plugin-defaults.js +4 -0
  112. package/project/plugins/package-version-plugins/flowr-analyzer-package-versions-description-file-plugin.js +5 -1
  113. package/project/plugins/package-version-plugins/flowr-analyzer-package-versions-namespace-file-plugin.d.ts +10 -0
  114. package/project/plugins/package-version-plugins/flowr-analyzer-package-versions-namespace-file-plugin.js +56 -0
  115. package/project/plugins/package-version-plugins/package.d.ts +15 -2
  116. package/project/plugins/package-version-plugins/package.js +33 -5
  117. package/project/plugins/plugin-registry.d.ts +3 -1
  118. package/project/plugins/plugin-registry.js +4 -0
  119. package/project/plugins/project-discovery/flowr-analyzer-project-discovery-plugin.js +7 -1
  120. package/queries/catalog/dependencies-query/dependencies-query-executor.js +2 -1
  121. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +2 -0
  122. package/queries/catalog/dependencies-query/dependencies-query-format.js +2 -1
  123. package/queries/catalog/df-shape-query/df-shape-query-executor.js +4 -2
  124. package/queries/catalog/files-query/files-query-executor.d.ts +6 -0
  125. package/queries/catalog/files-query/files-query-executor.js +49 -0
  126. package/queries/catalog/files-query/files-query-format.d.ts +36 -0
  127. package/queries/catalog/files-query/files-query-format.js +114 -0
  128. package/queries/catalog/linter-query/linter-query-format.js +1 -1
  129. package/queries/query.d.ts +10 -1
  130. package/queries/query.js +3 -1
  131. package/r-bridge/lang-4.x/ast/model/model.d.ts +1 -1
  132. package/r-bridge/lang-4.x/ast/model/processing/decorate.js +8 -8
  133. package/r-bridge/lang-4.x/ast/model/processing/role.d.ts +8 -8
  134. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-parameter.js +0 -1
  135. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +0 -1
  136. package/statistics/features/supported/data-access/data-access.js +1 -1
  137. package/util/containers.js +1 -1
  138. package/util/files.d.ts +0 -7
  139. package/util/files.js +0 -41
  140. package/util/mermaid/ast.d.ts +3 -2
  141. package/util/mermaid/ast.js +13 -7
  142. package/util/mermaid/cfg.d.ts +3 -2
  143. package/util/mermaid/cfg.js +26 -6
  144. package/util/mermaid/dfg.d.ts +1 -7
  145. package/util/mermaid/dfg.js +7 -3
  146. package/util/mermaid/info.d.ts +17 -0
  147. package/util/mermaid/info.js +5 -0
  148. package/util/prefix.d.ts +9 -5
  149. package/util/prefix.js +14 -6
  150. package/util/r-regex.d.ts +21 -0
  151. package/util/r-regex.js +25 -0
  152. package/util/text/args.js +12 -3
  153. package/util/version.js +1 -1
  154. package/abstract-interpretation/data-frame/absint-info.d.ts +0 -109
  155. package/abstract-interpretation/data-frame/absint-info.js +0 -31
  156. package/abstract-interpretation/data-frame/absint-visitor.d.ts +0 -57
  157. package/abstract-interpretation/data-frame/absint-visitor.js +0 -176
  158. package/abstract-interpretation/data-frame/mappers/assignment-mapper.d.ts +0 -21
  159. package/abstract-interpretation/data-frame/mappers/assignment-mapper.js +0 -34
  160. package/documentation/doc-util/doc-print.d.ts +0 -5
  161. package/documentation/doc-util/doc-print.js +0 -36
  162. package/project/plugins/file-plugins/flowr-description-file.js +0 -37
  163. package/project/plugins/file-plugins/notebooks/notebook.d.ts +0 -0
  164. package/project/plugins/file-plugins/notebooks/notebook.js +0 -2
  165. /package/project/plugins/file-plugins/{notebooks → files}/flowr-jupyter-file.d.ts +0 -0
  166. /package/project/plugins/file-plugins/{notebooks → files}/flowr-jupyter-file.js +0 -0
  167. /package/project/plugins/file-plugins/{notebooks → files}/flowr-rmarkdown-file.d.ts +0 -0
  168. /package/project/plugins/file-plugins/{notebooks → files}/flowr-rmarkdown-file.js +0 -0
@@ -1,35 +1,59 @@
1
- import { type ControlFlowInformation } from '../../control-flow/control-flow-graph';
2
- import type { DataflowGraph } from '../../dataflow/graph/graph';
3
- import type { ReadOnlyFlowrAnalyzerContext } from '../../project/context/flowr-analyzer-context';
4
- import type { RNode } from '../../r-bridge/lang-4.x/ast/model/model';
5
- import type { NormalizedAst, ParentInformation } from '../../r-bridge/lang-4.x/ast/model/processing/decorate';
1
+ import type { DataflowGraphVertexFunctionCall } from '../../dataflow/graph/vertex';
2
+ import type { NoInfo } from '../../r-bridge/lang-4.x/ast/model/model';
6
3
  import type { NodeId } from '../../r-bridge/lang-4.x/ast/model/processing/node-id';
7
- import { type AbstractInterpretationInfo } from './absint-info';
8
- import { type DataFrameDomain, DataFrameStateDomain } from './dataframe-domain';
4
+ import { AbstractInterpretationVisitor, type AbsintVisitorConfiguration } from '../absint-visitor';
5
+ import { DataFrameDomain, DataFrameStateDomain } from './dataframe-domain';
6
+ import { ConstraintType, type DataFrameOperationArgs, type DataFrameOperationName, type DataFrameOperationOptions } from './semantics';
7
+ interface Operation<Name extends DataFrameOperationName> {
8
+ /** The type of the abstract data frame operation (see {@link DataFrameOperationName}) */
9
+ operation: Name;
10
+ /** The ID of the data frame operand of the operation (may be `undefined`) */
11
+ operand: NodeId | undefined;
12
+ /** The optional constraint type to overwrite the default type of the operation (see {@link ConstraintType}) */
13
+ type?: ConstraintType;
14
+ /** The optional additional options for the abstract operation (see {@link DataFrameOperationOptions}) */
15
+ options?: DataFrameOperationOptions<Name>;
16
+ }
9
17
  /**
10
- * Infers the shape of data frames by performing abstract interpretation using the control flow graph of a program.
11
- * This directly attaches the inferred data frames shapes to the AST (see {@link AbstractInterpretationInfo}).
12
- * @param cfinfo - The control flow information containing the control flow graph
13
- * @param dfg - The data flow graph to resolve variable origins and function arguments
14
- * @param ast - The abstract syntax tree to resolve node IDs to AST nodes
15
- * @param ctx - The current flowr analyzer context
16
- * @returns The abstract data frame state at the exit node of the control flow graph (see {@link DataFrameStateDomain}).
17
- * The abstract data frame states for all other nodes are attached to the AST.
18
+ * An abstract data frame operation.
18
19
  */
19
- export declare function inferDataFrameShapes(cfinfo: ControlFlowInformation, dfg: DataflowGraph, ast: NormalizedAst<ParentInformation & AbstractInterpretationInfo>, ctx: ReadOnlyFlowrAnalyzerContext): DataFrameStateDomain;
20
+ export type DataFrameOperation<OperationName extends DataFrameOperationName = DataFrameOperationName> = {
21
+ [Name in OperationName]: Operation<Name> & DataFrameOperationArgs<Name>;
22
+ }[OperationName];
20
23
  /**
21
- * Resolves the abstract data frame shape of a node in the AST.
22
- * This requires that the data frame shape inference has been executed before using {@link inferDataFrameShapes}.
23
- * @param id - The node or node ID to get the data frame shape for
24
- * @param dfg - The data flow graph used to resolve the data frame shape
25
- * @param domain - An optional abstract data frame state domain used to resolve the data frame shape (defaults to the state at the requested node)
26
- * @returns The abstract data frame shape of the node, or `undefined` if no data frame shape was inferred for the node
24
+ * An abstract data frame operation without additional options.
27
25
  */
28
- export declare function resolveIdToDataFrameShape(id: RNode<ParentInformation & AbstractInterpretationInfo> | NodeId | undefined, dfg: DataflowGraph | undefined, domain?: DataFrameStateDomain): DataFrameDomain | undefined;
26
+ export type DataFrameOperationType<OperationName extends DataFrameOperationName = DataFrameOperationName> = {
27
+ [Name in OperationName]: Omit<Operation<Name>, 'type' | 'options'> & DataFrameOperationArgs<Name>;
28
+ }[OperationName];
29
29
  /**
30
- * Gets all origins of a variable in the data flow graph that have already been visited.
31
- * @param node - The node to get the origins for
32
- * @param dfg - The data flow graph for resolving the origins
33
- * @returns The origins nodes of the variable
30
+ * A possible `undefined` array of abstract data frame operations (see {@link DataFrameOperation}).
34
31
  */
35
- export declare function getVariableOrigins(node: NodeId, dfg: DataflowGraph): RNode<ParentInformation & AbstractInterpretationInfo>[];
32
+ export type DataFrameOperations<OperationName extends DataFrameOperationName = DataFrameOperationName> = DataFrameOperation<OperationName>[] | undefined;
33
+ interface DataFrameShapeInferenceConfiguration extends Omit<AbsintVisitorConfiguration<DataFrameDomain>, 'domain'> {
34
+ readonly trackOperations?: boolean;
35
+ }
36
+ /**
37
+ * The control flow graph visitor to infer the shape of data frames using abstract interpretation
38
+ */
39
+ export declare class DataFrameShapeInferenceVisitor extends AbstractInterpretationVisitor<DataFrameDomain, NoInfo, DataFrameShapeInferenceConfiguration & {
40
+ domain: DataFrameStateDomain;
41
+ }> {
42
+ /**
43
+ * The abstract data frame operations the function call nodes are mapped to.
44
+ */
45
+ private readonly operations?;
46
+ constructor({ trackOperations, ...config }: DataFrameShapeInferenceConfiguration);
47
+ /**
48
+ * Gets the mapped abstract data frame operations for an AST node (this only includes direct function calls, replacement calls, or access operations).
49
+ * This requires that the abstract interpretation visitor has been completed, or at least started.
50
+ * @param id - The ID of the node to get the mapped abstract operations for
51
+ * @returns The mapped abstract data frame operations for the node, or `undefined` if no abstract operation was mapped for the node or storing mapped abstract operations is disabled via the visitor config.
52
+ */
53
+ getAbstractOperations(id: NodeId | undefined): Readonly<DataFrameOperations>;
54
+ protected evalFunctionCall(call: DataflowGraphVertexFunctionCall, state: DataFrameStateDomain): DataFrameStateDomain;
55
+ protected evalReplacementCall(call: DataflowGraphVertexFunctionCall, target: NodeId, source: NodeId, state: DataFrameStateDomain): DataFrameStateDomain;
56
+ protected evalAccessCall(call: DataflowGraphVertexFunctionCall, state: DataFrameStateDomain): DataFrameStateDomain;
57
+ private applyDataFrameExpression;
58
+ }
59
+ export {};
@@ -1,109 +1,86 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.inferDataFrameShapes = inferDataFrameShapes;
4
- exports.resolveIdToDataFrameShape = resolveIdToDataFrameShape;
5
- exports.getVariableOrigins = getVariableOrigins;
6
- const control_flow_graph_1 = require("../../control-flow/control-flow-graph");
7
- const vertex_1 = require("../../dataflow/graph/vertex");
8
- const dfg_get_origin_1 = require("../../dataflow/origin/dfg-get-origin");
9
- const r_function_call_1 = require("../../r-bridge/lang-4.x/ast/model/nodes/r-function-call");
10
- const type_1 = require("../../r-bridge/lang-4.x/ast/model/type");
11
- const assert_1 = require("../../util/assert");
12
- const abstract_domain_1 = require("../domains/abstract-domain");
13
- const absint_info_1 = require("./absint-info");
14
- const absint_visitor_1 = require("./absint-visitor");
3
+ exports.DataFrameShapeInferenceVisitor = void 0;
4
+ const absint_visitor_1 = require("../absint-visitor");
15
5
  const dataframe_domain_1 = require("./dataframe-domain");
6
+ const access_mapper_1 = require("./mappers/access-mapper");
7
+ const function_mapper_1 = require("./mappers/function-mapper");
8
+ const replacement_mapper_1 = require("./mappers/replacement-mapper");
9
+ const semantics_1 = require("./semantics");
16
10
  /**
17
- * Infers the shape of data frames by performing abstract interpretation using the control flow graph of a program.
18
- * This directly attaches the inferred data frames shapes to the AST (see {@link AbstractInterpretationInfo}).
19
- * @param cfinfo - The control flow information containing the control flow graph
20
- * @param dfg - The data flow graph to resolve variable origins and function arguments
21
- * @param ast - The abstract syntax tree to resolve node IDs to AST nodes
22
- * @param ctx - The current flowr analyzer context
23
- * @returns The abstract data frame state at the exit node of the control flow graph (see {@link DataFrameStateDomain}).
24
- * The abstract data frame states for all other nodes are attached to the AST.
11
+ * The control flow graph visitor to infer the shape of data frames using abstract interpretation
25
12
  */
26
- function inferDataFrameShapes(cfinfo, dfg, ast, ctx) {
27
- const visitor = new absint_visitor_1.DataFrameShapeInferenceVisitor({ controlFlow: cfinfo, dfg: dfg, normalizedAst: ast, ctx });
28
- visitor.start();
29
- const exitPoints = cfinfo.exitPoints.map(id => cfinfo.graph.getVertex(id)).filter(assert_1.isNotUndefined);
30
- const exitNodes = exitPoints.map(vertex => ast.idMap.get((0, control_flow_graph_1.getVertexRootId)(vertex))).filter(assert_1.isNotUndefined);
31
- const domains = exitNodes.map(node => node.info.dataFrame?.domain).filter(assert_1.isNotUndefined);
32
- return dataframe_domain_1.DataFrameStateDomain.bottom().joinAll(domains);
33
- }
34
- /**
35
- * Resolves the abstract data frame shape of a node in the AST.
36
- * This requires that the data frame shape inference has been executed before using {@link inferDataFrameShapes}.
37
- * @param id - The node or node ID to get the data frame shape for
38
- * @param dfg - The data flow graph used to resolve the data frame shape
39
- * @param domain - An optional abstract data frame state domain used to resolve the data frame shape (defaults to the state at the requested node)
40
- * @returns The abstract data frame shape of the node, or `undefined` if no data frame shape was inferred for the node
41
- */
42
- function resolveIdToDataFrameShape(id, dfg, domain) {
43
- const node = id === undefined || typeof id === 'object' ? id : dfg?.idMap?.get(id);
44
- domain ??= node?.info.dataFrame?.domain;
45
- if (dfg === undefined || node === undefined || domain === undefined) {
46
- return;
13
+ class DataFrameShapeInferenceVisitor extends absint_visitor_1.AbstractInterpretationVisitor {
14
+ /**
15
+ * The abstract data frame operations the function call nodes are mapped to.
16
+ */
17
+ operations;
18
+ constructor({ trackOperations = true, ...config }) {
19
+ super({ ...config, domain: dataframe_domain_1.DataFrameStateDomain.bottom() });
20
+ if (trackOperations) {
21
+ this.operations = new Map();
22
+ }
47
23
  }
48
- else if (domain.has(node.info.id)) {
49
- return domain.get(node.info.id);
24
+ /**
25
+ * Gets the mapped abstract data frame operations for an AST node (this only includes direct function calls, replacement calls, or access operations).
26
+ * This requires that the abstract interpretation visitor has been completed, or at least started.
27
+ * @param id - The ID of the node to get the mapped abstract operations for
28
+ * @returns The mapped abstract data frame operations for the node, or `undefined` if no abstract operation was mapped for the node or storing mapped abstract operations is disabled via the visitor config.
29
+ */
30
+ getAbstractOperations(id) {
31
+ return id !== undefined ? this.operations?.get(id) : undefined;
50
32
  }
51
- const vertex = dfg.getVertex(node.info.id);
52
- const call = vertex?.tag === vertex_1.VertexType.FunctionCall ? vertex : undefined;
53
- const origins = Array.isArray(call?.origin) ? call.origin : [];
54
- if (node.type === type_1.RType.Symbol) {
55
- const values = getVariableOrigins(node.info.id, dfg).map(origin => domain.get(origin.info.id));
56
- if (values.length > 0 && values.every(assert_1.isNotUndefined)) {
57
- return abstract_domain_1.AbstractDomain.joinAll(values);
33
+ evalFunctionCall(call, state) {
34
+ const node = this.getNormalizedAst(call.id);
35
+ if (node === undefined) {
36
+ return state;
58
37
  }
38
+ const operations = (0, function_mapper_1.mapDataFrameFunctionCall)(node, this, this.config.dfg, this.config.ctx);
39
+ return this.applyDataFrameExpression(node, operations, state);
59
40
  }
60
- else if (node.type === type_1.RType.Argument && node.value !== undefined) {
61
- return resolveIdToDataFrameShape(node.value, dfg, domain);
62
- }
63
- else if (node.type === type_1.RType.ExpressionList && node.children.length > 0) {
64
- return resolveIdToDataFrameShape(node.children[node.children.length - 1], dfg, domain);
41
+ evalReplacementCall(call, target, source, state) {
42
+ const node = this.getNormalizedAst(call.id);
43
+ const targetNode = this.getNormalizedAst(target);
44
+ const sourceNode = this.getNormalizedAst(source);
45
+ if (node === undefined || targetNode === undefined || sourceNode === undefined) {
46
+ return state;
47
+ }
48
+ const operations = (0, replacement_mapper_1.mapDataFrameReplacementFunction)(node, sourceNode, this, this.config.dfg, this.config.ctx);
49
+ return this.applyDataFrameExpression(node, operations, state);
65
50
  }
66
- else if (node.type === type_1.RType.Pipe) {
67
- return resolveIdToDataFrameShape(node.rhs, dfg, domain);
51
+ evalAccessCall(call, state) {
52
+ const node = this.getNormalizedAst(call.id);
53
+ if (node === undefined) {
54
+ return state;
55
+ }
56
+ const operations = (0, access_mapper_1.mapDataFrameAccess)(node, this, this.config.dfg, this.config.ctx);
57
+ return this.applyDataFrameExpression(node, operations, state);
68
58
  }
69
- else if (origins.includes('builtin:pipe')) {
70
- if (node.type === type_1.RType.BinaryOp) {
71
- return resolveIdToDataFrameShape(node.rhs, dfg, domain);
59
+ applyDataFrameExpression(node, operations, state) {
60
+ if (operations === undefined) {
61
+ return state;
72
62
  }
73
- else if (call?.args.length === 2 && call?.args[1] !== r_function_call_1.EmptyArgument) {
74
- return resolveIdToDataFrameShape(call.args[1].nodeId, dfg, domain);
63
+ else if (this.operations !== undefined) {
64
+ this.operations.set(node.info.id, operations);
75
65
  }
76
- }
77
- else if (node.type === type_1.RType.IfThenElse) {
78
- if (node.otherwise !== undefined) {
79
- const values = [node.then, node.otherwise].map(entry => resolveIdToDataFrameShape(entry, dfg, domain));
80
- if (values.length > 0 && values.every(assert_1.isNotUndefined)) {
81
- return abstract_domain_1.AbstractDomain.joinAll(values);
66
+ const maxColNames = this.config.ctx.config.abstractInterpretation.dataFrame.maxColNames;
67
+ let value = dataframe_domain_1.DataFrameDomain.top(maxColNames);
68
+ for (const { operation, operand, type, options, ...args } of operations) {
69
+ const operandValue = operand !== undefined ? this.getAbstractValue(operand, state) : value;
70
+ value = (0, semantics_1.applyDataFrameSemantics)(operation, operandValue ?? dataframe_domain_1.DataFrameDomain.top(maxColNames), args, options);
71
+ const constraintType = type ?? (0, semantics_1.getConstraintType)(operation);
72
+ if (operand !== undefined && constraintType === semantics_1.ConstraintType.OperandModification) {
73
+ state.set(operand, value);
74
+ for (const origin of this.getVariableOrigins(operand)) {
75
+ state.set(origin, value);
76
+ }
82
77
  }
83
- }
84
- }
85
- else if (origins.includes('builtin:if-then-else') && call?.args.every(arg => arg !== r_function_call_1.EmptyArgument)) {
86
- if (call.args.length === 3) {
87
- const values = call.args.slice(1, 3).map(entry => resolveIdToDataFrameShape(entry.nodeId, dfg, domain));
88
- if (values.length > 0 && values.every(assert_1.isNotUndefined)) {
89
- return abstract_domain_1.AbstractDomain.joinAll(values);
78
+ else if (constraintType === semantics_1.ConstraintType.ResultPostcondition) {
79
+ state.set(node.info.id, value);
90
80
  }
91
81
  }
82
+ return state;
92
83
  }
93
84
  }
94
- /**
95
- * Gets all origins of a variable in the data flow graph that have already been visited.
96
- * @param node - The node to get the origins for
97
- * @param dfg - The data flow graph for resolving the origins
98
- * @returns The origins nodes of the variable
99
- */
100
- function getVariableOrigins(node, dfg) {
101
- // get each variable origin that has already been visited and whose assignment has already been processed
102
- return (0, dfg_get_origin_1.getOriginInDfg)(dfg, node)
103
- ?.filter(origin => origin.type === 0 /* OriginType.ReadVariableOrigin */)
104
- .map(entry => dfg.idMap?.get(entry.id))
105
- .filter(assert_1.isNotUndefined)
106
- .filter(origin => origin.info.dataFrame?.domain !== undefined)
107
- .filter(origin => !(0, absint_info_1.hasDataFrameInfoMarker)(origin, absint_info_1.DataFrameInfoMarker.Unassigned)) ?? [];
108
- }
85
+ exports.DataFrameShapeInferenceVisitor = DataFrameShapeInferenceVisitor;
109
86
  //# sourceMappingURL=shape-inference.js.map
@@ -34,10 +34,10 @@ export declare class BoundedSetDomain<T, Value extends BoundedSetLift<T> = Bound
34
34
  bottom(): this & BoundedSetDomain<T, BoundedSetBottom>;
35
35
  equals(other: this): boolean;
36
36
  leq(other: this): boolean;
37
- join(other: this): this;
38
37
  join(other: BoundedSetLift<T> | T[]): this;
39
- meet(other: this): this;
38
+ join(other: this): this;
40
39
  meet(other: BoundedSetLift<T> | T[]): this;
40
+ meet(other: this): this;
41
41
  /**
42
42
  * Subtracts another abstract value from the current abstract value by removing all elements of the other abstract value from the current abstract value.
43
43
  */
@@ -27,10 +27,10 @@ export declare class IntervalDomain<Value extends IntervalLift = IntervalLift> e
27
27
  bottom(): this & IntervalDomain<IntervalBottom>;
28
28
  equals(other: this): boolean;
29
29
  leq(other: this): boolean;
30
- join(other: this): this;
31
30
  join(other: IntervalLift): this;
32
- meet(other: this): this;
31
+ join(other: this): this;
33
32
  meet(other: IntervalLift): this;
33
+ meet(other: this): this;
34
34
  widen(other: this): this;
35
35
  narrow(other: this): this;
36
36
  concretize(limit: number): ReadonlySet<number> | typeof Top;
@@ -19,6 +19,11 @@ type SetRangeTop = typeof SetRangeTop;
19
19
  type SetRangeBottom = typeof Bottom;
20
20
  /** The type of the abstract values of the set range domain that are Top, Bottom, or actual values */
21
21
  type SetRangeLift<T> = SetRangeValue<T> | SetRangeTop | SetRangeBottom;
22
+ /** The type of the actual values of the set range domain with a finite range (the range cannot be Top) */
23
+ type SetRangeFinite<T> = {
24
+ readonly min: ReadonlySet<T>;
25
+ readonly range: ReadonlySet<T>;
26
+ };
22
27
  /** The type of the actual values of the set range domain as array tuple with a minimum array and range array for better readability (e.g. `[["id","name"], []]`, or `[["id"], ["score"]]`) */
23
28
  export type ArrayRangeValue<T> = {
24
29
  readonly min: T[];
@@ -48,11 +53,11 @@ export declare class SetRangeDomain<T, Value extends SetRangeLift<T> = SetRangeL
48
53
  /**
49
54
  * The minimum set (lower bound) of the set range representing all values that must exist (subset of {@link upper}).
50
55
  */
51
- lower(): SetRangeValue<T>['min'] | typeof Bottom;
56
+ lower(): Value extends SetRangeValue<T> ? ReadonlySet<T> : ReadonlySet<T> | typeof Bottom;
52
57
  /**
53
58
  * The maximum set (upper bound) of the set range representing all values that can possibly exist (union of {@link lower} and range).
54
59
  */
55
- upper(): SetRangeValue<T>['range'] | typeof Bottom;
60
+ upper(): Value extends SetRangeFinite<T> ? ReadonlySet<T> : Value extends SetRangeValue<T> ? ReadonlySet<T> | typeof Top : ReadonlySet<T> | typeof Top | typeof Bottom;
56
61
  static top<T>(limit?: SetRangeLimit | number, setType?: typeof Set<T>): SetRangeDomain<T, SetRangeTop>;
57
62
  static bottom<T>(limit?: SetRangeLimit | number, setType?: typeof Set<T>): SetRangeDomain<T, SetRangeBottom>;
58
63
  static abstract<T>(concrete: ReadonlySet<ReadonlySet<T>> | typeof Top, limit?: SetRangeLimit | number, setType?: typeof Set<T>): SetRangeDomain<T>;
@@ -60,10 +65,10 @@ export declare class SetRangeDomain<T, Value extends SetRangeLift<T> = SetRangeL
60
65
  bottom(): this & SetRangeDomain<T, SetRangeBottom>;
61
66
  equals(other: this): boolean;
62
67
  leq(other: this): boolean;
63
- join(other: this): this;
64
68
  join(other: SetRangeLift<T> | ArrayRangeValue<T>): this;
65
- meet(other: this): this;
69
+ join(other: this): this;
66
70
  meet(other: SetRangeLift<T> | ArrayRangeValue<T>): this;
71
+ meet(other: this): this;
67
72
  /**
68
73
  * Creates the union of this abstract value and another abstract value by creating the union of the minimum and maximum set, respectively.
69
74
  */
@@ -94,5 +99,6 @@ export declare class SetRangeDomain<T, Value extends SetRangeLift<T> = SetRangeL
94
99
  isTop(): this is SetRangeDomain<T, SetRangeTop>;
95
100
  isBottom(): this is SetRangeDomain<T, SetRangeBottom>;
96
101
  isValue(): this is SetRangeDomain<T, SetRangeValue<T>>;
102
+ isFinite(): this is SetRangeDomain<T, SetRangeFinite<T>>;
97
103
  }
98
104
  export {};
@@ -61,7 +61,10 @@ class SetRangeDomain extends abstract_domain_1.AbstractDomain {
61
61
  if (this.value === lattice_1.Bottom) {
62
62
  return lattice_1.Bottom;
63
63
  }
64
- return this.value.range === lattice_1.Top ? lattice_1.Top : this.value.min.union(this.value.range);
64
+ else if (this.value.range == lattice_1.Top) {
65
+ return lattice_1.Top;
66
+ }
67
+ return this.value.min.union(this.value.range);
65
68
  }
66
69
  static top(limit, setType) {
67
70
  return new SetRangeDomain(exports.SetRangeTop, limit, setType);
@@ -395,6 +398,9 @@ class SetRangeDomain extends abstract_domain_1.AbstractDomain {
395
398
  isValue() {
396
399
  return this.value !== lattice_1.Bottom;
397
400
  }
401
+ isFinite() {
402
+ return this.value !== lattice_1.Bottom && this.value.range !== lattice_1.Top;
403
+ }
398
404
  }
399
405
  exports.SetRangeDomain = SetRangeDomain;
400
406
  //# sourceMappingURL=set-range-domain.js.map
@@ -32,10 +32,10 @@ export declare class SetUpperBoundDomain<T, Value extends SetUpperBoundLift<T> =
32
32
  bottom(): this & SetUpperBoundDomain<T, SetUpperBoundBottom>;
33
33
  equals(other: this): boolean;
34
34
  leq(other: this): boolean;
35
- join(other: this): this;
36
35
  join(other: SetUpperBoundLift<T> | T[]): this;
37
- meet(other: this): this;
36
+ join(other: this): this;
38
37
  meet(other: SetUpperBoundLift<T> | T[]): this;
38
+ meet(other: this): this;
39
39
  /**
40
40
  * Subtracts another abstract value from the current abstract value by removing all elements of the other abstract value from the current abstract value.
41
41
  */
@@ -25,10 +25,10 @@ export declare class SingletonDomain<T, Value extends SingletonLift<T> = Singlet
25
25
  bottom(): this & SingletonDomain<T, SingletonBottom>;
26
26
  equals(other: this): boolean;
27
27
  leq(other: this): boolean;
28
- join(other: this): this;
29
28
  join(other: SingletonLift<T>): this;
30
- meet(other: this): this;
29
+ join(other: this): this;
31
30
  meet(other: SingletonLift<T>): this;
31
+ meet(other: this): this;
32
32
  widen(other: this): this;
33
33
  narrow(other: this): this;
34
34
  concretize(): ReadonlySet<T> | typeof Top;
@@ -26,7 +26,6 @@ const vertex_1 = require("../dataflow/graph/vertex");
26
26
  const arrays_1 = require("../util/collections/arrays");
27
27
  const config_1 = require("../config");
28
28
  const extract_cfg_1 = require("../control-flow/extract-cfg");
29
- const absint_info_1 = require("../abstract-interpretation/data-frame/absint-info");
30
29
  const shape_inference_1 = require("../abstract-interpretation/data-frame/shape-inference");
31
30
  const lattice_1 = require("../abstract-interpretation/domains/lattice");
32
31
  const set_range_domain_1 = require("../abstract-interpretation/domains/set-range-domain");
@@ -291,7 +290,7 @@ class BenchmarkSlicer {
291
290
  (0, assert_1.guard)(this.normalizedAst !== undefined, 'normalizedAst should be defined for data frame shape inference');
292
291
  (0, assert_1.guard)(this.dataflow !== undefined, 'dataflow should be defined for data frame shape inference');
293
292
  (0, assert_1.guard)(this.controlFlow !== undefined, 'controlFlow should be defined for data frame shape inference');
294
- (0, assert_1.guard)(this.config !== undefined, 'config should be defined for data frame shape inference');
293
+ (0, assert_1.guard)(this.context !== undefined, 'context should be defined for data frame shape inference');
295
294
  const ast = this.normalizedAst;
296
295
  const dfg = this.dataflow.graph;
297
296
  const cfinfo = this.controlFlow;
@@ -308,7 +307,9 @@ class BenchmarkSlicer {
308
307
  sizeOfInfo: 0,
309
308
  perNodeStats: new Map()
310
309
  };
311
- const result = this.measureSimpleStep('infer data frame shapes', () => (0, shape_inference_1.inferDataFrameShapes)(cfinfo, dfg, ast, this.context));
310
+ const inference = new shape_inference_1.DataFrameShapeInferenceVisitor({ controlFlow: cfinfo, dfg, normalizedAst: ast, ctx: this.context });
311
+ this.measureSimpleStep('infer data frame shapes', () => inference.start());
312
+ const result = inference.getEndState();
312
313
  stats.numberOfResultConstraints = result.value.size;
313
314
  for (const value of result.value.values()) {
314
315
  if (value.isTop()) {
@@ -321,23 +322,21 @@ class BenchmarkSlicer {
321
322
  stats.numberOfResultingValues++;
322
323
  }
323
324
  }
324
- (0, visitor_1.visitAst)(this.normalizedAst.ast.files.map(f => f.root), (node) => {
325
- if (node.info.dataFrame === undefined) {
326
- return;
327
- }
328
- stats.sizeOfInfo += (0, size_of_1.safeSizeOf)([node.info.dataFrame]);
329
- const expression = (0, absint_info_1.hasDataFrameExpressionInfo)(node) ? node.info.dataFrame : undefined;
330
- const value = node.info.dataFrame.domain?.get(node.info.id);
325
+ (0, visitor_1.visitAst)(this.normalizedAst.ast.files.map(file => file.root), node => {
326
+ const operations = inference.getAbstractOperations(node.info.id);
327
+ const value = inference.getAbstractValue(node.info.id);
331
328
  // Only store per-node information for nodes representing expressions or nodes with abstract values
332
- if (expression === undefined && value === undefined) {
329
+ if (operations === undefined && value === undefined) {
333
330
  stats.numberOfEmptyNodes++;
334
331
  return;
335
332
  }
333
+ const state = inference.getAbstractState(node.info.id);
334
+ stats.sizeOfInfo += (0, size_of_1.safeSizeOf)([state]);
336
335
  const nodeStats = {
337
- numberOfEntries: node.info.dataFrame?.domain?.value.size ?? 0
336
+ numberOfEntries: state?.value.size ?? 0
338
337
  };
339
- if (expression !== undefined) {
340
- nodeStats.mappedOperations = expression.operations.map(op => op.operation);
338
+ if (operations !== undefined) {
339
+ nodeStats.mappedOperations = operations.map(op => op.operation);
341
340
  stats.numberOfOperationNodes++;
342
341
  if (value !== undefined) {
343
342
  nodeStats.inferredColNames = this.getInferredNumber(value.colnames);