yukigo 0.1.0

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 (78) hide show
  1. package/.mocharc.json +4 -0
  2. package/CHANGELOG.md +6 -0
  3. package/README.md +199 -0
  4. package/dist/analyzer/index.d.ts +71 -0
  5. package/dist/analyzer/index.js +110 -0
  6. package/dist/analyzer/inspections/functional.d.ts +46 -0
  7. package/dist/analyzer/inspections/functional.js +123 -0
  8. package/dist/analyzer/inspections/generic.d.ts +151 -0
  9. package/dist/analyzer/inspections/generic.js +427 -0
  10. package/dist/analyzer/inspections/imperative.d.ts +37 -0
  11. package/dist/analyzer/inspections/imperative.js +105 -0
  12. package/dist/analyzer/inspections/logic.d.ts +49 -0
  13. package/dist/analyzer/inspections/logic.js +140 -0
  14. package/dist/analyzer/inspections/object.d.ts +83 -0
  15. package/dist/analyzer/inspections/object.js +235 -0
  16. package/dist/analyzer/utils.d.ts +4 -0
  17. package/dist/analyzer/utils.js +16 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.js +3 -0
  20. package/dist/interpreter/components/EnvBuilder.d.ts +16 -0
  21. package/dist/interpreter/components/EnvBuilder.js +78 -0
  22. package/dist/interpreter/components/FunctionRuntime.d.ts +8 -0
  23. package/dist/interpreter/components/FunctionRuntime.js +52 -0
  24. package/dist/interpreter/components/LazyRuntime.d.ts +7 -0
  25. package/dist/interpreter/components/LazyRuntime.js +75 -0
  26. package/dist/interpreter/components/LogicEngine.d.ts +21 -0
  27. package/dist/interpreter/components/LogicEngine.js +152 -0
  28. package/dist/interpreter/components/LogicResolver.d.ts +11 -0
  29. package/dist/interpreter/components/LogicResolver.js +87 -0
  30. package/dist/interpreter/components/Operations.d.ts +14 -0
  31. package/dist/interpreter/components/Operations.js +69 -0
  32. package/dist/interpreter/components/PatternMatcher.d.ts +41 -0
  33. package/dist/interpreter/components/PatternMatcher.js +206 -0
  34. package/dist/interpreter/components/Visitor.d.ts +64 -0
  35. package/dist/interpreter/components/Visitor.js +299 -0
  36. package/dist/interpreter/errors.d.ts +19 -0
  37. package/dist/interpreter/errors.js +36 -0
  38. package/dist/interpreter/index.d.ts +32 -0
  39. package/dist/interpreter/index.js +44 -0
  40. package/dist/interpreter/utils.d.ts +14 -0
  41. package/dist/interpreter/utils.js +57 -0
  42. package/dist/utils/helpers.d.ts +14 -0
  43. package/dist/utils/helpers.js +51 -0
  44. package/package.json +30 -0
  45. package/src/analyzer/index.ts +132 -0
  46. package/src/analyzer/inspections/functional.ts +159 -0
  47. package/src/analyzer/inspections/generic.ts +499 -0
  48. package/src/analyzer/inspections/imperative.ts +129 -0
  49. package/src/analyzer/inspections/logic.ts +166 -0
  50. package/src/analyzer/inspections/object.ts +282 -0
  51. package/src/analyzer/utils.ts +26 -0
  52. package/src/index.ts +3 -0
  53. package/src/interpreter/components/EnvBuilder.ts +97 -0
  54. package/src/interpreter/components/FunctionRuntime.ts +79 -0
  55. package/src/interpreter/components/LazyRuntime.ts +97 -0
  56. package/src/interpreter/components/LogicEngine.ts +227 -0
  57. package/src/interpreter/components/LogicResolver.ts +130 -0
  58. package/src/interpreter/components/Operations.ts +81 -0
  59. package/src/interpreter/components/PatternMatcher.ts +254 -0
  60. package/src/interpreter/components/Visitor.ts +493 -0
  61. package/src/interpreter/errors.ts +47 -0
  62. package/src/interpreter/index.ts +59 -0
  63. package/src/interpreter/utils.ts +79 -0
  64. package/src/utils/helpers.ts +73 -0
  65. package/tests/analyzer/functional.spec.ts +221 -0
  66. package/tests/analyzer/generic.spec.ts +100 -0
  67. package/tests/analyzer/helpers.spec.ts +83 -0
  68. package/tests/analyzer/logic.spec.ts +292 -0
  69. package/tests/analyzer/oop.spec.ts +338 -0
  70. package/tests/interpreter/EnvBuilder.spec.ts +178 -0
  71. package/tests/interpreter/FunctionRuntime.spec.ts +234 -0
  72. package/tests/interpreter/LazyRuntime.spec.ts +190 -0
  73. package/tests/interpreter/LogicEngine.spec.ts +194 -0
  74. package/tests/interpreter/Operations.spec.ts +220 -0
  75. package/tests/interpreter/PatternSystem.spec.ts +189 -0
  76. package/tests/interpreter/interpreter.spec.ts +937 -0
  77. package/tsconfig.build.json +7 -0
  78. package/tsconfig.json +17 -0
@@ -0,0 +1,499 @@
1
+ import {
2
+ ArithmeticBinaryOperation,
3
+ ArithmeticUnaryOperation,
4
+ Assignment,
5
+ AST,
6
+ ASTNode,
7
+ Attribute,
8
+ Call,
9
+ Catch,
10
+ ConstructorPattern,
11
+ EntryPoint,
12
+ Fact,
13
+ Function,
14
+ If,
15
+ ListType,
16
+ LogicalBinaryOperation,
17
+ LogicalUnaryOperation,
18
+ Method,
19
+ ParameterizedType,
20
+ Print,
21
+ Procedure,
22
+ Raise,
23
+ Record as RecordNode,
24
+ Rule,
25
+ SimpleType,
26
+ StopTraversalException,
27
+ SymbolPrimitive,
28
+ TraverseVisitor,
29
+ Try,
30
+ TupleType,
31
+ Type,
32
+ TypeAlias,
33
+ TypeApplication,
34
+ TypeSignature,
35
+ TypeVar,
36
+ Variable,
37
+ VariablePattern,
38
+ } from "yukigo-ast";
39
+ import { InspectionMap, executeVisitor } from "../utils.js";
40
+
41
+ export class Assigns extends TraverseVisitor {
42
+ private readonly targetIdentifier: string;
43
+ constructor(targetIdentifier: string) {
44
+ super();
45
+ this.targetIdentifier = targetIdentifier;
46
+ }
47
+ visitVariable(node: Variable): void {
48
+ if (node.identifier.value === this.targetIdentifier)
49
+ throw new StopTraversalException();
50
+ }
51
+ visitAttribute(node: Attribute): void {
52
+ if (node.identifier.value === this.targetIdentifier)
53
+ throw new StopTraversalException();
54
+ }
55
+ visitAssignment(node: Assignment): void {
56
+ if (node.identifier.value === this.targetIdentifier)
57
+ throw new StopTraversalException();
58
+ }
59
+ }
60
+ export class Calls extends TraverseVisitor {
61
+ private readonly targetCallee: string;
62
+ constructor(targetCallee: string) {
63
+ super();
64
+ this.targetCallee = targetCallee;
65
+ }
66
+ visitCall(node: Call): void {
67
+ if (node.callee.value === this.targetCallee)
68
+ throw new StopTraversalException();
69
+ }
70
+ }
71
+ export class Declares extends TraverseVisitor {
72
+ private readonly targetIdentifier: string;
73
+ constructor(targetIdentifier: string) {
74
+ super();
75
+ this.targetIdentifier = targetIdentifier;
76
+ }
77
+ visit(node: ASTNode): void {
78
+ if (
79
+ "identifier" in node &&
80
+ node.identifier instanceof SymbolPrimitive &&
81
+ node.identifier.value === this.targetIdentifier
82
+ )
83
+ throw new StopTraversalException();
84
+ }
85
+ }
86
+ export class DeclaresComputation extends TraverseVisitor {
87
+ private readonly callName: string;
88
+ constructor(callName: string) {
89
+ super();
90
+ this.callName = callName;
91
+ }
92
+ visitFunction(node: Function): void {
93
+ if (node.identifier.value === this.callName)
94
+ throw new StopTraversalException();
95
+ }
96
+ visitMethod(node: Method): void {
97
+ if (node.identifier.value === this.callName)
98
+ throw new StopTraversalException();
99
+ }
100
+ visitProcedure(node: Procedure): void {
101
+ if (node.identifier.value === this.callName)
102
+ throw new StopTraversalException();
103
+ }
104
+ visitFact(node: Fact): void {
105
+ if (node.identifier.value === this.callName)
106
+ throw new StopTraversalException();
107
+ }
108
+ visitRule(node: Rule): void {
109
+ if (node.identifier.value === this.callName)
110
+ throw new StopTraversalException();
111
+ }
112
+ }
113
+ export class DeclaresComputationWithArity extends TraverseVisitor {
114
+ private readonly targetBinding: string;
115
+ private readonly targetArity: number;
116
+ constructor(targetBinding: string, targetArity: number) {
117
+ super();
118
+ this.targetBinding = targetBinding;
119
+ this.targetArity = targetArity;
120
+ }
121
+ visitFunction(node: Function): void {
122
+ if (
123
+ node.identifier.value === this.targetBinding &&
124
+ node.equations.some((eq) => eq.patterns.length === this.targetArity)
125
+ )
126
+ throw new StopTraversalException();
127
+ }
128
+ visitMethod(node: Method): void {
129
+ if (
130
+ node.identifier.value === this.targetBinding &&
131
+ node.equations.some((eq) => eq.patterns.length === this.targetArity)
132
+ )
133
+ throw new StopTraversalException();
134
+ }
135
+ visitProcedure(node: Procedure): void {
136
+ if (
137
+ node.identifier.value === this.targetBinding &&
138
+ node.equations.some((eq) => eq.patterns.length === this.targetArity)
139
+ )
140
+ throw new StopTraversalException();
141
+ }
142
+ visitFact(node: Fact): void {
143
+ if (
144
+ node.identifier.value === this.targetBinding &&
145
+ node.patterns.length === this.targetArity
146
+ )
147
+ throw new StopTraversalException();
148
+ }
149
+ visitRule(node: Rule): void {
150
+ if (
151
+ node.identifier.value === this.targetBinding &&
152
+ node.patterns.length === this.targetArity
153
+ )
154
+ throw new StopTraversalException();
155
+ }
156
+ }
157
+ export class DeclaresEntryPoint extends TraverseVisitor {
158
+ visitEntryPoint(node: EntryPoint): void {
159
+ throw new StopTraversalException();
160
+ }
161
+ }
162
+ export class DeclaresFunction extends TraverseVisitor {
163
+ private readonly targetBinding: string;
164
+ constructor(targetBinding: string) {
165
+ super();
166
+ this.targetBinding = targetBinding;
167
+ }
168
+ visitFunction(node: Function): void {
169
+ if (node.identifier.value === this.targetBinding)
170
+ throw new StopTraversalException();
171
+ }
172
+ }
173
+
174
+ export class DeclaresRecursively extends DeclaresComputation {
175
+ private readonly targetBinding: string;
176
+ constructor(targetBinding: string) {
177
+ super(targetBinding);
178
+ this.targetBinding = targetBinding;
179
+ }
180
+ visitFunction(node: Function): void {
181
+ super.visitFunction(node);
182
+ this.visitNested(node);
183
+ }
184
+ visitMethod(node: Method): void {
185
+ super.visitMethod(node);
186
+ this.visitNested(node);
187
+ }
188
+ visitProcedure(node: Procedure): void {
189
+ super.visitProcedure(node);
190
+ this.visitNested(node);
191
+ }
192
+ visitFact(node: Fact): void {
193
+ super.visitFact(node);
194
+ this.visitNested(node);
195
+ }
196
+ visitRule(node: Rule): void {
197
+ super.visitRule(node);
198
+ this.visitNested(node);
199
+ }
200
+ visitNested(node: ASTNode): void {
201
+ if (
202
+ "identifier" in node &&
203
+ node.identifier instanceof SymbolPrimitive &&
204
+ node.identifier.value === this.targetBinding
205
+ )
206
+ throw new StopTraversalException();
207
+ }
208
+ }
209
+ export class DeclaresTypeAlias extends TraverseVisitor {
210
+ private readonly typeAliasName: string;
211
+ constructor(typeAliasName: string) {
212
+ super();
213
+ this.typeAliasName = typeAliasName;
214
+ }
215
+ visitTypeAlias(node: TypeAlias): void {
216
+ if (node.identifier.value === this.typeAliasName)
217
+ throw new StopTraversalException();
218
+ }
219
+ }
220
+ export class DeclaresTypeSignature extends TraverseVisitor {
221
+ private readonly targetBinding: string;
222
+ constructor(targetBinding: string) {
223
+ super();
224
+ this.targetBinding = targetBinding;
225
+ }
226
+ visitTypeSignature(node: TypeSignature): void {
227
+ if (node.identifier.value === this.targetBinding)
228
+ throw new StopTraversalException();
229
+ }
230
+ }
231
+ export class DeclaresVariable extends TraverseVisitor {
232
+ private readonly targetBinding: string;
233
+ constructor(targetBinding: string) {
234
+ super();
235
+ this.targetBinding = targetBinding;
236
+ }
237
+ visitVariable(node: Variable): void {
238
+ if (node.identifier.value === this.targetBinding)
239
+ throw new StopTraversalException();
240
+ }
241
+ }
242
+ export class Raises extends TraverseVisitor {
243
+ visitRaise(node: Raise): void {
244
+ throw new StopTraversalException();
245
+ }
246
+ }
247
+ export class Uses extends TraverseVisitor {
248
+ private readonly targetBinding: string;
249
+ constructor(targetBinding: string) {
250
+ super();
251
+ this.targetBinding = targetBinding;
252
+ }
253
+ visitSymbolPrimitive(node: SymbolPrimitive): void {
254
+ if (node.value === this.targetBinding) throw new StopTraversalException();
255
+ }
256
+ }
257
+ export class UsesArithmetic extends TraverseVisitor {
258
+ visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation): void {
259
+ throw new StopTraversalException();
260
+ }
261
+ visitArithmeticUnaryOperation(node: ArithmeticUnaryOperation): void {
262
+ throw new StopTraversalException();
263
+ }
264
+ }
265
+ export class UsesConditional extends TraverseVisitor {
266
+ visitIf(node: If): void {
267
+ throw new StopTraversalException();
268
+ }
269
+ }
270
+ export class UsesLogic extends TraverseVisitor {
271
+ visitLogicalBinaryOperation(node: LogicalBinaryOperation): void {
272
+ throw new StopTraversalException();
273
+ }
274
+ visitLogicalUnaryOperation(node: LogicalUnaryOperation): void {
275
+ throw new StopTraversalException();
276
+ }
277
+ }
278
+ export class UsesPrint extends TraverseVisitor {
279
+ visitPrint(node: Print): void {
280
+ throw new StopTraversalException();
281
+ }
282
+ }
283
+ export class UsesType extends TraverseVisitor {
284
+ private readonly targetBinding: string;
285
+ constructor(targetBinding: string) {
286
+ super();
287
+ this.targetBinding = targetBinding;
288
+ }
289
+ visitTypeSignature(node: TypeSignature): void {
290
+ node.body.accept(this);
291
+ }
292
+ visitSimpleType(node: SimpleType): void {
293
+ if (node.value === this.targetBinding) throw new StopTraversalException();
294
+ }
295
+ visitTypeVar(node: TypeVar): void {
296
+ if (node.value === this.targetBinding) throw new StopTraversalException();
297
+ }
298
+ }
299
+ export class HasBinding extends TraverseVisitor {
300
+ private readonly targetBinding: string;
301
+ constructor(targetBinding: string) {
302
+ super();
303
+ this.targetBinding = targetBinding;
304
+ }
305
+ visitFunction(node: Function): void {
306
+ if (node.identifier.value === this.targetBinding)
307
+ throw new StopTraversalException();
308
+ }
309
+ visitTypeAlias(node: TypeAlias): void {
310
+ if (node.identifier.value === this.targetBinding)
311
+ throw new StopTraversalException();
312
+ }
313
+ visitTypeSignature(node: TypeSignature): void {
314
+ if (node.identifier.value === this.targetBinding)
315
+ throw new StopTraversalException();
316
+ }
317
+ visitRecord(node: RecordNode): void {
318
+ if (node.name.value === this.targetBinding)
319
+ throw new StopTraversalException();
320
+ }
321
+ }
322
+
323
+ export class SubordinatesDeclarationsTo extends TraverseVisitor {
324
+ constructor(private childName: string, private parentName: string) {
325
+ super();
326
+ }
327
+
328
+ visitFunction(node: Function): void {
329
+ if (node.identifier.value === this.parentName) {
330
+ const childFinder = new Declares(this.childName);
331
+ node.equations.forEach((eq) => eq.accept(childFinder)); // we expect that this will throw if find the subordinated decl
332
+ } else {
333
+ super.visitFunction(node);
334
+ }
335
+ }
336
+ }
337
+
338
+ export class SubordinatesDeclarationsToEntryPoint extends TraverseVisitor {
339
+ constructor(private childName: string) {
340
+ super();
341
+ }
342
+
343
+ visitEntryPoint(node: EntryPoint): void {
344
+ const childFinder = new Declares(this.childName);
345
+ node.expression.statements.forEach((stmt) => stmt.accept(childFinder));
346
+ }
347
+ }
348
+
349
+ export class TypesAs extends TraverseVisitor {
350
+ constructor(private bindingName: string, private typeName: string) {
351
+ super();
352
+ }
353
+
354
+ visitTypeSignature(node: TypeSignature): void {
355
+ if (node.identifier.value === this.bindingName) {
356
+ const actualType = node.body.toString();
357
+ if (
358
+ actualType.replace(/\s+/g, " ").trim() ===
359
+ this.typeName.replace(/\s+/g, " ").trim()
360
+ ) {
361
+ throw new StopTraversalException();
362
+ }
363
+ }
364
+ }
365
+ }
366
+
367
+ export class TypesParameterAs extends TraverseVisitor {
368
+ constructor(
369
+ private bindingName: string,
370
+ private paramIndex: number,
371
+ private typeName: string
372
+ ) {
373
+ super();
374
+ }
375
+
376
+ visitTypeSignature(node: TypeSignature): void {
377
+ if (node.identifier.value === this.bindingName) {
378
+ if (node.body instanceof ParameterizedType) {
379
+ const paramType = node.body.inputs[this.paramIndex];
380
+ if (paramType) {
381
+ const actualType = paramType.toString();
382
+ if (
383
+ actualType.replace(/\s+/g, " ").trim() ===
384
+ this.typeName.replace(/\s+/g, " ").trim()
385
+ ) {
386
+ throw new StopTraversalException();
387
+ }
388
+ }
389
+ }
390
+ }
391
+ }
392
+ }
393
+
394
+ export class TypesReturnAs extends TraverseVisitor {
395
+ constructor(private bindingName: string, private typeName: string) {
396
+ super();
397
+ }
398
+
399
+ visitTypeSignature(node: TypeSignature): void {
400
+ if (node.identifier.value === this.bindingName) {
401
+ if (node.body instanceof ParameterizedType) {
402
+ const actualType = node.body.returnType.toString();
403
+ if (
404
+ actualType.replace(/\s+/g, " ").trim() ===
405
+ this.typeName.replace(/\s+/g, " ").trim()
406
+ ) {
407
+ throw new StopTraversalException();
408
+ }
409
+ }
410
+ }
411
+ }
412
+ }
413
+
414
+ export class Rescues extends TraverseVisitor {
415
+ constructor(private exceptionName: string) {
416
+ super();
417
+ }
418
+ visitCatch(node: Catch): void {
419
+ for (const pattern of node.patterns) {
420
+ if (
421
+ pattern instanceof VariablePattern &&
422
+ pattern.name.value === this.exceptionName
423
+ ) {
424
+ throw new StopTraversalException();
425
+ }
426
+ }
427
+ }
428
+ }
429
+
430
+ export class UsesExceptionHandling extends TraverseVisitor {
431
+ visitTry(node: Try): void {
432
+ throw new StopTraversalException();
433
+ }
434
+ }
435
+
436
+ export class UsesExceptions extends TraverseVisitor {
437
+ visitTry(node: Try): void {
438
+ throw new StopTraversalException();
439
+ }
440
+ visitRaise(node: Raise): void {
441
+ throw new StopTraversalException();
442
+ }
443
+ }
444
+
445
+ export const genericInspections: InspectionMap = {
446
+ Assigns: (node, args) => executeVisitor(node, new Assigns(args[0])),
447
+ Calls: (node, args) => executeVisitor(node, new Calls(args[0])),
448
+ Declares: (node, args) => executeVisitor(node, new Declares(args[0])),
449
+ DeclaresComputation: (node, args) =>
450
+ executeVisitor(node, new DeclaresComputation(args[0])),
451
+ DeclaresComputationWithArity: (node, args, binding) =>
452
+ executeVisitor(
453
+ node,
454
+ new DeclaresComputationWithArity(binding, Number(args[0]))
455
+ ),
456
+ DeclaresEntryPoint: (node, args) =>
457
+ executeVisitor(node, new DeclaresEntryPoint()),
458
+ DeclaresFunction: (node, args) =>
459
+ executeVisitor(node, new DeclaresFunction(args[0])),
460
+ DeclaresRecursively: (node, args) =>
461
+ executeVisitor(node, new DeclaresRecursively(args[0])),
462
+ DeclaresTypeAlias: (node, args) =>
463
+ executeVisitor(node, new DeclaresTypeAlias(args[0])),
464
+ DeclaresTypeSignature: (node, args) =>
465
+ executeVisitor(node, new DeclaresTypeSignature(args[0])),
466
+ DeclaresVariable: (node, args) =>
467
+ executeVisitor(node, new DeclaresVariable(args[0])),
468
+ Delegates: (ast, args) => {
469
+ const declares = genericInspections.Declares(ast, args);
470
+ const calls = genericInspections.Calls(ast, args);
471
+ return declares && calls;
472
+ },
473
+ Raises: (node, args) => executeVisitor(node, new Raises()),
474
+ Uses: (node, args) => executeVisitor(node, new Uses(args[0])),
475
+ UsesArithmetic: (node, args) => executeVisitor(node, new UsesArithmetic()),
476
+ SubordinatesDeclarationsTo: (node, args) =>
477
+ executeVisitor(node, new SubordinatesDeclarationsTo(args[0], args[1])),
478
+ SubordinatesDeclarationsToEntryPoint: (node, args) =>
479
+ executeVisitor(node, new SubordinatesDeclarationsToEntryPoint(args[0])),
480
+ TypesAs: (node, args) => executeVisitor(node, new TypesAs(args[0], args[1])),
481
+ TypesParameterAs: (node, args) =>
482
+ executeVisitor(
483
+ node,
484
+ new TypesParameterAs(args[0], Number(args[1]), args[2])
485
+ ),
486
+ TypesReturnAs: (node, args) =>
487
+ executeVisitor(node, new TypesReturnAs(args[0], args[1])),
488
+ UsesConditional: (node, args) => executeVisitor(node, new UsesConditional()),
489
+ Rescues: (node, args) => executeVisitor(node, new Rescues(args[0])),
490
+ UsesExceptionHandling: (node, args) =>
491
+ executeVisitor(node, new UsesExceptionHandling()),
492
+ UsesExceptions: (node, args) => executeVisitor(node, new UsesExceptions()),
493
+ UsesIf: (node, args) => executeVisitor(node, new UsesConditional()),
494
+ UsesLogic: (node, args) => executeVisitor(node, new UsesLogic()),
495
+ UsesMath: (node, args) => executeVisitor(node, new UsesArithmetic()),
496
+ UsesPrint: (node, args) => executeVisitor(node, new UsesPrint()),
497
+ UsesType: (node, args) => executeVisitor(node, new UsesType(args[0])),
498
+ HasBinding: (node, args) => executeVisitor(node, new HasBinding(args[0])),
499
+ };
@@ -0,0 +1,129 @@
1
+ import {
2
+ Enumeration,
3
+ ForLoop,
4
+ Function,
5
+ Procedure,
6
+ Repeat,
7
+ StopTraversalException,
8
+ Switch,
9
+ TraverseVisitor,
10
+ While,
11
+ } from "yukigo-ast";
12
+ import { InspectionMap, executeVisitor } from "../utils.js";
13
+
14
+ export class BindingVisitor extends TraverseVisitor {
15
+ private readonly targetBinding: string;
16
+ protected isInsideTargetScope: boolean = false; // this flag helps to check nested functions inside the targetBinding scope
17
+ constructor(binding: string) {
18
+ super();
19
+ this.targetBinding = binding;
20
+ }
21
+ visitProcedure(node: Procedure): void {
22
+ const currentFunctionName = node.identifier.value;
23
+
24
+ // if not inside scope then is top-level
25
+ if (!this.isInsideTargetScope) {
26
+ if (!this.targetBinding || currentFunctionName === this.targetBinding) {
27
+ this.isInsideTargetScope = true;
28
+ this.traverseCollection(node.equations);
29
+ this.isInsideTargetScope = false;
30
+ return;
31
+ }
32
+ return;
33
+ }
34
+ // if inside the scope of targetBinding then traverse
35
+ this.traverseCollection(node.equations);
36
+ }
37
+ visitFunction(node: Function): void {
38
+ const currentFunctionName = node.identifier.value;
39
+
40
+ // if not inside scope then is top-level
41
+ if (!this.isInsideTargetScope) {
42
+ if (!this.targetBinding || currentFunctionName === this.targetBinding) {
43
+ this.isInsideTargetScope = true;
44
+ this.traverseCollection(node.equations);
45
+ this.isInsideTargetScope = false;
46
+ return;
47
+ }
48
+ return;
49
+ }
50
+ // if inside the scope of targetBinding then traverse
51
+ this.traverseCollection(node.equations);
52
+ }
53
+ }
54
+
55
+ export class DeclaresEnumeration extends TraverseVisitor {
56
+ private readonly enumName: string;
57
+ constructor(enumName: string) {
58
+ super();
59
+ this.enumName = enumName;
60
+ }
61
+ visitEnumeration(node: Enumeration): void {
62
+ if (node.identifier.value === this.enumName) throw StopTraversalException;
63
+ }
64
+ }
65
+ export class DeclaresProcedure extends TraverseVisitor {
66
+ private readonly procedureName: string;
67
+ constructor(procedureName: string) {
68
+ super();
69
+ this.procedureName = procedureName;
70
+ }
71
+ visitProcedure(node: Procedure): void {
72
+ if (node.identifier.value === this.procedureName)
73
+ throw StopTraversalException;
74
+ }
75
+ }
76
+ export class UsesForLoop extends BindingVisitor {
77
+ visitForLoop(node: ForLoop): void {
78
+ throw StopTraversalException;
79
+ }
80
+ }
81
+ export class UsesWhile extends BindingVisitor {
82
+ visitWhile(node: While): void {
83
+ throw StopTraversalException;
84
+ }
85
+ }
86
+ export class UsesRepeat extends BindingVisitor {
87
+ visitRepeat(node: Repeat): void {
88
+ throw StopTraversalException;
89
+ }
90
+ }
91
+ export class UsesLoop extends BindingVisitor {
92
+ visitForLoop(node: ForLoop): void {
93
+ throw StopTraversalException;
94
+ }
95
+ visitWhile(node: While): void {
96
+ throw StopTraversalException;
97
+ }
98
+ visitRepeat(node: Repeat): void {
99
+ throw StopTraversalException;
100
+ }
101
+ // visitForEach(node: ForEach): void {
102
+ // throw StopTraversalException;
103
+ // }
104
+ }
105
+ export class UsesSwitch extends BindingVisitor {
106
+ visitSwitch(node: Switch): void {
107
+ throw StopTraversalException;
108
+ }
109
+ }
110
+
111
+ export const imperativeInspections: InspectionMap = {
112
+ DeclaresEnumeration: (node, args) =>
113
+ executeVisitor(node, new DeclaresEnumeration(args[0])),
114
+ DeclaresProcedure: (node, args) =>
115
+ executeVisitor(node, new DeclaresProcedure(args[0])),
116
+ UsesForEach: (node, args) => {
117
+ throw Error("Inspection not implemented");
118
+ },
119
+ UsesForLoop: (node, args, binding) =>
120
+ executeVisitor(node, new UsesForLoop(binding)),
121
+ UsesRepeat: (node, args, binding) =>
122
+ executeVisitor(node, new UsesRepeat(binding)),
123
+ UsesWhile: (node, args, binding) =>
124
+ executeVisitor(node, new UsesWhile(binding)),
125
+ UsesLoop: (node, args, binding) =>
126
+ executeVisitor(node, new UsesLoop(binding)),
127
+ UsesSwitch: (node, args, binding) =>
128
+ executeVisitor(node, new UsesSwitch(binding)),
129
+ };