@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.
Files changed (81) hide show
  1. package/README.md +37 -20
  2. package/abstract-interpretation/absint-visitor.d.ts +17 -21
  3. package/abstract-interpretation/absint-visitor.js +47 -48
  4. package/abstract-interpretation/data-frame/dataframe-domain.d.ts +0 -3
  5. package/abstract-interpretation/data-frame/shape-inference.d.ts +2 -1
  6. package/abstract-interpretation/data-frame/shape-inference.js +5 -4
  7. package/abstract-interpretation/domains/abstract-domain.d.ts +17 -16
  8. package/abstract-interpretation/domains/abstract-domain.js +25 -27
  9. package/abstract-interpretation/domains/bounded-set-domain.js +1 -1
  10. package/abstract-interpretation/domains/multi-value-state-domain.d.ts +32 -0
  11. package/abstract-interpretation/domains/multi-value-state-domain.js +60 -0
  12. package/abstract-interpretation/domains/partial-product-domain.d.ts +43 -0
  13. package/abstract-interpretation/domains/partial-product-domain.js +163 -0
  14. package/abstract-interpretation/domains/product-domain.d.ts +2 -29
  15. package/abstract-interpretation/domains/product-domain.js +6 -123
  16. package/abstract-interpretation/domains/set-range-domain.js +3 -3
  17. package/abstract-interpretation/domains/set-upper-bound-domain.js +1 -1
  18. package/abstract-interpretation/domains/singleton-domain.js +1 -1
  19. package/abstract-interpretation/domains/state-abstract-domain.d.ts +13 -28
  20. package/abstract-interpretation/domains/state-abstract-domain.js +16 -38
  21. package/abstract-interpretation/domains/state-domain-like.d.ts +36 -0
  22. package/abstract-interpretation/domains/state-domain-like.js +3 -0
  23. package/cli/flowr.js +11 -1
  24. package/config.d.ts +7 -0
  25. package/config.js +22 -3
  26. package/control-flow/semantic-cfg-guided-visitor.d.ts +4 -0
  27. package/control-flow/semantic-cfg-guided-visitor.js +20 -32
  28. package/dataflow/environments/default-builtin-config.d.ts +10 -0
  29. package/dataflow/environments/default-builtin-config.js +2 -1
  30. package/dataflow/internal/process/functions/call/built-in/built-in-eval.d.ts +2 -0
  31. package/dataflow/internal/process/functions/call/built-in/built-in-eval.js +38 -21
  32. package/documentation/doc-readme.js +13 -2
  33. package/documentation/wiki-absint.d.ts +1 -2
  34. package/documentation/wiki-absint.js +34 -10
  35. package/documentation/wiki-analyzer.js +3 -4
  36. package/documentation/wiki-interface.js +21 -16
  37. package/linter/linter-rules.d.ts +2 -2
  38. package/linter/rules/problematic-inputs.d.ts +4 -3
  39. package/linter/rules/problematic-inputs.js +3 -4
  40. package/package.json +3 -3
  41. package/project/flowr-analyzer-builder.d.ts +6 -3
  42. package/project/flowr-analyzer-builder.js +12 -5
  43. package/project/plugins/file-plugins/files/flowr-rmarkdown-file.d.ts +4 -3
  44. package/project/plugins/file-plugins/files/flowr-rmarkdown-file.js +17 -4
  45. package/project/plugins/flowr-analyzer-plugin.d.ts +1 -1
  46. package/project/plugins/flowr-analyzer-plugin.js +1 -1
  47. package/queries/catalog/input-sources-query/input-source-functions.d.ts +6 -0
  48. package/queries/catalog/input-sources-query/input-source-functions.js +50 -0
  49. package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +1 -1
  50. package/queries/catalog/input-sources-query/input-sources-query-executor.js +19 -53
  51. package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +2 -1
  52. package/queries/catalog/input-sources-query/input-sources-query-format.js +26 -11
  53. package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +18 -41
  54. package/queries/catalog/input-sources-query/simple-input-classifier.js +165 -103
  55. package/r-bridge/lang-4.x/ast/model/model.d.ts +4 -4
  56. package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +3 -3
  57. package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +3 -3
  58. package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +3 -3
  59. package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +3 -3
  60. package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +3 -3
  61. package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +3 -3
  62. package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +3 -3
  63. package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +3 -3
  64. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +3 -3
  65. package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +3 -3
  66. package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +3 -3
  67. package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +3 -3
  68. package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +3 -3
  69. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +3 -3
  70. package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +3 -3
  71. package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +3 -3
  72. package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +3 -3
  73. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +3 -3
  74. package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +3 -3
  75. package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +3 -3
  76. package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +3 -3
  77. package/util/record.d.ts +18 -3
  78. package/util/record.js +22 -1
  79. package/util/version.js +1 -1
  80. package/project/plugins/flowr-analyzer-plugin-defaults.d.ts +0 -5
  81. package/project/plugins/flowr-analyzer-plugin-defaults.js +0 -37
@@ -3,8 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WikiAbsint = void 0;
4
4
  const absint_visitor_1 = require("../abstract-interpretation/absint-visitor");
5
5
  const abstract_domain_1 = require("../abstract-interpretation/domains/abstract-domain");
6
+ const bounded_set_domain_1 = require("../abstract-interpretation/domains/bounded-set-domain");
6
7
  const interval_domain_1 = require("../abstract-interpretation/domains/interval-domain");
7
8
  const lattice_1 = require("../abstract-interpretation/domains/lattice");
9
+ const multi_value_state_domain_1 = require("../abstract-interpretation/domains/multi-value-state-domain");
8
10
  const state_abstract_domain_1 = require("../abstract-interpretation/domains/state-abstract-domain");
9
11
  const semantic_cfg_guided_visitor_1 = require("../control-flow/semantic-cfg-guided-visitor");
10
12
  const identifier_1 = require("../dataflow/environments/identifier");
@@ -15,10 +17,13 @@ const doc_code_1 = require("./doc-util/doc-code");
15
17
  const doc_structure_1 = require("./doc-util/doc-structure");
16
18
  const doc_maker_1 = require("./wiki-mk/doc-maker");
17
19
  class IntervalInferenceVisitor extends absint_visitor_1.AbstractInterpretationVisitor {
20
+ constructor(config) {
21
+ super(config, state_abstract_domain_1.StateAbstractDomain.top(interval_domain_1.IntervalDomain.top()));
22
+ }
18
23
  onNumberConstant({ vertex, node }) {
19
24
  super.onNumberConstant({ vertex, node });
20
25
  const interval = new interval_domain_1.IntervalDomain([node.content.num, node.content.num]);
21
- this.updateState(node.info.id, interval);
26
+ this.currentState.set(node.info.id, interval);
22
27
  }
23
28
  onFunctionCall({ call }) {
24
29
  super.onFunctionCall({ call });
@@ -32,9 +37,9 @@ class IntervalInferenceVisitor extends absint_visitor_1.AbstractInterpretationVi
32
37
  // We map the numerical operation to the resulting interval after applying the abstract semantics of the operation
33
38
  switch (identifier_1.Identifier.getName(call.name)) {
34
39
  case '+':
35
- return this.updateState(call.id, left.add(right));
40
+ return this.currentState.set(call.id, left.add(right));
36
41
  case '-':
37
- return this.updateState(call.id, left.subtract(right));
42
+ return this.currentState.set(call.id, left.subtract(right));
38
43
  }
39
44
  }
40
45
  }
@@ -52,7 +57,7 @@ async function inferIntervals() {
52
57
  const dfg = (await analyzer.dataflow()).graph;
53
58
  const cfg = await analyzer.controlflow(undefined, cfg_kind_1.CfgKind.NoFunctionDefs);
54
59
  const ctx = analyzer.inspectContext();
55
- const inference = new IntervalInferenceVisitor({ controlFlow: cfg, dfg: dfg, normalizedAst: ast, ctx: ctx }, interval_domain_1.IntervalDomain.top());
60
+ const inference = new IntervalInferenceVisitor({ controlFlow: cfg, dfg: dfg, normalizedAst: ast, ctx: ctx });
56
61
  inference.start();
57
62
  const result = inference.getEndState();
58
63
  return result.isValue() ? result.value.entries().toArray()
@@ -63,6 +68,21 @@ function nodeIdToSlicingCriterion(id, idMap) {
63
68
  const node = idMap.get(id);
64
69
  return `${node?.location?.[0]}@${node?.lexeme}`;
65
70
  }
71
+ function multiValueExample() {
72
+ const domain = {
73
+ number: new interval_domain_1.IntervalDomain(interval_domain_1.IntervalTop),
74
+ string: new bounded_set_domain_1.BoundedSetDomain(lattice_1.Top)
75
+ };
76
+ const reduction = ({ number, string }) => {
77
+ if (number?.isBottom() || string?.isBottom()) {
78
+ return { number: domain.number.bottom(), string: domain.string.bottom() };
79
+ }
80
+ return { number, string };
81
+ };
82
+ const state = new multi_value_state_domain_1.MultiValueStateDomain(new Map(), domain, [reduction]);
83
+ state.setValue(0, 'number', new interval_domain_1.IntervalDomain([42, 42]));
84
+ state.setValue(1, 'string', new bounded_set_domain_1.BoundedSetDomain(new Set(['Hello world!'])));
85
+ }
66
86
  class WikiAbsint extends doc_maker_1.DocMaker {
67
87
  constructor() {
68
88
  super('wiki/Abstract Interpretation.md', module.filename, 'abstract interpretation framework');
@@ -113,30 +133,34 @@ All boxes link to their respective implementation in the source code.
113
133
  ${(0, doc_code_1.codeBlock)('mermaid', ctx.mermaid(abstract_domain_1.AbstractDomain, { simplify: true, reverse: true }))}
114
134
  `.trim())}
115
135
 
136
+ Multiple abstract domains can be combined using a ${ctx.link(multi_value_state_domain_1.MultiValueDomain)} (for example, to use an interval domain for numbers and bounded set domain for strings at the same time). A multi-value state domain (${ctx.link(multi_value_state_domain_1.MultiValueStateDomain)}) as state domain of a multi-value domain can be used to track the state of multiple value domains in a program. Additionally, is enables to define reductions on the multi-value domain to refine the inferred value for a value domain based on the other value domains in the multi-value domain. For example, the following example shows how a multi-value state domain can be defined to track numbers and strings at the same time with a simple reduction that sets both domains to bottom if one domain is bottom.
137
+
138
+ ${ctx.code(multiValueExample, { dropLinesStart: 1, dropLinesEnd: 1 })}
139
+
116
140
  ${(0, doc_structure_1.section)('Abstract Interpretation', 2, 'abstract-interpretation')}
117
141
 
118
142
  We perform abstract interpretation by forward-traversing the ${ctx.linkPage('wiki/Control Flow Graph', 'control flow graph')} of _flowR_ using an ${ctx.link(absint_visitor_1.AbstractInterpretationVisitor)}. For each visited control flow vertex, the visitor retrieves the current abstract state by joining the abstract states of the predecessors, applies the abstract semantics of the visited control flow vertex to the current state, and updates the abstract state of the currently visited vertex to the current state. The visitor already handles assignments and (delayed) widening at widening points. However, the visitor does not yet support interprocedural abstract interpretation.
119
143
 
120
- To implement a custom abstract interpretation analysis, we can just create a new class and extend the ${ctx.link(absint_visitor_1.AbstractInterpretationVisitor)}. The abstract interpretation visitor uses a ${ctx.link(state_abstract_domain_1.StateAbstractDomain)} to capture the current abstract state at each vertex in the control flow graph. Hence, the abstract interpretation visitor requires a value abstract domain \`Domain\` as type parameter to specify the state abstract domain. We can then extend the callback functions of the ${ctx.link(absint_visitor_1.AbstractInterpretationVisitor)} to implement the abstract semantics of expressions, such as ${ctx.link(`${semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor.name}:::onNumberConstant`)}, ${ctx.link(`${absint_visitor_1.AbstractInterpretationVisitor.name}:::onFunctionCall`)}, and ${ctx.link(`${semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor.name}:::onReplacementCall`)} (make sure to still call the respective super function). The abstract interpretation visitor provides the following functions to retrieve the currently inferred values:
144
+ To implement a custom abstract interpretation analysis, we can just create a new class and extend the ${ctx.link(absint_visitor_1.AbstractInterpretationVisitor)}. The abstract interpretation visitor uses a \`StateDomain\` (e.g., a ${ctx.link(state_abstract_domain_1.StateAbstractDomain)}) to capture the current abstract state at each vertex in the control flow graph. We can then extend the callback functions of the ${ctx.link(absint_visitor_1.AbstractInterpretationVisitor)} to implement the abstract semantics of expressions, such as ${ctx.link(`${semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor.name}:::onNumberConstant`)}, ${ctx.link(`${absint_visitor_1.AbstractInterpretationVisitor.name}:::onFunctionCall`)} and ${ctx.link(`${semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor.name}:::onReplacementCall`)} (make sure to still call the respective super function). The abstract interpretation visitor provides the following functions to retrieve the currently inferred values:
121
145
 
122
146
  * ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'getAbstractValue')} to resolve the inferred abstract value for an AST node (this includes resolving symbols, pipes, and if expressions)
123
147
  * ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'getAbstractState')} to get the inferred abstract state at an AST node mapping AST nodes to abstract values
124
148
  * ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'getAbstractTrace')} to get the complete abstract trace mapping AST nodes to abstract states at the respective node
125
149
  * ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'getEndState')} to get the inferred abstract state at the end of the program (at the exit points of the control flow graph)
126
150
 
127
- For example, if we want to perform a (very basic) interval analysis using abstract interpretation in _flowR_, we can implement the following ${ctx.link(IntervalInferenceVisitor)} that extends ${ctx.link(absint_visitor_1.AbstractInterpretationVisitor)} using the ${ctx.link(interval_domain_1.IntervalDomain)}:
151
+ For example, if we want to perform a (very basic) interval analysis using abstract interpretation in _flowR_, we can implement the following ${ctx.link(IntervalInferenceVisitor)} that extends ${ctx.link(absint_visitor_1.AbstractInterpretationVisitor)} using a ${ctx.link(state_abstract_domain_1.StateAbstractDomain)} for the ${ctx.link(interval_domain_1.IntervalDomain)}:
128
152
 
129
- ${ctx.code(IntervalInferenceVisitor)}
153
+ ${ctx.code(inferIntervals, { dropLinesStart: 1, dropLinesEnd: 5 })}
130
154
 
131
- The interval inference visitor first overrides the ${ctx.link(`${semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor.name}:::onNumberConstant`)} function to infer intervals for visited control flow vertices that represent numeric constants. For numeric constants, the resulting interval consists just of the number value of the constant. We then update the current abstract state of the visitor via ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'updateState', { hideClass: true })} by setting the inferred abstract value of the currently visited control flow vertex to the new interval.
155
+ The interval inference visitor first overrides the ${ctx.link(`${semantic_cfg_guided_visitor_1.SemanticCfgGuidedVisitor.name}:::onNumberConstant`)} function to infer intervals for visited control flow vertices that represent numeric constants. For numeric constants, the resulting interval consists just of the number value of the constant. We then update the current abstract state of the visitor by setting the inferred abstract value of the currently visited control flow vertex to the new interval.
132
156
 
133
- In this simple example, we only want to support the addition and subtraction of numeric values. Therefore, we override the ${ctx.link(`${absint_visitor_1.AbstractInterpretationVisitor.name}:::onFunctionCall`)} function to apply the abstract semantics of additions and subtraction with resprect to the interval domain. For the addition and subtraction, we are only interested in function calls with exactly two non-empty arguments. We first resolve the currently inferred abstract value for the left and right operand of the function call. If we have no inferred value for one of the operands, this function call might not be a numeric function call and we ignore it. Otherwise, we check whether the function call represents an addition or subtraction and apply the abstract semantics of the operation to the left and right operand. We then again update the current abstract state of the visitor via ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'updateState', { hideClass: true })} by setting the inferred abstract value of the currently visited function call vertex to the abstract value resulting from applying the abstract semantics of the operation to the operands.
157
+ In this simple example, we only want to support the addition and subtraction of numeric values. Therefore, we override the ${ctx.link(`${absint_visitor_1.AbstractInterpretationVisitor.name}:::onFunctionCall`)} function to apply the abstract semantics of additions and subtraction with resprect to the interval domain. For the addition and subtraction, we are only interested in function calls with exactly two non-empty arguments. We first resolve the currently inferred abstract value for the left and right operand of the function call. If we have not inferred a value for one of the operands, this function call might not be a numeric function call and we ignore it. Otherwise, we check whether the function call represents an addition or subtraction and apply the abstract semantics of the operation to the left and right operand. We then again update the current abstract state of the visitor by setting the inferred abstract value of the currently visited function call vertex to the abstract value resulting from applying the abstract semantics of the operation to the operands.
134
158
 
135
159
  If we now want to run the interval inference, we can write the following code:
136
160
 
137
161
  ${ctx.code(inferIntervals, { dropLinesStart: 1, dropLinesEnd: 5 })}
138
162
 
139
- We first need a ${ctx.linkPage('wiki/Analyzer', 'flowR analyzer')} (in this case, using the ${ctx.linkPage('wiki/Engines', 'tree-sitter engine')}). In this example, we want to analyze a small example code that assigns \`42\` to the variable \`x\`, randomly assigns \`6\` or \`12\` to the variable \`y\`, and assignes the sum of \`x\` and \`y\` to the variable \`z\`. For the abstract interpretation visitor, we need to retrieve the ${ctx.linkPage('wiki/Normalized AST', 'normalized AST')}, ${ctx.linkPage('wiki/Dataflow Graph', 'dataflow graph')}, ${ctx.linkPage('wiki/Control Flow Graph', 'control flow graph')}, context of the flowR anaylzer, and provide a value domain for the state domain. For performance reasons, we construct the control flow graph without simplification passes, data flow information, and function definitions. We then create a new ${ctx.link(IntervalInferenceVisitor)} using the control flow graph, dataflow graph, normalized AST, and analyzer context, and start the visitor using ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'start', { hideClass: true })}. After the visitor is finished, we retrieve the inferred abstract state at the end of the program using ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'getEndState', { hideClass: true })}.
163
+ We first need a ${ctx.linkPage('wiki/Analyzer', 'flowR analyzer')} (in this case, using the ${ctx.linkPage('wiki/Engines', 'tree-sitter engine')}). In this example, we want to analyze a small example code that assigns \`42\` to the variable \`x\`, randomly assigns \`6\` or \`12\` to the variable \`y\`, and assignes the sum of \`x\` and \`y\` to the variable \`z\`. For the abstract interpretation visitor, we need to retrieve the ${ctx.linkPage('wiki/Normalized AST', 'normalized AST')}, ${ctx.linkPage('wiki/Dataflow Graph', 'dataflow graph')}, ${ctx.linkPage('wiki/Control Flow Graph', 'control flow graph')}, and context of the flowR anaylzer. For performance reasons, we construct the control flow graph without simplification passes, data flow information, and function definitions. We then create a new ${ctx.link(IntervalInferenceVisitor)} using the control flow graph, dataflow graph, normalized AST, and analyzer context, and start the visitor using ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'start', { hideClass: true })}. After the visitor is finished, we retrieve the inferred abstract state at the end of the program using ${ctx.linkM(absint_visitor_1.AbstractInterpretationVisitor, 'getEndState', { hideClass: true })}.
140
164
 
141
165
  If we now print the inferred abstract state at the end of the program, we get the following output:
142
166
 
@@ -22,7 +22,6 @@ const flowr_analyzer_loading_order_context_1 = require("../project/context/flowr
22
22
  const flowr_analyzer_dependencies_context_1 = require("../project/context/flowr-analyzer-dependencies-context");
23
23
  const flowr_analyzer_cache_1 = require("../project/cache/flowr-analyzer-cache");
24
24
  const pipeline_executor_1 = require("../core/pipeline-executor");
25
- const flowr_analyzer_plugin_defaults_1 = require("../project/plugins/flowr-analyzer-plugin-defaults");
26
25
  const doc_maker_1 = require("./wiki-mk/doc-maker");
27
26
  const flowr_analyzer_rmd_file_plugin_1 = require("../project/plugins/file-plugins/notebooks/flowr-analyzer-rmd-file-plugin");
28
27
  const flowr_analyzer_plugin_1 = require("../project/plugins/flowr-analyzer-plugin");
@@ -219,7 +218,7 @@ This indicates three ways to add a new plugin:
219
218
  3. By providing a tuple of the plugin name and its constructor arguments (e.g., \`['file:rmd', [/.*.rmd/i]]\` for the ${ctx.link(flowr_analyzer_rmd_file_plugin_1.FlowrAnalyzerRmdFilePlugin)}).\\
220
219
  This will also use the ${ctx.link(plugin_registry_1.makePlugin)} function under the hood to create the plugin instance.
221
220
 
222
- Please note, that by passing \`false\` to the builder constructor, no default plugins (see ${ctx.link(flowr_analyzer_plugin_defaults_1.FlowrAnalyzerPluginDefaults)}) are registered (otherwise, all of the plugins in the example above would be registered by default).
221
+ Please note, that by passing \`false\` to the builder constructor, no default plugins (see ${ctx.link('FlowrDefaultPlugins')}) are registered (otherwise, all of the plugins in the example above would be registered by default).
223
222
  If you want to unregister specific plugins, you can use the ${ctx.linkM(flowr_analyzer_builder_1.FlowrAnalyzerBuilder, 'unregisterPlugins')} method.
224
223
 
225
224
  ${(0, doc_structure_1.block)({
@@ -251,7 +250,7 @@ Plugins allow you to extend the capabilities of the analyzer in many different w
251
250
  For example, they can be used to support other file formats, or to provide new algorithms to determine the loading order of files in a project.
252
251
  All plugins have to extend the ${ctx.link(flowr_analyzer_plugin_1.FlowrAnalyzerPlugin)} base class and specify their ${ctx.link('PluginType')}.
253
252
  During the analysis, the analyzer will apply all registered plugins of the different types at the appropriate stages of the analysis.
254
- If you just want to _use_ these plugins, you can usually ignore their [type](#plugin-types) and just register them with the builder as described
253
+ If you just want to _use_ these plugins, you can usually ignore their [type](#plugin-types) and just register them with the builder as described
255
254
  in the [Builder Configuration](#builder-configuration) section above.
256
255
  However, if you want to _create_ new plugins, you should be aware of the different plugin types and when they are applied during the analysis.
257
256
 
@@ -285,7 +284,7 @@ ${(0, doc_structure_1.section)('Project Discovery', 4)}
285
284
 
286
285
  These plugins trigger when confronted with a project analysis request (see, ${ctx.link('RProjectAnalysisRequest')}).
287
286
  Their job is to identify the files that belong to the project and add them to the analysis.
288
- flowR provides the ${ctx.link(flowr_analyzer_project_discovery_plugin_1.FlowrAnalyzerProjectDiscoveryPlugin)} with a
287
+ flowR provides the ${ctx.link(flowr_analyzer_project_discovery_plugin_1.FlowrAnalyzerProjectDiscoveryPlugin)} with a
289
288
  ${ctx.link(flowr_analyzer_project_discovery_plugin_1.FlowrAnalyzerProjectDiscoveryPlugin.defaultPlugin.name)} as the default implementation that simply collects all R source files in the given folder.
290
289
 
291
290
  Please note that all project discovery plugins should conform to the ${ctx.link(flowr_analyzer_project_discovery_plugin_1.FlowrAnalyzerProjectDiscoveryPlugin)} base class.
@@ -20,6 +20,7 @@ const doc_structure_1 = require("./doc-util/doc-structure");
20
20
  const doc_maker_1 = require("./wiki-mk/doc-maker");
21
21
  const doc_writing_code_1 = require("./data/interface/doc-writing-code");
22
22
  const built_in_proc_name_1 = require("../dataflow/environments/built-in-proc-name");
23
+ const flowr_analyzer_1 = require("../project/flowr-analyzer");
23
24
  async function explainServer(parser) {
24
25
  (0, doc_data_server_messages_1.documentAllServerMessages)();
25
26
  return `
@@ -42,7 +43,7 @@ ${await (0, doc_server_message_1.printServerMessages)(parser)}
42
43
  ### 📡 Ways of Connecting
43
44
 
44
45
  If you are interested in clients that communicate with _flowR_, please check out the [R adapter](${doc_files_1.FlowrGithubBaseRef}/flowr-r-adapter)
45
- as well as the [Visual Studio Code extension](${doc_files_1.FlowrGithubBaseRef}/vscode-flowr).
46
+ as well as the [Visual Studio Code extension](${doc_files_1.FlowrGithubBaseRef}/vscode-flowr).
46
47
 
47
48
  <ol>
48
49
 
@@ -99,9 +100,9 @@ async function explainRepl(parser, ctx) {
99
100
  > To execute arbitrary R commands with a repl request, _flowR_ has to be started explicitly with ${ctx.cliOption('flowr', 'r-session-access')}.
100
101
  > Please be aware that this introduces a security risk and note that this relies on the ${ctx.linkPage('wiki/Engines', '`r-shell` engine')} .
101
102
 
102
- Although primarily meant for users to explore,
103
- there is nothing which forbids simply calling _flowR_ as a subprocess to use standard-in, -output, and -error
104
- for communication (although you can access the REPL using the server as well,
103
+ Although primarily meant for users to explore,
104
+ there is nothing which forbids simply calling _flowR_ as a subprocess to use standard-in, -output, and -error
105
+ for communication (although you can access the REPL using the server as well,
105
106
  with the [REPL Request](#message-request-repl-execution) message).
106
107
 
107
108
  The read-eval-print loop&nbsp;(REPL) works relatively simple.
@@ -111,7 +112,7 @@ The best command to get started with the REPL is ${ctx.replCmd('help')}.
111
112
  Besides, you can leave the REPL either with the command ${ctx.replCmd('quit')} or by pressing <kbd>Ctrl</kbd>+<kbd>C</kbd> twice.
112
113
  When writing a *command*, you may press <kbd>Tab</kbd> to get a list of completions, if available.
113
114
  Multiple commands can be entered in a single line by separating them with a semicolon (\`;\`), e.g. \`:parse "x<-2"; :df*\`.
114
- If a command is given without R code, the REPL will re-use R code given in a previous command.
115
+ If a command is given without R code, the REPL will re-use R code given in a previous command.
115
116
  The prior example will hence return first the parsed AST of the program and then the dataflow graph for \`"x <- 2"\`.
116
117
 
117
118
  > [!NOTE]
@@ -144,7 +145,7 @@ can be used to also modify the currently active configuration of _flowR_ within
144
145
 
145
146
  ### Example: Retrieving the Dataflow Graph
146
147
 
147
- To retrieve a URL to the [mermaid](https://mermaid.js.org/) diagram of the dataflow of a given expression,
148
+ To retrieve a URL to the [mermaid](https://mermaid.js.org/) diagram of the dataflow of a given expression,
148
149
  use ${ctx.replCmd('dataflow*')} (or ${ctx.replCmd('dataflow')} to get the mermaid code in the cli):
149
150
 
150
151
  ${await (0, doc_repl_1.documentReplSession)(parser, [{
@@ -163,8 +164,8 @@ For the slicing with ${ctx.replCmd('slicer')}, you have access to the same [magi
163
164
 
164
165
  ### Example: Interfacing with the File System
165
166
 
166
- Many commands that allow for an R-expression (like ${ctx.replCmd('dataflow*')}) allow for a file as well
167
- if the argument starts with \`${retriever_1.fileProtocol}\`.
167
+ Many commands that allow for an R-expression (like ${ctx.replCmd('dataflow*')}) allow for a file as well
168
+ if the argument starts with \`${retriever_1.fileProtocol}\`.
168
169
  If you are working from the root directory of the _flowR_ repository, the following gives you the parsed AST of the example file using the ${ctx.replCmd('parse')} command:
169
170
 
170
171
  ${await (0, doc_repl_1.documentReplSession)(parser, [{
@@ -179,7 +180,7 @@ ${(0, doc_code_1.codeBlock)('r', (0, doc_files_1.getFileContentFromRoot)('test/t
179
180
 
180
181
  </details>
181
182
 
182
- As _flowR_ directly transforms this AST the output focuses on being human-readable instead of being machine-readable.
183
+ As _flowR_ directly transforms this AST the output focuses on being human-readable instead of being machine-readable.
183
184
  `
184
185
  }])}
185
186
 
@@ -203,8 +204,8 @@ For more information on the available queries, please check out the ${ctx.linkPa
203
204
  function explainConfigFile(ctx) {
204
205
  return `
205
206
 
206
- When running _flowR_, you may want to specify some behaviors with a dedicated configuration file.
207
- By default, flowR looks for a file named \`${flowr_main_options_1.defaultConfigFile}\` in the current working directory (or any higher directory).
207
+ When running _flowR_, you may want to specify some behaviors with a dedicated configuration file.
208
+ By default, flowR looks for a file named \`${flowr_main_options_1.defaultConfigFile}\` in the current working directory (or any higher directory).
208
209
  You can also specify a different file with ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'config-file')} or pass the configuration inline using ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'config-json')}.
209
210
  To inspect the current configuration, you can run flowr with the ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'verbose')} flag, or use the \`config\` [Query](${doc_files_1.FlowrWikiBaseRef}/Query%20API).
210
211
  Within the REPL this works by running the following:
@@ -216,13 +217,15 @@ ${ctx.linkO(config_1.FlowrConfig, 'amend')}.
216
217
  The following summarizes the configuration options:
217
218
 
218
219
  - \`ignoreSourceCalls\`: If set to \`true\`, _flowR_ will ignore source calls when analyzing the code, i.e., ignoring the inclusion of other files.
219
- - \`semantics\`: allows to configure the way _flowR_ handles R, although we currently only support \`semantics/environment/overwriteBuiltIns\`.
220
- You may use this to overwrite _flowR_'s handling of built-in function and even completely clear the preset definitions shipped with flowR.
220
+ - \`semantics\`: allows to configure the way _flowR_ handles R, although we currently only support \`semantics/environment/overwriteBuiltIns\`.
221
+ You may use this to overwrite _flowR_'s handling of built-in function and even completely clear the preset definitions shipped with flowR.
221
222
  See [Configure BuiltIn Semantics](#configure-builtin-semantics) for more information.
222
223
  - \`solver\`: allows to configure how _flowR_ resolves variables and their values (currently we support: ${Object.values(config_1.VariableResolve).map(v => `\`${v}\``).join(', ')}), as well as if pointer analysis should be active.
223
224
  - \`engines\`: allows to configure the engines used by _flowR_ to interact with R code. See the [Engines wiki page](${doc_files_1.FlowrWikiBaseRef}/Engines) for more information.
224
225
  - \`defaultEngine\`: allows to specify the default engine to use for interacting with R code. If not set, an arbitrary engine from the specified list will be used.
225
226
  - \`abstractInterpretation\`: allows to configure how _flowR_ performs abstract interpretation, although we currently only support data frame shape inference through abstract interpretation.
227
+ - \`defaultPlugins\`: allows to configure which plugins to load by default when creating a new ${ctx.link(flowr_analyzer_1.FlowrAnalyzer)} instance.
228
+ - \`repl.plugins\`: allows to configure which plugins to load in the _flowR_ REPL. Use \`flowr:default\` to reference the plugins specified by \`defaultPlugins\`.
226
229
 
227
230
  So you can configure _flowR_ by adding a file like the following:
228
231
 
@@ -241,9 +244,11 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify({
241
244
  }
242
245
  }
243
246
  },
247
+ defaultPlugins: ['file:description', 'versions:description'],
244
248
  repl: {
245
249
  quickStats: false,
246
- dfProcessorHeat: false
250
+ dfProcessorHeat: false,
251
+ plugins: ['flowr:default']
247
252
  },
248
253
  project: {
249
254
  resolveUnknownPathsOnDisk: true
@@ -277,9 +282,9 @@ ${(0, doc_code_1.codeBlock)('json', JSON.stringify({
277
282
 
278
283
  </details>
279
284
 
280
- <details>
285
+ <details>
281
286
  <a id='configure-builtin-semantics'></a>
282
- <summary>Configure Built-In Semantics</summary>
287
+ <summary>Configure Built-In Semantics</summary>
283
288
 
284
289
 
285
290
  \`semantics/environment/overwriteBuiltins\` accepts two keys:
@@ -283,14 +283,14 @@ export declare const LintingRules: {
283
283
  };
284
284
  readonly 'problematic-inputs': {
285
285
  readonly createSearch: (config: import("./rules/problematic-inputs").ProblematicInputsConfig) => import("../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
286
- readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: import("./rules/problematic-inputs").ProblematicInputsConfig, data: {
286
+ readonly processSearchResult: (elements: import("../search/flowr-search").FlowrSearchElements<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../search/flowr-search").FlowrSearchElement<import("../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: import("./rules/problematic-inputs").ProblematicInputsConfig, data: {
287
287
  normalize: import("../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
288
288
  dataflow: import("../dataflow/info").DataflowInformation;
289
289
  cfg: import("../control-flow/control-flow-graph").ControlFlowInformation;
290
290
  analyzer: import("../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider;
291
291
  }) => Promise<{
292
292
  results: import("./rules/problematic-inputs").ProblematicInputsResult[];
293
- ".meta": import("./rules/problematic-inputs").ProblematicInputsMetadata;
293
+ '.meta': {};
294
294
  }>;
295
295
  readonly prettyPrint: {
296
296
  readonly query: (result: import("./rules/problematic-inputs").ProblematicInputsResult) => string;
@@ -2,7 +2,7 @@ import { type LintingResult, LintingRuleCertainty } from '../linter-format';
2
2
  import type { MergeableRecord } from '../../util/objects';
3
3
  import { SourceLocation } from '../../util/range';
4
4
  import { LintingRuleTag } from '../linter-tags';
5
- import type { InputSources } from '../../queries/catalog/input-sources-query/simple-input-classifier';
5
+ import type { InputClassifierConfig, InputSources } from '../../queries/catalog/input-sources-query/simple-input-classifier';
6
6
  /**
7
7
  * Describes a linting result for a problematic eval usage, including the location of the eval call and the computed input sources that lead to it.
8
8
  */
@@ -13,18 +13,19 @@ export interface ProblematicInputsResult extends LintingResult {
13
13
  }
14
14
  export interface ProblematicInputsConfig extends MergeableRecord {
15
15
  consider?: string | string[];
16
+ inputFns?: InputClassifierConfig;
16
17
  }
17
18
  export type ProblematicInputsMetadata = MergeableRecord;
18
19
  export declare const PROBLEMATIC_INPUTS: {
19
20
  readonly createSearch: (config: ProblematicInputsConfig) => import("../../search/flowr-search-builder").FlowrSearchBuilder<"from-query", [], import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>>;
20
- readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, _config: ProblematicInputsConfig, data: {
21
+ readonly processSearchResult: (elements: import("../../search/flowr-search").FlowrSearchElements<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation, import("../../search/flowr-search").FlowrSearchElement<import("../../r-bridge/lang-4.x/ast/model/processing/decorate").ParentInformation>[]>, config: ProblematicInputsConfig, data: {
21
22
  normalize: import("../../r-bridge/lang-4.x/ast/model/processing/decorate").NormalizedAst;
22
23
  dataflow: import("../../dataflow/info").DataflowInformation;
23
24
  cfg: import("../../control-flow/control-flow-graph").ControlFlowInformation;
24
25
  analyzer: import("../../project/flowr-analyzer").ReadonlyFlowrAnalysisProvider;
25
26
  }) => Promise<{
26
27
  results: ProblematicInputsResult[];
27
- ".meta": ProblematicInputsMetadata;
28
+ '.meta': {};
28
29
  }>;
29
30
  readonly prettyPrint: {
30
31
  readonly query: (result: ProblematicInputsResult) => string;
@@ -49,8 +49,7 @@ function isProblematicForAllowed(sources, allowed) {
49
49
  }
50
50
  exports.PROBLEMATIC_INPUTS = {
51
51
  createSearch: config => {
52
- const cfg = config;
53
- const considerArr = normalizeConsider(cfg);
52
+ const considerArr = normalizeConsider(config);
54
53
  const queries = considerArr.map((name, i) => ({
55
54
  type: 'call-context',
56
55
  callName: name,
@@ -59,13 +58,13 @@ exports.PROBLEMATIC_INPUTS = {
59
58
  }));
60
59
  return flowr_search_builder_1.Q.fromQuery(...queries);
61
60
  },
62
- processSearchResult: async (elements, _config, data) => {
61
+ processSearchResult: async (elements, config, data) => {
63
62
  const results = [];
64
63
  const defaultAccept = [simple_input_classifier_1.InputType.Constant, simple_input_classifier_1.InputType.DerivedConstant];
65
64
  for (const element of elements.getElements()) {
66
65
  const nid = element.node.info.id;
67
66
  const criterion = parse_1.SlicingCriterion.fromId(nid);
68
- const q = { type: 'input-sources', criterion };
67
+ const q = { type: 'input-sources', criterion, config: config.inputFns };
69
68
  const all = await data.analyzer.query([q]);
70
69
  const inputSourcesResult = all['input-sources'];
71
70
  const sources = inputSourcesResult?.results?.[criterion] ?? [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eagleoutice/flowr",
3
- "version": "2.10.4",
3
+ "version": "2.10.5",
4
4
  "description": "Static Dataflow Analyzer and Program Slicer for the R Programming Language",
5
5
  "types": "dist/src/index.d.ts",
6
6
  "repository": {
@@ -170,7 +170,7 @@
170
170
  "@eagleoutice/eslint-config-flowr": "^1.0.40",
171
171
  "@eslint/eslintrc": "^3.3.3",
172
172
  "@eslint/js": "^9.39.2",
173
- "@j-ulrich/release-it-regex-bumper": "^5.3.0",
173
+ "@j-ulrich/release-it-regex-bumper": "^5.4.0",
174
174
  "@types/command-line-args": "^5.2.3",
175
175
  "@types/command-line-usage": "^5.0.4",
176
176
  "@types/commonmark": "^0.27.10",
@@ -188,7 +188,7 @@
188
188
  "eslint": "^9.39.2",
189
189
  "license-checker-rseidelsohn": "^4.4.2",
190
190
  "npm-run-all": "^4.1.5",
191
- "release-it": "^19.2.3",
191
+ "release-it": "^20.0.0",
192
192
  "ts-node": "^10.9.2",
193
193
  "typedoc": "^0.28.17",
194
194
  "typedoc-plugin-missing-exports": "^4.1.2",
@@ -34,11 +34,12 @@ export declare class FlowrAnalyzerBuilder {
34
34
  private parser?;
35
35
  private input?;
36
36
  private readonly plugins;
37
+ private readonly withDefaultPlugins;
37
38
  /**
38
39
  * Creates a new builder for the {@link FlowrAnalyzer}.
39
- * By default, the standard set of plugins as returned by {@link FlowrAnalyzerPluginDefaults} are registered.
40
+ * By default, the standard set of plugins as returned by {@link FlowrConfig#defaultPlugins} are registered.
40
41
  * @param withDefaultPlugins - Whether to register the default plugins upon creation. Default is `true`.
41
- * @see {@link FlowrAnalyzerPluginDefaults} - for the default plugin set.
42
+ * @see {@link FlowrDefaultPlugins} - for the default plugin set.
42
43
  * @see {@link FlowrAnalyzerBuilder#registerPlugins} - to add more plugins.
43
44
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} - to remove plugins.
44
45
  */
@@ -53,6 +54,8 @@ export declare class FlowrAnalyzerBuilder {
53
54
  amendConfig(func: (config: DeepWritable<FlowrConfig>) => FlowrConfig | void): this;
54
55
  /**
55
56
  * Overwrite the configuration used by the resulting analyzer.
57
+ * This also unloads all default plugins and reloads them as set in the new config
58
+ * if the withDefaultPlugins flag was set in the constructor
56
59
  * @param config - The new configuration.
57
60
  */
58
61
  setConfig(config: FlowrConfig): this;
@@ -78,7 +81,7 @@ export declare class FlowrAnalyzerBuilder {
78
81
  setInput(input: Omit<NormalizeRequiredInput, 'context'>): this;
79
82
  /**
80
83
  * Register one or multiple additional plugins.
81
- * For the default plugin set, please refer to {@link FlowrAnalyzerPluginDefaults}, they can be registered
84
+ * For the default plugin set, please refer to {@link FlowrDefaultPlugins}, they can be registered
82
85
  * by passing `true` to the {@link FlowrAnalyzerBuilder} constructor.
83
86
  * @param plugin - One or multiple plugins to register.
84
87
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} to remove plugins.
@@ -7,7 +7,6 @@ const engines_1 = require("../engines");
7
7
  const assert_1 = require("../util/assert");
8
8
  const flowr_analyzer_context_1 = require("./context/flowr-analyzer-context");
9
9
  const flowr_analyzer_cache_1 = require("./cache/flowr-analyzer-cache");
10
- const flowr_analyzer_plugin_defaults_1 = require("./plugins/flowr-analyzer-plugin-defaults");
11
10
  const plugin_registry_1 = require("./plugins/plugin-registry");
12
11
  /**
13
12
  * Builder for the {@link FlowrAnalyzer}, use it to configure all analysis aspects before creating the analyzer instance
@@ -37,17 +36,19 @@ class FlowrAnalyzerBuilder {
37
36
  parser;
38
37
  input;
39
38
  plugins = new Map();
39
+ withDefaultPlugins;
40
40
  /**
41
41
  * Creates a new builder for the {@link FlowrAnalyzer}.
42
- * By default, the standard set of plugins as returned by {@link FlowrAnalyzerPluginDefaults} are registered.
42
+ * By default, the standard set of plugins as returned by {@link FlowrConfig#defaultPlugins} are registered.
43
43
  * @param withDefaultPlugins - Whether to register the default plugins upon creation. Default is `true`.
44
- * @see {@link FlowrAnalyzerPluginDefaults} - for the default plugin set.
44
+ * @see {@link FlowrDefaultPlugins} - for the default plugin set.
45
45
  * @see {@link FlowrAnalyzerBuilder#registerPlugins} - to add more plugins.
46
46
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} - to remove plugins.
47
47
  */
48
48
  constructor(withDefaultPlugins = true) {
49
+ this.withDefaultPlugins = withDefaultPlugins;
49
50
  if (withDefaultPlugins) {
50
- this.registerPlugins(...(0, flowr_analyzer_plugin_defaults_1.FlowrAnalyzerPluginDefaults)());
51
+ this.registerPlugins(...this.flowrConfig.defaultPlugins);
51
52
  }
52
53
  }
53
54
  /**
@@ -64,9 +65,15 @@ class FlowrAnalyzerBuilder {
64
65
  }
65
66
  /**
66
67
  * Overwrite the configuration used by the resulting analyzer.
68
+ * This also unloads all default plugins and reloads them as set in the new config
69
+ * if the withDefaultPlugins flag was set in the constructor
67
70
  * @param config - The new configuration.
68
71
  */
69
72
  setConfig(config) {
73
+ if (this.withDefaultPlugins) {
74
+ this.unregisterPlugins(...this.flowrConfig.defaultPlugins.map(p => Array.isArray(p) ? p[0] : p));
75
+ this.registerPlugins(...config.defaultPlugins);
76
+ }
70
77
  this.flowrConfig = config;
71
78
  return this;
72
79
  }
@@ -104,7 +111,7 @@ class FlowrAnalyzerBuilder {
104
111
  }
105
112
  /**
106
113
  * Register one or multiple additional plugins.
107
- * For the default plugin set, please refer to {@link FlowrAnalyzerPluginDefaults}, they can be registered
114
+ * For the default plugin set, please refer to {@link FlowrDefaultPlugins}, they can be registered
108
115
  * by passing `true` to the {@link FlowrAnalyzerBuilder} constructor.
109
116
  * @param plugin - One or multiple plugins to register.
110
117
  * @see {@link FlowrAnalyzerBuilder#unregisterPlugins} to remove plugins.
@@ -3,7 +3,7 @@ import { FlowrFile } from '../../../context/flowr-file';
3
3
  import { type Node } from 'commonmark';
4
4
  /**
5
5
  * This decorates a text file and parses its contents as a R Markdown file.
6
- * Finnaly, it provides access to the single cells, and all cells fused together as one R file.
6
+ * Finally, it provides access to the single cells, and all cells fused together as one R file.
7
7
  */
8
8
  export declare class FlowrRMarkdownFile extends FlowrFile<string> {
9
9
  private data?;
@@ -24,8 +24,9 @@ export declare class FlowrRMarkdownFile extends FlowrFile<string> {
24
24
  protected loadContent(): string;
25
25
  static from(file: FlowrFileProvider<string> | FlowrRMarkdownFile): FlowrRMarkdownFile;
26
26
  }
27
+ export type CodeBlockOptions = Map<string, string>;
27
28
  export interface CodeBlock {
28
- options: string;
29
+ options: CodeBlockOptions;
29
30
  code: string;
30
31
  }
31
32
  export type CodeBlockEx = CodeBlock & {
@@ -59,4 +60,4 @@ export declare function restoreBlocksWithoutMd(blocks: CodeBlockEx[], totalLines
59
60
  /**
60
61
  * Parses the options of an R code block from its header and content
61
62
  */
62
- export declare function parseCodeBlockOptions(header: string, content: string): string;
63
+ export declare function parseCodeBlockOptions(header: string, content: string): CodeBlockOptions;
@@ -15,7 +15,7 @@ const gray_matter_1 = __importDefault(require("gray-matter"));
15
15
  const log_1 = require("../../../../util/log");
16
16
  /**
17
17
  * This decorates a text file and parses its contents as a R Markdown file.
18
- * Finnaly, it provides access to the single cells, and all cells fused together as one R file.
18
+ * Finally, it provides access to the single cells, and all cells fused together as one R file.
19
19
  */
20
20
  class FlowrRMarkdownFile extends flowr_file_1.FlowrFile {
21
21
  data;
@@ -78,9 +78,14 @@ function parseRMarkdownFile(raw) {
78
78
  if (!isRCodeBlock(node)) {
79
79
  continue;
80
80
  }
81
+ const options = parseCodeBlockOptions(node.info, node.literal);
82
+ const engineOpt = options.get('engine');
83
+ if (engineOpt !== undefined && engineOpt.trim().toLowerCase() !== 'r') {
84
+ continue;
85
+ }
81
86
  blocks.push({
82
87
  code: node.literal,
83
- options: parseCodeBlockOptions(node.info, node.literal),
88
+ options: options,
84
89
  startpos: { line: node.sourcepos[0][0] + 1, col: 0 }
85
90
  });
86
91
  }
@@ -91,6 +96,7 @@ function parseRMarkdownFile(raw) {
91
96
  options: frontmatter?.data ?? {}
92
97
  };
93
98
  }
99
+ // We need the [\s,] part, otherwise {rust} would also match
94
100
  const RTagRegex = /{[rR](?:[\s,][^}]*)?}/;
95
101
  /**
96
102
  * Checks whether a CommonMark node is an R code block
@@ -123,6 +129,7 @@ function restoreBlocksWithoutMd(blocks, totalLines) {
123
129
  goToLine(totalLines + 1);
124
130
  return output;
125
131
  }
132
+ const OptionsRegex = /([\w_.-]*)\s*[:=]\s*["']?([^,"']*)/g;
126
133
  /**
127
134
  * Parses the options of an R code block from its header and content
128
135
  */
@@ -135,9 +142,15 @@ function parseCodeBlockOptions(header, content) {
135
142
  if (!line.trim().startsWith('#|')) {
136
143
  break;
137
144
  }
138
- const opt = line.substring(3);
145
+ const opt = line.substring(2).trim();
139
146
  opts += opts.length === 0 ? opt : `, ${opt}`;
140
147
  }
141
- return opts;
148
+ const parsedOptions = new Map();
149
+ for (const match of opts.matchAll(OptionsRegex)) {
150
+ if (match[1] && match[2] !== undefined) { // key must not be empty, but value can be empty string for example
151
+ parsedOptions.set(match[1], match[2]);
152
+ }
153
+ }
154
+ return parsedOptions;
142
155
  }
143
156
  //# sourceMappingURL=flowr-rmarkdown-file.js.map
@@ -73,7 +73,7 @@ export interface FlowrAnalyzerPluginInterface<In = unknown, Out = In> {
73
73
  * For example, if you want to create a plugin that determines the loading order of files, extend {@link FlowrAnalyzerLoadingOrderPlugin} instead.
74
74
  * These classes also provide sensible overrides of {@link FlowrAnalyzerPlugin.defaultPlugin} to be used when no plugin of this type is registered or triggered.
75
75
  *
76
- * For a collection of default plugins, see {@link FlowrAnalyzerPluginDefaults}.
76
+ * For a collection of default plugins, see {@link FlowrDefaultPlugins}.
77
77
  */
78
78
  export declare abstract class FlowrAnalyzerPlugin<In = unknown, Out extends AsyncOrSync<unknown> = In> implements FlowrAnalyzerPluginInterface<In, Out> {
79
79
  abstract readonly name: string;
@@ -53,7 +53,7 @@ const generalPluginLog = log_1.log.getSubLogger({ name: 'plugins' });
53
53
  * For example, if you want to create a plugin that determines the loading order of files, extend {@link FlowrAnalyzerLoadingOrderPlugin} instead.
54
54
  * These classes also provide sensible overrides of {@link FlowrAnalyzerPlugin.defaultPlugin} to be used when no plugin of this type is registered or triggered.
55
55
  *
56
- * For a collection of default plugins, see {@link FlowrAnalyzerPluginDefaults}.
56
+ * For a collection of default plugins, see {@link FlowrDefaultPlugins}.
57
57
  */
58
58
  class FlowrAnalyzerPlugin {
59
59
  /**
@@ -0,0 +1,6 @@
1
+ import type { Identifier } from '../../../dataflow/environments/identifier';
2
+ export declare const PureFunctions: Identifier[];
3
+ export declare const SystemFunctions: Identifier[];
4
+ export declare const FfiFunctions: Identifier[];
5
+ export declare const LangFunctions: Identifier[];
6
+ export declare const OptionsFunctions: Identifier[];