@kalada/core 0.3.0 → 0.4.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 (114) hide show
  1. package/README.md +62 -3
  2. package/dist/kalada-v1/canonical-input.cjs.map +1 -1
  3. package/dist/kalada-v1/canonical-input.d.cts +3 -2
  4. package/dist/kalada-v1/canonical-input.d.ts +3 -2
  5. package/dist/kalada-v1/canonical-input.js.map +1 -1
  6. package/dist/kalada-v1/canonicalize.cjs +16 -1
  7. package/dist/kalada-v1/canonicalize.cjs.map +1 -1
  8. package/dist/kalada-v1/canonicalize.js +16 -1
  9. package/dist/kalada-v1/canonicalize.js.map +1 -1
  10. package/dist/kalada-v1/compile.cjs +13 -4
  11. package/dist/kalada-v1/compile.cjs.map +1 -1
  12. package/dist/kalada-v1/compile.js +14 -5
  13. package/dist/kalada-v1/compile.js.map +1 -1
  14. package/dist/kalada-v1/dependencies.cjs +49 -2
  15. package/dist/kalada-v1/dependencies.cjs.map +1 -1
  16. package/dist/kalada-v1/dependencies.js +49 -2
  17. package/dist/kalada-v1/dependencies.js.map +1 -1
  18. package/dist/kalada-v1/diagnostics.cjs +24 -4
  19. package/dist/kalada-v1/diagnostics.cjs.map +1 -1
  20. package/dist/kalada-v1/diagnostics.d.cts +4 -3
  21. package/dist/kalada-v1/diagnostics.d.ts +4 -3
  22. package/dist/kalada-v1/diagnostics.js +24 -4
  23. package/dist/kalada-v1/diagnostics.js.map +1 -1
  24. package/dist/kalada-v1/evaluate.cjs +10 -139
  25. package/dist/kalada-v1/evaluate.cjs.map +1 -1
  26. package/dist/kalada-v1/evaluate.d.cts +3 -2
  27. package/dist/kalada-v1/evaluate.d.ts +3 -2
  28. package/dist/kalada-v1/evaluate.js +12 -141
  29. package/dist/kalada-v1/evaluate.js.map +1 -1
  30. package/dist/kalada-v1/evaluation-delivery.cjs +286 -0
  31. package/dist/kalada-v1/evaluation-delivery.cjs.map +1 -0
  32. package/dist/kalada-v1/evaluation-delivery.d.cts +13 -0
  33. package/dist/kalada-v1/evaluation-delivery.d.ts +13 -0
  34. package/dist/kalada-v1/evaluation-delivery.js +284 -0
  35. package/dist/kalada-v1/evaluation-delivery.js.map +1 -0
  36. package/dist/kalada-v1/evaluation-frames.cjs +16 -0
  37. package/dist/kalada-v1/evaluation-frames.cjs.map +1 -0
  38. package/dist/kalada-v1/evaluation-frames.d.cts +83 -0
  39. package/dist/kalada-v1/evaluation-frames.d.ts +83 -0
  40. package/dist/kalada-v1/evaluation-frames.js +14 -0
  41. package/dist/kalada-v1/evaluation-frames.js.map +1 -0
  42. package/dist/kalada-v1/evaluation-machine.cjs +226 -0
  43. package/dist/kalada-v1/evaluation-machine.cjs.map +1 -0
  44. package/dist/kalada-v1/evaluation-machine.d.cts +9 -0
  45. package/dist/kalada-v1/evaluation-machine.d.ts +9 -0
  46. package/dist/kalada-v1/evaluation-machine.js +224 -0
  47. package/dist/kalada-v1/evaluation-machine.js.map +1 -0
  48. package/dist/kalada-v1/evaluation-resolution.cjs +80 -0
  49. package/dist/kalada-v1/evaluation-resolution.cjs.map +1 -0
  50. package/dist/kalada-v1/evaluation-resolution.d.cts +11 -0
  51. package/dist/kalada-v1/evaluation-resolution.d.ts +11 -0
  52. package/dist/kalada-v1/evaluation-resolution.js +78 -0
  53. package/dist/kalada-v1/evaluation-resolution.js.map +1 -0
  54. package/dist/kalada-v1/evaluation-state.cjs +94 -0
  55. package/dist/kalada-v1/evaluation-state.cjs.map +1 -0
  56. package/dist/kalada-v1/evaluation-state.d.cts +38 -0
  57. package/dist/kalada-v1/evaluation-state.d.ts +38 -0
  58. package/dist/kalada-v1/evaluation-state.js +81 -0
  59. package/dist/kalada-v1/evaluation-state.js.map +1 -0
  60. package/dist/kalada-v1/factories.cjs +28 -0
  61. package/dist/kalada-v1/factories.cjs.map +1 -1
  62. package/dist/kalada-v1/factories.d.cts +16 -1
  63. package/dist/kalada-v1/factories.d.ts +16 -1
  64. package/dist/kalada-v1/factories.js +28 -0
  65. package/dist/kalada-v1/factories.js.map +1 -1
  66. package/dist/kalada-v1/function-contracts.cjs +150 -0
  67. package/dist/kalada-v1/function-contracts.cjs.map +1 -0
  68. package/dist/kalada-v1/function-contracts.d.cts +15 -0
  69. package/dist/kalada-v1/function-contracts.d.ts +15 -0
  70. package/dist/kalada-v1/function-contracts.js +144 -0
  71. package/dist/kalada-v1/function-contracts.js.map +1 -0
  72. package/dist/kalada-v1/index.cjs +13 -0
  73. package/dist/kalada-v1/index.d.cts +4 -3
  74. package/dist/kalada-v1/index.d.ts +4 -3
  75. package/dist/kalada-v1/index.js +3 -2
  76. package/dist/kalada-v1/limits.cjs +23 -2
  77. package/dist/kalada-v1/limits.cjs.map +1 -1
  78. package/dist/kalada-v1/limits.d.cts +5 -3
  79. package/dist/kalada-v1/limits.d.ts +5 -3
  80. package/dist/kalada-v1/limits.js +23 -3
  81. package/dist/kalada-v1/limits.js.map +1 -1
  82. package/dist/kalada-v1/runtime-values.cjs +112 -0
  83. package/dist/kalada-v1/runtime-values.cjs.map +1 -0
  84. package/dist/kalada-v1/runtime-values.d.cts +35 -0
  85. package/dist/kalada-v1/runtime-values.d.ts +35 -0
  86. package/dist/kalada-v1/runtime-values.js +105 -0
  87. package/dist/kalada-v1/runtime-values.js.map +1 -0
  88. package/dist/kalada-v1/schemas.cjs +107 -2
  89. package/dist/kalada-v1/schemas.cjs.map +1 -1
  90. package/dist/kalada-v1/schemas.d.cts +2 -1
  91. package/dist/kalada-v1/schemas.d.ts +2 -1
  92. package/dist/kalada-v1/schemas.js +108 -4
  93. package/dist/kalada-v1/schemas.js.map +1 -1
  94. package/dist/kalada-v1/static-analysis.cjs +177 -0
  95. package/dist/kalada-v1/static-analysis.cjs.map +1 -0
  96. package/dist/kalada-v1/static-analysis.d.cts +9 -0
  97. package/dist/kalada-v1/static-analysis.d.ts +9 -0
  98. package/dist/kalada-v1/static-analysis.js +175 -0
  99. package/dist/kalada-v1/static-analysis.js.map +1 -0
  100. package/dist/kalada-v1/static-types.cjs +229 -0
  101. package/dist/kalada-v1/static-types.cjs.map +1 -0
  102. package/dist/kalada-v1/static-types.d.cts +8 -0
  103. package/dist/kalada-v1/static-types.d.ts +8 -0
  104. package/dist/kalada-v1/static-types.js +227 -0
  105. package/dist/kalada-v1/static-types.js.map +1 -0
  106. package/dist/kalada-v1/temporal-evaluation.cjs +21 -0
  107. package/dist/kalada-v1/temporal-evaluation.cjs.map +1 -1
  108. package/dist/kalada-v1/temporal-evaluation.d.cts +7 -2
  109. package/dist/kalada-v1/temporal-evaluation.d.ts +7 -2
  110. package/dist/kalada-v1/temporal-evaluation.js +20 -1
  111. package/dist/kalada-v1/temporal-evaluation.js.map +1 -1
  112. package/dist/kalada-v1/types.d.cts +78 -4
  113. package/dist/kalada-v1/types.d.ts +78 -4
  114. package/package.json +1 -1
@@ -0,0 +1,177 @@
1
+ 'use strict';
2
+
3
+ var diagnostics_js = require('./diagnostics.js');
4
+ var staticTypes_js = require('./static-types.js');
5
+
6
+ function analyzeKaladaV1Functions(expression, limits) {
7
+ const state = { limits, functions: [] };
8
+ scan(expression, ["expression"], /* @__PURE__ */ new Set(), state);
9
+ staticTypes_js.checkKaladaV1Types(expression);
10
+ return Object.freeze(state.functions);
11
+ }
12
+ function scan(node, path, scope, state) {
13
+ if (node.kind === "function") {
14
+ const parameters = node.parameters.map((item) => item.name);
15
+ record(path, null, collectCaptures(node.body, scope, new Set(parameters)), state);
16
+ scan(node.body, [...path, "body"], extendedMany(scope, parameters), state);
17
+ return;
18
+ }
19
+ if (node.kind === "function-group") {
20
+ scanGroup(node, path, scope, state);
21
+ return;
22
+ }
23
+ scanChildren(node, path, scope, state);
24
+ }
25
+ function scanGroup(node, path, scope, state) {
26
+ const names = node.functions.map((item) => item.name);
27
+ const groupScope = extendedMany(scope, names);
28
+ node.functions.forEach((fn, index) => {
29
+ const memberPath = [...path, "functions", index];
30
+ const parameters = fn.parameters.map((item) => item.name);
31
+ const locals = /* @__PURE__ */ new Set([...names, ...parameters]);
32
+ record(memberPath, fn.name, collectCaptures(fn.body, scope, locals), state);
33
+ scan(fn.body, [...memberPath, "body"], extendedMany(groupScope, parameters), state);
34
+ });
35
+ scan(node.body, [...path, "body"], groupScope, state);
36
+ }
37
+ function scanChildren(node, path, scope, state) {
38
+ if (isLeaf(node)) return;
39
+ if (node.kind === "binding") {
40
+ scan(node.value, [...path, "value"], scope, state);
41
+ scan(node.body, [...path, "body"], extended(scope, node.name), state);
42
+ return;
43
+ }
44
+ if (node.kind === "call") {
45
+ scan(node.callee, [...path, "callee"], scope, state);
46
+ node.arguments.forEach((item, index) => {
47
+ scan(item, [...path, "arguments", index], scope, state);
48
+ });
49
+ return;
50
+ }
51
+ if (node.kind === "match") {
52
+ scanMatch(node, path, scope, state);
53
+ return;
54
+ }
55
+ if (node.kind === "temporal-arithmetic" || node.kind === "temporal-comparison") {
56
+ scan(node.left, [...path, "left"], scope, state);
57
+ scan(node.right, [...path, "right"], scope, state);
58
+ return;
59
+ }
60
+ if (node.kind === "option" && node.variant === "some")
61
+ scan(node.value, [...path, "value"], scope, state);
62
+ if (node.kind === "result") scan(node.value, [...path, "value"], scope, state);
63
+ }
64
+ function scanMatch(node, path, scope, state) {
65
+ scan(node.value, [...path, "value"], scope, state);
66
+ node.arms.forEach((arm, index) => {
67
+ const armScope = arm.binding ? extended(scope, arm.binding) : scope;
68
+ scan(arm.body, [...path, "arms", index, "body"], armScope, state);
69
+ });
70
+ }
71
+ function collectCaptures(node, outer, locals) {
72
+ const found = [];
73
+ const seen = /* @__PURE__ */ new Set();
74
+ visitReferences(node, new Set(locals), (name) => {
75
+ if (outer.has(name) && !seen.has(name)) {
76
+ seen.add(name);
77
+ found.push(name);
78
+ }
79
+ });
80
+ return found;
81
+ }
82
+ function visitReferences(node, locals, add) {
83
+ if (node.kind === "ref") {
84
+ if (typeof node.ref === "string" && !locals.has(node.ref)) add(node.ref);
85
+ return;
86
+ }
87
+ if (isLeaf(node)) return;
88
+ if (node.kind === "binding") {
89
+ visitReferences(node.value, locals, add);
90
+ visitReferences(node.body, added(locals, node.name), add);
91
+ return;
92
+ }
93
+ if (node.kind === "function") {
94
+ visitReferences(
95
+ node.body,
96
+ addedMany(
97
+ locals,
98
+ node.parameters.map((item) => item.name)
99
+ ),
100
+ add
101
+ );
102
+ return;
103
+ }
104
+ if (node.kind === "function-group") {
105
+ visitGroupReferences(node, locals, add);
106
+ return;
107
+ }
108
+ visitReferenceChildren(node, locals, add);
109
+ }
110
+ function visitReferenceChildren(node, locals, add) {
111
+ if (node.kind === "call") {
112
+ visitReferences(node.callee, locals, add);
113
+ for (const item of node.arguments) visitReferences(item, locals, add);
114
+ return;
115
+ }
116
+ if (node.kind === "match") {
117
+ visitReferences(node.value, locals, add);
118
+ for (const arm of node.arms)
119
+ visitReferences(arm.body, arm.binding ? added(locals, arm.binding) : locals, add);
120
+ return;
121
+ }
122
+ if (node.kind === "temporal-arithmetic" || node.kind === "temporal-comparison") {
123
+ visitReferences(node.left, locals, add);
124
+ visitReferences(node.right, locals, add);
125
+ return;
126
+ }
127
+ if (node.kind === "option" && node.variant === "some") visitReferences(node.value, locals, add);
128
+ if (node.kind === "result") visitReferences(node.value, locals, add);
129
+ }
130
+ function visitGroupReferences(node, locals, add) {
131
+ const group = addedMany(
132
+ locals,
133
+ node.functions.map((item) => item.name)
134
+ );
135
+ for (const fn of node.functions)
136
+ visitReferences(
137
+ fn.body,
138
+ addedMany(
139
+ group,
140
+ fn.parameters.map((item) => item.name)
141
+ ),
142
+ add
143
+ );
144
+ visitReferences(node.body, group, add);
145
+ }
146
+ function isLeaf(node) {
147
+ return node.kind === "literal" || node.kind === "ref" || node.kind === "instant" || node.kind === "duration" || node.kind === "current-instant" || node.kind === "core-function" || node.kind === "option" && node.variant === "none";
148
+ }
149
+ function record(path, name, captures, state) {
150
+ if (captures.length > state.limits.maxCapturesPerClosure)
151
+ throw new diagnostics_js.KaladaFailure("KALADA_CAPTURE_LIMIT", path);
152
+ state.functions.push(
153
+ Object.freeze({
154
+ path: Object.freeze([...path]),
155
+ name,
156
+ captures: Object.freeze(captures)
157
+ })
158
+ );
159
+ }
160
+ function extended(scope, name) {
161
+ return extendedMany(scope, [name]);
162
+ }
163
+ function extendedMany(scope, names) {
164
+ const output = new Set(scope);
165
+ for (const name of names) output.add(name);
166
+ return output;
167
+ }
168
+ function added(scope, name) {
169
+ return addedMany(scope, [name]);
170
+ }
171
+ function addedMany(scope, names) {
172
+ return /* @__PURE__ */ new Set([...scope, ...names]);
173
+ }
174
+
175
+ exports.analyzeKaladaV1Functions = analyzeKaladaV1Functions;
176
+ //# sourceMappingURL=static-analysis.cjs.map
177
+ //# sourceMappingURL=static-analysis.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/kalada-v1/static-analysis.ts"],"names":["checkKaladaV1Types","KaladaFailure"],"mappings":"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","file":"static-analysis.cjs","sourcesContent":["import { KaladaFailure } from \"./diagnostics.js\";\nimport type { JsonValue } from \"./json.js\";\nimport type { ResolvedKaladaV1Limits } from \"./limits.js\";\nimport { checkKaladaV1Types } from \"./static-types.js\";\nimport type { KaladaV1Expression, KaladaV1FunctionCapture } from \"./types.js\";\n\ntype Path = readonly (string | number)[];\ntype Names = ReadonlySet<string>;\n\ninterface AnalysisState {\n readonly limits: ResolvedKaladaV1Limits;\n readonly functions: KaladaV1FunctionCapture[];\n}\n\nexport function analyzeKaladaV1Functions<R extends JsonValue>(\n expression: KaladaV1Expression<R>,\n limits: ResolvedKaladaV1Limits,\n): readonly KaladaV1FunctionCapture[] {\n const state: AnalysisState = { limits, functions: [] };\n scan(expression, [\"expression\"], new Set(), state);\n checkKaladaV1Types(expression);\n return Object.freeze(state.functions);\n}\n\nfunction scan<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n if (node.kind === \"function\") {\n const parameters = node.parameters.map((item) => item.name);\n record(path, null, collectCaptures(node.body, scope, new Set(parameters)), state);\n scan(node.body, [...path, \"body\"], extendedMany(scope, parameters), state);\n return;\n }\n if (node.kind === \"function-group\") {\n scanGroup(node, path, scope, state);\n return;\n }\n scanChildren(node, path, scope, state);\n}\n\nfunction scanGroup<R extends JsonValue>(\n node: Extract<KaladaV1Expression<R>, { kind: \"function-group\" }>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n const names = node.functions.map((item) => item.name);\n const groupScope = extendedMany(scope, names);\n node.functions.forEach((fn, index) => {\n const memberPath = [...path, \"functions\", index];\n const parameters = fn.parameters.map((item) => item.name);\n const locals = new Set([...names, ...parameters]);\n record(memberPath, fn.name, collectCaptures(fn.body, scope, locals), state);\n scan(fn.body, [...memberPath, \"body\"], extendedMany(groupScope, parameters), state);\n });\n scan(node.body, [...path, \"body\"], groupScope, state);\n}\n\nfunction scanChildren<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n if (isLeaf(node)) return;\n if (node.kind === \"binding\") {\n scan(node.value, [...path, \"value\"], scope, state);\n scan(node.body, [...path, \"body\"], extended(scope, node.name), state);\n return;\n }\n if (node.kind === \"call\") {\n scan(node.callee, [...path, \"callee\"], scope, state);\n node.arguments.forEach((item, index) => {\n scan(item, [...path, \"arguments\", index], scope, state);\n });\n return;\n }\n if (node.kind === \"match\") {\n scanMatch(node, path, scope, state);\n return;\n }\n if (node.kind === \"temporal-arithmetic\" || node.kind === \"temporal-comparison\") {\n scan(node.left, [...path, \"left\"], scope, state);\n scan(node.right, [...path, \"right\"], scope, state);\n return;\n }\n if (node.kind === \"option\" && node.variant === \"some\")\n scan(node.value, [...path, \"value\"], scope, state);\n if (node.kind === \"result\") scan(node.value, [...path, \"value\"], scope, state);\n}\n\nfunction scanMatch<R extends JsonValue>(\n node: Extract<KaladaV1Expression<R>, { kind: \"match\" }>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n scan(node.value, [...path, \"value\"], scope, state);\n node.arms.forEach((arm, index) => {\n const armScope = arm.binding ? extended(scope, arm.binding) : scope;\n scan(arm.body, [...path, \"arms\", index, \"body\"], armScope, state);\n });\n}\n\nfunction collectCaptures<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n outer: Names,\n locals: Names,\n): string[] {\n const found: string[] = [];\n const seen = new Set<string>();\n visitReferences(node, new Set(locals), (name) => {\n if (outer.has(name) && !seen.has(name)) {\n seen.add(name);\n found.push(name);\n }\n });\n return found;\n}\n\nfunction visitReferences<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n locals: Set<string>,\n add: (name: string) => void,\n): void {\n if (node.kind === \"ref\") {\n if (typeof node.ref === \"string\" && !locals.has(node.ref)) add(node.ref);\n return;\n }\n if (isLeaf(node)) return;\n if (node.kind === \"binding\") {\n visitReferences(node.value, locals, add);\n visitReferences(node.body, added(locals, node.name), add);\n return;\n }\n if (node.kind === \"function\") {\n visitReferences(\n node.body,\n addedMany(\n locals,\n node.parameters.map((item) => item.name),\n ),\n add,\n );\n return;\n }\n if (node.kind === \"function-group\") {\n visitGroupReferences(node, locals, add);\n return;\n }\n visitReferenceChildren(node, locals, add);\n}\n\nfunction visitReferenceChildren<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n locals: Set<string>,\n add: (name: string) => void,\n): void {\n if (node.kind === \"call\") {\n visitReferences(node.callee, locals, add);\n for (const item of node.arguments) visitReferences(item, locals, add);\n return;\n }\n if (node.kind === \"match\") {\n visitReferences(node.value, locals, add);\n for (const arm of node.arms)\n visitReferences(arm.body, arm.binding ? added(locals, arm.binding) : locals, add);\n return;\n }\n if (node.kind === \"temporal-arithmetic\" || node.kind === \"temporal-comparison\") {\n visitReferences(node.left, locals, add);\n visitReferences(node.right, locals, add);\n return;\n }\n if (node.kind === \"option\" && node.variant === \"some\") visitReferences(node.value, locals, add);\n if (node.kind === \"result\") visitReferences(node.value, locals, add);\n}\n\nfunction visitGroupReferences<R extends JsonValue>(\n node: Extract<KaladaV1Expression<R>, { kind: \"function-group\" }>,\n locals: Set<string>,\n add: (name: string) => void,\n): void {\n const group = addedMany(\n locals,\n node.functions.map((item) => item.name),\n );\n for (const fn of node.functions)\n visitReferences(\n fn.body,\n addedMany(\n group,\n fn.parameters.map((item) => item.name),\n ),\n add,\n );\n visitReferences(node.body, group, add);\n}\n\nfunction isLeaf<R extends JsonValue>(node: KaladaV1Expression<R>): boolean {\n return (\n node.kind === \"literal\" ||\n node.kind === \"ref\" ||\n node.kind === \"instant\" ||\n node.kind === \"duration\" ||\n node.kind === \"current-instant\" ||\n node.kind === \"core-function\" ||\n (node.kind === \"option\" && node.variant === \"none\")\n );\n}\n\nfunction record(path: Path, name: string | null, captures: string[], state: AnalysisState): void {\n if (captures.length > state.limits.maxCapturesPerClosure)\n throw new KaladaFailure(\"KALADA_CAPTURE_LIMIT\", path);\n state.functions.push(\n Object.freeze({\n path: Object.freeze([...path]),\n name,\n captures: Object.freeze(captures),\n }),\n );\n}\n\nfunction extended(scope: Names, name: string): Names {\n return extendedMany(scope, [name]);\n}\n\nfunction extendedMany(scope: Names, names: readonly string[]): Names {\n const output = new Set(scope);\n for (const name of names) output.add(name);\n return output;\n}\n\nfunction added(scope: Set<string>, name: string): Set<string> {\n return addedMany(scope, [name]);\n}\n\nfunction addedMany(scope: Set<string>, names: readonly string[]): Set<string> {\n return new Set([...scope, ...names]);\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { JsonValue } from './json.cjs';
2
+ import { ResolvedKaladaV1Limits } from './limits.cjs';
3
+ import { KaladaV1Expression, KaladaV1FunctionCapture } from './types.cjs';
4
+ import './temporal.cjs';
5
+ import './values.cjs';
6
+
7
+ declare function analyzeKaladaV1Functions<R extends JsonValue>(expression: KaladaV1Expression<R>, limits: ResolvedKaladaV1Limits): readonly KaladaV1FunctionCapture[];
8
+
9
+ export { analyzeKaladaV1Functions };
@@ -0,0 +1,9 @@
1
+ import { JsonValue } from './json.js';
2
+ import { ResolvedKaladaV1Limits } from './limits.js';
3
+ import { KaladaV1Expression, KaladaV1FunctionCapture } from './types.js';
4
+ import './temporal.js';
5
+ import './values.js';
6
+
7
+ declare function analyzeKaladaV1Functions<R extends JsonValue>(expression: KaladaV1Expression<R>, limits: ResolvedKaladaV1Limits): readonly KaladaV1FunctionCapture[];
8
+
9
+ export { analyzeKaladaV1Functions };
@@ -0,0 +1,175 @@
1
+ import { KaladaFailure } from './diagnostics.js';
2
+ import { checkKaladaV1Types } from './static-types.js';
3
+
4
+ function analyzeKaladaV1Functions(expression, limits) {
5
+ const state = { limits, functions: [] };
6
+ scan(expression, ["expression"], /* @__PURE__ */ new Set(), state);
7
+ checkKaladaV1Types(expression);
8
+ return Object.freeze(state.functions);
9
+ }
10
+ function scan(node, path, scope, state) {
11
+ if (node.kind === "function") {
12
+ const parameters = node.parameters.map((item) => item.name);
13
+ record(path, null, collectCaptures(node.body, scope, new Set(parameters)), state);
14
+ scan(node.body, [...path, "body"], extendedMany(scope, parameters), state);
15
+ return;
16
+ }
17
+ if (node.kind === "function-group") {
18
+ scanGroup(node, path, scope, state);
19
+ return;
20
+ }
21
+ scanChildren(node, path, scope, state);
22
+ }
23
+ function scanGroup(node, path, scope, state) {
24
+ const names = node.functions.map((item) => item.name);
25
+ const groupScope = extendedMany(scope, names);
26
+ node.functions.forEach((fn, index) => {
27
+ const memberPath = [...path, "functions", index];
28
+ const parameters = fn.parameters.map((item) => item.name);
29
+ const locals = /* @__PURE__ */ new Set([...names, ...parameters]);
30
+ record(memberPath, fn.name, collectCaptures(fn.body, scope, locals), state);
31
+ scan(fn.body, [...memberPath, "body"], extendedMany(groupScope, parameters), state);
32
+ });
33
+ scan(node.body, [...path, "body"], groupScope, state);
34
+ }
35
+ function scanChildren(node, path, scope, state) {
36
+ if (isLeaf(node)) return;
37
+ if (node.kind === "binding") {
38
+ scan(node.value, [...path, "value"], scope, state);
39
+ scan(node.body, [...path, "body"], extended(scope, node.name), state);
40
+ return;
41
+ }
42
+ if (node.kind === "call") {
43
+ scan(node.callee, [...path, "callee"], scope, state);
44
+ node.arguments.forEach((item, index) => {
45
+ scan(item, [...path, "arguments", index], scope, state);
46
+ });
47
+ return;
48
+ }
49
+ if (node.kind === "match") {
50
+ scanMatch(node, path, scope, state);
51
+ return;
52
+ }
53
+ if (node.kind === "temporal-arithmetic" || node.kind === "temporal-comparison") {
54
+ scan(node.left, [...path, "left"], scope, state);
55
+ scan(node.right, [...path, "right"], scope, state);
56
+ return;
57
+ }
58
+ if (node.kind === "option" && node.variant === "some")
59
+ scan(node.value, [...path, "value"], scope, state);
60
+ if (node.kind === "result") scan(node.value, [...path, "value"], scope, state);
61
+ }
62
+ function scanMatch(node, path, scope, state) {
63
+ scan(node.value, [...path, "value"], scope, state);
64
+ node.arms.forEach((arm, index) => {
65
+ const armScope = arm.binding ? extended(scope, arm.binding) : scope;
66
+ scan(arm.body, [...path, "arms", index, "body"], armScope, state);
67
+ });
68
+ }
69
+ function collectCaptures(node, outer, locals) {
70
+ const found = [];
71
+ const seen = /* @__PURE__ */ new Set();
72
+ visitReferences(node, new Set(locals), (name) => {
73
+ if (outer.has(name) && !seen.has(name)) {
74
+ seen.add(name);
75
+ found.push(name);
76
+ }
77
+ });
78
+ return found;
79
+ }
80
+ function visitReferences(node, locals, add) {
81
+ if (node.kind === "ref") {
82
+ if (typeof node.ref === "string" && !locals.has(node.ref)) add(node.ref);
83
+ return;
84
+ }
85
+ if (isLeaf(node)) return;
86
+ if (node.kind === "binding") {
87
+ visitReferences(node.value, locals, add);
88
+ visitReferences(node.body, added(locals, node.name), add);
89
+ return;
90
+ }
91
+ if (node.kind === "function") {
92
+ visitReferences(
93
+ node.body,
94
+ addedMany(
95
+ locals,
96
+ node.parameters.map((item) => item.name)
97
+ ),
98
+ add
99
+ );
100
+ return;
101
+ }
102
+ if (node.kind === "function-group") {
103
+ visitGroupReferences(node, locals, add);
104
+ return;
105
+ }
106
+ visitReferenceChildren(node, locals, add);
107
+ }
108
+ function visitReferenceChildren(node, locals, add) {
109
+ if (node.kind === "call") {
110
+ visitReferences(node.callee, locals, add);
111
+ for (const item of node.arguments) visitReferences(item, locals, add);
112
+ return;
113
+ }
114
+ if (node.kind === "match") {
115
+ visitReferences(node.value, locals, add);
116
+ for (const arm of node.arms)
117
+ visitReferences(arm.body, arm.binding ? added(locals, arm.binding) : locals, add);
118
+ return;
119
+ }
120
+ if (node.kind === "temporal-arithmetic" || node.kind === "temporal-comparison") {
121
+ visitReferences(node.left, locals, add);
122
+ visitReferences(node.right, locals, add);
123
+ return;
124
+ }
125
+ if (node.kind === "option" && node.variant === "some") visitReferences(node.value, locals, add);
126
+ if (node.kind === "result") visitReferences(node.value, locals, add);
127
+ }
128
+ function visitGroupReferences(node, locals, add) {
129
+ const group = addedMany(
130
+ locals,
131
+ node.functions.map((item) => item.name)
132
+ );
133
+ for (const fn of node.functions)
134
+ visitReferences(
135
+ fn.body,
136
+ addedMany(
137
+ group,
138
+ fn.parameters.map((item) => item.name)
139
+ ),
140
+ add
141
+ );
142
+ visitReferences(node.body, group, add);
143
+ }
144
+ function isLeaf(node) {
145
+ return node.kind === "literal" || node.kind === "ref" || node.kind === "instant" || node.kind === "duration" || node.kind === "current-instant" || node.kind === "core-function" || node.kind === "option" && node.variant === "none";
146
+ }
147
+ function record(path, name, captures, state) {
148
+ if (captures.length > state.limits.maxCapturesPerClosure)
149
+ throw new KaladaFailure("KALADA_CAPTURE_LIMIT", path);
150
+ state.functions.push(
151
+ Object.freeze({
152
+ path: Object.freeze([...path]),
153
+ name,
154
+ captures: Object.freeze(captures)
155
+ })
156
+ );
157
+ }
158
+ function extended(scope, name) {
159
+ return extendedMany(scope, [name]);
160
+ }
161
+ function extendedMany(scope, names) {
162
+ const output = new Set(scope);
163
+ for (const name of names) output.add(name);
164
+ return output;
165
+ }
166
+ function added(scope, name) {
167
+ return addedMany(scope, [name]);
168
+ }
169
+ function addedMany(scope, names) {
170
+ return /* @__PURE__ */ new Set([...scope, ...names]);
171
+ }
172
+
173
+ export { analyzeKaladaV1Functions };
174
+ //# sourceMappingURL=static-analysis.js.map
175
+ //# sourceMappingURL=static-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/kalada-v1/static-analysis.ts"],"names":[],"mappings":"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","file":"static-analysis.js","sourcesContent":["import { KaladaFailure } from \"./diagnostics.js\";\nimport type { JsonValue } from \"./json.js\";\nimport type { ResolvedKaladaV1Limits } from \"./limits.js\";\nimport { checkKaladaV1Types } from \"./static-types.js\";\nimport type { KaladaV1Expression, KaladaV1FunctionCapture } from \"./types.js\";\n\ntype Path = readonly (string | number)[];\ntype Names = ReadonlySet<string>;\n\ninterface AnalysisState {\n readonly limits: ResolvedKaladaV1Limits;\n readonly functions: KaladaV1FunctionCapture[];\n}\n\nexport function analyzeKaladaV1Functions<R extends JsonValue>(\n expression: KaladaV1Expression<R>,\n limits: ResolvedKaladaV1Limits,\n): readonly KaladaV1FunctionCapture[] {\n const state: AnalysisState = { limits, functions: [] };\n scan(expression, [\"expression\"], new Set(), state);\n checkKaladaV1Types(expression);\n return Object.freeze(state.functions);\n}\n\nfunction scan<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n if (node.kind === \"function\") {\n const parameters = node.parameters.map((item) => item.name);\n record(path, null, collectCaptures(node.body, scope, new Set(parameters)), state);\n scan(node.body, [...path, \"body\"], extendedMany(scope, parameters), state);\n return;\n }\n if (node.kind === \"function-group\") {\n scanGroup(node, path, scope, state);\n return;\n }\n scanChildren(node, path, scope, state);\n}\n\nfunction scanGroup<R extends JsonValue>(\n node: Extract<KaladaV1Expression<R>, { kind: \"function-group\" }>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n const names = node.functions.map((item) => item.name);\n const groupScope = extendedMany(scope, names);\n node.functions.forEach((fn, index) => {\n const memberPath = [...path, \"functions\", index];\n const parameters = fn.parameters.map((item) => item.name);\n const locals = new Set([...names, ...parameters]);\n record(memberPath, fn.name, collectCaptures(fn.body, scope, locals), state);\n scan(fn.body, [...memberPath, \"body\"], extendedMany(groupScope, parameters), state);\n });\n scan(node.body, [...path, \"body\"], groupScope, state);\n}\n\nfunction scanChildren<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n if (isLeaf(node)) return;\n if (node.kind === \"binding\") {\n scan(node.value, [...path, \"value\"], scope, state);\n scan(node.body, [...path, \"body\"], extended(scope, node.name), state);\n return;\n }\n if (node.kind === \"call\") {\n scan(node.callee, [...path, \"callee\"], scope, state);\n node.arguments.forEach((item, index) => {\n scan(item, [...path, \"arguments\", index], scope, state);\n });\n return;\n }\n if (node.kind === \"match\") {\n scanMatch(node, path, scope, state);\n return;\n }\n if (node.kind === \"temporal-arithmetic\" || node.kind === \"temporal-comparison\") {\n scan(node.left, [...path, \"left\"], scope, state);\n scan(node.right, [...path, \"right\"], scope, state);\n return;\n }\n if (node.kind === \"option\" && node.variant === \"some\")\n scan(node.value, [...path, \"value\"], scope, state);\n if (node.kind === \"result\") scan(node.value, [...path, \"value\"], scope, state);\n}\n\nfunction scanMatch<R extends JsonValue>(\n node: Extract<KaladaV1Expression<R>, { kind: \"match\" }>,\n path: Path,\n scope: Names,\n state: AnalysisState,\n): void {\n scan(node.value, [...path, \"value\"], scope, state);\n node.arms.forEach((arm, index) => {\n const armScope = arm.binding ? extended(scope, arm.binding) : scope;\n scan(arm.body, [...path, \"arms\", index, \"body\"], armScope, state);\n });\n}\n\nfunction collectCaptures<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n outer: Names,\n locals: Names,\n): string[] {\n const found: string[] = [];\n const seen = new Set<string>();\n visitReferences(node, new Set(locals), (name) => {\n if (outer.has(name) && !seen.has(name)) {\n seen.add(name);\n found.push(name);\n }\n });\n return found;\n}\n\nfunction visitReferences<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n locals: Set<string>,\n add: (name: string) => void,\n): void {\n if (node.kind === \"ref\") {\n if (typeof node.ref === \"string\" && !locals.has(node.ref)) add(node.ref);\n return;\n }\n if (isLeaf(node)) return;\n if (node.kind === \"binding\") {\n visitReferences(node.value, locals, add);\n visitReferences(node.body, added(locals, node.name), add);\n return;\n }\n if (node.kind === \"function\") {\n visitReferences(\n node.body,\n addedMany(\n locals,\n node.parameters.map((item) => item.name),\n ),\n add,\n );\n return;\n }\n if (node.kind === \"function-group\") {\n visitGroupReferences(node, locals, add);\n return;\n }\n visitReferenceChildren(node, locals, add);\n}\n\nfunction visitReferenceChildren<R extends JsonValue>(\n node: KaladaV1Expression<R>,\n locals: Set<string>,\n add: (name: string) => void,\n): void {\n if (node.kind === \"call\") {\n visitReferences(node.callee, locals, add);\n for (const item of node.arguments) visitReferences(item, locals, add);\n return;\n }\n if (node.kind === \"match\") {\n visitReferences(node.value, locals, add);\n for (const arm of node.arms)\n visitReferences(arm.body, arm.binding ? added(locals, arm.binding) : locals, add);\n return;\n }\n if (node.kind === \"temporal-arithmetic\" || node.kind === \"temporal-comparison\") {\n visitReferences(node.left, locals, add);\n visitReferences(node.right, locals, add);\n return;\n }\n if (node.kind === \"option\" && node.variant === \"some\") visitReferences(node.value, locals, add);\n if (node.kind === \"result\") visitReferences(node.value, locals, add);\n}\n\nfunction visitGroupReferences<R extends JsonValue>(\n node: Extract<KaladaV1Expression<R>, { kind: \"function-group\" }>,\n locals: Set<string>,\n add: (name: string) => void,\n): void {\n const group = addedMany(\n locals,\n node.functions.map((item) => item.name),\n );\n for (const fn of node.functions)\n visitReferences(\n fn.body,\n addedMany(\n group,\n fn.parameters.map((item) => item.name),\n ),\n add,\n );\n visitReferences(node.body, group, add);\n}\n\nfunction isLeaf<R extends JsonValue>(node: KaladaV1Expression<R>): boolean {\n return (\n node.kind === \"literal\" ||\n node.kind === \"ref\" ||\n node.kind === \"instant\" ||\n node.kind === \"duration\" ||\n node.kind === \"current-instant\" ||\n node.kind === \"core-function\" ||\n (node.kind === \"option\" && node.variant === \"none\")\n );\n}\n\nfunction record(path: Path, name: string | null, captures: string[], state: AnalysisState): void {\n if (captures.length > state.limits.maxCapturesPerClosure)\n throw new KaladaFailure(\"KALADA_CAPTURE_LIMIT\", path);\n state.functions.push(\n Object.freeze({\n path: Object.freeze([...path]),\n name,\n captures: Object.freeze(captures),\n }),\n );\n}\n\nfunction extended(scope: Names, name: string): Names {\n return extendedMany(scope, [name]);\n}\n\nfunction extendedMany(scope: Names, names: readonly string[]): Names {\n const output = new Set(scope);\n for (const name of names) output.add(name);\n return output;\n}\n\nfunction added(scope: Set<string>, name: string): Set<string> {\n return addedMany(scope, [name]);\n}\n\nfunction addedMany(scope: Set<string>, names: readonly string[]): Set<string> {\n return new Set([...scope, ...names]);\n}\n"]}
@@ -0,0 +1,229 @@
1
+ 'use strict';
2
+
3
+ var diagnostics_js = require('./diagnostics.js');
4
+
5
+ const DYNAMIC = /* @__PURE__ */ Symbol("dynamic");
6
+ function checkKaladaV1Types(expression) {
7
+ infer(expression, ["expression"], /* @__PURE__ */ new Map());
8
+ }
9
+ function infer(node, path, scope) {
10
+ if (node.kind === "literal") return literalType(node.value);
11
+ if (node.kind === "ref")
12
+ return typeof node.ref === "string" ? scope.get(node.ref) ?? DYNAMIC : DYNAMIC;
13
+ if (node.kind === "function") return checkFunction(node, path, scope);
14
+ if (node.kind === "function-group") return checkGroup(node, path, scope);
15
+ if (node.kind === "call") return checkCall(node, path, scope);
16
+ if (node.kind === "core-function") return coreType(node.name);
17
+ if (node.kind === "binding") return checkBinding(node, path, scope);
18
+ if (node.kind === "option") return optionType(node, path, scope);
19
+ if (node.kind === "result") return resultType(node, path, scope);
20
+ if (node.kind === "match") return checkMatch(node, path, scope);
21
+ return inferTemporal(node, path, scope);
22
+ }
23
+ function checkFunction(node, path, outer) {
24
+ const parameters = /* @__PURE__ */ new Map();
25
+ for (const parameter of node.parameters) parameters.set(parameter.name, parameter.type);
26
+ const actual = infer(node.body, [...path, "body"], merged(outer, parameters));
27
+ requireAssignable(actual, node.returns, [...path, "body"]);
28
+ return functionType(
29
+ node.parameters.map((item) => item.type),
30
+ node.returns
31
+ );
32
+ }
33
+ function checkGroup(node, path, outer) {
34
+ const signatures = /* @__PURE__ */ new Map();
35
+ for (const fn of node.functions) signatures.set(fn.name, signature(fn));
36
+ const groupScope = merged(outer, signatures);
37
+ node.functions.forEach((fn, index) => {
38
+ checkMember(fn, [...path, "functions", index], groupScope);
39
+ });
40
+ return infer(node.body, [...path, "body"], groupScope);
41
+ }
42
+ function checkMember(fn, path, group) {
43
+ const parameters = /* @__PURE__ */ new Map();
44
+ for (const parameter of fn.parameters) parameters.set(parameter.name, parameter.type);
45
+ const actual = infer(fn.body, [...path, "body"], merged(group, parameters));
46
+ requireAssignable(actual, fn.returns, [...path, "body"]);
47
+ }
48
+ function checkCall(node, path, scope) {
49
+ const callee = infer(node.callee, [...path, "callee"], scope);
50
+ const args = node.arguments.map(
51
+ (item, index) => infer(item, [...path, "arguments", index], scope)
52
+ );
53
+ if (callee === DYNAMIC) return DYNAMIC;
54
+ if (!isFunctionType(callee)) fail("KALADA_NOT_CALLABLE", [...path, "callee"]);
55
+ if (args.length !== callee.parameters.length)
56
+ fail("KALADA_FUNCTION_ARITY", [...path, "arguments"]);
57
+ args.forEach((actual, index) => {
58
+ requireAssignable(actual, callee.parameters[index], [
59
+ ...path,
60
+ "arguments",
61
+ index
62
+ ]);
63
+ });
64
+ return callee.returns;
65
+ }
66
+ function checkBinding(node, path, scope) {
67
+ const value = infer(node.value, [...path, "value"], scope);
68
+ return infer(node.body, [...path, "body"], merged(scope, /* @__PURE__ */ new Map([[node.name, value]])));
69
+ }
70
+ function checkMatch(node, path, scope) {
71
+ const scrutinee = infer(node.value, [...path, "value"], scope);
72
+ const payloads = matchPayloads(node.type, scrutinee);
73
+ const branches = node.arms.map((arm, index) => {
74
+ const payload = payloads.get(arm.variant) ?? DYNAMIC;
75
+ const nested = arm.binding ? merged(scope, /* @__PURE__ */ new Map([[arm.binding, payload]])) : scope;
76
+ return infer(arm.body, [...path, "arms", index, "body"], nested);
77
+ });
78
+ return join(branches);
79
+ }
80
+ function matchPayloads(type, value) {
81
+ if (value === DYNAMIC) return /* @__PURE__ */ new Map();
82
+ if (type === "Option" && isOptionShape(value)) return /* @__PURE__ */ new Map([["some", value.value]]);
83
+ if (type === "Option" && !isShape(value) && value.kind === "option-type")
84
+ return /* @__PURE__ */ new Map([["some", value.value]]);
85
+ if (type === "Result" && isResultShape(value))
86
+ return /* @__PURE__ */ new Map([
87
+ ["ok", value.ok],
88
+ ["err", value.error]
89
+ ]);
90
+ if (type === "Result" && !isShape(value) && value.kind === "result-type")
91
+ return /* @__PURE__ */ new Map([
92
+ ["ok", value.ok],
93
+ ["err", value.error]
94
+ ]);
95
+ return /* @__PURE__ */ new Map();
96
+ }
97
+ function inferTemporal(node, path, scope) {
98
+ if (node.kind === "instant" || node.kind === "current-instant") return primitive("Instant");
99
+ if (node.kind === "duration") return primitive("Duration");
100
+ const left = infer(node.left, [...path, "left"], scope);
101
+ const right = infer(node.right, [...path, "right"], scope);
102
+ if (node.kind === "temporal-comparison") return primitive("boolean");
103
+ return temporalArithmetic(node.operator, left, right);
104
+ }
105
+ function temporalArithmetic(operator, left, right) {
106
+ if (operator === "add") return additionType(left);
107
+ if (isPrimitive(left, "Duration")) return primitive("Duration");
108
+ if (isPrimitive(right, "Instant")) return primitive("Duration");
109
+ if (isPrimitive(left, "Instant") && isPrimitive(right, "Duration")) return primitive("Instant");
110
+ return union([primitive("Instant"), primitive("Duration")]);
111
+ }
112
+ function additionType(left, _right) {
113
+ if (isPrimitive(left, "Instant")) return primitive("Instant");
114
+ if (isPrimitive(left, "Duration")) return primitive("Duration");
115
+ return union([primitive("Instant"), primitive("Duration")]);
116
+ }
117
+ function optionType(node, path, scope) {
118
+ return Object.freeze({
119
+ shape: "option",
120
+ value: node.variant === "none" ? DYNAMIC : infer(node.value, [...path, "value"], scope)
121
+ });
122
+ }
123
+ function resultType(node, path, scope) {
124
+ const value = infer(node.value, [...path, "value"], scope);
125
+ return Object.freeze({
126
+ shape: "result",
127
+ ok: node.variant === "ok" ? value : DYNAMIC,
128
+ error: node.variant === "err" ? value : DYNAMIC
129
+ });
130
+ }
131
+ function requireAssignable(actual, expected, path) {
132
+ if (!assignable(actual, expected)) fail("KALADA_FUNCTION_TYPE_MISMATCH", path);
133
+ }
134
+ function assignable(actual, expected) {
135
+ if (actual === DYNAMIC) return true;
136
+ if (isUnion(actual)) return actual.members.every((member) => assignable(member, expected));
137
+ if (isOptionShape(actual))
138
+ return expected.kind === "option-type" && assignable(actual.value, expected.value);
139
+ if (isResultShape(actual))
140
+ return expected.kind === "result-type" && assignable(actual.ok, expected.ok) && assignable(actual.error, expected.error);
141
+ if (expected.kind === "primitive-type" && expected.name === "json" && !isShape(actual)) {
142
+ return isJsonType(actual);
143
+ }
144
+ return equalType(actual, expected);
145
+ }
146
+ function isJsonType(type) {
147
+ if (type.kind === "array-type") return isJsonType(type.element);
148
+ if (type.kind !== "primitive-type") return false;
149
+ return ["null", "boolean", "number", "string", "json"].includes(type.name);
150
+ }
151
+ function join(types) {
152
+ const unique = [];
153
+ for (const item of types) {
154
+ if (!unique.some((candidate) => staticEqual(candidate, item))) unique.push(item);
155
+ }
156
+ return unique.length === 1 ? unique[0] : union(unique);
157
+ }
158
+ function staticEqual(left, right) {
159
+ if (left === DYNAMIC || right === DYNAMIC) return left === right;
160
+ return JSON.stringify(left) === JSON.stringify(right);
161
+ }
162
+ function union(members) {
163
+ return Object.freeze({ shape: "union", members: Object.freeze([...members]) });
164
+ }
165
+ function coreType(name) {
166
+ const callback = functionType(
167
+ [primitive("json"), primitive("number")],
168
+ primitive(name === "map" ? "json" : "boolean")
169
+ );
170
+ const array = Object.freeze({ kind: "array-type", element: primitive("json") });
171
+ return functionType(
172
+ [array, callback],
173
+ name === "some" || name === "every" ? primitive("boolean") : array
174
+ );
175
+ }
176
+ function signature(fn) {
177
+ return functionType(
178
+ fn.parameters.map((item) => item.type),
179
+ fn.returns
180
+ );
181
+ }
182
+ function functionType(parameters, returns) {
183
+ return Object.freeze({
184
+ kind: "function-type",
185
+ parameters: Object.freeze([...parameters]),
186
+ returns
187
+ });
188
+ }
189
+ function literalType(value) {
190
+ if (Array.isArray(value))
191
+ return Object.freeze({ kind: "array-type", element: primitive("json") });
192
+ return primitive(
193
+ value === null ? "null" : typeof value === "object" ? "json" : typeof value
194
+ );
195
+ }
196
+ function primitive(name) {
197
+ return Object.freeze({ kind: "primitive-type", name });
198
+ }
199
+ function isFunctionType(value) {
200
+ return value !== DYNAMIC && !isShape(value) && value.kind === "function-type";
201
+ }
202
+ function isPrimitive(value, name) {
203
+ return value !== DYNAMIC && !isShape(value) && value.kind === "primitive-type" && value.name === name;
204
+ }
205
+ function isShape(value) {
206
+ return value !== DYNAMIC && "shape" in value;
207
+ }
208
+ function isOptionShape(value) {
209
+ return isShape(value) && value.shape === "option";
210
+ }
211
+ function isResultShape(value) {
212
+ return isShape(value) && value.shape === "result";
213
+ }
214
+ function isUnion(value) {
215
+ return isShape(value) && value.shape === "union";
216
+ }
217
+ function equalType(left, right) {
218
+ return JSON.stringify(left) === JSON.stringify(right);
219
+ }
220
+ function merged(base, extra) {
221
+ return new Map([...base, ...extra]);
222
+ }
223
+ function fail(code, path) {
224
+ throw new diagnostics_js.KaladaFailure(code, path);
225
+ }
226
+
227
+ exports.checkKaladaV1Types = checkKaladaV1Types;
228
+ //# sourceMappingURL=static-types.cjs.map
229
+ //# sourceMappingURL=static-types.cjs.map