@eagleoutice/flowr 2.4.6 → 2.4.8

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 (107) hide show
  1. package/README.md +37 -33
  2. package/abstract-interpretation/data-frame/absint-visitor.js +3 -2
  3. package/abstract-interpretation/data-frame/dataframe-domain.d.ts +40 -0
  4. package/abstract-interpretation/data-frame/dataframe-domain.js +62 -0
  5. package/abstract-interpretation/data-frame/domain.js +1 -1
  6. package/abstract-interpretation/domains/abstract-domain.d.ts +56 -0
  7. package/abstract-interpretation/domains/abstract-domain.js +19 -0
  8. package/abstract-interpretation/domains/bounded-set-domain.d.ts +43 -0
  9. package/abstract-interpretation/domains/bounded-set-domain.js +121 -0
  10. package/abstract-interpretation/domains/interval-domain.d.ts +61 -0
  11. package/abstract-interpretation/domains/interval-domain.js +208 -0
  12. package/abstract-interpretation/domains/lattice.d.ts +62 -0
  13. package/abstract-interpretation/domains/lattice.js +12 -0
  14. package/abstract-interpretation/domains/positive-interval-domain.d.ts +32 -0
  15. package/abstract-interpretation/domains/positive-interval-domain.js +91 -0
  16. package/abstract-interpretation/domains/product-domain.d.ts +37 -0
  17. package/abstract-interpretation/domains/product-domain.js +133 -0
  18. package/abstract-interpretation/domains/set-bounded-set-domain.d.ts +43 -0
  19. package/abstract-interpretation/domains/set-bounded-set-domain.js +164 -0
  20. package/abstract-interpretation/domains/singleton-domain.d.ts +38 -0
  21. package/abstract-interpretation/domains/singleton-domain.js +115 -0
  22. package/abstract-interpretation/domains/state-abstract-domain.d.ts +32 -0
  23. package/abstract-interpretation/domains/state-abstract-domain.js +179 -0
  24. package/benchmark/slicer.js +1 -1
  25. package/benchmark/summarizer/first-phase/process.js +1 -1
  26. package/cli/repl/commands/repl-query.js +11 -2
  27. package/cli/repl/core.d.ts +2 -2
  28. package/cli/repl/core.js +26 -7
  29. package/cli/repl/server/connection.js +3 -1
  30. package/cli/repl/server/messages/message-slice.d.ts +3 -0
  31. package/cli/repl/server/messages/message-slice.js +2 -0
  32. package/control-flow/extract-cfg.d.ts +3 -3
  33. package/control-flow/extract-cfg.js +4 -4
  34. package/control-flow/useless-loop.js +30 -21
  35. package/dataflow/environments/built-in.d.ts +1 -1
  36. package/dataflow/environments/default-builtin-config.d.ts +9 -0
  37. package/dataflow/environments/default-builtin-config.js +21 -21
  38. package/dataflow/environments/environment.js +18 -9
  39. package/dataflow/environments/overwrite.js +2 -2
  40. package/dataflow/extractor.js +1 -1
  41. package/dataflow/graph/diff-dataflow-graph.js +4 -4
  42. package/dataflow/graph/graph.d.ts +3 -3
  43. package/dataflow/graph/graph.js +4 -1
  44. package/dataflow/graph/quads.js +4 -4
  45. package/dataflow/info.js +1 -1
  46. package/dataflow/internal/linker.d.ts +2 -0
  47. package/dataflow/internal/linker.js +18 -1
  48. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.d.ts +3 -1
  49. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +68 -21
  50. package/dataflow/internal/process/functions/call/built-in/built-in-expression-list.js +1 -2
  51. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +4 -4
  52. package/dataflow/internal/process/functions/call/built-in/built-in-if-then-else.js +5 -18
  53. package/dataflow/internal/process/functions/call/built-in/built-in-repeat-loop.js +1 -0
  54. package/dataflow/internal/process/functions/call/built-in/built-in-while-loop.js +4 -5
  55. package/dataflow/internal/process/functions/call/common.js +4 -3
  56. package/documentation/doc-util/doc-query.js +6 -2
  57. package/documentation/doc-util/doc-types.d.ts +7 -2
  58. package/documentation/doc-util/doc-types.js +20 -4
  59. package/documentation/print-core-wiki.js +5 -1
  60. package/documentation/print-dataflow-graph-wiki.js +21 -12
  61. package/documentation/print-faq-wiki.js +5 -0
  62. package/documentation/print-interface-wiki.js +2 -0
  63. package/documentation/print-linter-wiki.js +2 -3
  64. package/documentation/print-query-wiki.js +22 -7
  65. package/linter/linter-executor.js +25 -17
  66. package/linter/linter-format.d.ts +10 -1
  67. package/linter/linter-format.js +8 -0
  68. package/linter/linter-rules.d.ts +1 -0
  69. package/linter/rules/absolute-path.js +8 -8
  70. package/linter/rules/dataframe-access-validation.js +1 -1
  71. package/linter/rules/file-path-validity.js +8 -11
  72. package/linter/rules/naming-convention.d.ts +5 -1
  73. package/linter/rules/naming-convention.js +24 -8
  74. package/linter/rules/seeded-randomness.js +2 -2
  75. package/linter/rules/unused-definition.js +1 -1
  76. package/package.json +17 -15
  77. package/queries/catalog/call-context-query/call-context-query-executor.d.ts +5 -1
  78. package/queries/catalog/call-context-query/call-context-query-executor.js +14 -12
  79. package/queries/catalog/call-context-query/call-context-query-format.d.ts +6 -5
  80. package/queries/catalog/call-context-query/call-context-query-format.js +1 -1
  81. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.d.ts +2 -1
  82. package/queries/catalog/call-context-query/identify-link-to-last-call-relation.js +1 -1
  83. package/queries/catalog/config-query/config-query-executor.js +7 -1
  84. package/queries/catalog/config-query/config-query-format.d.ts +7 -0
  85. package/queries/catalog/config-query/config-query-format.js +72 -1
  86. package/queries/catalog/dependencies-query/dependencies-query-executor.js +50 -75
  87. package/queries/catalog/dependencies-query/dependencies-query-format.d.ts +50 -26
  88. package/queries/catalog/dependencies-query/dependencies-query-format.js +75 -20
  89. package/queries/catalog/dependencies-query/function-info/function-info.d.ts +2 -2
  90. package/queries/catalog/dependencies-query/function-info/visualize-functions.d.ts +2 -0
  91. package/queries/catalog/dependencies-query/function-info/visualize-functions.js +13 -0
  92. package/queries/catalog/happens-before-query/happens-before-query-executor.js +1 -1
  93. package/queries/catalog/linter-query/linter-query-format.js +4 -0
  94. package/queries/query-print.d.ts +2 -2
  95. package/queries/query-print.js +3 -2
  96. package/queries/query.d.ts +28 -21
  97. package/search/flowr-search-builder.d.ts +1 -1
  98. package/search/flowr-search-builder.js +1 -1
  99. package/search/flowr-search-filters.d.ts +20 -10
  100. package/search/flowr-search-filters.js +19 -3
  101. package/search/search-executor/search-enrichers.d.ts +1 -1
  102. package/search/search-executor/search-enrichers.js +3 -2
  103. package/search/search-executor/search-generators.js +1 -1
  104. package/search/search-executor/search-transformer.js +1 -1
  105. package/util/objects.d.ts +11 -0
  106. package/util/objects.js +26 -0
  107. package/util/version.js +1 -1
@@ -21,6 +21,7 @@ const named_call_handling_1 = require("../named-call-handling");
21
21
  const built_in_1 = require("../../../../../environments/built-in");
22
22
  const unknown_side_effect_1 = require("../../../../../graph/unknown-side-effect");
23
23
  const alias_tracking_1 = require("../../../../../eval/resolve/alias-tracking");
24
+ const r_value_1 = require("../../../../../eval/values/r-value");
24
25
  function toReplacementSymbol(target, prefix, superAssignment) {
25
26
  return {
26
27
  type: type_1.RType.Symbol,
@@ -87,18 +88,57 @@ args, rootId, data, config) {
87
88
  return (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, forceArgs: config.forceArgs, origin: 'default' }).information;
88
89
  }
89
90
  const { type, named } = target;
90
- if (!config.targetVariable && type === type_1.RType.Symbol) {
91
- const res = (0, known_call_handling_1.processKnownFunctionCall)({ name, args, rootId, data, reverseOrder: !config.swapSourceAndTarget, forceArgs: config.forceArgs, origin: 'builtin:assignment' });
92
- return processAssignmentToSymbol({
93
- ...config,
94
- nameOfAssignmentFunction: name.content,
95
- source,
96
- target,
97
- args: getEffectiveOrder(config, res.processedArguments),
98
- rootId,
99
- data,
100
- information: res.information,
101
- });
91
+ if (type === type_1.RType.Symbol) {
92
+ if (!config.targetVariable) {
93
+ const res = (0, known_call_handling_1.processKnownFunctionCall)({
94
+ name,
95
+ args,
96
+ rootId,
97
+ data,
98
+ reverseOrder: !config.swapSourceAndTarget,
99
+ forceArgs: config.forceArgs,
100
+ origin: 'builtin:assignment'
101
+ });
102
+ return processAssignmentToSymbol({
103
+ ...config,
104
+ nameOfAssignmentFunction: name.content,
105
+ source,
106
+ targetId: target.info.id,
107
+ args: getEffectiveOrder(config, res.processedArguments),
108
+ rootId,
109
+ data,
110
+ information: res.information,
111
+ });
112
+ }
113
+ else {
114
+ // try to resolve the variable first
115
+ const n = (0, alias_tracking_1.resolveIdToValue)(target.info.id, { environment: data.environment, resolve: data.flowrConfig.solver.variables, idMap: data.completeAst.idMap, full: true });
116
+ if (n.type === 'set' && n.elements.length === 1 && n.elements[0].type === 'string') {
117
+ const val = n.elements[0].value;
118
+ if ((0, r_value_1.isValue)(val)) {
119
+ const res = (0, known_call_handling_1.processKnownFunctionCall)({
120
+ name,
121
+ args,
122
+ rootId,
123
+ data,
124
+ reverseOrder: !config.swapSourceAndTarget,
125
+ forceArgs: config.forceArgs,
126
+ origin: 'builtin:assignment'
127
+ });
128
+ return processAssignmentToSymbol({
129
+ ...config,
130
+ nameOfAssignmentFunction: name.content,
131
+ source,
132
+ targetId: target.info.id,
133
+ targetName: val.str,
134
+ args: getEffectiveOrder(config, res.processedArguments),
135
+ rootId,
136
+ data,
137
+ information: res.information,
138
+ });
139
+ }
140
+ }
141
+ }
102
142
  }
103
143
  else if (config.canBeReplacement && type === type_1.RType.FunctionCall && named) {
104
144
  /* as replacement functions take precedence over the lhs fn-call (i.e., `names(x) <- ...` is independent from the definition of `names`), we do not have to process the call */
@@ -127,7 +167,7 @@ args, rootId, data, config) {
127
167
  ...config,
128
168
  nameOfAssignmentFunction: name.content,
129
169
  source,
130
- target: rootArg,
170
+ targetId: rootArg.info.id,
131
171
  args: getEffectiveOrder(config, res.processedArguments),
132
172
  rootId,
133
173
  data,
@@ -155,12 +195,12 @@ function extractSourceAndTarget(args) {
155
195
  * Promotes the ingoing/unknown references of target (an assignment) to definitions
156
196
  */
157
197
  function produceWrittenNodes(rootId, target, referenceType, data, makeMaybe, value) {
158
- return [...target.in, ...target.unknownReferences].map(ref => ({
198
+ return target.in.concat(target.unknownReferences).map(ref => ({
159
199
  ...ref,
160
200
  type: referenceType,
161
201
  definedAt: rootId,
162
202
  controlDependencies: data.controlDependencies ?? (makeMaybe ? [] : undefined),
163
- value: value
203
+ value
164
204
  }));
165
205
  }
166
206
  function processAssignmentToString(target, args, name, rootId, data, config, source) {
@@ -190,7 +230,7 @@ function processAssignmentToString(target, args, name, rootId, data, config, sou
190
230
  ...config,
191
231
  nameOfAssignmentFunction: name.content,
192
232
  source,
193
- target: symbol,
233
+ targetId: symbol.info.id,
194
234
  args: getEffectiveOrder(config, res.processedArguments),
195
235
  rootId,
196
236
  data,
@@ -269,19 +309,26 @@ function markAsAssignment(information, nodeToDefine, sourceIds, rootIdOfAssignme
269
309
  * Helper function whenever it is known that the _target_ of an assignment is a (single) symbol (i.e. `x <- ...`, but not `names(x) <- ...`).
270
310
  */
271
311
  function processAssignmentToSymbol(config) {
272
- const { nameOfAssignmentFunction, source, args: [targetArg, sourceArg], target, rootId, data, information, makeMaybe, quoteSource } = config;
312
+ const { nameOfAssignmentFunction, source, args: [targetArg, sourceArg], targetId, targetName, rootId, data, information, makeMaybe, quoteSource } = config;
273
313
  const referenceType = checkTargetReferenceType(source, sourceArg);
274
314
  const aliases = (0, alias_tracking_1.getAliases)([source.info.id], information.graph, information.environment);
275
- const writeNodes = produceWrittenNodes(rootId, targetArg, referenceType, data, makeMaybe ?? false, aliases);
315
+ const writeNodes = targetName ? [{
316
+ nodeId: targetId,
317
+ name: targetName,
318
+ type: referenceType,
319
+ definedAt: rootId,
320
+ controlDependencies: data.controlDependencies ?? (makeMaybe ? [] : undefined),
321
+ value: aliases
322
+ }]
323
+ : produceWrittenNodes(rootId, targetArg, referenceType, data, makeMaybe ?? false, aliases);
276
324
  if (writeNodes.length !== 1 && log_1.log.settings.minLevel <= 4 /* LogLevel.Warn */) {
277
325
  log_1.log.warn(`Unexpected write number in assignment: ${JSON.stringify(writeNodes)}`);
278
326
  }
279
327
  // we drop the first arg which we use to pass along arguments :D
280
328
  const readFromSourceWritten = sourceArg.out.slice(1);
281
329
  const readTargets = [
282
- { nodeId: rootId, name: nameOfAssignmentFunction, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function },
283
- ...sourceArg.unknownReferences, ...sourceArg.in, ...targetArg.in.filter(i => i.nodeId !== target.info.id), ...readFromSourceWritten
284
- ];
330
+ { nodeId: rootId, name: nameOfAssignmentFunction, controlDependencies: data.controlDependencies, type: identifier_1.ReferenceType.Function }
331
+ ].concat(sourceArg.unknownReferences, sourceArg.in, targetName ? targetArg.in : targetArg.in.filter(i => i.nodeId !== targetId), readFromSourceWritten);
285
332
  information.environment = (0, overwrite_1.overwriteEnvironment)(sourceArg.environment, targetArg.environment);
286
333
  // install assigned variables in environment
287
334
  for (const write of writeNodes) {
@@ -181,8 +181,7 @@ function processExpressionList(name, args, rootId, data) {
181
181
  graph: nextGraph,
182
182
  /* if we have no group, we take the last evaluated expr */
183
183
  entryPoint: meId,
184
- exitPoints: withGroup ? [{ nodeId: rootId, type: 0 /* ExitPointType.Default */, controlDependencies: data.controlDependencies }]
185
- : exitPoints
184
+ exitPoints: exitPoints
186
185
  };
187
186
  }
188
187
  //# sourceMappingURL=built-in-expression-list.js.map
@@ -30,14 +30,13 @@ function processForLoop(name, args, rootId, data) {
30
30
  const variable = (0, processor_1.processDataflowFor)(variableArg, data);
31
31
  // this should not be able to exit always!
32
32
  const originalDependency = data.controlDependencies;
33
- data = { ...data, controlDependencies: [...data.controlDependencies ?? [], { id: name.info.id, when: true }] };
34
33
  let headEnvironments = (0, overwrite_1.overwriteEnvironment)(vector.environment, variable.environment);
35
34
  const headGraph = variable.graph.mergeWith(vector.graph);
36
- const writtenVariable = [...variable.unknownReferences, ...variable.in];
35
+ const writtenVariable = variable.unknownReferences.concat(variable.in);
37
36
  for (const write of writtenVariable) {
38
37
  headEnvironments = (0, define_1.define)({ ...write, definedAt: name.info.id, type: identifier_1.ReferenceType.Variable }, false, headEnvironments, data.flowrConfig);
39
38
  }
40
- data = { ...data, environment: headEnvironments };
39
+ data = { ...data, controlDependencies: [...data.controlDependencies ?? [], { id: name.info.id, when: true }], environment: headEnvironments };
41
40
  const body = (0, processor_1.processDataflowFor)(bodyArg, data);
42
41
  const nextGraph = headGraph.mergeWith(body.graph);
43
42
  const outEnvironment = (0, append_1.appendEnvironment)(headEnvironments, body.environment);
@@ -48,8 +47,9 @@ function processForLoop(name, args, rootId, data) {
48
47
  nextGraph.addEdge(write.nodeId, vector.entryPoint, edge_1.EdgeType.DefinedBy);
49
48
  nextGraph.setDefinitionOfVertex(write);
50
49
  }
51
- const outgoing = [...variable.out, ...writtenVariable, ...(0, environment_1.makeAllMaybe)(body.out, nextGraph, outEnvironment, true)];
50
+ const outgoing = variable.out.concat(writtenVariable, (0, environment_1.makeAllMaybe)(body.out, nextGraph, outEnvironment, true));
52
51
  (0, linker_1.linkCircularRedefinitionsWithinALoop)(nextGraph, nameIdShares, body.out);
52
+ (0, linker_1.reapplyLoopExitPoints)(body.exitPoints, body.in.concat(body.out, body.unknownReferences));
53
53
  (0, common_1.patchFunctionCall)({
54
54
  nextGraph,
55
55
  rootId,
@@ -28,7 +28,7 @@ function processIfThenElse(name, args, rootId, data) {
28
28
  logger_1.dataflowLogger.warn(`If-then-else ${rootId} forces exit in condition, skipping rest`);
29
29
  return cond;
30
30
  }
31
- const originalDependency = data.controlDependencies;
31
+ const originalDependency = data.controlDependencies?.slice();
32
32
  // currently we update the cd afterward :sweat:
33
33
  data = { ...data, environment: cond.environment };
34
34
  let then;
@@ -73,21 +73,10 @@ function processIfThenElse(name, args, rootId, data) {
73
73
  const cdTrue = { id: rootId, when: true };
74
74
  const cdFalse = { id: rootId, when: false };
75
75
  // again within an if-then-else we consider all actives to be read
76
- const ingoing = [
77
- ...cond.in,
78
- ...(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.in, nextGraph, finalEnvironment, false, cdTrue) : then?.in ?? []),
79
- ...(makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.in, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.in ?? []),
80
- ...cond.unknownReferences,
81
- ...(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.unknownReferences, nextGraph, finalEnvironment, false, cdTrue) : then?.unknownReferences ?? []),
82
- ...(makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.unknownReferences, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.unknownReferences ?? []),
83
- ];
76
+ const ingoing = cond.in.concat(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.in, nextGraph, finalEnvironment, false, cdTrue) : then?.in ?? [], makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.in, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.in ?? [], cond.unknownReferences, makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.unknownReferences, nextGraph, finalEnvironment, false, cdTrue) : then?.unknownReferences ?? [], makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.unknownReferences, nextGraph, finalEnvironment, false, cdFalse) : otherwise?.unknownReferences ?? []);
84
77
  // we assign all with a maybe marker
85
78
  // we do not merge even if they appear in both branches because the maybe links will refer to different ids
86
- const outgoing = [
87
- ...cond.out,
88
- ...(makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.out, nextGraph, finalEnvironment, true, cdTrue) : then?.out ?? []),
89
- ...(makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.out, nextGraph, finalEnvironment, true, cdFalse) : otherwise?.out ?? []),
90
- ];
79
+ const outgoing = cond.out.concat((makeThenMaybe ? (0, environment_1.makeAllMaybe)(then?.out, nextGraph, finalEnvironment, true, cdTrue) : then?.out ?? []), (makeOtherwiseMaybe ? (0, environment_1.makeAllMaybe)(otherwise?.out, nextGraph, finalEnvironment, true, cdFalse) : otherwise?.out ?? []));
91
80
  (0, common_1.patchFunctionCall)({
92
81
  nextGraph,
93
82
  rootId,
@@ -98,10 +87,8 @@ function processIfThenElse(name, args, rootId, data) {
98
87
  });
99
88
  // as an if always evaluates its condition, we add a 'reads'-edge
100
89
  nextGraph.addEdge(name.info.id, cond.entryPoint, edge_1.EdgeType.Reads);
101
- const exitPoints = [
102
- ...(then?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeThenMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: true }] : e.controlDependencies })),
103
- ...(otherwise?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeOtherwiseMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: false }] : e.controlDependencies }))
104
- ];
90
+ const exitPoints = (then?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeThenMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: true }] : e.controlDependencies }))
91
+ .concat((otherwise?.exitPoints ?? []).map(e => ({ ...e, controlDependencies: makeOtherwiseMaybe ? [...data.controlDependencies ?? [], { id: rootId, when: false }] : e.controlDependencies })));
105
92
  return {
106
93
  unknownReferences: [],
107
94
  in: [{ nodeId: rootId, name: name.content, controlDependencies: originalDependency, type: identifier_1.ReferenceType.Function }, ...ingoing],
@@ -31,6 +31,7 @@ function processRepeatLoop(name, args, rootId, data) {
31
31
  const body = processedArguments[0];
32
32
  (0, assert_1.guard)(body !== undefined, () => `Repeat-Loop ${name.content} has no body, impossible!`);
33
33
  (0, linker_1.linkCircularRedefinitionsWithinALoop)(information.graph, (0, linker_1.produceNameSharedIdMap)((0, linker_1.findNonLocalReads)(information.graph, [])), body.out);
34
+ (0, linker_1.reapplyLoopExitPoints)(body.exitPoints, body.in.concat(body.out, body.unknownReferences));
34
35
  information.exitPoints = (0, info_1.filterOutLoopExitPoints)(information.exitPoints);
35
36
  return information;
36
37
  }
@@ -65,17 +65,16 @@ function processWhileLoop(name, args, rootId, data) {
65
65
  information.graph.addEdge(name.info.id, condition.entryPoint, edge_1.EdgeType.Reads);
66
66
  return condition;
67
67
  }
68
- const remainingInputs = (0, linker_1.linkInputs)([
69
- ...(0, environment_1.makeAllMaybe)(body.unknownReferences, information.graph, information.environment, false),
70
- ...(0, environment_1.makeAllMaybe)(body.in, information.graph, information.environment, false)
71
- ], information.environment, [...condition.in, ...condition.unknownReferences], information.graph, true);
68
+ const cdTrue = { id: name.info.id, when: true };
69
+ const remainingInputs = (0, linker_1.linkInputs)((0, environment_1.makeAllMaybe)(body.unknownReferences, information.graph, information.environment, false, cdTrue).concat((0, environment_1.makeAllMaybe)(body.in, information.graph, information.environment, false, cdTrue)), information.environment, condition.in.concat(condition.unknownReferences), information.graph, true);
72
70
  (0, linker_1.linkCircularRedefinitionsWithinALoop)(information.graph, (0, linker_1.produceNameSharedIdMap)((0, linker_1.findNonLocalReads)(information.graph, condition.in)), body.out);
71
+ (0, linker_1.reapplyLoopExitPoints)(body.exitPoints, body.in.concat(body.out, body.unknownReferences));
73
72
  // as the while-loop always evaluates its condition
74
73
  information.graph.addEdge(name.info.id, condition.entryPoint, edge_1.EdgeType.Reads);
75
74
  return {
76
75
  unknownReferences: [],
77
76
  in: [{ nodeId: name.info.id, name: name.lexeme, controlDependencies: originalDependency, type: identifier_1.ReferenceType.Function }, ...remainingInputs],
78
- out: [...(0, environment_1.makeAllMaybe)(body.out, information.graph, information.environment, true), ...condition.out],
77
+ out: condition.out.concat((0, environment_1.makeAllMaybe)(body.out, information.graph, information.environment, true, cdTrue)),
79
78
  entryPoint: name.info.id,
80
79
  exitPoints: (0, info_1.filterOutLoopExitPoints)(body.exitPoints),
81
80
  graph: information.graph,
@@ -29,11 +29,12 @@ function forceVertexArgumentValueReferences(rootId, value, graph, env) {
29
29
  }
30
30
  }
31
31
  }
32
- const containedSubflowIn = [...graph.vertices(true)]
32
+ const containedSubflowIn = graph.vertices(true)
33
33
  .filter(([, info]) => (0, vertex_1.isFunctionDefinitionVertex)(info))
34
- .flatMap(([, info]) => info);
34
+ .flatMap(([, info]) => info.subflow.in)
35
+ .toArray();
35
36
  // try to resolve them against the current environment
36
- for (const ref of [...value.in, ...containedSubflowIn.flatMap(n => n.subflow.in)]) {
37
+ for (const ref of value.in.concat(containedSubflowIn)) {
37
38
  if (ref.name) {
38
39
  const resolved = ref.name ? (0, resolve_by_name_1.resolveByName)(ref.name, env, ref.type) ?? [] : [];
39
40
  for (const resolve of resolved) {
@@ -25,7 +25,11 @@ async function showQuery(shell, code, queries, { showCode, collapseResult, colla
25
25
  parser: shell,
26
26
  request: (0, retriever_1.requestFromInput)(code)
27
27
  }, config_1.defaultConfigOptions).allRemainingSteps();
28
- const results = await Promise.resolve((0, query_1.executeQueries)({ dataflow: analysis.dataflow, ast: analysis.normalize, config: config_1.defaultConfigOptions }, queries));
28
+ const results = await Promise.resolve((0, query_1.executeQueries)({
29
+ dataflow: analysis.dataflow,
30
+ ast: analysis.normalize,
31
+ config: (0, config_1.cloneConfig)(config_1.defaultConfigOptions)
32
+ }, queries));
29
33
  const duration = performance.now() - now;
30
34
  const metaInfo = `
31
35
  The analysis required _${(0, time_1.printAsMs)(duration)}_ (including parsing and normalization and the query) within the generation environment.
@@ -48,7 +52,7 @@ ${collapseResult ? ' <details> <summary style="color:gray">Show Results</summary
48
52
 
49
53
  _Results (prettified and summarized):_
50
54
 
51
- ${(0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.markdownFormatter, duration, results, analysis)}
55
+ ${(0, query_print_1.asciiSummaryOfQueryResult)(ansi_1.markdownFormatter, duration, results, analysis, queries)}
52
56
 
53
57
  <details> <summary style="color:gray">Show Detailed Results as Json</summary>
54
58
 
@@ -1,8 +1,9 @@
1
1
  import ts from 'typescript';
2
+ export type TypeElementKind = 'interface' | 'type' | 'enum' | 'class' | 'variable';
2
3
  export interface TypeElementInSource {
3
4
  name: string;
4
5
  node: ts.Node;
5
- kind: 'interface' | 'type' | 'enum' | 'class' | 'variable';
6
+ kind: TypeElementKind;
6
7
  extends: string[];
7
8
  generics: string[];
8
9
  filePath: string;
@@ -73,5 +74,9 @@ export declare function printCodeOfElement({ program, info }: FnInfo, name: stri
73
74
  */
74
75
  export declare function shortLink(name: string, hierarchy: readonly TypeElementInSource[], codeStyle?: boolean, realNameWrapper?: string): string;
75
76
  export declare function shortLinkFile(name: string, hierarchy: readonly TypeElementInSource[]): string;
76
- export declare function getDocumentationForType(name: string, hierarchy: TypeElementInSource[], prefix?: string, fuzzy?: boolean): string;
77
+ export interface GetDocumentationForTypeFilters {
78
+ fuzzy?: boolean;
79
+ type?: TypeElementKind;
80
+ }
81
+ export declare function getDocumentationForType(name: string, hierarchy: TypeElementInSource[], prefix?: string, filter?: GetDocumentationForTypeFilters): string;
77
82
  export {};
@@ -32,7 +32,17 @@ const html_hover_over_1 = require("../../util/html-hover-over");
32
32
  const doc_general_1 = require("./doc-general");
33
33
  function getTypeScriptSourceFiles(fileNames) {
34
34
  try {
35
- const program = typescript_1.default.createProgram(fileNames, { target: typescript_1.default.ScriptTarget.ESNext });
35
+ const program = typescript_1.default.createProgram(fileNames, {
36
+ target: typescript_1.default.ScriptTarget.ESNext,
37
+ skipLibCheck: true,
38
+ skipDefaultLibCheck: true,
39
+ allowJs: true,
40
+ checkJs: false,
41
+ strictNullChecks: false,
42
+ noUncheckedIndexedAccess: false,
43
+ noUncheckedSideEffectImports: false,
44
+ noCheck: true
45
+ });
36
46
  return { program, files: fileNames.map(fileName => program.getSourceFile(fileName)).filter(file => !!file) };
37
47
  }
38
48
  catch (err) {
@@ -391,7 +401,7 @@ function fuzzyCompare(a, b) {
391
401
  const bStr = b.toLowerCase().replace(/[^a-z0-9]/g, '-').trim();
392
402
  return aStr === bStr || aStr.includes(bStr) || bStr.includes(aStr);
393
403
  }
394
- function retrieveNode(name, hierarchy, fuzzy = false) {
404
+ function retrieveNode(name, hierarchy, fuzzy = false, type = undefined) {
395
405
  let container = undefined;
396
406
  if (name.includes('::')) {
397
407
  [container, name] = name.split(/:::?/);
@@ -406,6 +416,12 @@ function retrieveNode(name, hierarchy, fuzzy = false) {
406
416
  return undefined;
407
417
  }
408
418
  }
419
+ if (type) {
420
+ node = node.filter(n => n.kind === type);
421
+ if (node.length === 0) {
422
+ return undefined;
423
+ }
424
+ }
409
425
  return [container, name, node[0]];
410
426
  }
411
427
  /**
@@ -440,8 +456,8 @@ function shortLinkFile(name, hierarchy) {
440
456
  const [, , node] = res;
441
457
  return `<a href="${getTypePathLink(node)}">${getTypePathForTypeScript(node)}</a>`;
442
458
  }
443
- function getDocumentationForType(name, hierarchy, prefix = '', fuzzy = false) {
444
- const res = retrieveNode(name, hierarchy, fuzzy);
459
+ function getDocumentationForType(name, hierarchy, prefix = '', filter) {
460
+ const res = retrieveNode(name, hierarchy, filter?.fuzzy, filter?.type);
445
461
  if (!res) {
446
462
  return '';
447
463
  }
@@ -50,6 +50,10 @@ async function getText(shell) {
50
50
  rootFolder: path_1.default.resolve('./src'),
51
51
  inlineTypes: doc_types_1.mermaidHide
52
52
  });
53
+ const testInfo = (0, doc_types_1.getTypesFromFolder)({
54
+ rootFolder: path_1.default.resolve('./test'),
55
+ inlineTypes: doc_types_1.mermaidHide
56
+ }).info;
53
57
  return `${(0, doc_auto_gen_1.autoGenHeader)({ filename: module.filename, purpose: 'core', rVersion: rversion })}
54
58
 
55
59
  This wiki page provides an overview of the inner workings of _flowR_.
@@ -390,7 +394,7 @@ ${await (0, doc_repl_1.documentReplSession)(shell, [{
390
394
  ### Getting flowR to Talk
391
395
 
392
396
  When using flowR from the CLI, you can use the ${(0, doc_cli_option_1.getCliLongOptionOf)('flowr', 'verbose')} option to get more information about what flowR is doing.
393
- While coding, however, you can use the ${(0, doc_types_1.shortLink)(log_1.setMinLevelOfAllLogs.name, info)} function to set the minimum level of logs to be displayed (this works with the ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name, info)} abstraction).
397
+ While coding, however, you can use the ${(0, doc_types_1.shortLink)(log_1.setMinLevelOfAllLogs.name, testInfo)} function to set the minimum level of logs to be displayed (this works with the ${(0, doc_types_1.shortLink)(log_2.FlowrLogger.name, info)} abstraction).
394
398
  In general, you can configure the levels of individual logs, such as the general \`log\` (obtained with ${(0, doc_types_1.shortLink)('getActiveLog', info)}) or the ${(0, doc_types_1.shortLink)('parseLog', info)}.
395
399
  Please note that flowR makes no guarantees that log outputs are persistent across versions, and it is up to the implementors to provide sensible logging.
396
400
  If you are an implementor and want to add logging, please make sure there are no larger runtime impliciations when logging is disabled.
@@ -74,7 +74,7 @@ async function explanation({ shell, name, type, description, code, expectedSubgr
74
74
  <a id='${name.toLowerCase().replaceAll(' ', '-')}'> </a>
75
75
  ### ${index}) ${name}
76
76
 
77
- Type: \`${type}\` (this is the numeric value of the bit-flag encountered when looking at the serialized vertex type)
77
+ Type: \`${type}\` (this is the bit-flag value, e.g., when looking at the serialization)
78
78
 
79
79
  ${await subExplanation(shell, { name, description, code, expectedSubgraph })}
80
80
 
@@ -268,7 +268,7 @@ ${await (async () => {
268
268
  const code = 'foo <- function() 3\nfoo()';
269
269
  const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, code, { exposeResult: true, mark: new Set([6, '6->0', '6->1', '6->3']) });
270
270
  const numberOfEdges = [...info.dataflow.graph.edges()].flatMap(e => [...e[1].keys()]).length;
271
- const callVertex = [...info.dataflow.graph.vertices(true)].find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionCall && vertex.name === 'foo');
271
+ const callVertex = info.dataflow.graph.vertices(true).find(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionCall && vertex.name === 'foo');
272
272
  (0, assert_1.guard)(callVertex !== undefined, () => `Could not find call vertex for ${code}`);
273
273
  const [callId] = callVertex;
274
274
  return `
@@ -367,11 +367,11 @@ ${(0, doc_structure_1.block)({
367
367
  content: `Now you might be asking yourself how to differentiate anonymous and named functions and what you have to keep in mind when working with them?
368
368
 
369
369
  Unnamed functions have an array of signatures which you can use to identify them.
370
- But in short - the \`origin\` attribute of the ${(0, doc_types_1.shortLink)('DataflowGraphVertexFunctionCall', vertexType.info)} is \`${unnamed_call_handling_1.UnnamedFunctionCallOrigin}\`.
370
+ But in short: the \`origin\` attribute of the ${(0, doc_types_1.shortLink)('DataflowGraphVertexFunctionCall', vertexType.info)} is \`${unnamed_call_handling_1.UnnamedFunctionCallOrigin}\`.
371
371
  Please be aware that unnamed functions still have a \`name\` property to give it a unique identifier that can be used for debugging and reference.
372
372
  This name _always_ starts with \`${unnamed_call_handling_1.UnnamedFunctionCallPrefix}\`.
373
373
 
374
- To identify these calls please do not rely on the [Normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST). An expression like \`1 + 1\` will be correctly
374
+ To identify these calls please do not rely on the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST). An expression like \`1 + 1\` will be correctly
375
375
  identified as a syntactical binary operation. Yet, from a dataflow/semantic perspective this is equivalent to \`\` \`+\`(1, 1) \`\` (which is a named function call and marked as such in the dataflow graph).
376
376
  To know which function is called, please rely on the ${linkEdgeName(edge_1.EdgeType.Calls)} edge.
377
377
  `
@@ -458,9 +458,10 @@ vertices of function definitions or not (e.g., \`${new graph_1.DataflowGraph(und
458
458
 
459
459
  ${(0, doc_structure_1.details)('Example: Nested Function Definitions', await (async () => {
460
460
  const [text, info] = await (0, doc_dfg_1.printDfGraphForCode)(shell, 'f <- function() { g <- function() 3 }', { mark: new Set([9, 6]), exposeResult: true });
461
- const definitions = [...info.dataflow.graph.vertices(true)]
461
+ const definitions = info.dataflow.graph.vertices(true)
462
462
  .filter(([, vertex]) => vertex.tag === vertex_1.VertexType.FunctionDefinition)
463
- .map(([id, vertex]) => `| \`${id}\` | { \`${[...vertex.subflow.graph].join('`, `')}\` } |`);
463
+ .map(([id, vertex]) => `| \`${id}\` | { \`${[...vertex.subflow.graph].join('`, `')}\` } |`)
464
+ .toArray();
464
465
  return `
465
466
  ${text}
466
467
 
@@ -766,6 +767,7 @@ async function getText(shell) {
766
767
 
767
768
  This page briefly summarizes flowR's dataflow graph, represented by the ${(0, doc_types_1.shortLink)(graph_1.DataflowGraph.name, vertexType.info)} class within the code.
768
769
  In case you want to manually build such a graph (e.g., for testing), you can use the ${(0, doc_types_1.shortLink)(dataflowgraph_builder_1.DataflowGraphBuilder.name, vertexType.info)}.
770
+ If you are interested in which features we support and which features are still to be worked on, please refer to our [capabilities](${doc_files_1.FlowrWikiBaseRef}/Capabilities) page.
769
771
  In summary, we discuss the following topics:
770
772
 
771
773
  - [Vertices](#vertices)
@@ -777,7 +779,7 @@ In summary, we discuss the following topics:
777
779
 
778
780
  Please be aware that the accompanied [dataflow information](#dataflow-information) (${(0, doc_types_1.shortLink)('DataflowInformation', vertexType.info)}) returned by _flowR_ contains things besides the graph,
779
781
  like the entry and exit points of the subgraphs, and currently active references (see [below](#dataflow-information)).
780
- Additionally, you may be interested in the set of [Unknown Side Effects](#unknown-side-effects) marking calls which _flowR_ is unable to handle correctly.
782
+ Additionally, you may be interested in the set of [Unknown Side Effects](#unknown-side-effects), marking calls which _flowR_ is unable to handle correctly.
781
783
 
782
784
  Potentially, you are interested in another perspective that flowR provides, the [control flow graph](${doc_files_1.FlowrWikiBaseRef}/Control%20Flow%20Graph), so please check the correpsonding
783
785
  wiki page if you are unsure.
@@ -829,16 +831,16 @@ From an implementation perspective all of these types are represented by respect
829
831
  The following sections present details on the different types of vertices and edges, including examples and explanations.
830
832
 
831
833
  > [!NOTE]
832
- > Every dataflow vertex holds an \`id\` which links it to the respective node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized%20AST).
834
+ > Every dataflow vertex holds an \`id\` which links it to the respective node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST).
833
835
  > So if you want more information about the respective vertex, you can usually access more information
834
836
  > using the <code>${(0, doc_types_1.shortLink)(`${graph_1.DataflowGraph.name}`, vertexType.info, false, 'i')}::idMap</code> linked to the dataflow graph:
835
837
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', 'const node = graph.idMap.get(id);'), '> ')}
836
838
  > In case you just need the name (\`lexeme\`) of the respective vertex, ${(0, doc_types_1.shortLink)(node_id_1.recoverName.name, vertexType.info)} can help you out:
837
839
  ${(0, doc_general_1.prefixLines)((0, doc_code_1.codeBlock)('ts', `const name = ${node_id_1.recoverName.name}(id, graph.idMap);`), '> ')}
838
840
  >
839
- > Please note that not every node in the normalized AST is represented in the dataflow graph.
841
+ > Please note, that not every node in the [normalized AST](${doc_files_1.FlowrWikiBaseRef}/Normalized-AST) is represented in the dataflow graph.
840
842
  > For example, if the node is unreachable in a way that can be detected during the analysis and flowR
841
- > is configured to ignore dead code. Likewise, empty argument wrappers do not have a corresponding
843
+ > is configured to ignore dead code (there are more powerful dead code capabilities with the [CFG](${doc_files_1.FlowrWikiBaseRef}/Control-Flow-Graph)). Likewise, empty argument wrappers do not have a corresponding
842
844
  > dataflow graph vertex (as they are not relevant for the dataflow graph). It depends on the scenario what to do in such a case.
843
845
  > For argument wrappers you can access the dataflow information for their value. For dead code, however, flowR currently contains
844
846
  > some core heuristics that remove it which cannot be reversed easily. So please open [an issue](${doc_issue_1.NewIssueUrl}) if you encounter such a case and require the node to be present in the dataflow graph.
@@ -990,7 +992,8 @@ Depending on what you are interested in, there exists a plethora of functions an
990
992
  * ${(0, doc_types_1.shortLink)(identify_link_to_last_call_relation_1.getValueOfArgument.name, vertexType.info)} to get the (syntactical) value of an argument in a function call
991
993
  * ${(0, doc_types_1.shortLink)(dfg_get_origin_1.getOriginInDfg.name, vertexType.info)} to get information about where a read, call, ... comes from (see [below](#dfg-resolving-values))
992
994
 
993
- Some of these functions have been explained in their respective wiki pages. However, some are part of the [Dataflow Graph API](${doc_files_1.FlowrWikiBaseRef}/Dataflow%20Graph%20API) and so we explain them here.
995
+ Some of these functions have been explained in their respective wiki pages. However, some are part of the [Dataflow Graph API](${doc_files_1.FlowrWikiBaseRef}/Dataflow-Graph) and so we explain them here.
996
+ If you are interested in which features we support and which features are still to be worked on, please refer to our [capabilities](${doc_files_1.FlowrWikiBaseRef}/Capabilities) page.
994
997
 
995
998
  ${(0, doc_structure_1.section)('Resolving Values', 3, 'dfg-resolving-values')}
996
999
 
@@ -999,6 +1002,12 @@ These capabilities are exposed by the [resolve value Query](${doc_files_1.FlowrW
999
1002
 
1000
1003
  ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)} provides an environment-sensitive (see ${(0, doc_types_1.shortLink)('REnvironmentInformation', vertexType.info)})
1001
1004
  value resolution depending on if the environment is provided.
1005
+ The idea of ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)} is to provide a compromise between precision and performance, to
1006
+ be used _during_ and _after_ the core analysis. After the dataflow analysis completes, there are much more expensive queries possible (such as the resolution of the data frame shape, see the [Query API](${doc_files_1.FlowrWikiBaseRef}/Query-API)).
1007
+
1008
+ Additionally, to ${(0, doc_types_1.shortLink)(alias_tracking_1.resolveIdToValue.name, vertexType.info)}, we offer the aforementioned ${(0, doc_types_1.shortLink)(identify_link_to_last_call_relation_1.getValueOfArgument.name, vertexType.info)} to retrieve the value of an argument in a function call.
1009
+ Be aware, that this function is currently not optimized for speed, so if you frequently require the values of multiple arguments of the same function call, you may want to open [an issue](${doc_issue_1.NewIssueUrl}) to request support for resolving
1010
+ multiple arguments at once.
1002
1011
 
1003
1012
  ${(0, doc_structure_1.section)('Assessing Edges', 3, 'dfg-assess-edge')}
1004
1013
 
@@ -1035,7 +1044,7 @@ ${(0, doc_types_1.printHierarchy)({ program: vertexType.program, info: vertexTyp
1035
1044
 
1036
1045
  Their respective uses are documented alongside their implementation:
1037
1046
 
1038
- ${['SimpleOrigin', 'FunctionCallOrigin', 'BuiltInFunctionOrigin'].sort().map(key => `- ${(0, doc_types_1.shortLink)(`${key}`, vertexType.info)}\\\n${(0, doc_types_1.getDocumentationForType)(`${key}`, vertexType.info)}`).join('\n')}
1047
+ ${['SimpleOrigin', 'FunctionCallOrigin', 'BuiltInFunctionOrigin'].sort().map(key => `- ${(0, doc_types_1.shortLink)(key, vertexType.info)}\\\n${(0, doc_types_1.getDocumentationForType)(key, vertexType.info, '', { type: 'interface' })}`).join('\n')}
1039
1048
 
1040
1049
  Please note, the current structure of this function is biased by what implementations already exist in flowR.
1041
1050
  Hence, we do not just track definitions and constants, but also the origins of function calls, albeit we do not yet track the origins of values (only resorting to
@@ -15,6 +15,11 @@ ${qAndA('What are test labels and how do they work?', `
15
15
  Tests are labeled based on the *flowR* capabilities that they test for. The list of supported capabilities can be found on the [Capabilities](${doc_files_1.FlowrWikiBaseRef}/Capabilities) wiki page. For more extensive information on test labels, see the [test labels wiki section](${doc_files_1.FlowrWikiBaseRef}/Linting-and-Testing#test-labels).
16
16
  `)}
17
17
 
18
+ ${qAndA('How to get a REPL with debug-info/hot-reload?', `
19
+ To enter the development repl, execute \`npm run main-dev\` in contrast to \`npm run flowr\` this will use an unminified build (keeping debug info)
20
+ and will also watch the source files for changes and automatically recompile them. Please note, that this may have negative performance implications.
21
+ `)}
22
+
18
23
  ${qAndA('How do I generate mermaid diagrams?', `
19
24
  There are several ways to generate mermaid diagrams based on the input data that you want to use.
20
25
  - From the AST (abstract syntax tree): ${(0, doc_files_1.getFilePathMd)('../util/mermaid/ast.ts')}
@@ -116,6 +116,8 @@ which is interpreted as an R&nbsp;expression by default but interpreted as a *co
116
116
  The best command to get started with the REPL is ${(0, doc_cli_option_1.getReplCommand)('help')}.
117
117
  Besides, you can leave the REPL either with the command ${(0, doc_cli_option_1.getReplCommand)('quit')} or by pressing <kbd>CTRL</kbd>+<kbd>C</kbd> twice.
118
118
 
119
+ > [!NOTE]
120
+ > If you develop flowR, you may want to launch the repl using the \`npm run main-dev\` command, this way, you get a non-minified version of flowR with debug information and hot-reloading of source files.
119
121
 
120
122
  <details>
121
123
  <summary>Available Commands</summary>
@@ -28,7 +28,7 @@ const SpecialTagColors = {
28
28
  [linter_tags_1.LintingRuleTag.QuickFix]: 'lightgray'
29
29
  };
30
30
  function makeTagBadge(name, info) {
31
- const doc = (0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, info, '', true).replaceAll('\n', ' ');
31
+ const doc = (0, doc_types_1.getDocumentationForType)('LintingRuleTag::' + name, info, '', { fuzzy: true }).replaceAll('\n', ' ');
32
32
  return (0, html_hover_over_1.textWithTooltip)(`<a href='#${name}'>![` + name + '](https://img.shields.io/badge/' + name.toLowerCase() + `-${SpecialTagColors[name] ?? 'teal'}) </a>`, doc);
33
33
  }
34
34
  function prettyPrintExpectedOutput(expected) {
@@ -66,7 +66,6 @@ These examples are synthesized from the test cases in: ${(0, doc_files_1.linkFlo
66
66
  }
67
67
  const testName = args[0].getText(report.source);
68
68
  if (report.comments?.some(c => c.includes('@ignore-in-wiki'))) {
69
- console.warn(`Skipping test case for linter rule ${testName} (${testFile}) as it is marked with @ignore-in-wiki`);
70
69
  continue;
71
70
  }
72
71
  // drop any quotes around the test name
@@ -133,7 +132,7 @@ df[6, "value"]
133
132
  }
134
133
  return a.localeCompare(b);
135
134
  }).map(t => makeTagBadge(t, types)).join(' ');
136
- const certaintyDoc = (0, doc_types_1.getDocumentationForType)(`LintingRuleCertainty::${rule.info.certainty}`, types, '', true).replaceAll('\n', ' ');
135
+ const certaintyDoc = (0, doc_types_1.getDocumentationForType)(`LintingRuleCertainty::${rule.info.certainty}`, types, '', { fuzzy: true }).replaceAll('\n', ' ');
137
136
  const certaintyText = `\`${(0, html_hover_over_1.textWithTooltip)(rule.info.certainty, certaintyDoc)}\``;
138
137
  if (format === 'short') {
139
138
  ruleExplanations.set(name, () => Promise.resolve(`
@@ -38,6 +38,7 @@ const control_flow_query_executor_1 = require("../queries/catalog/control-flow-q
38
38
  const doc_cfg_1 = require("./doc-util/doc-cfg");
39
39
  const df_shape_query_executor_1 = require("../queries/catalog/df-shape-query/df-shape-query-executor");
40
40
  const _00_slice_1 = require("../core/steps/all/static-slicing/00-slice");
41
+ const doc_repl_1 = require("./doc-util/doc-repl");
41
42
  (0, doc_query_1.registerQueryDocumentation)('call-context', {
42
43
  name: 'Call-Context Query',
43
44
  type: 'active',
@@ -329,10 +330,26 @@ ${await (0, doc_query_1.showQuery)(shell, exampleCode, [{
329
330
  shortDescription: 'Returns the current configuration of flowR.',
330
331
  functionName: config_query_executor_1.executeConfigQuery.name,
331
332
  functionFile: '../queries/catalog/config-query/config-query-format.ts',
332
- // eslint-disable-next-line @typescript-eslint/require-await -- no need for async here
333
- buildExplanation: async () => {
333
+ buildExplanation: async (shell) => {
334
334
  return `
335
- This query provides access to the current configuration of the flowR instance. See the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on what the configuration represents.`;
335
+ This query provides access to the current configuration of the flowR instance. See the [Interface](${doc_files_1.FlowrWikiBaseRef}/Interface) wiki page for more information on what the configuration represents.
336
+ Additionally, you can use this query to update the configuration of flowR on-the-fly (please do not rely on this mechanism it is mostly of interest for demonstrations).
337
+ ${await (0, doc_query_1.showQuery)(shell, '', [{
338
+ type: 'config',
339
+ update: {
340
+ ignoreSourceCalls: true
341
+ }
342
+ }], { showCode: false, collapseQuery: true, collapseResult: true })}
343
+
344
+ Please note that, in the repl, a special syntax starting with \`+\` (which should be autocompleted) can be used to update the configuration on the fly:
345
+
346
+ ${await (0, doc_repl_1.documentReplSession)(shell, [
347
+ {
348
+ command: ':query @config +solver.slicer.threshold=10000',
349
+ description: 'Set the slicing threshold to 10,000.'
350
+ }
351
+ ])}
352
+ `;
336
353
  }
337
354
  });
338
355
  (0, doc_query_1.registerQueryDocumentation)('df-shape', {
@@ -495,10 +512,8 @@ In the meantime we offer several properties to overwrite the default behavior (e
495
512
  ${await (0, doc_query_1.showQuery)(shell, longerCode, [{
496
513
  type: 'dependencies',
497
514
  ignoreDefaultFunctions: true,
515
+ enabledCategories: ['library'],
498
516
  libraryFunctions: [{ package: 'base', name: 'print', argIdx: 0, argName: 'library', resolveValue: true }],
499
- sourceFunctions: [],
500
- readFunctions: [],
501
- writeFunctions: []
502
517
  }], { showCode: false, collapseQuery: false, collapseResult: true })}
503
518
 
504
519
  Here, \`resolveValue\` tells the dependency query to resolve the value of this argument in case it is not a constant.
@@ -651,7 +666,7 @@ ${(0, doc_query_1.tocForQueryType)('virtual')}
651
666
 
652
667
  <summary>Detailed Query Format (Automatically Generated)</summary>
653
668
 
654
- Although it is probably better to consult the detailed explanations below, if you want to have a look at the scehma, here is its description:
669
+ Although it is probably better to consult the detailed explanations below, if you want to have a look at the schema, here is its description:
655
670
 
656
671
  ${(0, schema_1.describeSchema)((0, query_1.QueriesSchema)(), ansi_1.markdownFormatter)}
657
672