yukigo 0.2.0 → 0.2.3

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 (76) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/analyzer/index.d.ts +7 -0
  3. package/dist/analyzer/inspections/generic/generic.d.ts +1 -2
  4. package/dist/analyzer/inspections/generic/generic.js +2 -5
  5. package/dist/src/analyzer/GraphBuilder.d.ts +30 -0
  6. package/dist/src/analyzer/GraphBuilder.js +100 -0
  7. package/dist/src/analyzer/index.d.ts +59 -0
  8. package/dist/src/analyzer/index.js +152 -0
  9. package/dist/src/analyzer/inspections/functional/functional.d.ts +44 -0
  10. package/dist/src/analyzer/inspections/functional/functional.js +149 -0
  11. package/dist/src/analyzer/inspections/functional/smells.d.ts +16 -0
  12. package/dist/src/analyzer/inspections/functional/smells.js +98 -0
  13. package/dist/src/analyzer/inspections/generic/generic.d.ts +178 -0
  14. package/dist/src/analyzer/inspections/generic/generic.js +604 -0
  15. package/dist/src/analyzer/inspections/generic/smells.d.ts +61 -0
  16. package/dist/src/analyzer/inspections/generic/smells.js +349 -0
  17. package/dist/src/analyzer/inspections/imperative/imperative.d.ts +35 -0
  18. package/dist/src/analyzer/inspections/imperative/imperative.js +109 -0
  19. package/dist/src/analyzer/inspections/imperative/smells.d.ts +16 -0
  20. package/dist/src/analyzer/inspections/imperative/smells.js +58 -0
  21. package/dist/src/analyzer/inspections/logic/logic.d.ts +32 -0
  22. package/dist/src/analyzer/inspections/logic/logic.js +96 -0
  23. package/dist/src/analyzer/inspections/logic/smells.d.ts +15 -0
  24. package/dist/src/analyzer/inspections/logic/smells.js +60 -0
  25. package/dist/src/analyzer/inspections/object/object.d.ts +90 -0
  26. package/dist/src/analyzer/inspections/object/object.js +321 -0
  27. package/dist/src/analyzer/inspections/object/smells.d.ts +30 -0
  28. package/dist/src/analyzer/inspections/object/smells.js +135 -0
  29. package/dist/src/analyzer/utils.d.ts +30 -0
  30. package/dist/src/analyzer/utils.js +78 -0
  31. package/dist/src/index.d.ts +4 -0
  32. package/dist/src/index.js +4 -0
  33. package/dist/src/interpreter/components/EnvBuilder.d.ts +21 -0
  34. package/dist/src/interpreter/components/EnvBuilder.js +155 -0
  35. package/dist/src/interpreter/components/Operations.d.ts +14 -0
  36. package/dist/src/interpreter/components/Operations.js +84 -0
  37. package/dist/src/interpreter/components/PatternMatcher.d.ts +73 -0
  38. package/dist/src/interpreter/components/PatternMatcher.js +358 -0
  39. package/dist/src/interpreter/components/RuntimeContext.d.ts +35 -0
  40. package/dist/src/interpreter/components/RuntimeContext.js +93 -0
  41. package/dist/src/interpreter/components/TestRunner.d.ts +19 -0
  42. package/dist/src/interpreter/components/TestRunner.js +110 -0
  43. package/dist/src/interpreter/components/Visitor.d.ts +71 -0
  44. package/dist/src/interpreter/components/Visitor.js +638 -0
  45. package/dist/src/interpreter/components/logic/LogicEngine.d.ts +29 -0
  46. package/dist/src/interpreter/components/logic/LogicEngine.js +259 -0
  47. package/dist/src/interpreter/components/logic/LogicResolver.d.ts +53 -0
  48. package/dist/src/interpreter/components/logic/LogicResolver.js +484 -0
  49. package/dist/src/interpreter/components/logic/LogicTranslator.d.ts +14 -0
  50. package/dist/src/interpreter/components/logic/LogicTranslator.js +99 -0
  51. package/dist/src/interpreter/components/runtimes/FunctionRuntime.d.ts +12 -0
  52. package/dist/src/interpreter/components/runtimes/FunctionRuntime.js +149 -0
  53. package/dist/src/interpreter/components/runtimes/LazyRuntime.d.ts +19 -0
  54. package/dist/src/interpreter/components/runtimes/LazyRuntime.js +269 -0
  55. package/dist/src/interpreter/components/runtimes/ObjectRuntime.d.ts +35 -0
  56. package/dist/src/interpreter/components/runtimes/ObjectRuntime.js +126 -0
  57. package/dist/src/interpreter/errors.d.ts +19 -0
  58. package/dist/src/interpreter/errors.js +36 -0
  59. package/dist/src/interpreter/index.d.ts +24 -0
  60. package/dist/src/interpreter/index.js +41 -0
  61. package/dist/src/interpreter/trampoline.d.ts +17 -0
  62. package/dist/src/interpreter/trampoline.js +38 -0
  63. package/dist/src/interpreter/utils.d.ts +11 -0
  64. package/dist/src/interpreter/utils.js +65 -0
  65. package/dist/src/tester/index.d.ts +25 -0
  66. package/dist/src/tester/index.js +113 -0
  67. package/dist/src/utils/helpers.d.ts +13 -0
  68. package/dist/src/utils/helpers.js +52 -0
  69. package/dist/utils/helpers.d.ts +5 -1
  70. package/dist/utils/helpers.js +82 -6
  71. package/package.json +4 -2
  72. package/src/analyzer/index.ts +9 -0
  73. package/src/analyzer/inspections/generic/generic.ts +2 -6
  74. package/src/utils/helpers.ts +112 -10
  75. package/tests/analyzer/helpers.spec.ts +16 -10
  76. package/tests/tester/Tester.spec.ts +0 -1
@@ -1,11 +1,32 @@
1
1
  import { parseDocument } from "yaml";
2
- import { InspectionRule } from "../analyzer/index.js";
2
+ import {
3
+ InspectionRule,
4
+ TargetSuffix,
5
+ } from "../analyzer/index.js";
6
+
7
+ const declareMap: Record<string, string> = {
8
+ HasBinding: "Declares",
9
+ HasTypeDeclaration: "DeclaresTypeAlias",
10
+ HasTypeSignature: "DeclaresTypeSignature",
11
+ HasVariable: "DeclaresVariable",
12
+ };
13
+ const V0_HAS_INSPECTIONS = new Set([
14
+ "HasBinding", "HasTypeDeclaration", "HasTypeSignature", "HasVariable",
15
+ "HasArity", "HasDirectRecursion", "HasComposition", "HasComprehension",
16
+ "HasForeach", "HasIf", "HasGuards", "HasConditional", "HasLambda",
17
+ "HasRepeat", "HasWhile", "HasUsage", "HasAnonymousVariable",
18
+ "HasNot", "HasForall", "HasFindall",
19
+ ]);
3
20
 
4
21
  type MulangInspection = {
5
22
  inspection: string;
6
23
  binding: string;
24
+ args?: string[];
7
25
  };
8
26
 
27
+ const NEGATION_PREFIXES = new Set(["Not", "Except"]);
28
+ const SUFFIX_ARGS = new Set<TargetSuffix>(["like", "except"]);
29
+
9
30
  const isValidFormat = (inspection: any): inspection is MulangInspection =>
10
31
  typeof inspection === "object" &&
11
32
  "inspection" in inspection &&
@@ -17,22 +38,27 @@ const isValidFormat = (inspection: any): inspection is MulangInspection =>
17
38
  * @returns An array of InspectionRule objects.
18
39
  */
19
40
  export class MulangAdapter {
20
- public translateMulangInspection(mulangInspection: any): InspectionRule {
41
+ public translateMulangInspection(mulangInspection: unknown): InspectionRule {
21
42
  if (!isValidFormat(mulangInspection))
22
43
  throw new Error(
23
- `Skipping malformed Mulang inspection entry: ${mulangInspection}`
44
+ `Skipping malformed Mulang inspection entry: ${mulangInspection}`,
24
45
  );
25
46
 
26
- const inspection: string[] = mulangInspection.inspection.split(":");
27
- const expected: boolean =
28
- inspection[0] !== "Not" && inspection[0] !== "Except";
29
- const args: string[] = inspection.slice(expected ? 1 : 2);
47
+ // transforms Mulang v0 to v2
48
+ const { inspection, expected, binding, args } =
49
+ this.transformToV2(mulangInspection);
50
+
51
+ const { resolvedArgs, targetSuffix, matcher } =
52
+ this.retrieveArguments(args);
30
53
 
31
54
  return {
32
- inspection: expected ? inspection[0] : inspection[1],
55
+ inspection,
33
56
  expected,
34
- args,
35
- binding: mulangInspection.binding,
57
+ binding,
58
+ args: resolvedArgs,
59
+ // these should not exist in the InspectionRule if they are undefined
60
+ ...(targetSuffix !== undefined && { targetSuffix }),
61
+ ...(matcher !== undefined && { matcher }),
36
62
  };
37
63
  }
38
64
 
@@ -64,4 +90,80 @@ export class MulangAdapter {
64
90
 
65
91
  return inspectionRules;
66
92
  }
93
+
94
+ private transformToV2(mulangInspection: MulangInspection) {
95
+ const parts = mulangInspection.inspection.split(":");
96
+ const {
97
+ expected,
98
+ inspection,
99
+ args: parsedArgs,
100
+ } = this.parseNegation(parts);
101
+ const args = mulangInspection.args ?? parsedArgs;
102
+ const v2 = this.applyV0ToV2(inspection, args, mulangInspection.binding);
103
+ return { expected, ...v2 };
104
+ }
105
+ private parseNegation(parts: string[]) {
106
+ const negated = NEGATION_PREFIXES.has(parts[0]);
107
+ return {
108
+ expected: !negated,
109
+ inspection: parts[negated ? 1 : 0],
110
+ args: parts.slice(negated ? 2 : 1),
111
+ };
112
+ }
113
+ private applyV0ToV2(inspection: string, args: string[], binding: string) {
114
+ if (inspection in declareMap)
115
+ return {
116
+ inspection: declareMap[inspection],
117
+ ...promoteBindingToTarget(args, binding),
118
+ };
119
+
120
+ if (inspection === "HasArity")
121
+ return {
122
+ inspection: "DeclaresComputationWithArity",
123
+ args: [args[0], ...(binding && binding !== "*" ? [binding] : [])],
124
+ binding: "*",
125
+ };
126
+
127
+ if (V0_HAS_INSPECTIONS.has(inspection))
128
+ return { inspection: inspection === "HasUsage" ? "Uses" : inspection.replace(/^Has/, "Uses"), args, binding };
129
+
130
+ return { inspection, args, binding };
131
+ }
132
+
133
+ private retrieveArguments(args: string[]) {
134
+ const targetSuffix = args.find((a): a is TargetSuffix =>
135
+ SUFFIX_ARGS.has(a as TargetSuffix),
136
+ );
137
+
138
+ const matcherIndex = args.findIndex((a) => a.startsWith("With"));
139
+ const matcher =
140
+ matcherIndex !== -1
141
+ ? {
142
+ type: "with_" + args[matcherIndex].slice(4).toLowerCase(),
143
+ value: args[matcherIndex + 1],
144
+ }
145
+ : undefined;
146
+
147
+ const consumed = new Set([
148
+ ...(targetSuffix ? [targetSuffix] : []),
149
+ ...(matcherIndex !== -1
150
+ ? [args[matcherIndex], args[matcherIndex + 1]]
151
+ : []),
152
+ ]);
153
+
154
+ const resolvedArgs = args.filter((a) => !consumed.has(a));
155
+
156
+ return {
157
+ targetSuffix:
158
+ targetSuffix ??
159
+ (resolvedArgs.length > 0 ? ("named" as TargetSuffix) : undefined),
160
+ matcher,
161
+ resolvedArgs,
162
+ };
163
+ }
67
164
  }
165
+
166
+ const promoteBindingToTarget = (args: string[], binding: string) => ({
167
+ args: binding && binding !== "*" ? [binding, ...args] : args,
168
+ binding: "*",
169
+ });
@@ -12,10 +12,10 @@ expectations:
12
12
  inspection: HasBinding
13
13
  - !ruby/hash:ActiveSupport::HashWithIndifferentAccess
14
14
  binding: squareList
15
- inspection: HasLambdaExpression
15
+ inspection: HasLambda
16
16
  - !ruby/hash:ActiveSupport::HashWithIndifferentAccess
17
17
  binding: square
18
- inspection: HasArithmetic
18
+ inspection: UsesArithmetic
19
19
  - !ruby/hash:ActiveSupport::HashWithIndifferentAccess
20
20
  binding: doble
21
21
  inspection: Not:HasBinding
@@ -31,48 +31,54 @@ expectations:
31
31
 
32
32
  const yukigoExpectations =
33
33
  mulangAdapter.translateMulangExpectations(mulangExpectations);
34
+
34
35
  assert.deepEqual(yukigoExpectations, [
35
36
  {
36
- inspection: "HasBinding",
37
- binding: "squareList",
38
- args: [],
37
+ inspection: "Declares",
38
+ binding: "*",
39
+ args: ["squareList"],
39
40
  expected: true,
41
+ targetSuffix: "named",
40
42
  },
41
43
  {
42
- inspection: "HasLambdaExpression",
44
+ inspection: "UsesLambda",
43
45
  binding: "squareList",
44
46
  args: [],
45
47
  expected: true,
46
48
  },
47
49
  {
48
- inspection: "HasArithmetic",
50
+ inspection: "UsesArithmetic",
49
51
  binding: "square",
50
52
  args: [],
51
53
  expected: true,
52
54
  },
53
55
  {
54
- inspection: "HasBinding",
55
- binding: "doble",
56
- args: [],
56
+ inspection: "Declares",
57
+ binding: "*",
58
+ args: ["doble"],
57
59
  expected: false,
60
+ targetSuffix: "named",
58
61
  },
59
62
  {
60
63
  inspection: "Uses",
61
64
  binding: "square",
62
65
  args: ["x"],
63
66
  expected: true,
67
+ targetSuffix: "named",
64
68
  },
65
69
  {
66
70
  inspection: "Uses",
67
71
  binding: "squareList",
68
72
  args: ["map"],
69
73
  expected: true,
74
+ targetSuffix: "named",
70
75
  },
71
76
  {
72
77
  inspection: "Uses",
73
78
  binding: "squareList",
74
79
  args: ["map"],
75
80
  expected: false,
81
+ targetSuffix: "named",
76
82
  },
77
83
  ]);
78
84
  });
@@ -12,7 +12,6 @@ import {
12
12
  SymbolPrimitive,
13
13
  ArithmeticBinaryOperation,
14
14
  Lambda,
15
- Call,
16
15
  Application,
17
16
  VariablePattern,
18
17
  } from "yukigo-ast";