yukigo 0.1.0 → 0.2.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 (144) hide show
  1. package/.mocharc.json +3 -3
  2. package/CHANGELOG.md +26 -0
  3. package/README.md +193 -199
  4. package/dist/analyzer/GraphBuilder.d.ts +29 -0
  5. package/dist/analyzer/GraphBuilder.js +99 -0
  6. package/dist/analyzer/index.d.ts +11 -23
  7. package/dist/analyzer/index.js +100 -58
  8. package/dist/analyzer/inspections/functional/functional.d.ts +44 -0
  9. package/dist/analyzer/inspections/functional/functional.js +149 -0
  10. package/dist/analyzer/inspections/functional/smells.d.ts +16 -0
  11. package/dist/analyzer/inspections/functional/smells.js +98 -0
  12. package/dist/analyzer/inspections/{generic.d.ts → generic/generic.d.ts} +70 -43
  13. package/dist/analyzer/inspections/generic/generic.js +604 -0
  14. package/dist/analyzer/inspections/generic/smells.d.ts +61 -0
  15. package/dist/analyzer/inspections/generic/smells.js +349 -0
  16. package/dist/analyzer/inspections/imperative/imperative.d.ts +35 -0
  17. package/dist/analyzer/inspections/imperative/imperative.js +109 -0
  18. package/dist/analyzer/inspections/imperative/smells.d.ts +16 -0
  19. package/dist/analyzer/inspections/imperative/smells.js +58 -0
  20. package/dist/analyzer/inspections/logic/logic.d.ts +32 -0
  21. package/dist/analyzer/inspections/logic/logic.js +96 -0
  22. package/dist/analyzer/inspections/logic/smells.d.ts +15 -0
  23. package/dist/analyzer/inspections/logic/smells.js +60 -0
  24. package/dist/analyzer/inspections/object/object.d.ts +88 -0
  25. package/dist/analyzer/inspections/object/object.js +319 -0
  26. package/dist/analyzer/inspections/object/smells.d.ts +30 -0
  27. package/dist/analyzer/inspections/object/smells.js +135 -0
  28. package/dist/analyzer/utils.d.ts +26 -4
  29. package/dist/analyzer/utils.js +71 -13
  30. package/dist/index.d.ts +1 -0
  31. package/dist/index.js +1 -0
  32. package/dist/interpreter/components/EnvBuilder.d.ts +9 -5
  33. package/dist/interpreter/components/EnvBuilder.js +100 -30
  34. package/dist/interpreter/components/Operations.d.ts +4 -4
  35. package/dist/interpreter/components/Operations.js +17 -2
  36. package/dist/interpreter/components/PatternMatcher.d.ts +47 -17
  37. package/dist/interpreter/components/PatternMatcher.js +264 -119
  38. package/dist/interpreter/components/RuntimeContext.d.ts +35 -0
  39. package/dist/interpreter/components/RuntimeContext.js +93 -0
  40. package/dist/interpreter/components/TestRunner.d.ts +18 -0
  41. package/dist/interpreter/components/TestRunner.js +103 -0
  42. package/dist/interpreter/components/Visitor.d.ts +63 -57
  43. package/dist/interpreter/components/Visitor.js +508 -173
  44. package/dist/interpreter/components/logic/LogicEngine.d.ts +29 -0
  45. package/dist/interpreter/components/logic/LogicEngine.js +259 -0
  46. package/dist/interpreter/components/logic/LogicResolver.d.ts +53 -0
  47. package/dist/interpreter/components/logic/LogicResolver.js +471 -0
  48. package/dist/interpreter/components/logic/LogicTranslator.d.ts +14 -0
  49. package/dist/interpreter/components/logic/LogicTranslator.js +99 -0
  50. package/dist/interpreter/components/runtimes/FunctionRuntime.d.ts +12 -0
  51. package/dist/interpreter/components/runtimes/FunctionRuntime.js +147 -0
  52. package/dist/interpreter/components/runtimes/LazyRuntime.d.ts +19 -0
  53. package/dist/interpreter/components/runtimes/LazyRuntime.js +269 -0
  54. package/dist/interpreter/components/runtimes/ObjectRuntime.d.ts +35 -0
  55. package/dist/interpreter/components/runtimes/ObjectRuntime.js +126 -0
  56. package/dist/interpreter/entities.d.ts +105 -0
  57. package/dist/interpreter/entities.js +96 -0
  58. package/dist/interpreter/errors.d.ts +1 -1
  59. package/dist/interpreter/index.d.ts +4 -12
  60. package/dist/interpreter/index.js +10 -13
  61. package/dist/interpreter/trampoline.d.ts +17 -0
  62. package/dist/interpreter/trampoline.js +38 -0
  63. package/dist/interpreter/utils.d.ts +4 -7
  64. package/dist/interpreter/utils.js +25 -17
  65. package/dist/tester/index.d.ts +25 -0
  66. package/dist/tester/index.js +108 -0
  67. package/dist/utils/helpers.d.ts +0 -4
  68. package/dist/utils/helpers.js +20 -24
  69. package/package.json +2 -2
  70. package/src/analyzer/GraphBuilder.ts +142 -0
  71. package/src/analyzer/index.ts +185 -132
  72. package/src/analyzer/inspections/functional/functional.ts +121 -0
  73. package/src/analyzer/inspections/functional/smells.ts +102 -0
  74. package/src/analyzer/inspections/{generic.ts → generic/generic.ts} +581 -499
  75. package/src/analyzer/inspections/generic/smells.ts +365 -0
  76. package/src/analyzer/inspections/imperative/imperative.ts +101 -0
  77. package/src/analyzer/inspections/imperative/smells.ts +54 -0
  78. package/src/analyzer/inspections/logic/logic.ts +90 -0
  79. package/src/analyzer/inspections/logic/smells.ts +54 -0
  80. package/src/analyzer/inspections/{object.ts → object/object.ts} +264 -282
  81. package/src/analyzer/inspections/object/smells.ts +144 -0
  82. package/src/analyzer/utils.ts +109 -26
  83. package/src/index.ts +3 -2
  84. package/src/interpreter/components/EnvBuilder.ts +202 -97
  85. package/src/interpreter/components/Operations.ts +99 -81
  86. package/src/interpreter/components/PatternMatcher.ts +475 -254
  87. package/src/interpreter/components/RuntimeContext.ts +119 -0
  88. package/src/interpreter/components/TestRunner.ts +151 -0
  89. package/src/interpreter/components/Visitor.ts +1065 -493
  90. package/src/interpreter/components/logic/LogicEngine.ts +519 -0
  91. package/src/interpreter/components/logic/LogicResolver.ts +858 -0
  92. package/src/interpreter/components/logic/LogicTranslator.ts +149 -0
  93. package/src/interpreter/components/runtimes/FunctionRuntime.ts +227 -0
  94. package/src/interpreter/components/runtimes/LazyRuntime.ts +334 -0
  95. package/src/interpreter/components/runtimes/ObjectRuntime.ts +224 -0
  96. package/src/interpreter/errors.ts +47 -47
  97. package/src/interpreter/index.ts +52 -59
  98. package/src/interpreter/trampoline.ts +71 -0
  99. package/src/interpreter/utils.ts +84 -79
  100. package/src/tester/index.ts +128 -0
  101. package/src/utils/helpers.ts +67 -73
  102. package/tests/analyzer/functional.spec.ts +207 -221
  103. package/tests/analyzer/generic.spec.ts +178 -100
  104. package/tests/analyzer/helpers.spec.ts +83 -83
  105. package/tests/analyzer/logic.spec.ts +237 -292
  106. package/tests/analyzer/oop.spec.ts +323 -338
  107. package/tests/analyzer/transitive.spec.ts +166 -0
  108. package/tests/interpreter/EnvBuilder.spec.ts +183 -178
  109. package/tests/interpreter/FunctionRuntime.spec.ts +223 -234
  110. package/tests/interpreter/LazyRuntime.spec.ts +225 -190
  111. package/tests/interpreter/LogicEngine.spec.ts +327 -194
  112. package/tests/interpreter/LogicSubstitution.spec.ts +80 -0
  113. package/tests/interpreter/ObjectRuntime.spec.ts +606 -0
  114. package/tests/interpreter/Operations.spec.ts +220 -220
  115. package/tests/interpreter/PatternSystem.spec.ts +213 -189
  116. package/tests/interpreter/Tests.spec.ts +122 -0
  117. package/tests/interpreter/interpreter.spec.ts +991 -937
  118. package/tests/tester/Tester.spec.ts +153 -0
  119. package/tsconfig.build.json +15 -7
  120. package/tsconfig.json +25 -17
  121. package/dist/analyzer/inspections/functional.d.ts +0 -46
  122. package/dist/analyzer/inspections/functional.js +0 -123
  123. package/dist/analyzer/inspections/generic.js +0 -427
  124. package/dist/analyzer/inspections/imperative.d.ts +0 -37
  125. package/dist/analyzer/inspections/imperative.js +0 -105
  126. package/dist/analyzer/inspections/logic.d.ts +0 -49
  127. package/dist/analyzer/inspections/logic.js +0 -140
  128. package/dist/analyzer/inspections/object.d.ts +0 -83
  129. package/dist/analyzer/inspections/object.js +0 -235
  130. package/dist/interpreter/components/FunctionRuntime.d.ts +0 -8
  131. package/dist/interpreter/components/FunctionRuntime.js +0 -52
  132. package/dist/interpreter/components/LazyRuntime.d.ts +0 -7
  133. package/dist/interpreter/components/LazyRuntime.js +0 -75
  134. package/dist/interpreter/components/LogicEngine.d.ts +0 -21
  135. package/dist/interpreter/components/LogicEngine.js +0 -152
  136. package/dist/interpreter/components/LogicResolver.d.ts +0 -11
  137. package/dist/interpreter/components/LogicResolver.js +0 -87
  138. package/src/analyzer/inspections/functional.ts +0 -159
  139. package/src/analyzer/inspections/imperative.ts +0 -129
  140. package/src/analyzer/inspections/logic.ts +0 -166
  141. package/src/interpreter/components/FunctionRuntime.ts +0 -79
  142. package/src/interpreter/components/LazyRuntime.ts +0 -97
  143. package/src/interpreter/components/LogicEngine.ts +0 -227
  144. package/src/interpreter/components/LogicResolver.ts +0 -130
@@ -1,19 +1,33 @@
1
- import { genericInspections } from "./inspections/generic.js";
2
- import { functionalInspections } from "./inspections/functional.js";
3
- import { logicInspections } from "./inspections/logic.js";
4
- import { objectInspections } from "./inspections/object.js";
5
- import { imperativeInspections } from "./inspections/imperative.js";
6
- export const defaultInspectionSet = {
1
+ import { StopTraversalException } from "yukigo-ast";
2
+ import { genericInspections } from "./inspections/generic/generic.js";
3
+ import { functionalInspections } from "./inspections/functional/functional.js";
4
+ import { logicInspections } from "./inspections/logic/logic.js";
5
+ import { objectInspections } from "./inspections/object/object.js";
6
+ import { imperativeInspections } from "./inspections/imperative/imperative.js";
7
+ import { functionalSmells } from "./inspections/functional/smells.js";
8
+ import { logicSmells } from "./inspections/logic/smells.js";
9
+ import { objectSmells } from "./inspections/object/smells.js";
10
+ import { imperativeSmells } from "./inspections/imperative/smells.js";
11
+ import { genericSmells } from "./inspections/generic/smells.js";
12
+ import { GraphBuilder } from "./GraphBuilder.js";
13
+ export const DefaultInspectionSet = {
7
14
  ...genericInspections,
8
15
  ...functionalInspections,
9
16
  ...logicInspections,
10
17
  ...objectInspections,
11
18
  ...imperativeInspections,
12
19
  };
20
+ export const DefaultSmellsSet = {
21
+ ...genericSmells,
22
+ ...functionalSmells,
23
+ ...logicSmells,
24
+ ...objectSmells,
25
+ ...imperativeSmells,
26
+ };
13
27
  /**
14
28
  * The Analyzer class.
15
29
  * @remarks
16
- * The Analyzer is the part of Yukigo which runs the inspections on the AST.
30
+ * The Analyzer is the part of Yukigo which runs the inspections on the AST.s
17
31
  */
18
32
  export class Analyzer {
19
33
  /**
@@ -21,30 +35,19 @@ export class Analyzer {
21
35
  * You can load your set of inspections or leave the default one.
22
36
  * @defaultValue a default set of inspections for each supported paradigm
23
37
  */
24
- inspectionHandlers = {};
25
- constructor(inspectionSet) {
26
- this.inspectionHandlers = inspectionSet ?? defaultInspectionSet;
38
+ inspectionConstructors = {};
39
+ smellsConstructors = {};
40
+ constructor(inspectionSet, smellsSet) {
41
+ this.inspectionConstructors = inspectionSet ?? DefaultInspectionSet;
42
+ this.smellsConstructors = smellsSet ?? DefaultSmellsSet;
27
43
  }
28
44
  /**
29
45
  * Registers a new custom inspection handler after Analyzer was instantiated.
30
46
  * @param name The name of the inspection (e.g., "HasArithmetic").
31
- * @param handler The function that implements the inspection logic.
32
- *
33
- * @example
34
- * // Implementation of HasArithmetic inspection
35
- * export class UsesArithmetic extends TraverseVisitor {
36
- * visitArithmeticBinaryOperation(node: ArithmeticBinaryOperation): void {
37
- * throw new StopTraversalException();
38
- * }
39
- * visitArithmeticUnaryOperation(node: ArithmeticUnaryOperation): void {
40
- * throw new StopTraversalException();
41
- * }
42
- * }
43
- * const analyzer = new ASTAnalyzer(ast);
44
- * analyzer.registerInspection("HasArithmetic", (node, args) => executeVisitor(node, new UsesArithmetic()));
47
+ * @param visitorConstructor The constructor for the TraverseVisitor class.
45
48
  */
46
- registerInspection(name, handler) {
47
- this.inspectionHandlers[name] = handler;
49
+ registerInspection(name, visitorConstructor) {
50
+ this.inspectionConstructors[name] = visitorConstructor;
48
51
  }
49
52
  /**
50
53
  * Runs a list of inspection rules against the AST.
@@ -68,43 +71,82 @@ export class Analyzer {
68
71
  * const analysisResults = analyzer.analyze(expectations);
69
72
  */
70
73
  analyze(ast, rules) {
71
- const results = [];
74
+ const ruleResults = new Map();
75
+ const graphBuilder = new GraphBuilder();
76
+ const { defs, calls } = graphBuilder.build(ast);
72
77
  for (const rule of rules) {
73
- results.push(this.runRule(rule, ast));
74
- }
75
- return results;
76
- }
77
- runRule(rule, ast) {
78
- const inspection = this.inspectionHandlers[rule.inspection];
79
- if (!inspection)
80
- return {
81
- rule,
82
- passed: false,
83
- actual: false,
84
- error: "Unknown inspection",
85
- };
86
- try {
87
- let result = false;
88
- for (const node of ast) {
89
- if (inspection(node, rule.args, rule.binding)) {
90
- result = true;
91
- break;
78
+ let inspectionName = rule.inspection;
79
+ let isTransitive = true;
80
+ if (inspectionName.startsWith("Intransitive:")) {
81
+ isTransitive = false;
82
+ inspectionName = inspectionName.replace("Intransitive:", "");
83
+ }
84
+ const InspectionClass = this.inspectionConstructors[inspectionName];
85
+ if (!InspectionClass) {
86
+ ruleResults.set(rule, {
87
+ rule,
88
+ passed: false,
89
+ actual: false,
90
+ error: "Unknown inspection: " + inspectionName,
91
+ });
92
+ continue;
93
+ }
94
+ if (InspectionClass.IS_INTRANSITIVE)
95
+ isTransitive = false;
96
+ let targets = [];
97
+ // Case 1: Global Inspection (No binding or wildcard)
98
+ if (!rule.binding || rule.binding === "*") {
99
+ targets = ast.map((n) => ({ node: n, binding: undefined }));
100
+ }
101
+ // Case 2: Directed Inspection (Specific binding)
102
+ else {
103
+ const workList = [rule.binding];
104
+ const visited = new Set();
105
+ while (workList.length > 0) {
106
+ const currentBinding = workList.shift();
107
+ if (visited.has(currentBinding))
108
+ continue;
109
+ visited.add(currentBinding);
110
+ const node = defs.get(currentBinding);
111
+ if (node)
112
+ node.forEach((n) => targets.push({ node: n, binding: currentBinding }));
113
+ if (isTransitive) {
114
+ const deps = calls.get(currentBinding) || [];
115
+ workList.push(...deps);
116
+ }
92
117
  }
93
118
  }
94
- const passed = result === rule.expected;
95
- return {
96
- rule,
97
- passed,
98
- actual: result,
99
- };
100
- }
101
- catch (error) {
102
- return {
119
+ let actual = false;
120
+ let error;
121
+ // Execution Loop
122
+ const isGlobalVisitor = !rule.binding || rule.binding === "*";
123
+ const normalizedBinding = isGlobalVisitor ? undefined : rule.binding;
124
+ const args = rule.args ?? [];
125
+ const visitor = new InspectionClass(...args, normalizedBinding);
126
+ for (const { node, binding } of targets) {
127
+ try {
128
+ if (!isGlobalVisitor && visitor.setBinding) {
129
+ visitor.setBinding(binding);
130
+ }
131
+ node.accept(visitor);
132
+ }
133
+ catch (e) {
134
+ if (e instanceof StopTraversalException) {
135
+ actual = true;
136
+ break; // Short-circuit: Rule passed
137
+ }
138
+ else {
139
+ error = e.message;
140
+ }
141
+ }
142
+ }
143
+ ruleResults.set(rule, {
103
144
  rule,
104
- passed: false,
105
- actual: false,
145
+ passed: actual === rule.expected,
146
+ actual,
106
147
  error,
107
- };
148
+ });
108
149
  }
150
+ return [...ruleResults.values()];
109
151
  }
110
152
  }
@@ -0,0 +1,44 @@
1
+ import * as Yu from "yukigo-ast";
2
+ import { VisitorConstructor, ScopedVisitor } from "../../utils.js";
3
+ export declare class UsesComposition extends ScopedVisitor {
4
+ constructor(scope?: string);
5
+ visitCompositionExpression(node: Yu.CompositionExpression): void;
6
+ }
7
+ export declare class UsesAnonymousVariable extends ScopedVisitor {
8
+ constructor(scope?: string);
9
+ visitWildcardPattern(node: Yu.WildcardPattern): void;
10
+ }
11
+ export declare class UsesComprehension extends ScopedVisitor {
12
+ constructor(scope?: string);
13
+ visitListComprehension(node: Yu.ListComprehension): void;
14
+ }
15
+ export declare class UsesGuards extends ScopedVisitor {
16
+ constructor(scope?: string);
17
+ visitGuardedBody(node: Yu.GuardedBody): void;
18
+ }
19
+ export declare class UsesOtherwise extends ScopedVisitor {
20
+ constructor(scope?: string);
21
+ visitOtherwise(node: Yu.Otherwise): void;
22
+ }
23
+ export declare class UsesLambda extends ScopedVisitor {
24
+ constructor(scope?: string);
25
+ visitLambda(node: Yu.Lambda): void;
26
+ }
27
+ export declare class UsesYield extends ScopedVisitor {
28
+ constructor(scope?: string);
29
+ visitYield(node: Yu.Yield): void;
30
+ }
31
+ export declare class UsesPatternMatching extends ScopedVisitor {
32
+ constructor(scope?: string);
33
+ visitConsPattern(node: Yu.ConsPattern): void;
34
+ visitAsPattern(node: Yu.AsPattern): void;
35
+ visitListPattern(node: Yu.ListPattern): void;
36
+ visitTuplePattern(node: Yu.TuplePattern): void;
37
+ visitLiteralPattern(node: Yu.LiteralPattern): void;
38
+ visitApplicationPattern(node: Yu.ApplicationPattern): void;
39
+ visitConstructorPattern(node: Yu.ConstructorPattern): void;
40
+ visitUnionPattern(node: Yu.UnionPattern): void;
41
+ visitFunctorPattern(node: Yu.FunctorPattern): void;
42
+ visitWildcardPattern(node: Yu.WildcardPattern): void;
43
+ }
44
+ export declare const functionalInspections: Record<string, VisitorConstructor>;
@@ -0,0 +1,149 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import * as Yu from "yukigo-ast";
8
+ import { ScopedVisitor, AutoScoped } from "../../utils.js";
9
+ let UsesComposition = class UsesComposition extends ScopedVisitor {
10
+ constructor(scope) {
11
+ super(scope);
12
+ }
13
+ visitCompositionExpression(node) {
14
+ throw new Yu.StopTraversalException();
15
+ }
16
+ };
17
+ UsesComposition = __decorate([
18
+ AutoScoped
19
+ ], UsesComposition);
20
+ export { UsesComposition };
21
+ let UsesAnonymousVariable = class UsesAnonymousVariable extends ScopedVisitor {
22
+ constructor(scope) {
23
+ super(scope);
24
+ }
25
+ visitWildcardPattern(node) {
26
+ throw new Yu.StopTraversalException();
27
+ }
28
+ };
29
+ UsesAnonymousVariable = __decorate([
30
+ AutoScoped
31
+ ], UsesAnonymousVariable);
32
+ export { UsesAnonymousVariable };
33
+ let UsesComprehension = class UsesComprehension extends ScopedVisitor {
34
+ constructor(scope) {
35
+ super(scope);
36
+ }
37
+ visitListComprehension(node) {
38
+ throw new Yu.StopTraversalException();
39
+ }
40
+ };
41
+ UsesComprehension = __decorate([
42
+ AutoScoped
43
+ ], UsesComprehension);
44
+ export { UsesComprehension };
45
+ let UsesGuards = class UsesGuards extends ScopedVisitor {
46
+ constructor(scope) {
47
+ super(scope);
48
+ }
49
+ visitGuardedBody(node) {
50
+ throw new Yu.StopTraversalException();
51
+ }
52
+ };
53
+ UsesGuards = __decorate([
54
+ AutoScoped
55
+ ], UsesGuards);
56
+ export { UsesGuards };
57
+ let UsesOtherwise = class UsesOtherwise extends ScopedVisitor {
58
+ constructor(scope) {
59
+ super(scope);
60
+ }
61
+ visitOtherwise(node) {
62
+ throw new Yu.StopTraversalException();
63
+ }
64
+ };
65
+ UsesOtherwise = __decorate([
66
+ AutoScoped
67
+ ], UsesOtherwise);
68
+ export { UsesOtherwise };
69
+ let UsesLambda = class UsesLambda extends ScopedVisitor {
70
+ constructor(scope) {
71
+ super(scope);
72
+ }
73
+ visitLambda(node) {
74
+ throw new Yu.StopTraversalException();
75
+ }
76
+ };
77
+ UsesLambda = __decorate([
78
+ AutoScoped
79
+ ], UsesLambda);
80
+ export { UsesLambda };
81
+ let UsesYield = class UsesYield extends ScopedVisitor {
82
+ constructor(scope) {
83
+ super(scope);
84
+ }
85
+ visitYield(node) {
86
+ throw new Yu.StopTraversalException();
87
+ }
88
+ };
89
+ UsesYield = __decorate([
90
+ AutoScoped
91
+ ], UsesYield);
92
+ export { UsesYield };
93
+ let UsesPatternMatching = class UsesPatternMatching extends ScopedVisitor {
94
+ constructor(scope) {
95
+ super(scope);
96
+ }
97
+ visitConsPattern(node) {
98
+ throw new Yu.StopTraversalException();
99
+ }
100
+ visitAsPattern(node) {
101
+ throw new Yu.StopTraversalException();
102
+ }
103
+ visitListPattern(node) {
104
+ throw new Yu.StopTraversalException();
105
+ }
106
+ visitTuplePattern(node) {
107
+ throw new Yu.StopTraversalException();
108
+ }
109
+ visitLiteralPattern(node) {
110
+ throw new Yu.StopTraversalException();
111
+ }
112
+ visitApplicationPattern(node) {
113
+ throw new Yu.StopTraversalException();
114
+ }
115
+ visitConstructorPattern(node) {
116
+ throw new Yu.StopTraversalException();
117
+ }
118
+ visitUnionPattern(node) {
119
+ throw new Yu.StopTraversalException();
120
+ }
121
+ visitFunctorPattern(node) {
122
+ throw new Yu.StopTraversalException();
123
+ }
124
+ visitWildcardPattern(node) {
125
+ throw new Yu.StopTraversalException();
126
+ }
127
+ };
128
+ UsesPatternMatching = __decorate([
129
+ AutoScoped
130
+ ], UsesPatternMatching);
131
+ export { UsesPatternMatching };
132
+ export const functionalInspections = {
133
+ UsesComposition: UsesComposition,
134
+ HasComposition: UsesComposition,
135
+ UsesAnonymousVariable: UsesAnonymousVariable,
136
+ HasAnonymousVariable: UsesAnonymousVariable,
137
+ UsesComprehension: UsesComprehension,
138
+ HasComprehension: UsesComprehension,
139
+ UsesGuards: UsesGuards,
140
+ HasGuards: UsesGuards,
141
+ UsesOtherwise: UsesOtherwise,
142
+ HasOtherwise: UsesOtherwise,
143
+ UsesLambda: UsesLambda,
144
+ HasLambda: UsesLambda,
145
+ UsesYield: UsesYield,
146
+ HasYield: UsesYield,
147
+ UsesPatternMatching: UsesPatternMatching,
148
+ HasPatternMatching: UsesPatternMatching,
149
+ };
@@ -0,0 +1,16 @@
1
+ import { Lambda, Equation, GuardedBody } from "yukigo-ast";
2
+ import { ScopedVisitor, VisitorConstructor } from "../../utils.js";
3
+ export declare class HasRedundantLambda extends ScopedVisitor {
4
+ visitLambda(node: Lambda): void;
5
+ }
6
+ export declare class HasRedundantGuards extends ScopedVisitor {
7
+ visitEquation(node: Equation): void;
8
+ private isAlwaysTrue;
9
+ }
10
+ export declare class ShouldUseOtherwise extends ScopedVisitor {
11
+ visitGuardedBody(node: GuardedBody): void;
12
+ }
13
+ export declare class HasRedundantParameter extends ScopedVisitor {
14
+ visitEquation(node: Equation): void;
15
+ }
16
+ export declare const functionalSmells: Record<string, VisitorConstructor>;
@@ -0,0 +1,98 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { Call, VariablePattern, Variable, StopTraversalException, BooleanPrimitive, Application, isUnguardedBody, Otherwise, } from "yukigo-ast";
8
+ import { AutoScoped, ScopedVisitor } from "../../utils.js";
9
+ import { Uses } from "../generic/generic.js";
10
+ let HasRedundantLambda = class HasRedundantLambda extends ScopedVisitor {
11
+ visitLambda(node) {
12
+ if (node.parameters.length !== 1)
13
+ return;
14
+ if (!(node.body instanceof Application))
15
+ return;
16
+ const param = node.parameters[0];
17
+ const call = node.body;
18
+ if (call.functionExpr instanceof Application ||
19
+ call.functionExpr instanceof Call)
20
+ return;
21
+ const arg = call.parameter;
22
+ if (param instanceof VariablePattern &&
23
+ arg instanceof Variable &&
24
+ param.name.value === arg.identifier.value)
25
+ throw new StopTraversalException();
26
+ }
27
+ };
28
+ HasRedundantLambda = __decorate([
29
+ AutoScoped
30
+ ], HasRedundantLambda);
31
+ export { HasRedundantLambda };
32
+ let HasRedundantGuards = class HasRedundantGuards extends ScopedVisitor {
33
+ visitEquation(node) {
34
+ if (isUnguardedBody(node.body))
35
+ return;
36
+ // If there is only 1 guard...
37
+ if (node.body.length === 1) {
38
+ const guard = node.body[0];
39
+ // ...and that guard is "True" or "otherwise"
40
+ if (this.isAlwaysTrue(guard.condition))
41
+ throw new StopTraversalException();
42
+ }
43
+ }
44
+ isAlwaysTrue(node) {
45
+ // check for boolean literal 'True'
46
+ if (node instanceof BooleanPrimitive && node.value === true)
47
+ return true;
48
+ // check for default case
49
+ if (node instanceof Otherwise)
50
+ return true;
51
+ return false;
52
+ }
53
+ };
54
+ HasRedundantGuards = __decorate([
55
+ AutoScoped
56
+ ], HasRedundantGuards);
57
+ export { HasRedundantGuards };
58
+ let ShouldUseOtherwise = class ShouldUseOtherwise extends ScopedVisitor {
59
+ visitGuardedBody(node) {
60
+ if (node.condition instanceof BooleanPrimitive &&
61
+ node.condition.value === true)
62
+ throw new StopTraversalException();
63
+ }
64
+ };
65
+ ShouldUseOtherwise = __decorate([
66
+ AutoScoped
67
+ ], ShouldUseOtherwise);
68
+ export { ShouldUseOtherwise };
69
+ let HasRedundantParameter = class HasRedundantParameter extends ScopedVisitor {
70
+ visitEquation(node) {
71
+ for (const pattern of node.patterns) {
72
+ if (pattern instanceof VariablePattern) {
73
+ const paramName = pattern.name.value;
74
+ const usageChecker = new Uses(paramName, this.binding);
75
+ try {
76
+ node.accept(usageChecker);
77
+ // uses didnt throw so the param is not being used
78
+ throw new StopTraversalException();
79
+ }
80
+ catch (e) {
81
+ if (e instanceof StopTraversalException)
82
+ continue;
83
+ throw e;
84
+ }
85
+ }
86
+ }
87
+ }
88
+ };
89
+ HasRedundantParameter = __decorate([
90
+ AutoScoped
91
+ ], HasRedundantParameter);
92
+ export { HasRedundantParameter };
93
+ export const functionalSmells = {
94
+ HasRedundantGuards: HasRedundantGuards,
95
+ HasRedundantLambda: HasRedundantLambda,
96
+ HasRedundantParameter: HasRedundantParameter,
97
+ ShouldUseOtherwise: ShouldUseOtherwise,
98
+ };