@eagleoutice/flowr 2.9.0 → 2.9.1

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 (72) hide show
  1. package/README.md +22 -22
  2. package/benchmark/slicer.js +1 -1
  3. package/benchmark/summarizer/first-phase/process.js +1 -1
  4. package/control-flow/semantic-cfg-guided-visitor.d.ts +25 -0
  5. package/control-flow/semantic-cfg-guided-visitor.js +25 -0
  6. package/dataflow/environments/built-in-config.d.ts +1 -1
  7. package/dataflow/environments/built-in.d.ts +10 -0
  8. package/dataflow/environments/built-in.js +10 -0
  9. package/dataflow/environments/default-builtin-config.d.ts +49 -7
  10. package/dataflow/environments/default-builtin-config.js +14 -2
  11. package/dataflow/environments/identifier.d.ts +4 -2
  12. package/dataflow/environments/identifier.js +3 -1
  13. package/dataflow/environments/resolve-by-name.js +5 -2
  14. package/dataflow/eval/resolve/alias-tracking.js +8 -1
  15. package/dataflow/eval/values/general.js +1 -1
  16. package/dataflow/eval/values/r-value.d.ts +4 -1
  17. package/dataflow/eval/values/r-value.js +2 -0
  18. package/dataflow/internal/linker.js +10 -2
  19. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +6 -5
  20. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +26 -4
  21. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.d.ts +1 -0
  22. package/dataflow/internal/process/functions/call/built-in/built-in-replacement.js +20 -1
  23. package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-dispatch.d.ts +12 -0
  24. package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-dispatch.js +27 -0
  25. package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.d.ts +19 -0
  26. package/dataflow/internal/process/functions/call/built-in/built-in-s-seven-new-generic.js +204 -0
  27. package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.d.ts +2 -0
  28. package/dataflow/internal/process/functions/call/built-in/built-in-s-three-dispatch.js +24 -2
  29. package/dataflow/internal/process/functions/call/named-call-handling.d.ts +1 -0
  30. package/dataflow/internal/process/functions/call/named-call-handling.js +1 -0
  31. package/dataflow/internal/process/functions/call/unnamed-call-handling.d.ts +1 -0
  32. package/dataflow/internal/process/functions/call/unnamed-call-handling.js +1 -0
  33. package/documentation/data/interface/doc-writing-code.js +1 -2
  34. package/linter/rules/naming-convention.d.ts +9 -2
  35. package/linter/rules/naming-convention.js +38 -36
  36. package/package.json +2 -1
  37. package/project/plugins/file-plugins/files/flowr-namespace-file.d.ts +24 -1
  38. package/project/plugins/file-plugins/files/flowr-namespace-file.js +61 -0
  39. package/r-bridge/data/data.d.ts +4 -4
  40. package/r-bridge/data/data.js +4 -4
  41. package/r-bridge/lang-4.x/ast/model/model.d.ts +1 -1
  42. package/r-bridge/lang-4.x/ast/model/type.d.ts +1 -1
  43. package/r-bridge/lang-4.x/ast/model/type.js +1 -1
  44. package/r-bridge/lang-4.x/ast/parser/main/internal/control/normalize-if-then.js +1 -1
  45. package/r-bridge/lang-4.x/ast/parser/main/internal/expression/normalize-expression.js +5 -5
  46. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-argument.js +2 -2
  47. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-call.js +4 -4
  48. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-definition.js +1 -1
  49. package/r-bridge/lang-4.x/ast/parser/main/internal/functions/normalize-parameter.js +2 -2
  50. package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-break.js +1 -1
  51. package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-for.js +1 -1
  52. package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-next.js +1 -1
  53. package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-repeat.js +1 -1
  54. package/r-bridge/lang-4.x/ast/parser/main/internal/loops/normalize-while.js +1 -1
  55. package/r-bridge/lang-4.x/ast/parser/main/internal/normalize-access.js +2 -2
  56. package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-binary.js +2 -2
  57. package/r-bridge/lang-4.x/ast/parser/main/internal/operators/normalize-unary.js +1 -1
  58. package/r-bridge/lang-4.x/ast/parser/main/internal/other/normalize-comment.js +1 -1
  59. package/r-bridge/lang-4.x/ast/parser/main/internal/other/normalize-line-directive.js +2 -2
  60. package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-expressions.js +3 -3
  61. package/r-bridge/lang-4.x/ast/parser/main/internal/structure/normalize-root.js +1 -1
  62. package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-number.js +1 -1
  63. package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-string.js +1 -1
  64. package/r-bridge/lang-4.x/ast/parser/main/internal/values/normalize-symbol.js +1 -1
  65. package/r-bridge/lang-4.x/tree-sitter/tree-sitter-normalize.js +20 -20
  66. package/r-bridge/roxygen2/roxygen-parse.js +1 -1
  67. package/reconstruct/auto-select/magic-comments.js +1 -1
  68. package/slicing/static/slice-call.d.ts +1 -1
  69. package/slicing/static/slice-call.js +3 -3
  70. package/util/r-value.d.ts +3 -2
  71. package/util/r-value.js +3 -0
  72. package/util/version.js +1 -1
package/README.md CHANGED
@@ -24,7 +24,7 @@ It offers a wide variety of features, for example:
24
24
 
25
25
  ```shell
26
26
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
27
- flowR repl using flowR v2.8.15, R grammar v14 (tree-sitter engine)
27
+ flowR repl using flowR v2.9.0, R grammar v14 (tree-sitter engine)
28
28
  R> :query @linter "read.csv(\"/root/x.txt\")"
29
29
  ```
30
30
 
@@ -33,13 +33,13 @@ It offers a wide variety of features, for example:
33
33
 
34
34
 
35
35
  ```text
36
- Query: linter (3 ms)
36
+ Query: linter (2 ms)
37
37
  ╰ Deprecated Functions (deprecated-functions):
38
- ╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 1, processTimeMs: 0
38
+ ╰ Metadata: totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0
39
39
  ╰ File Path Validity (file-path-validity):
40
40
  ╰ certain:
41
41
  ╰ Path `/root/x.txt` at 1.1-23
42
- ╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 0, processTimeMs: 0
42
+ ╰ Metadata: totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 1, processTimeMs: 0
43
43
  ╰ Seeded Randomness (seeded-randomness):
44
44
  ╰ Metadata: consumerCalls: 0, callsWithFunctionProducers: 0, callsWithAssignmentProducers: 0, callsWithNonConstantProducers: 0, callsWithOtherBranchProducers: 0, searchTimeMs: 0, processTimeMs: 0
45
45
  ╰ Absolute Paths (absolute-file-paths):
@@ -58,7 +58,7 @@ It offers a wide variety of features, for example:
58
58
  ╰ Metadata: consideredNodes: 5, searchTimeMs: 0, processTimeMs: 0
59
59
  ╰ Useless Loops (useless-loop):
60
60
  ╰ Metadata: numOfUselessLoops: 0, searchTimeMs: 0, processTimeMs: 0
61
- All queries together required ≈3 ms (1ms accuracy, total 3 ms)
61
+ All queries together required ≈2 ms (1ms accuracy, total 2 ms)
62
62
  ```
63
63
 
64
64
 
@@ -80,19 +80,19 @@ It offers a wide variety of features, for example:
80
80
 
81
81
  _Results (prettified and summarized):_
82
82
 
83
- Query: **linter** (3 ms)\
83
+ Query: **linter** (2 ms)\
84
84
     ╰ **Deprecated Functions** (deprecated-functions):\
85
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 0</code>\
85
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalCalls: 0, totalFunctionDefinitions: 0, searchTimeMs: 0, processTimeMs: 1</code>\
86
86
  &nbsp;&nbsp;&nbsp;╰ **File Path Validity** (file-path-validity):\
87
87
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ certain:\
88
88
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ Path `/root/x.txt` at 1.1-23\
89
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 1, processTimeMs: 0</code>\
89
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalReads: 1, totalUnknown: 0, totalWritesBeforeAlways: 0, totalValid: 0, searchTimeMs: 0, processTimeMs: 0</code>\
90
90
  &nbsp;&nbsp;&nbsp;╰ **Seeded Randomness** (seeded-randomness):\
91
91
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>consumerCalls: 0, callsWithFunctionProducers: 0, callsWithAssignmentProducers: 0, callsWithNonConstantProducers: 0, callsWithOtherBranchProducers: 0, searchTimeMs: 0, processTimeMs: 0</code>\
92
92
  &nbsp;&nbsp;&nbsp;╰ **Absolute Paths** (absolute-file-paths):\
93
93
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ certain:\
94
94
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ Path `/root/x.txt` at 1.1-23\
95
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs: 1, processTimeMs: 0</code>\
95
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalConsidered: 1, totalUnknown: 0, searchTimeMs: 0, processTimeMs: 0</code>\
96
96
  &nbsp;&nbsp;&nbsp;╰ **Unused Definitions** (unused-definitions):\
97
97
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>totalConsidered: 0, searchTimeMs: 0, processTimeMs: 0</code>\
98
98
  &nbsp;&nbsp;&nbsp;╰ **Naming Convention** (naming-convention):\
@@ -102,14 +102,14 @@ It offers a wide variety of features, for example:
102
102
  &nbsp;&nbsp;&nbsp;╰ **Dataframe Access Validation** (dataframe-access-validation):\
103
103
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>numOperations: 0, numAccesses: 0, totalAccessed: 0, searchTimeMs: 0, processTimeMs: 0</code>\
104
104
  &nbsp;&nbsp;&nbsp;╰ **Dead Code** (dead-code):\
105
- &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>consideredNodes: 5, searchTimeMs: 1, processTimeMs: 0</code>\
105
+ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>consideredNodes: 5, searchTimeMs: 0, processTimeMs: 0</code>\
106
106
  &nbsp;&nbsp;&nbsp;╰ **Useless Loops** (useless-loop):\
107
107
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;╰ _Metadata_: <code>numOfUselessLoops: 0, searchTimeMs: 0, processTimeMs: 0</code>\
108
- _All queries together required ≈3 ms (1ms accuracy, total 3 ms)_
108
+ _All queries together required ≈2 ms (1ms accuracy, total 2 ms)_
109
109
 
110
110
  <details> <summary style="color:gray">Show Detailed Results as Json</summary>
111
111
 
112
- The analysis required _2.8 ms_ (including parsing and normalization and the query) within the generation environment.
112
+ The analysis required _2.2 ms_ (including parsing and normalization and the query) within the generation environment.
113
113
 
114
114
  In general, the JSON contains the Ids of the nodes in question as they are present in the normalized AST or the dataflow graph of flowR.
115
115
  Please consult the [Interface](https://github.com/flowr-analysis/flowr/wiki/Interface) wiki page for more information on how to get those.
@@ -127,7 +127,7 @@ It offers a wide variety of features, for example:
127
127
  "totalCalls": 0,
128
128
  "totalFunctionDefinitions": 0,
129
129
  "searchTimeMs": 0,
130
- "processTimeMs": 0
130
+ "processTimeMs": 1
131
131
  }
132
132
  },
133
133
  "file-path-validity": {
@@ -149,7 +149,7 @@ It offers a wide variety of features, for example:
149
149
  "totalUnknown": 0,
150
150
  "totalWritesBeforeAlways": 0,
151
151
  "totalValid": 0,
152
- "searchTimeMs": 1,
152
+ "searchTimeMs": 0,
153
153
  "processTimeMs": 0
154
154
  }
155
155
  },
@@ -181,7 +181,7 @@ It offers a wide variety of features, for example:
181
181
  ".meta": {
182
182
  "totalConsidered": 1,
183
183
  "totalUnknown": 0,
184
- "searchTimeMs": 1,
184
+ "searchTimeMs": 0,
185
185
  "processTimeMs": 0
186
186
  }
187
187
  },
@@ -225,7 +225,7 @@ It offers a wide variety of features, for example:
225
225
  "results": [],
226
226
  ".meta": {
227
227
  "consideredNodes": 5,
228
- "searchTimeMs": 1,
228
+ "searchTimeMs": 0,
229
229
  "processTimeMs": 0
230
230
  }
231
231
  },
@@ -239,11 +239,11 @@ It offers a wide variety of features, for example:
239
239
  }
240
240
  },
241
241
  ".meta": {
242
- "timing": 3
242
+ "timing": 2
243
243
  }
244
244
  },
245
245
  ".meta": {
246
- "timing": 3
246
+ "timing": 2
247
247
  }
248
248
  }
249
249
  ```
@@ -308,7 +308,7 @@ It offers a wide variety of features, for example:
308
308
 
309
309
  ```shell
310
310
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
311
- flowR repl using flowR v2.8.15, R grammar v14 (tree-sitter engine)
311
+ flowR repl using flowR v2.9.0, R grammar v14 (tree-sitter engine)
312
312
  R> :query @static-slice (11@sum) file://test/testfiles/example.R
313
313
  ```
314
314
 
@@ -356,7 +356,7 @@ It offers a wide variety of features, for example:
356
356
 
357
357
 
358
358
  * 🚀 **fast call-graph, data-, and control-flow graphs**\
359
- Within just [<i><span title="This measurement is automatically fetched from the latest benchmark!">118.7 ms</span></i> (as of Jan 30, 2026)](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark),
359
+ Within just [<i><span title="This measurement is automatically fetched from the latest benchmark!">117.5 ms</span></i> (as of Feb 2, 2026)](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark),
360
360
  _flowR_ can analyze the data- and control-flow of the average real-world R script. See the [benchmarks](https://flowr-analysis.github.io/flowr/wiki/stats/benchmark) for more information,
361
361
  and consult the [wiki pages](https://github.com/flowr-analysis/flowr/wiki/wiki/dataflow-graph) for more details on the dataflow graphs as well as call graphs.
362
362
 
@@ -392,7 +392,7 @@ It offers a wide variety of features, for example:
392
392
 
393
393
  ```shell
394
394
  $ docker run -it --rm eagleoutice/flowr # or npm run flowr
395
- flowR repl using flowR v2.8.15, R grammar v14 (tree-sitter engine)
395
+ flowR repl using flowR v2.9.0, R grammar v14 (tree-sitter engine)
396
396
  R> :dataflow* test/testfiles/example.R
397
397
  ```
398
398
 
@@ -697,7 +697,7 @@ It offers a wide variety of features, for example:
697
697
  ```
698
698
 
699
699
 
700
- (The analysis required _1.9 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
700
+ (The analysis required _1.7 ms_ (including parse and normalize, using the [tree-sitter](https://github.com/flowr-analysis/flowr/wiki/Engines) engine) within the generation environment.)
701
701
 
702
702
 
703
703
 
@@ -131,7 +131,7 @@ class BenchmarkSlicer {
131
131
  let commentCharsNoWhitespace = 0;
132
132
  (0, visitor_1.visitAst)(this.normalizedAst.ast.files.map(f => f.root), t => {
133
133
  nodes++;
134
- const comments = t.info.additionalTokens?.filter(t => t.type === type_1.RType.Comment);
134
+ const comments = t.info.adToks?.filter(t => t.type === type_1.RType.Comment);
135
135
  if (comments && comments.length > 0) {
136
136
  const content = comments.map(c => c.lexeme ?? '').join('');
137
137
  commentChars += content.length;
@@ -161,7 +161,7 @@ async function summarizeSlicerStats(stats, report = () => {
161
161
  let commentCharsNoWhitespace = 0;
162
162
  (0, visitor_1.visitAst)(reParsed.ast.files.map(f => f.root), t => {
163
163
  numberOfNormalizedTokens++;
164
- const comments = t.info.additionalTokens?.filter(t => t.type === type_1.RType.Comment);
164
+ const comments = t.info.adToks?.filter(t => t.type === type_1.RType.Comment);
165
165
  if (comments && comments.length > 0) {
166
166
  const content = comments.map(c => c.lexeme ?? '').join('');
167
167
  commentChars += content.length;
@@ -496,11 +496,36 @@ export declare class SemanticCfgGuidedVisitor<OtherInfo = NoInfo, ControlFlow ex
496
496
  * This event triggers for every call to a function that performs an S3-like dispatch.
497
497
  *
498
498
  * For example, this triggers for `UseMethod` in `UseMethod("print")`.
499
+ * @see {@link SemanticCfgGuidedVisitor#onS3DispatchNextCall|`onS3DispatchNextCall`} for `NextMethod` calls.
499
500
  * @protected
500
501
  */
501
502
  protected onS3DispatchCall(_data: {
502
503
  call: DataflowGraphVertexFunctionCall;
503
504
  }): void;
505
+ /**
506
+ * This event triggers for every call to a function that performs an S3-like *next* dispatch.
507
+ *
508
+ * For example, this triggers for `NextMethod`.
509
+ * @see {@link SemanticCfgGuidedVisitor#onS3DispatchCall|`onS3DispatchCall`} for `UseMethod` calls.
510
+ * @protected
511
+ */
512
+ protected onS3DispatchNextCall(_data: {
513
+ call: DataflowGraphVertexFunctionCall;
514
+ }): void;
515
+ /**
516
+ * This event triggers for every call to a function that creates a new S7 generic, such as `new_generic`.
517
+ * @protected
518
+ */
519
+ protected onS7NewGenericCall(_data: {
520
+ call: DataflowGraphVertexFunctionCall;
521
+ }): void;
522
+ /**
523
+ * This event triggers for every call to a function that performs an S7 dispatch, such as `S7_dispatch`.
524
+ * @protected
525
+ */
526
+ protected onS7DispatchCall(_data: {
527
+ call: DataflowGraphVertexFunctionCall;
528
+ }): void;
504
529
  /**
505
530
  * This event triggers for every call to a function that registers a hook, such as `on.exit`.
506
531
  *
@@ -263,6 +263,12 @@ class SemanticCfgGuidedVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfg
263
263
  return this.onLocalCall({ call });
264
264
  case built_in_1.BuiltInProcName.S3Dispatch:
265
265
  return this.onS3DispatchCall({ call });
266
+ case built_in_1.BuiltInProcName.S3DispatchNext:
267
+ return this.onS3DispatchNextCall({ call });
268
+ case built_in_1.BuiltInProcName.S7NewGeneric:
269
+ return this.onS7NewGenericCall({ call });
270
+ case built_in_1.BuiltInProcName.S7Dispatch:
271
+ return this.onS7DispatchCall({ call });
266
272
  case built_in_1.BuiltInProcName.Break:
267
273
  return this.onBreakCall({ call });
268
274
  case built_in_1.BuiltInProcName.Return:
@@ -578,9 +584,28 @@ class SemanticCfgGuidedVisitor extends dfg_cfg_guided_visitor_1.DataflowAwareCfg
578
584
  * This event triggers for every call to a function that performs an S3-like dispatch.
579
585
  *
580
586
  * For example, this triggers for `UseMethod` in `UseMethod("print")`.
587
+ * @see {@link SemanticCfgGuidedVisitor#onS3DispatchNextCall|`onS3DispatchNextCall`} for `NextMethod` calls.
581
588
  * @protected
582
589
  */
583
590
  onS3DispatchCall(_data) { }
591
+ /**
592
+ * This event triggers for every call to a function that performs an S3-like *next* dispatch.
593
+ *
594
+ * For example, this triggers for `NextMethod`.
595
+ * @see {@link SemanticCfgGuidedVisitor#onS3DispatchCall|`onS3DispatchCall`} for `UseMethod` calls.
596
+ * @protected
597
+ */
598
+ onS3DispatchNextCall(_data) { }
599
+ /**
600
+ * This event triggers for every call to a function that creates a new S7 generic, such as `new_generic`.
601
+ * @protected
602
+ */
603
+ onS7NewGenericCall(_data) { }
604
+ /**
605
+ * This event triggers for every call to a function that performs an S7 dispatch, such as `S7_dispatch`.
606
+ * @protected
607
+ */
608
+ onS7DispatchCall(_data) { }
584
609
  /**
585
610
  * This event triggers for every call to a function that registers a hook, such as `on.exit`.
586
611
  *
@@ -39,7 +39,7 @@ export interface BuiltInReplacementDefinition extends BaseBuiltInDefinition {
39
39
  readonly suffixes: ('<<-' | '<-')[];
40
40
  readonly config: {
41
41
  readIndices: boolean;
42
- libFn?: boolean;
42
+ constructName?: 's7';
43
43
  };
44
44
  }
45
45
  export type BuiltInDefinition<T extends keyof typeof BuiltInProcessorMapper = keyof typeof BuiltInProcessorMapper> = BuiltInConstantDefinition<unknown> | BuiltInFunctionDefinition<T> | BuiltInReplacementDefinition;
@@ -40,6 +40,8 @@ import { processRegisterHook } from '../internal/process/functions/call/built-in
40
40
  import { processLocal } from '../internal/process/functions/call/built-in/built-in-local';
41
41
  import { processS3Dispatch } from '../internal/process/functions/call/built-in/built-in-s-three-dispatch';
42
42
  import { processRecall } from '../internal/process/functions/call/built-in/built-in-recall';
43
+ import { processS7NewGeneric } from '../internal/process/functions/call/built-in/built-in-s-seven-new-generic';
44
+ import { processS7Dispatch } from '../internal/process/functions/call/built-in/built-in-s-seven-dispatch';
43
45
  export type BuiltIn = `built-in:${string}`;
44
46
  /**
45
47
  * Generate a built-in id for the given name
@@ -139,6 +141,12 @@ export declare enum BuiltInProcName {
139
141
  Rm = "builtin:rm",
140
142
  /** for `UseMethod` calls, see {@link processS3Dispatch} */
141
143
  S3Dispatch = "builtin:s3-dispatch",
144
+ /** for `NextMethod` calls, see {@link processS3Dispatch} */
145
+ S3DispatchNext = "builtin:s3-dispatch-next",
146
+ /** for `new.generic` calls, see {@link processS7NewGeneric} */
147
+ S7NewGeneric = "builtin:s7-new-generic",
148
+ /** for `S7_dispatch` calls (and their implicit creations), see {@link processS7Dispatch} */
149
+ S7Dispatch = "builtin:s7-dispatch",
142
150
  /** for `source` calls, see {@link processSourceCall} */
143
151
  Source = "builtin:source",
144
152
  /** for special binary operators like `%x%`, see {@link processSpecialBinOp} */
@@ -181,6 +189,8 @@ export declare const BuiltInProcessorMapper: {
181
189
  readonly "builtin:replacement": typeof processReplacementFunction;
182
190
  readonly "builtin:rm": typeof processRm;
183
191
  readonly "builtin:s3-dispatch": typeof processS3Dispatch;
192
+ readonly "builtin:s7-new-generic": typeof processS7NewGeneric;
193
+ readonly "builtin:s7-dispatch": typeof processS7Dispatch;
184
194
  readonly "builtin:source": typeof processSourceCall;
185
195
  readonly "builtin:special-bin-op": typeof processSpecialBinOp;
186
196
  readonly "builtin:stopifnot": typeof processStopIfNot;
@@ -39,6 +39,8 @@ const built_in_register_hook_1 = require("../internal/process/functions/call/bui
39
39
  const built_in_local_1 = require("../internal/process/functions/call/built-in/built-in-local");
40
40
  const built_in_s_three_dispatch_1 = require("../internal/process/functions/call/built-in/built-in-s-three-dispatch");
41
41
  const built_in_recall_1 = require("../internal/process/functions/call/built-in/built-in-recall");
42
+ const built_in_s_seven_new_generic_1 = require("../internal/process/functions/call/built-in/built-in-s-seven-new-generic");
43
+ const built_in_s_seven_dispatch_1 = require("../internal/process/functions/call/built-in/built-in-s-seven-dispatch");
42
44
  /**
43
45
  * Generate a built-in id for the given name
44
46
  */
@@ -175,6 +177,12 @@ var BuiltInProcName;
175
177
  BuiltInProcName["Rm"] = "builtin:rm";
176
178
  /** for `UseMethod` calls, see {@link processS3Dispatch} */
177
179
  BuiltInProcName["S3Dispatch"] = "builtin:s3-dispatch";
180
+ /** for `NextMethod` calls, see {@link processS3Dispatch} */
181
+ BuiltInProcName["S3DispatchNext"] = "builtin:s3-dispatch-next";
182
+ /** for `new.generic` calls, see {@link processS7NewGeneric} */
183
+ BuiltInProcName["S7NewGeneric"] = "builtin:s7-new-generic";
184
+ /** for `S7_dispatch` calls (and their implicit creations), see {@link processS7Dispatch} */
185
+ BuiltInProcName["S7Dispatch"] = "builtin:s7-dispatch";
178
186
  /** for `source` calls, see {@link processSourceCall} */
179
187
  BuiltInProcName["Source"] = "builtin:source";
180
188
  /** for special binary operators like `%x%`, see {@link processSpecialBinOp} */
@@ -217,6 +225,8 @@ exports.BuiltInProcessorMapper = {
217
225
  [BuiltInProcName.Replacement]: built_in_replacement_1.processReplacementFunction,
218
226
  [BuiltInProcName.Rm]: built_in_rm_1.processRm,
219
227
  [BuiltInProcName.S3Dispatch]: built_in_s_three_dispatch_1.processS3Dispatch,
228
+ [BuiltInProcName.S7NewGeneric]: built_in_s_seven_new_generic_1.processS7NewGeneric,
229
+ [BuiltInProcName.S7Dispatch]: built_in_s_seven_dispatch_1.processS7Dispatch,
220
230
  [BuiltInProcName.Source]: built_in_source_1.processSourceCall,
221
231
  [BuiltInProcName.SpecialBinOp]: built_in_special_bin_op_1.processSpecialBinOp,
222
232
  [BuiltInProcName.StopIfNot]: built_in_stop_if_not_1.processStopIfNot,
@@ -404,7 +404,7 @@ export declare const DefaultBuiltinConfig: [{
404
404
  readonly assumePrimitive: true;
405
405
  }, {
406
406
  readonly type: "function";
407
- readonly names: ["assign", "setGeneric", "setValidity"];
407
+ readonly names: ["assign", "setValidity"];
408
408
  readonly processor: BuiltInProcName.Assignment;
409
409
  readonly config: {
410
410
  readonly targetVariable: true;
@@ -543,23 +543,57 @@ export declare const DefaultBuiltinConfig: [{
543
543
  readonly assumePrimitive: true;
544
544
  }, {
545
545
  readonly type: "function";
546
- readonly names: ["NextMethod"];
547
- readonly processor: BuiltInProcName.Apply;
546
+ readonly names: ["UseMethod"];
547
+ readonly processor: BuiltInProcName.S3Dispatch;
548
548
  readonly config: {
549
- readonly indexOfFunction: 0;
550
- readonly unquoteFunction: true;
551
- readonly resolveInEnvironment: "global";
549
+ readonly args: {
550
+ readonly generic: "generic";
551
+ readonly object: "object";
552
+ };
552
553
  };
553
554
  readonly assumePrimitive: true;
554
555
  }, {
555
556
  readonly type: "function";
556
- readonly names: ["UseMethod"];
557
+ readonly names: ["NextMethod"];
557
558
  readonly processor: BuiltInProcName.S3Dispatch;
558
559
  readonly config: {
559
560
  readonly args: {
560
561
  readonly generic: "generic";
561
562
  readonly object: "object";
562
563
  };
564
+ readonly inferFromClosure: true;
565
+ };
566
+ readonly assumePrimitive: true;
567
+ }, {
568
+ readonly type: "function";
569
+ readonly names: ["new_generic"];
570
+ readonly processor: BuiltInProcName.S7NewGeneric;
571
+ readonly config: {
572
+ readonly args: {
573
+ readonly name: "name";
574
+ readonly dispatchArg: "dispatch_args";
575
+ readonly fun: "fun";
576
+ };
577
+ };
578
+ readonly assumePrimitive: true;
579
+ }, {
580
+ readonly type: "function";
581
+ readonly names: ["setGeneric"];
582
+ readonly processor: BuiltInProcName.S7NewGeneric;
583
+ readonly config: {
584
+ readonly args: {
585
+ readonly name: "name";
586
+ readonly dispatchArg: undefined;
587
+ readonly fun: "fun";
588
+ };
589
+ };
590
+ readonly assumePrimitive: true;
591
+ }, {
592
+ readonly type: "function";
593
+ readonly names: ["S7_dispatch"];
594
+ readonly processor: BuiltInProcName.S7Dispatch;
595
+ readonly config: {
596
+ readonly libFn: true;
563
597
  };
564
598
  readonly assumePrimitive: true;
565
599
  }, {
@@ -672,6 +706,14 @@ export declare const DefaultBuiltinConfig: [{
672
706
  readonly config: {
673
707
  readonly readIndices: true;
674
708
  };
709
+ }, {
710
+ readonly type: "replacement";
711
+ readonly suffixes: ["<-", "<<-"];
712
+ readonly names: ["method"];
713
+ readonly config: {
714
+ readonly readIndices: true;
715
+ readonly constructName: "s7";
716
+ };
675
717
  }, {
676
718
  readonly type: "replacement";
677
719
  readonly suffixes: ["<-", "<<-"];
@@ -257,7 +257,7 @@ exports.DefaultBuiltinConfig = [
257
257
  { type: 'function', names: [identifier_1.Identifier.make('library', 'base'), identifier_1.Identifier.make('require', 'base')], processor: built_in_1.BuiltInProcName.Library, config: {}, assumePrimitive: false },
258
258
  { type: 'function', names: ['<-', '='], processor: built_in_1.BuiltInProcName.Assignment, config: { canBeReplacement: true }, assumePrimitive: true },
259
259
  { type: 'function', names: [':='], processor: built_in_1.BuiltInProcName.Assignment, config: {}, assumePrimitive: true },
260
- { type: 'function', names: ['assign', 'setGeneric', 'setValidity'], processor: built_in_1.BuiltInProcName.Assignment, config: { targetVariable: true, mayHaveMoreArgs: true }, assumePrimitive: true },
260
+ { type: 'function', names: ['assign', 'setValidity'], processor: built_in_1.BuiltInProcName.Assignment, config: { targetVariable: true, mayHaveMoreArgs: true }, assumePrimitive: true },
261
261
  { type: 'function', names: ['setMethod'], processor: built_in_1.BuiltInProcName.AssignmentLike, config: { targetVariable: true, canBeReplacement: false, target: { idx: 0, name: 'f' }, source: { idx: 2, name: 'definition' } }, assumePrimitive: true },
262
262
  { type: 'function', names: ['delayedAssign'], processor: built_in_1.BuiltInProcName.Assignment, config: { quoteSource: true, targetVariable: true }, assumePrimitive: true },
263
263
  { type: 'function', names: ['<<-'], processor: built_in_1.BuiltInProcName.Assignment, config: { superAssignment: true, canBeReplacement: true }, assumePrimitive: true },
@@ -273,8 +273,11 @@ exports.DefaultBuiltinConfig = [
273
273
  { type: 'function', names: ['repeat'], processor: built_in_1.BuiltInProcName.RepeatLoop, config: {}, assumePrimitive: true },
274
274
  { type: 'function', names: ['while'], processor: built_in_1.BuiltInProcName.WhileLoop, config: {}, assumePrimitive: true },
275
275
  { type: 'function', names: ['do.call'], processor: built_in_1.BuiltInProcName.Apply, config: { indexOfFunction: 0, unquoteFunction: true }, assumePrimitive: true },
276
- { type: 'function', names: ['NextMethod'], processor: built_in_1.BuiltInProcName.Apply, config: { indexOfFunction: 0, unquoteFunction: true, resolveInEnvironment: 'global' }, assumePrimitive: true },
277
276
  { type: 'function', names: ['UseMethod'], processor: built_in_1.BuiltInProcName.S3Dispatch, config: { args: { generic: 'generic', object: 'object' } }, assumePrimitive: true },
277
+ { type: 'function', names: ['NextMethod'], processor: built_in_1.BuiltInProcName.S3Dispatch, config: { args: { generic: 'generic', object: 'object' }, inferFromClosure: true }, assumePrimitive: true },
278
+ { type: 'function', names: ['new_generic'], processor: built_in_1.BuiltInProcName.S7NewGeneric, config: { args: { name: 'name', dispatchArg: 'dispatch_args', fun: 'fun' } }, assumePrimitive: true },
279
+ { type: 'function', names: ['setGeneric'], processor: built_in_1.BuiltInProcName.S7NewGeneric, config: { args: { name: 'name', dispatchArg: undefined, fun: 'fun' } }, assumePrimitive: true },
280
+ { type: 'function', names: ['S7_dispatch'], processor: built_in_1.BuiltInProcName.S7Dispatch, config: { libFn: true }, assumePrimitive: true },
278
281
  { type: 'function', names: ['.Primitive', '.Internal'], processor: built_in_1.BuiltInProcName.Apply, config: { indexOfFunction: 0, unquoteFunction: true, resolveInEnvironment: 'global' }, assumePrimitive: true },
279
282
  { type: 'function', names: ['interference'], processor: built_in_1.BuiltInProcName.Apply, config: { unquoteFunction: true, nameOfFunctionArgument: 'propensity_integrand', libFn: true }, assumePrimitive: false },
280
283
  { type: 'function', names: ['ddply'], processor: built_in_1.BuiltInProcName.Apply, config: { unquoteFunction: true, indexOfFunction: 2, nameOfFunctionArgument: '.fun', libFn: true }, assumePrimitive: false },
@@ -341,6 +344,15 @@ exports.DefaultBuiltinConfig = [
341
344
  readIndices: true
342
345
  }
343
346
  },
347
+ {
348
+ type: 'replacement',
349
+ suffixes: ['<-', '<<-'],
350
+ names: ['method'],
351
+ config: {
352
+ readIndices: true,
353
+ constructName: 's7'
354
+ }
355
+ },
344
356
  {
345
357
  type: 'replacement',
346
358
  suffixes: ['<-', '<<-'],
@@ -40,7 +40,7 @@ export declare const Identifier: {
40
40
  readonly make: (this: void, name: BrandedIdentifier, namespace?: BrandedNamespace, internal?: boolean) => Identifier;
41
41
  /**
42
42
  * Parse an identifier from its string representation,
43
- * Please note, that in R if one writes `"pkg::a"` this refers to a symbol named `pkag::a` and NOT to the namespaced identifier `a` in package `pkg`.
43
+ * Please note, that in R if one writes `"pkg::a"` this refers to a symbol named `pkg::a` and NOT to the namespaced identifier `a` in package `pkg`.
44
44
  * In this scenario, see {@link Identifier.make} instead.
45
45
  */
46
46
  readonly parse: (this: void, str: string) => Identifier;
@@ -125,7 +125,9 @@ export declare enum ReferenceType {
125
125
  /** The identifier is defined by a built-in function */
126
126
  BuiltInFunction = 128,
127
127
  /** Prefix to identify S3 methods, use this, to for example dispatch a call to `f` which will then link to `f.*` */
128
- S3MethodPrefix = 256
128
+ S3MethodPrefix = 256,
129
+ /** Prefix to identify S7 methods, use this, to for example dispatch a call to `f` which will then link to `f<7>*` */
130
+ S7MethodPrefix = 512
129
131
  }
130
132
  /** Reverse mapping of the reference types so you can get the name from the bitmask (useful for debugging) */
131
133
  export declare const ReferenceTypeReverseMapping: Map<ReferenceType, string>;
@@ -34,7 +34,7 @@ exports.Identifier = {
34
34
  },
35
35
  /**
36
36
  * Parse an identifier from its string representation,
37
- * Please note, that in R if one writes `"pkg::a"` this refers to a symbol named `pkag::a` and NOT to the namespaced identifier `a` in package `pkg`.
37
+ * Please note, that in R if one writes `"pkg::a"` this refers to a symbol named `pkg::a` and NOT to the namespaced identifier `a` in package `pkg`.
38
38
  * In this scenario, see {@link Identifier.make} instead.
39
39
  */
40
40
  parse(str) {
@@ -192,6 +192,8 @@ var ReferenceType;
192
192
  ReferenceType[ReferenceType["BuiltInFunction"] = 128] = "BuiltInFunction";
193
193
  /** Prefix to identify S3 methods, use this, to for example dispatch a call to `f` which will then link to `f.*` */
194
194
  ReferenceType[ReferenceType["S3MethodPrefix"] = 256] = "S3MethodPrefix";
195
+ /** Prefix to identify S7 methods, use this, to for example dispatch a call to `f` which will then link to `f<7>*` */
196
+ ReferenceType[ReferenceType["S7MethodPrefix"] = 512] = "S7MethodPrefix";
195
197
  })(ReferenceType || (exports.ReferenceType = ReferenceType = {}));
196
198
  /** Reverse mapping of the reference types so you can get the name from the bitmask (useful for debugging) */
197
199
  exports.ReferenceTypeReverseMapping = new Map(Object.entries(ReferenceType).map(([k, v]) => [v, k]));
@@ -6,6 +6,7 @@ exports.resolvesToBuiltInConstant = resolvesToBuiltInConstant;
6
6
  const logic_1 = require("../../util/logic");
7
7
  const identifier_1 = require("./identifier");
8
8
  const info_1 = require("../info");
9
+ const built_in_s_seven_dispatch_1 = require("../internal/process/functions/call/built-in/built-in-s-seven-dispatch");
9
10
  const FunctionTargetTypes = identifier_1.ReferenceType.Function | identifier_1.ReferenceType.BuiltInFunction | identifier_1.ReferenceType.Unknown | identifier_1.ReferenceType.Argument | identifier_1.ReferenceType.Parameter;
10
11
  const VariableTargetTypes = identifier_1.ReferenceType.Variable | identifier_1.ReferenceType.Parameter | identifier_1.ReferenceType.Argument | identifier_1.ReferenceType.Unknown;
11
12
  const ConstantTargetTypes = identifier_1.ReferenceType.Constant | identifier_1.ReferenceType.BuiltInConstant | identifier_1.ReferenceType.Unknown;
@@ -21,6 +22,7 @@ const TargetTypePredicate = {
21
22
  [identifier_1.ReferenceType.BuiltInConstant]: ({ type }) => (0, identifier_1.isReferenceType)(type, BuiltInConstantTargetTypes),
22
23
  [identifier_1.ReferenceType.BuiltInFunction]: ({ type }) => (0, identifier_1.isReferenceType)(type, BuiltInFunctionTargetTypes),
23
24
  [identifier_1.ReferenceType.S3MethodPrefix]: ({ type }) => (0, identifier_1.isReferenceType)(type, FunctionTargetTypes),
25
+ [identifier_1.ReferenceType.S7MethodPrefix]: ({ type }) => (0, identifier_1.isReferenceType)(type, FunctionTargetTypes),
24
26
  };
25
27
  /**
26
28
  * Resolves a given identifier name to a list of its possible definition location using R scoping and resolving rules.
@@ -45,10 +47,11 @@ function resolveByName(id, environment, target) {
45
47
  continue;
46
48
  }
47
49
  let definition;
48
- if (target === identifier_1.ReferenceType.S3MethodPrefix) {
50
+ if (target === identifier_1.ReferenceType.S3MethodPrefix || target === identifier_1.ReferenceType.S7MethodPrefix) {
49
51
  // S3 method prefixes only resolve to functions, S3s must not match the exported criteria!
52
+ const infix = target === identifier_1.ReferenceType.S3MethodPrefix ? '.' : built_in_s_seven_dispatch_1.S7DispatchSeparator;
50
53
  definition = current.memory.entries()
51
- .filter(([defName]) => defName.startsWith(name + '.'))
54
+ .filter(([defName]) => defName.startsWith(name + infix))
52
55
  .flatMap(([, defs]) => defs)
53
56
  .toArray();
54
57
  }
@@ -87,6 +87,10 @@ function getAliases(sourceIds, dataflow, environment) {
87
87
  if (info === undefined) {
88
88
  return undefined;
89
89
  }
90
+ else if (info.tag === vertex_1.VertexType.FunctionDefinition) {
91
+ definitions.add(sourceId);
92
+ continue;
93
+ }
90
94
  const defs = AliasHandler[info.tag](sourceId, dataflow, environment);
91
95
  for (const def of defs ?? []) {
92
96
  definitions.add(def);
@@ -351,7 +355,10 @@ function resolveToConstants(name, environment) {
351
355
  return r_value_1.Top;
352
356
  }
353
357
  const values = new Set();
354
- definitions.forEach(def => values.add((0, general_1.valueFromTsValue)(def.value ?? r_value_1.Top)));
358
+ definitions.forEach(def => {
359
+ const d = def.value;
360
+ values.add(d === undefined ? r_value_1.Top : (0, general_1.valueFromTsValue)(d));
361
+ });
355
362
  return (0, set_constants_1.setFrom)(...values);
356
363
  }
357
364
  //# sourceMappingURL=alias-tracking.js.map
@@ -39,7 +39,7 @@ function valueFromTsValue(a) {
39
39
  return r_value_1.Bottom;
40
40
  }
41
41
  else if (a === null) {
42
- return r_value_1.Top;
42
+ return { type: 'null' };
43
43
  }
44
44
  else if (typeof a === 'string') {
45
45
  return (0, string_constants_1.stringFrom)(a);
@@ -37,6 +37,9 @@ export interface ValueString<Str extends Lift<RStringValue> = Lift<RStringValue>
37
37
  type: 'string';
38
38
  value: Str;
39
39
  }
40
+ export interface ValueNull {
41
+ type: 'null';
42
+ }
40
43
  export interface ValueFunctionDefinition {
41
44
  type: 'function-definition';
42
45
  }
@@ -48,7 +51,7 @@ export interface ValueLogical {
48
51
  type: 'logical';
49
52
  value: Lift<TernaryLogical>;
50
53
  }
51
- export type Value = Lift<ValueInterval | ValueVector | ValueSet | ValueNumber | ValueString | ValueLogical | ValueMissing | ValueFunctionDefinition>;
54
+ export type Value = Lift<ValueInterval | ValueVector | ValueSet | ValueNumber | ValueString | ValueLogical | ValueMissing | ValueFunctionDefinition | ValueNull>;
52
55
  export type ValueType<V> = V extends {
53
56
  type: infer T;
54
57
  } ? T : never;
@@ -76,6 +76,8 @@ function stringifyValue(value) {
76
76
  return tryStringifyBoTop(value, v => {
77
77
  const t = v.type;
78
78
  switch (t) {
79
+ case 'null':
80
+ return 'NULL';
79
81
  case 'interval':
80
82
  return `${v.startInclusive ? '[' : '('}${stringifyValue(v.start)}, ${stringifyValue(v.end)}${v.endInclusive ? ']' : ')'}`;
81
83
  case 'vector':
@@ -231,10 +231,16 @@ function linkFunctionCallWithSingleTarget(graph, { subflow: fnSubflow, exitPoint
231
231
  if (defs === undefined) {
232
232
  continue;
233
233
  }
234
- for (const { nodeId } of defs) {
234
+ for (const { nodeId, type, value } of defs) {
235
235
  if (!(0, built_in_1.isBuiltIn)(nodeId)) {
236
236
  graph.addEdge(ingoing.nodeId, nodeId, edge_1.EdgeType.DefinedByOnCall);
237
237
  graph.addEdge(id, nodeId, edge_1.EdgeType.DefinesOnCall);
238
+ if (type === identifier_1.ReferenceType.Function && ingoing.type === identifier_1.ReferenceType.S7MethodPrefix && Array.isArray(value)) {
239
+ for (const v of value) {
240
+ graph.addEdge(id, v, edge_1.EdgeType.Calls);
241
+ graph.addEdge(ingoing.nodeId, v, edge_1.EdgeType.Calls);
242
+ }
243
+ }
238
244
  }
239
245
  }
240
246
  }
@@ -325,8 +331,10 @@ function getAllFunctionCallTargets(call, graph, environment) {
325
331
  }
326
332
  if (environment !== undefined || info.environment !== undefined) {
327
333
  let functionCallDefs = [];
334
+ const refType = info.origin.includes(built_in_1.BuiltInProcName.S3Dispatch) ? identifier_1.ReferenceType.S3MethodPrefix :
335
+ info.origin.includes(built_in_1.BuiltInProcName.S7Dispatch) ? identifier_1.ReferenceType.S7MethodPrefix : identifier_1.ReferenceType.Function;
328
336
  if (info.name !== undefined && !identifier_1.Identifier.getName(info.name).startsWith(unnamed_call_handling_1.UnnamedFunctionCallPrefix)) {
329
- functionCallDefs = (0, resolve_by_name_1.resolveByName)(info.name, environment ?? info.environment, info.origin.includes(built_in_1.BuiltInProcName.S3Dispatch) ? identifier_1.ReferenceType.S3MethodPrefix : identifier_1.ReferenceType.Function)?.map(d => d.nodeId) ?? [];
337
+ functionCallDefs = (0, resolve_by_name_1.resolveByName)(info.name, environment ?? info.environment, refType)?.map(d => d.nodeId) ?? [];
330
338
  }
331
339
  for (const [target, outgoingEdge] of outgoingEdges.entries()) {
332
340
  if (edge_1.DfEdge.includesType(outgoingEdge, edge_1.EdgeType.Calls)) {