@holoscript/core 6.0.4 → 7.0.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 (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1 -1
  3. package/dist/compiler/index.d.ts +82 -0
  4. package/dist/constants.d.ts +3 -2
  5. package/dist/coordinators/index.d.ts +189 -0
  6. package/dist/index.d.ts +501 -19
  7. package/dist/paper-0c-spike/index.d.ts +29 -0
  8. package/dist/reconstruction/index.d.ts +78 -0
  9. package/dist/tools/index.d.ts +22 -1
  10. package/dist/traitDocs/traitDocs.d.ts +69 -0
  11. package/dist/traits/index.d.ts +61 -0
  12. package/package.json +105 -57
  13. package/dist/GLTFPipeline-DEN36VNK.js +0 -12
  14. package/dist/GLTFPipeline-YPCAK236.cjs +0 -33
  15. package/dist/HoloScriptPlusParser-BN6KVRCM.js +0 -692
  16. package/dist/HoloScriptPlusParser-NC5FE6AL.cjs +0 -697
  17. package/dist/USDZExporter-NTMBNTDB.js +0 -707
  18. package/dist/USDZExporter-UWGWNMMD.cjs +0 -709
  19. package/dist/chunk-27LWW5FU.cjs +0 -410
  20. package/dist/chunk-2CWOLHTE.js +0 -69
  21. package/dist/chunk-33LSUQDD.cjs +0 -835
  22. package/dist/chunk-3FJCK5XA.js +0 -2232
  23. package/dist/chunk-3FXV5S25.cjs +0 -633
  24. package/dist/chunk-3FYZOR7S.cjs +0 -69
  25. package/dist/chunk-3SAK5KFL.cjs +0 -83
  26. package/dist/chunk-4XSNJCLC.cjs +0 -1859
  27. package/dist/chunk-54FHG2MX.js +0 -655
  28. package/dist/chunk-56IF4NTA.js +0 -56
  29. package/dist/chunk-5BGSECRJ.cjs +0 -2237
  30. package/dist/chunk-5GLCTO44.js +0 -161
  31. package/dist/chunk-5O6TQC6M.cjs +0 -1871
  32. package/dist/chunk-5OEOHAAW.cjs +0 -682
  33. package/dist/chunk-5TOFIR6L.js +0 -407
  34. package/dist/chunk-5WUNN6ZN.cjs +0 -428
  35. package/dist/chunk-6TZPZCOJ.cjs +0 -1404
  36. package/dist/chunk-6UEHYZ7V.cjs +0 -773
  37. package/dist/chunk-6XSERL6L.js +0 -5678
  38. package/dist/chunk-72EQECGT.cjs +0 -908
  39. package/dist/chunk-7AGYRWKW.cjs +0 -507
  40. package/dist/chunk-7LCYLPW2.cjs +0 -663
  41. package/dist/chunk-A7PIMZGU.js +0 -263
  42. package/dist/chunk-ATSKSYVE.cjs +0 -51683
  43. package/dist/chunk-B5TCIAPQ.cjs +0 -117
  44. package/dist/chunk-BF2235SI.cjs +0 -5714
  45. package/dist/chunk-BKIGPPVM.js +0 -629
  46. package/dist/chunk-BND3ST2K.cjs +0 -662
  47. package/dist/chunk-BU7VWW2K.js +0 -2522
  48. package/dist/chunk-BWFJEM5A.js +0 -5419
  49. package/dist/chunk-CAUCGUEA.cjs +0 -130
  50. package/dist/chunk-CBJSLA2E.cjs +0 -5423
  51. package/dist/chunk-CDPGV4DN.js +0 -114
  52. package/dist/chunk-CLYEIWA5.cjs +0 -408
  53. package/dist/chunk-CS2EMTGF.js +0 -1966
  54. package/dist/chunk-DMG7C4H2.js +0 -975
  55. package/dist/chunk-DXJQDCFL.js +0 -468
  56. package/dist/chunk-E3FWRT3Z.js +0 -608
  57. package/dist/chunk-E3UALNFA.js +0 -421
  58. package/dist/chunk-EONILVMF.js +0 -762
  59. package/dist/chunk-EQV4R3EV.cjs +0 -769
  60. package/dist/chunk-F3HH56EB.cjs +0 -5538
  61. package/dist/chunk-F4IULT7N.js +0 -1488
  62. package/dist/chunk-FF3Q7ADR.js +0 -380
  63. package/dist/chunk-FFKU7BTK.cjs +0 -1046
  64. package/dist/chunk-FHQVYCH2.js +0 -70
  65. package/dist/chunk-FSF7EQVA.cjs +0 -1974
  66. package/dist/chunk-G4VZTCIB.js +0 -659
  67. package/dist/chunk-G7CT3EMP.cjs +0 -1002
  68. package/dist/chunk-GGHSW2NN.js +0 -51334
  69. package/dist/chunk-GVUR45UF.cjs +0 -777
  70. package/dist/chunk-H5Z7NASB.js +0 -9662
  71. package/dist/chunk-HE7ULERA.cjs +0 -697
  72. package/dist/chunk-HJJLD366.js +0 -1169
  73. package/dist/chunk-HPS76H7Q.js +0 -309
  74. package/dist/chunk-HQUEA5R6.cjs +0 -424
  75. package/dist/chunk-HYNTS5CP.js +0 -422
  76. package/dist/chunk-I6XZ5DZF.cjs +0 -488
  77. package/dist/chunk-IBDG74G2.cjs +0 -1219
  78. package/dist/chunk-IFNQFCTM.js +0 -3098
  79. package/dist/chunk-IHOUYQIA.js +0 -406
  80. package/dist/chunk-ILRBGFVD.cjs +0 -72
  81. package/dist/chunk-IWI6J7FX.js +0 -421
  82. package/dist/chunk-K3JDKWGI.cjs +0 -270
  83. package/dist/chunk-K6EKD26I.js +0 -630
  84. package/dist/chunk-KCQ5NDYC.cjs +0 -3172
  85. package/dist/chunk-KED34ILP.js +0 -832
  86. package/dist/chunk-KSGXLT74.cjs +0 -457
  87. package/dist/chunk-L4G4RLXX.js +0 -767
  88. package/dist/chunk-LDP5OK6G.js +0 -1216
  89. package/dist/chunk-LGGRPKTV.cjs +0 -735
  90. package/dist/chunk-LK5IAVH6.cjs +0 -1173
  91. package/dist/chunk-LSW7P7ML.js +0 -3675
  92. package/dist/chunk-LXJ4667L.cjs +0 -3874
  93. package/dist/chunk-LZ266PCM.cjs +0 -4499
  94. package/dist/chunk-MD6KDHVE.cjs +0 -237
  95. package/dist/chunk-MEASWI2Y.js +0 -126
  96. package/dist/chunk-MPXBVFHQ.js +0 -768
  97. package/dist/chunk-N5FTS757.cjs +0 -415
  98. package/dist/chunk-NCUKG4SK.cjs +0 -3075
  99. package/dist/chunk-NDQNIJEH.js +0 -1715
  100. package/dist/chunk-NOZZ46QU.js +0 -168
  101. package/dist/chunk-OFKWH2IP.js +0 -449
  102. package/dist/chunk-PHENW4MQ.js +0 -65
  103. package/dist/chunk-PMGODDJA.cjs +0 -319
  104. package/dist/chunk-Q4QX3AET.cjs +0 -1505
  105. package/dist/chunk-Q56TT7IL.js +0 -483
  106. package/dist/chunk-Q5JT3YML.cjs +0 -129
  107. package/dist/chunk-Q5SJOGHQ.cjs +0 -4256
  108. package/dist/chunk-QGKNANZ3.js +0 -3071
  109. package/dist/chunk-QLEAOI3Q.cjs +0 -424
  110. package/dist/chunk-R7MA7QWV.js +0 -732
  111. package/dist/chunk-RVYPEYPX.js +0 -678
  112. package/dist/chunk-S2N5TNMA.js +0 -1855
  113. package/dist/chunk-S565K7NK.js +0 -752
  114. package/dist/chunk-SDAMZIRE.js +0 -765
  115. package/dist/chunk-T36DDXSF.js +0 -4250
  116. package/dist/chunk-T4NKMBDL.js +0 -5474
  117. package/dist/chunk-T7LEXZUZ.cjs +0 -2526
  118. package/dist/chunk-TEWCN33Y.js +0 -694
  119. package/dist/chunk-TQSZUOW5.cjs +0 -793
  120. package/dist/chunk-TSH3MSQU.cjs +0 -129
  121. package/dist/chunk-UERJ3YJV.js +0 -504
  122. package/dist/chunk-UPJBDCVF.js +0 -1395
  123. package/dist/chunk-V3NN3HPP.js +0 -4462
  124. package/dist/chunk-VJ3L7CHT.cjs +0 -169
  125. package/dist/chunk-WB4Z63GG.js +0 -229
  126. package/dist/chunk-WDW67DZB.cjs +0 -9728
  127. package/dist/chunk-WGMEAYBG.js +0 -126
  128. package/dist/chunk-X4ZF6CNE.cjs +0 -473
  129. package/dist/chunk-X6SEAXAX.cjs +0 -3681
  130. package/dist/chunk-XCWFGZAA.js +0 -1043
  131. package/dist/chunk-XD6IYDUX.js +0 -903
  132. package/dist/chunk-XG23EUQX.cjs +0 -1717
  133. package/dist/chunk-XRKWN5PL.cjs +0 -173
  134. package/dist/chunk-XUILI4KB.cjs +0 -430
  135. package/dist/chunk-XUTX5CBW.js +0 -126
  136. package/dist/chunk-XWPNTWDN.cjs +0 -755
  137. package/dist/chunk-XXINBTZK.cjs +0 -633
  138. package/dist/chunk-YCXFCXDS.js +0 -1868
  139. package/dist/chunk-YQK5JNFK.js +0 -3725
  140. package/dist/chunk-YYXH45E2.js +0 -426
  141. package/dist/chunk-Z34RLXRA.cjs +0 -612
  142. package/dist/chunk-ZP4D3CSX.cjs +0 -72
  143. package/dist/cli/holoscript-runner.cjs +0 -2259
  144. package/dist/cli/holoscript-runner.js +0 -2234
  145. package/dist/codebase/index.cjs +0 -336
  146. package/dist/codebase/index.js +0 -331
  147. package/dist/compiler/agent-inference.cjs +0 -28
  148. package/dist/compiler/agent-inference.js +0 -5
  149. package/dist/compiler/android-xr.cjs +0 -19
  150. package/dist/compiler/android-xr.js +0 -9
  151. package/dist/compiler/android.cjs +0 -20
  152. package/dist/compiler/android.js +0 -10
  153. package/dist/compiler/ar.cjs +0 -20
  154. package/dist/compiler/ar.js +0 -8
  155. package/dist/compiler/babylon.cjs +0 -17
  156. package/dist/compiler/babylon.js +0 -11
  157. package/dist/compiler/coco.cjs +0 -27
  158. package/dist/compiler/coco.js +0 -4
  159. package/dist/compiler/domain-block-utils.cjs +0 -602
  160. package/dist/compiler/domain-block-utils.js +0 -8
  161. package/dist/compiler/dtdl.cjs +0 -24
  162. package/dist/compiler/dtdl.js +0 -8
  163. package/dist/compiler/gltf-pipeline.cjs +0 -39
  164. package/dist/compiler/gltf-pipeline.js +0 -4
  165. package/dist/compiler/godot.cjs +0 -15
  166. package/dist/compiler/godot.js +0 -9
  167. package/dist/compiler/incremental.cjs +0 -29
  168. package/dist/compiler/incremental.js +0 -4
  169. package/dist/compiler/index.cjs +0 -2578
  170. package/dist/compiler/index.js +0 -2383
  171. package/dist/compiler/ios.cjs +0 -20
  172. package/dist/compiler/ios.js +0 -10
  173. package/dist/compiler/multi-layer.cjs +0 -20
  174. package/dist/compiler/multi-layer.js +0 -11
  175. package/dist/compiler/nodetoy.cjs +0 -23
  176. package/dist/compiler/nodetoy.js +0 -4
  177. package/dist/compiler/openxr.cjs +0 -15
  178. package/dist/compiler/openxr.js +0 -9
  179. package/dist/compiler/playcanvas.cjs +0 -16
  180. package/dist/compiler/playcanvas.js +0 -10
  181. package/dist/compiler/r3f.cjs +0 -34
  182. package/dist/compiler/r3f.js +0 -12
  183. package/dist/compiler/remotion.cjs +0 -23
  184. package/dist/compiler/remotion.js +0 -4
  185. package/dist/compiler/reproducibility.cjs +0 -39
  186. package/dist/compiler/reproducibility.js +0 -4
  187. package/dist/compiler/sdf.cjs +0 -21
  188. package/dist/compiler/sdf.js +0 -9
  189. package/dist/compiler/semantic-scene.cjs +0 -31
  190. package/dist/compiler/semantic-scene.js +0 -4
  191. package/dist/compiler/state.cjs +0 -17
  192. package/dist/compiler/state.js +0 -7
  193. package/dist/compiler/trait-composition.cjs +0 -26
  194. package/dist/compiler/trait-composition.js +0 -5
  195. package/dist/compiler/unity.cjs +0 -15
  196. package/dist/compiler/unity.js +0 -9
  197. package/dist/compiler/unreal.cjs +0 -19
  198. package/dist/compiler/unreal.js +0 -9
  199. package/dist/compiler/urdf.cjs +0 -45
  200. package/dist/compiler/urdf.js +0 -9
  201. package/dist/compiler/usd-physics.cjs +0 -23
  202. package/dist/compiler/usd-physics.js +0 -6
  203. package/dist/compiler/visionos.cjs +0 -15
  204. package/dist/compiler/visionos.js +0 -9
  205. package/dist/compiler/vrchat.cjs +0 -19
  206. package/dist/compiler/vrchat.js +0 -9
  207. package/dist/compiler/vrr.cjs +0 -21
  208. package/dist/compiler/vrr.js +0 -9
  209. package/dist/compiler/wasm.cjs +0 -33
  210. package/dist/compiler/wasm.js +0 -9
  211. package/dist/compiler/webgpu.cjs +0 -15
  212. package/dist/compiler/webgpu.js +0 -9
  213. package/dist/debugger.cjs +0 -21
  214. package/dist/debugger.js +0 -8
  215. package/dist/entries/interop.cjs +0 -62
  216. package/dist/entries/interop.js +0 -5
  217. package/dist/entries/scripting.cjs +0 -68
  218. package/dist/entries/scripting.js +0 -11
  219. package/dist/index.cjs +0 -40921
  220. package/dist/index.js +0 -37763
  221. package/dist/math/vec3.cjs +0 -57
  222. package/dist/math/vec3.js +0 -4
  223. package/dist/ml-dsa-PHCWUBPX.cjs +0 -1178
  224. package/dist/ml-dsa-WYLJHJO6.js +0 -1178
  225. package/dist/parser.cjs +0 -27
  226. package/dist/parser.js +0 -10
  227. package/dist/playwright-5OSAPTNH.js +0 -98660
  228. package/dist/playwright-RL6GY4F7.cjs +0 -98673
  229. package/dist/runtime.cjs +0 -16
  230. package/dist/runtime.js +0 -7
  231. package/dist/storage/index.cjs +0 -37
  232. package/dist/storage/index.js +0 -4
  233. package/dist/traits/index.cjs +0 -14649
  234. package/dist/traits/index.js +0 -12243
  235. package/dist/type-checker.cjs +0 -18
  236. package/dist/type-checker.js +0 -5
@@ -1,1219 +0,0 @@
1
- 'use strict';
2
-
3
- var chunk3FXV5S25_cjs = require('./chunk-3FXV5S25.cjs');
4
-
5
- // src/types/AdvancedTypeSystem.ts
6
- var ExhaustivenessChecker = class {
7
- /**
8
- * Check if all union members are covered in match statement
9
- */
10
- checkMatch(unionType, casePatterns) {
11
- const patterns = new Set(casePatterns.map((p) => p.toLowerCase()));
12
- const uncovered = [];
13
- for (const member of unionType.members) {
14
- const caseName = this.getCaseName(member);
15
- if (!patterns.has(caseName.toLowerCase()) && caseName !== "_") {
16
- uncovered.push(caseName);
17
- }
18
- }
19
- return {
20
- isExhaustive: uncovered.length === 0 || patterns.has("_"),
21
- uncoveredCases: uncovered
22
- };
23
- }
24
- getCaseName(type) {
25
- if (type.kind === "literal") {
26
- return String(type.value);
27
- }
28
- if (type.kind === "custom") {
29
- return type.name;
30
- }
31
- return type.kind;
32
- }
33
- };
34
-
35
- // src/types/TypeAliasRegistry.ts
36
- var TypeAliasRegistry = class {
37
- constructor() {
38
- this.aliases = /* @__PURE__ */ new Map();
39
- /** Tracks which aliases are currently being expanded (cycle detection) */
40
- this.expanding = /* @__PURE__ */ new Set();
41
- }
42
- // ---------------------------------------------------------------------------
43
- // Registration
44
- // ---------------------------------------------------------------------------
45
- register(decl) {
46
- this.aliases.set(decl.name, decl);
47
- }
48
- has(name) {
49
- return this.aliases.has(name);
50
- }
51
- get(name) {
52
- return this.aliases.get(name);
53
- }
54
- all() {
55
- return Array.from(this.aliases.values());
56
- }
57
- clear() {
58
- this.aliases.clear();
59
- this.expanding.clear();
60
- }
61
- // ---------------------------------------------------------------------------
62
- // Parsing helper (parses a `type Foo = ...` source line)
63
- // ---------------------------------------------------------------------------
64
- /**
65
- * Parse a type alias declaration from source text.
66
- * Recognises:
67
- * type Name = definition
68
- * type Name<T, U> = definition
69
- */
70
- static parse(source, line) {
71
- const match = source.match(/^\s*type\s+([A-Z][A-Za-z0-9_]*)(?:<([^>]+)>)?\s*=\s*(.+)$/);
72
- if (!match) return null;
73
- const name = match[1];
74
- const rawParams = match[2];
75
- const definition = match[3].trim();
76
- const typeParams = rawParams ? rawParams.split(",").map((p) => p.trim()).filter(Boolean) : [];
77
- const isUnion = definition.includes("|");
78
- const kind = typeParams.length > 0 ? "generic" : isUnion ? "union" : "simple";
79
- return { name, kind, definition, typeParams, line };
80
- }
81
- // ---------------------------------------------------------------------------
82
- // Resolution
83
- // ---------------------------------------------------------------------------
84
- /**
85
- * Resolve an alias by name, substituting type params if provided.
86
- * Returns null if unknown or recursive.
87
- *
88
- * Example:
89
- * registry.resolve('Optional', ['string'])
90
- * → 'string | null'
91
- */
92
- resolve(name, typeArgs = []) {
93
- if (this.expanding.has(name)) {
94
- return null;
95
- }
96
- const decl = this.aliases.get(name);
97
- if (!decl) return null;
98
- if (this.containsAlias(decl.definition, name)) {
99
- return null;
100
- }
101
- this.expanding.add(name);
102
- try {
103
- let expanded = decl.definition;
104
- if (decl.typeParams && decl.typeParams.length > 0) {
105
- for (let i = 0; i < decl.typeParams.length; i++) {
106
- const param = decl.typeParams[i];
107
- const arg = typeArgs[i] ?? "any";
108
- expanded = expanded.replace(new RegExp(`\\b${param}\\b`, "g"), arg);
109
- }
110
- }
111
- expanded = this.expandReferences(expanded);
112
- return expanded;
113
- } finally {
114
- this.expanding.delete(name);
115
- }
116
- }
117
- /**
118
- * Detect recursive/self-referential type aliases.
119
- */
120
- isRecursive(name) {
121
- const decl = this.aliases.get(name);
122
- if (!decl) return false;
123
- this.expanding.add(name);
124
- const result = this.containsAlias(decl.definition, name);
125
- this.expanding.delete(name);
126
- return result;
127
- }
128
- // ---------------------------------------------------------------------------
129
- // Private helpers
130
- // ---------------------------------------------------------------------------
131
- expandReferences(definition) {
132
- let result = definition;
133
- for (const [aliasName, decl] of this.aliases) {
134
- if (this.expanding.has(aliasName)) continue;
135
- const pattern = new RegExp(`\\b${aliasName}\\b`, "g");
136
- if (pattern.test(result)) {
137
- const resolved = this.resolve(aliasName);
138
- if (resolved) {
139
- result = result.replace(new RegExp(`\\b${aliasName}\\b`, "g"), `(${resolved})`);
140
- }
141
- }
142
- }
143
- return result;
144
- }
145
- containsAlias(definition, targetName) {
146
- const pattern = new RegExp(`\\b${targetName}\\b`);
147
- return pattern.test(definition);
148
- }
149
- };
150
-
151
- // src/HoloScriptTypeChecker.ts
152
- var BUILTIN_FUNCTIONS = /* @__PURE__ */ new Map([
153
- [
154
- "add",
155
- {
156
- type: "function",
157
- parameters: [
158
- { name: "a", type: "number" },
159
- { name: "b", type: "number" }
160
- ],
161
- returnType: "number"
162
- }
163
- ],
164
- [
165
- "subtract",
166
- {
167
- type: "function",
168
- parameters: [
169
- { name: "a", type: "number" },
170
- { name: "b", type: "number" }
171
- ],
172
- returnType: "number"
173
- }
174
- ],
175
- [
176
- "multiply",
177
- {
178
- type: "function",
179
- parameters: [
180
- { name: "a", type: "number" },
181
- { name: "b", type: "number" }
182
- ],
183
- returnType: "number"
184
- }
185
- ],
186
- [
187
- "divide",
188
- {
189
- type: "function",
190
- parameters: [
191
- { name: "a", type: "number" },
192
- { name: "b", type: "number" }
193
- ],
194
- returnType: "number"
195
- }
196
- ],
197
- [
198
- "concat",
199
- {
200
- type: "function",
201
- parameters: [
202
- { name: "a", type: "string" },
203
- { name: "b", type: "string" }
204
- ],
205
- returnType: "string"
206
- }
207
- ],
208
- [
209
- "length",
210
- { type: "function", parameters: [{ name: "value", type: "any" }], returnType: "number" }
211
- ],
212
- [
213
- "push",
214
- {
215
- type: "function",
216
- parameters: [
217
- { name: "arr", type: "array" },
218
- { name: "item", type: "any" }
219
- ],
220
- returnType: "array"
221
- }
222
- ],
223
- ["pop", { type: "function", parameters: [{ name: "arr", type: "array" }], returnType: "any" }],
224
- ["log", { type: "function", parameters: [{ name: "message", type: "any" }], returnType: "void" }],
225
- [
226
- "print",
227
- { type: "function", parameters: [{ name: "message", type: "any" }], returnType: "void" }
228
- ],
229
- ["show", { type: "function", parameters: [{ name: "target", type: "orb" }], returnType: "void" }],
230
- ["hide", { type: "function", parameters: [{ name: "target", type: "orb" }], returnType: "void" }],
231
- [
232
- "pulse",
233
- { type: "function", parameters: [{ name: "target", type: "orb" }], returnType: "void" }
234
- ],
235
- [
236
- "animate",
237
- {
238
- type: "function",
239
- parameters: [
240
- { name: "target", type: "orb" },
241
- { name: "config", type: "object" }
242
- ],
243
- returnType: "void"
244
- }
245
- ],
246
- [
247
- "spawn",
248
- {
249
- type: "function",
250
- parameters: [
251
- { name: "type", type: "string" },
252
- { name: "position", type: "object" }
253
- ],
254
- returnType: "orb"
255
- }
256
- ],
257
- [
258
- "isNumber",
259
- { type: "function", parameters: [{ name: "value", type: "any" }], returnType: "boolean" }
260
- ],
261
- [
262
- "isString",
263
- { type: "function", parameters: [{ name: "value", type: "any" }], returnType: "boolean" }
264
- ],
265
- [
266
- "isArray",
267
- { type: "function", parameters: [{ name: "value", type: "any" }], returnType: "boolean" }
268
- ],
269
- // Simulation built-in functions (v4.2)
270
- [
271
- "createCollider",
272
- {
273
- type: "function",
274
- parameters: [
275
- { name: "shape", type: "string" },
276
- { name: "config", type: "object" }
277
- ],
278
- returnType: "object"
279
- }
280
- ],
281
- [
282
- "createRigidbody",
283
- {
284
- type: "function",
285
- parameters: [
286
- { name: "mass", type: "number" },
287
- { name: "config", type: "object" }
288
- ],
289
- returnType: "object"
290
- }
291
- ],
292
- [
293
- "createMaterial",
294
- {
295
- type: "function",
296
- parameters: [
297
- { name: "name", type: "string" },
298
- { name: "preset", type: "string" }
299
- ],
300
- returnType: "object"
301
- }
302
- ],
303
- [
304
- "createParticleSystem",
305
- { type: "function", parameters: [{ name: "config", type: "object" }], returnType: "object" }
306
- ],
307
- [
308
- "applyForce",
309
- {
310
- type: "function",
311
- parameters: [
312
- { name: "target", type: "orb" },
313
- { name: "force", type: "vec3" }
314
- ],
315
- returnType: "void"
316
- }
317
- ],
318
- [
319
- "raycast",
320
- {
321
- type: "function",
322
- parameters: [
323
- { name: "origin", type: "vec3" },
324
- { name: "direction", type: "vec3" },
325
- { name: "maxDistance", type: "number" }
326
- ],
327
- returnType: "object"
328
- }
329
- ],
330
- [
331
- "playAudio",
332
- {
333
- type: "function",
334
- parameters: [
335
- { name: "clip", type: "string" },
336
- { name: "config", type: "object" }
337
- ],
338
- returnType: "void"
339
- }
340
- ],
341
- [
342
- "setWeather",
343
- { type: "function", parameters: [{ name: "preset", type: "string" }], returnType: "void" }
344
- ],
345
- [
346
- "generateTerrain",
347
- { type: "function", parameters: [{ name: "config", type: "object" }], returnType: "object" }
348
- ],
349
- [
350
- "navigate",
351
- {
352
- type: "function",
353
- parameters: [
354
- { name: "agent", type: "orb" },
355
- { name: "target", type: "vec3" }
356
- ],
357
- returnType: "void"
358
- }
359
- ],
360
- [
361
- "distance",
362
- {
363
- type: "function",
364
- parameters: [
365
- { name: "a", type: "vec3" },
366
- { name: "b", type: "vec3" }
367
- ],
368
- returnType: "number"
369
- }
370
- ]
371
- ]);
372
- var HoloScriptTypeChecker = class {
373
- constructor() {
374
- this.typeMap = /* @__PURE__ */ new Map();
375
- this.diagnostics = [];
376
- this.currentLine = 0;
377
- this.currentColumn = 0;
378
- /** Registry for user-defined union types (e.g., type State = "idle" | "loading" | "error") */
379
- this.unionTypes = /* @__PURE__ */ new Map();
380
- /** Type alias registry (type Color = string | number[], type List<T> = T[]) */
381
- this.typeAliasRegistry = new TypeAliasRegistry();
382
- /** Custom constraints merged from holoscript.config.json */
383
- this.customConstraints = [];
384
- /** Diagnostics accumulated before check() so they survive the diagnostics reset */
385
- this.preCheckDiagnostics = [];
386
- BUILTIN_FUNCTIONS.forEach((type, name) => {
387
- this.typeMap.set(name, type);
388
- });
389
- this.exhaustivenessChecker = new ExhaustivenessChecker();
390
- }
391
- /**
392
- * Merge custom constraints from a parsed config object.
393
- * Call before check() when you have a holoscript.config.json.
394
- */
395
- loadConfig(config) {
396
- this.customConstraints = chunk3FXV5S25_cjs.loadConstraintsFromConfig(config);
397
- }
398
- /**
399
- * Register a type alias (e.g. from a `type Foo = ...` declaration in source).
400
- */
401
- registerTypeAlias(decl) {
402
- this.typeAliasRegistry.register(decl);
403
- if (this.typeAliasRegistry.isRecursive(decl.name)) {
404
- this.preCheckDiagnostics.push({
405
- severity: "error",
406
- message: `Type alias '${decl.name}' is recursive and cannot be expanded.`,
407
- line: decl.line ?? 0,
408
- column: 0,
409
- code: "HSP020",
410
- suggestions: [`Remove the self-reference in '${decl.name}' definition.`]
411
- });
412
- }
413
- }
414
- /**
415
- * Type check an AST
416
- */
417
- check(ast) {
418
- this.diagnostics = [...this.preCheckDiagnostics];
419
- for (const node of ast) {
420
- this.collectDeclaration(node);
421
- }
422
- this.checkBlock(ast);
423
- return {
424
- valid: this.diagnostics.filter((d) => d.severity === "error").length === 0,
425
- diagnostics: this.diagnostics,
426
- typeMap: new Map(this.typeMap)
427
- };
428
- }
429
- /**
430
- * Collect type declarations
431
- */
432
- collectDeclaration(node) {
433
- switch (node.type) {
434
- case "orb":
435
- this.collectOrbDeclaration(node);
436
- break;
437
- case "method":
438
- this.collectMethodDeclaration(node);
439
- break;
440
- case "variable-declaration":
441
- this.collectVariableDeclaration(node);
442
- break;
443
- case "stream":
444
- this.collectStreamDeclaration(node);
445
- break;
446
- case "template":
447
- this.collectTemplateDeclaration(node);
448
- break;
449
- }
450
- }
451
- collectTemplateDeclaration(node) {
452
- this.typeMap.set(node.name, {
453
- type: "object"
454
- // We could try to infer properties from body if structure allows,
455
- // but for now simple registration is enough to pass "Unknown variable" checks
456
- });
457
- }
458
- collectOrbDeclaration(node) {
459
- const properties = /* @__PURE__ */ new Map();
460
- properties.set("position", { type: "vec3" });
461
- properties.set("rotation", { type: "euler" });
462
- properties.set("scale", { type: "vec3" });
463
- properties.set("color", { type: "color" });
464
- properties.set("glow", { type: "boolean" });
465
- properties.set("interactive", { type: "boolean" });
466
- properties.set("visible", { type: "boolean" });
467
- for (const [key, value] of Object.entries(node.properties)) {
468
- const expectedType = properties.get(key);
469
- properties.set(key, this.inferTypeWithContext(value, expectedType));
470
- }
471
- this.typeMap.set(node.name, {
472
- type: "orb",
473
- properties
474
- });
475
- }
476
- collectMethodDeclaration(node) {
477
- const parameters = node.parameters.map((p) => ({
478
- name: p.name,
479
- type: this.parseTypeString(p.dataType),
480
- optional: p.defaultValue !== void 0,
481
- defaultValue: p.defaultValue
482
- }));
483
- this.typeMap.set(node.name, {
484
- type: "function",
485
- parameters,
486
- returnType: node.returnType ? this.parseTypeString(node.returnType) : "void"
487
- });
488
- }
489
- collectVariableDeclaration(node) {
490
- let typeInfo = { type: "any" };
491
- if (node.dataType) {
492
- typeInfo = { type: this.parseTypeString(node.dataType) };
493
- if (node.value !== void 0) {
494
- this.inferTypeWithContext(node.value, typeInfo);
495
- }
496
- } else if (node.value !== void 0) {
497
- typeInfo = this.inferType(node.value);
498
- }
499
- this.typeMap.set(node.name, typeInfo);
500
- }
501
- collectStreamDeclaration(node) {
502
- this.typeMap.set(node.name, {
503
- type: "stream",
504
- properties: /* @__PURE__ */ new Map([
505
- ["source", { type: "string" }],
506
- ["result", { type: "any" }]
507
- ])
508
- });
509
- }
510
- /**
511
- * Check a node for type errors
512
- */
513
- checkNode(node) {
514
- this.currentLine = node.position?.x ?? 0;
515
- this.currentColumn = node.position?.y ?? 0;
516
- switch (node.type) {
517
- case "connection":
518
- this.checkConnection(node);
519
- break;
520
- case "gate":
521
- this.checkGate(node);
522
- break;
523
- case "for-loop":
524
- this.checkForLoop(node);
525
- break;
526
- case "while-loop":
527
- this.checkWhileLoop(node);
528
- break;
529
- case "foreach-loop":
530
- this.checkForEachLoop(node);
531
- break;
532
- case "import":
533
- this.checkImport(node);
534
- break;
535
- case "export":
536
- this.checkExport(node);
537
- break;
538
- case "type-guard":
539
- this.checkTypeGuard(node);
540
- break;
541
- case "variable-declaration":
542
- this.checkVariableDeclaration(node);
543
- break;
544
- case "method":
545
- this.checkBlock(node.body);
546
- break;
547
- case "orb":
548
- this.validateTraitConstraints(node);
549
- this.checkBlock(node.children || []);
550
- break;
551
- case "template":
552
- this.validateTraitConstraints(node);
553
- this.checkBlock(node.children || []);
554
- break;
555
- case "spread":
556
- this.checkSpread(node);
557
- break;
558
- case "nullCoalescingAssignment":
559
- this.checkNullCoalescingAssignment(node);
560
- break;
561
- case "match":
562
- this.checkMatchExpression(node);
563
- break;
564
- }
565
- }
566
- checkNullCoalescingAssignment(node) {
567
- if (!node.target) {
568
- this.addDiagnostic("error", `Null coalescing assignment missing target`, "E104");
569
- return;
570
- }
571
- const targetStr = typeof node.target === "string" ? node.target : node.target?.__ref || node.target?.name;
572
- if (!targetStr) {
573
- this.addDiagnostic(
574
- "error",
575
- `Null coalescing assignment to non-assignable expression`,
576
- "E105"
577
- );
578
- return;
579
- }
580
- const targetType = this.typeMap.get(targetStr);
581
- const valueType = node.value ? this.inferType(node.value) : "unknown";
582
- this.typeMap.set(
583
- targetStr,
584
- targetType || { type: valueType, nullable: false }
585
- );
586
- }
587
- checkSpread(node) {
588
- if (!node.target) {
589
- this.addDiagnostic("error", `Spread expression missing target`, "E102");
590
- return;
591
- }
592
- if (!this.typeMap.has(node.target)) {
593
- this.addDiagnostic("error", `Unknown template or object '${node.target}' in spread`, "E102");
594
- } else {
595
- const type = this.typeMap.get(node.target);
596
- if (type && type.type !== "object" && type.type !== "orb" && type.type !== "any") {
597
- this.addDiagnostic(
598
- "error",
599
- `Cannot spread '${node.target}' type '${type.type}', must be object or template`,
600
- "E103"
601
- );
602
- }
603
- }
604
- }
605
- /**
606
- * Check a match expression for:
607
- * 1. Valid subject expression
608
- * 2. Exhaustiveness - all union cases are covered
609
- * 3. Unreachable patterns (after wildcard)
610
- * 4. Type consistency in case bodies
611
- */
612
- checkMatchExpression(node) {
613
- if (!node.subject) {
614
- this.addDiagnostic("error", "Match expression missing subject", "E200");
615
- return;
616
- }
617
- if (!node.cases || node.cases.length === 0) {
618
- this.addDiagnostic("error", "Match expression has no cases", "E201");
619
- return;
620
- }
621
- const subjectId = typeof node.subject === "string" ? node.subject : node.subject?.__ref || node.subject?.name;
622
- let unionType;
623
- if (subjectId && this.unionTypes.has(subjectId)) {
624
- unionType = this.unionTypes.get(subjectId);
625
- }
626
- const casePatterns = [];
627
- let hasWildcard = false;
628
- let wildcardIndex = -1;
629
- for (let i = 0; i < node.cases.length; i++) {
630
- const matchCase = node.cases[i];
631
- const pattern = matchCase.pattern;
632
- if (!pattern) {
633
- this.addDiagnostic("error", `Match case ${i + 1} has no pattern`, "E202");
634
- continue;
635
- }
636
- if (pattern.type === "wildcard-pattern") {
637
- if (hasWildcard) {
638
- this.addDiagnostic(
639
- "warning",
640
- `Duplicate wildcard pattern at case ${i + 1} - only the first wildcard will be reached`,
641
- "W200"
642
- );
643
- } else {
644
- hasWildcard = true;
645
- wildcardIndex = i;
646
- }
647
- casePatterns.push("_");
648
- } else if (pattern.type === "literal-pattern") {
649
- const value = String(pattern.value);
650
- if (casePatterns.includes(value)) {
651
- this.addDiagnostic(
652
- "warning",
653
- `Duplicate pattern "${value}" at case ${i + 1} - this case will never be reached`,
654
- "W201"
655
- );
656
- }
657
- casePatterns.push(value);
658
- } else if (pattern.type === "binding-pattern") {
659
- casePatterns.push(pattern.name);
660
- }
661
- if (hasWildcard && i > wildcardIndex) {
662
- this.addDiagnostic(
663
- "warning",
664
- `Unreachable pattern at case ${i + 1} - previous wildcard (_) matches all remaining cases`,
665
- "W202",
666
- ["Remove this case or reorder patterns"]
667
- );
668
- }
669
- if (Array.isArray(matchCase.body)) {
670
- this.checkBlock(matchCase.body);
671
- }
672
- }
673
- if (unionType) {
674
- const result = this.exhaustivenessChecker.checkMatch(unionType, casePatterns);
675
- if (!result.isExhaustive && !hasWildcard) {
676
- const missingCases = result.uncoveredCases.map((c) => `"${c}"`).join(", ");
677
- this.addDiagnostic(
678
- "error",
679
- `Non-exhaustive match. Missing cases: ${missingCases}`,
680
- "E203",
681
- result.uncoveredCases.map((c) => `Add case: "${c}" => ...`)
682
- );
683
- }
684
- } else if (!hasWildcard && subjectId) {
685
- this.addDiagnostic(
686
- "info",
687
- `Match expression on '${subjectId}' may be non-exhaustive. Consider adding a wildcard (_) case.`,
688
- "I200"
689
- );
690
- }
691
- }
692
- /**
693
- * Register a union type for exhaustiveness checking
694
- * Example: type State = "idle" | "loading" | "success" | "error"
695
- */
696
- registerUnionType(name, members) {
697
- const unionMembers = members.map((m) => ({
698
- kind: "literal",
699
- value: m
700
- }));
701
- this.unionTypes.set(name, {
702
- kind: "union",
703
- members: unionMembers
704
- });
705
- }
706
- /**
707
- * Get the union type for a registered name
708
- */
709
- getUnionType(name) {
710
- return this.unionTypes.get(name);
711
- }
712
- /**
713
- * Check if a match expression is exhaustive given the union type.
714
- * Returns HSP021 diagnostics for missing cases.
715
- */
716
- checkExhaustiveMatch(matchExpr) {
717
- const decl = this.typeAliasRegistry.get(matchExpr.typeName);
718
- if (!decl) return [];
719
- if (decl.kind !== "union" && decl.kind !== "simple") return [];
720
- if (matchExpr.coveredPatterns.includes("_")) return [];
721
- const members = this.extractUnionMembers(decl.definition);
722
- if (members.length === 0) return [];
723
- const coveredSet = new Set(matchExpr.coveredPatterns);
724
- const missing = members.filter((m) => !coveredSet.has(m));
725
- if (missing.length === 0) return [];
726
- const missingStr = missing.map((m) => '"' + m + '"').join(", ");
727
- return [
728
- {
729
- code: "HSP021",
730
- message: "Non-exhaustive match on '" + matchExpr.typeName + "'. Missing: " + missingStr,
731
- severity: "error",
732
- line: matchExpr.line ?? 0,
733
- column: matchExpr.column ?? 0,
734
- suggestions: missing.map((m) => "Add case: " + m + " => ...")
735
- }
736
- ];
737
- }
738
- /**
739
- * Extract individual members from a union type definition string.
740
- * Handles string literals, number literals, and identifiers.
741
- */
742
- extractUnionMembers(definition) {
743
- const parts = definition.split("|").map((p) => p.trim()).filter(Boolean);
744
- const members = [];
745
- for (const part of parts) {
746
- const strMatch = part.match(/^["'](.+?)["']$/);
747
- if (strMatch) {
748
- members.push(strMatch[1]);
749
- continue;
750
- }
751
- if (/^-?\d+(\.\d+)?$/.test(part)) {
752
- members.push(part);
753
- continue;
754
- }
755
- }
756
- return members;
757
- }
758
- checkBlock(nodes) {
759
- if (!nodes) return;
760
- for (const node of nodes) {
761
- this.checkNode(node);
762
- if (node.type === "expression-statement" && typeof node.expression === "string") {
763
- const varName = node.expression;
764
- const typeInfo = this.typeMap.get(varName);
765
- if (typeInfo) {
766
- this.addDiagnostic("info", `Type of '${varName}' is ${typeInfo.type}`, "DEBUG");
767
- }
768
- }
769
- }
770
- }
771
- /**
772
- * Check if two types are compatible
773
- */
774
- isCompatible(source, target) {
775
- if (source.type === "any" || target.type === "any") return true;
776
- if (source.type === target.type) return true;
777
- if (target.type === "vec3" && source.type === "euler") return true;
778
- if (target.type === "euler" && source.type === "vec3") return true;
779
- if (target.type === "vec4" && source.type === "quat") return true;
780
- if (target.type === "quat" && source.type === "vec4") return true;
781
- return false;
782
- }
783
- checkConnection(node) {
784
- const fromType = this.typeMap.get(node.from);
785
- const toType = this.typeMap.get(node.to);
786
- if (!fromType) {
787
- this.addDiagnostic("error", `Unknown source '${node.from}' in connection`, "E001");
788
- }
789
- if (!toType) {
790
- this.addDiagnostic("error", `Unknown target '${node.to}' in connection`, "E002");
791
- }
792
- if (fromType && toType && node.dataType !== "any") {
793
- if (!this.isCompatible(fromType, toType)) {
794
- this.addDiagnostic(
795
- "warning",
796
- `Connection from '${node.from}' (${fromType.type}) to '${node.to}' (${toType.type}) may be incompatible`,
797
- "W001",
798
- [`Consider using 'as "any"' to bypass type checking`]
799
- );
800
- }
801
- }
802
- }
803
- checkGate(node) {
804
- let narrowedVar;
805
- let narrowedType;
806
- if (typeof node.condition === "string") {
807
- const conditionVars = this.extractVariables(node.condition);
808
- for (const varName of conditionVars) {
809
- if (!this.typeMap.has(varName) && !this.isLiteral(varName)) {
810
- this.addDiagnostic("error", `Unknown variable '${varName}' in gate condition`, "E003");
811
- }
812
- }
813
- } else if (node.condition.type === "type-guard") {
814
- narrowedVar = node.condition.subject;
815
- narrowedType = { type: this.parseTypeString(node.condition.guardType) };
816
- this.checkTypeGuard(node.condition);
817
- }
818
- if (narrowedVar && narrowedType) {
819
- const originalType = this.typeMap.get(narrowedVar);
820
- this.typeMap.set(narrowedVar, narrowedType);
821
- this.addDiagnostic("info", `Type of '${narrowedVar}' is ${narrowedType.type}`, "DEBUG");
822
- this.checkBlock(node.truePath);
823
- if (originalType) this.typeMap.set(narrowedVar, originalType);
824
- else this.typeMap.delete(narrowedVar);
825
- } else {
826
- this.checkBlock(node.truePath);
827
- }
828
- if (node.falsePath && node.falsePath.length > 0) {
829
- this.checkBlock(node.falsePath);
830
- }
831
- }
832
- checkTypeGuard(node) {
833
- if (!this.typeMap.has(node.subject)) {
834
- this.addDiagnostic("error", `Unknown variable '${node.subject}' in type guard`, "E101");
835
- }
836
- }
837
- checkVariableDeclaration(node) {
838
- const typeInfo = this.typeMap.get(node.name);
839
- if (typeInfo && node.value !== void 0 && !node.isExpression) {
840
- const inferredValueType = this.inferTypeWithContext(node.value, typeInfo);
841
- if (!this.isCompatible(inferredValueType, typeInfo)) {
842
- this.addDiagnostic(
843
- "error",
844
- `Type mismatch: cannot assign ${inferredValueType.type} to ${typeInfo.type}`,
845
- "E102"
846
- );
847
- }
848
- }
849
- if (node.isExpression && typeof node.value === "string") {
850
- const vars = this.extractVariables(node.value);
851
- for (const v of vars) {
852
- if (!this.typeMap.has(v) && !this.isLiteral(v) && !BUILTIN_FUNCTIONS.has(v)) {
853
- this.addDiagnostic(
854
- "warning",
855
- `Reference to potentially undeclared variable '${v}'`,
856
- "W101"
857
- );
858
- }
859
- }
860
- }
861
- }
862
- checkForLoop(node) {
863
- const initVars = this.extractVariables(node.init);
864
- for (const varName of initVars) {
865
- if (!this.typeMap.has(varName)) {
866
- this.typeMap.set(varName, { type: "number" });
867
- }
868
- }
869
- if (typeof node.condition === "string") {
870
- const condVars = this.extractVariables(node.condition);
871
- for (const varName of condVars) {
872
- if (!this.typeMap.has(varName) && !this.isLiteral(varName)) {
873
- this.addDiagnostic(
874
- "error",
875
- `Unknown variable '${varName}' in for loop condition`,
876
- "E004"
877
- );
878
- }
879
- }
880
- } else {
881
- this.checkTypeGuard(node.condition);
882
- }
883
- this.checkBlock(node.body);
884
- }
885
- checkWhileLoop(node) {
886
- if (typeof node.condition === "string") {
887
- const condVars = this.extractVariables(node.condition);
888
- for (const varName of condVars) {
889
- if (!this.typeMap.has(varName) && !this.isLiteral(varName)) {
890
- this.addDiagnostic(
891
- "error",
892
- `Unknown variable '${varName}' in while loop condition`,
893
- "E005"
894
- );
895
- }
896
- }
897
- } else {
898
- this.checkTypeGuard(node.condition);
899
- }
900
- this.checkBlock(node.body);
901
- }
902
- checkForEachLoop(node) {
903
- if (!this.typeMap.has(node.collection)) {
904
- this.addDiagnostic(
905
- "error",
906
- `Unknown collection '${node.collection}' in forEach loop`,
907
- "E006"
908
- );
909
- } else {
910
- const collectionType2 = this.typeMap.get(node.collection);
911
- if (collectionType2 && collectionType2.type !== "array" && collectionType2.type !== "any") {
912
- this.addDiagnostic(
913
- "error",
914
- `'${node.collection}' is not iterable (type: ${collectionType2.type})`,
915
- "E007"
916
- );
917
- }
918
- }
919
- const collectionType = this.typeMap.get(node.collection);
920
- const itemType = collectionType?.type === "array" && collectionType.elementType ? collectionType.elementType : "any";
921
- const originalType = this.typeMap.get(node.variable);
922
- this.typeMap.set(node.variable, { type: itemType });
923
- this.checkBlock(node.body);
924
- if (originalType) this.typeMap.set(node.variable, originalType);
925
- else this.typeMap.delete(node.variable);
926
- }
927
- checkImport(node) {
928
- if (!node.modulePath) {
929
- this.addDiagnostic("error", "Import statement missing module path", "E008");
930
- }
931
- for (const name of node.imports) {
932
- this.typeMap.set(name, { type: "any" });
933
- }
934
- if (node.defaultImport) {
935
- this.typeMap.set(node.defaultImport, { type: "any" });
936
- }
937
- }
938
- checkExport(node) {
939
- if (node.exports) {
940
- for (const name of node.exports) {
941
- if (!this.typeMap.has(name)) {
942
- this.addDiagnostic("error", `Cannot export unknown identifier '${name}'`, "E009");
943
- }
944
- }
945
- }
946
- }
947
- /**
948
- * Infer type from a value
949
- */
950
- inferType(value) {
951
- if (value === null || value === void 0) {
952
- return { type: "any", nullable: true };
953
- }
954
- if (typeof value === "function") {
955
- const fn = value;
956
- return {
957
- type: "function",
958
- parameters: Array.from({ length: fn.length }, (_, i) => ({
959
- name: `arg${i}`,
960
- type: "any"
961
- })),
962
- returnType: "void"
963
- };
964
- }
965
- if (typeof value === "number") {
966
- return { type: "number" };
967
- }
968
- if (typeof value === "string") {
969
- if (/^\(.*\)\s*=>/.test(value) || /^\w+\s*=>/.test(value)) {
970
- const arrowMatch = value.match(/=>\s*(.+)$/s);
971
- let returnType = "void";
972
- if (arrowMatch) {
973
- const body = arrowMatch[1].trim();
974
- if (/^["']/.test(body)) returnType = "string";
975
- else if (/^-?\d/.test(body)) returnType = "number";
976
- else if (body === "true" || body === "false") returnType = "boolean";
977
- else if (/^\[/.test(body)) returnType = "array";
978
- else if (/^\{/.test(body) && !body.startsWith("{\n")) returnType = "object";
979
- else if (body !== "" && !body.startsWith("{")) returnType = "any";
980
- }
981
- return { type: "function", parameters: [], returnType };
982
- }
983
- if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(value)) return { type: "color" };
984
- if (/^rgba?\s*\(/.test(value)) return { type: "color" };
985
- return { type: "string" };
986
- }
987
- if (typeof value === "boolean") {
988
- return { type: "boolean" };
989
- }
990
- if (Array.isArray(value)) {
991
- if (value.length === 2 && value.every((v) => typeof v === "number")) return { type: "vec2" };
992
- if (value.length === 3 && value.every((v) => typeof v === "number")) return { type: "vec3" };
993
- if (value.length === 4 && value.every((v) => typeof v === "number")) return { type: "vec4" };
994
- const elementType = value.length > 0 ? this.inferType(value[0]).type : "any";
995
- return { type: "array", elementType };
996
- }
997
- if (typeof value === "object") {
998
- if ("x" in value && "y" in value) {
999
- if ("z" in value) return { type: "vec3" };
1000
- return { type: "vec2" };
1001
- }
1002
- const properties = /* @__PURE__ */ new Map();
1003
- for (const [key, val] of Object.entries(value)) {
1004
- properties.set(key, this.inferType(val));
1005
- }
1006
- return { type: "object", properties };
1007
- }
1008
- return { type: "any" };
1009
- }
1010
- /**
1011
- * Infer type with context
1012
- */
1013
- inferTypeWithContext(value, expectedType) {
1014
- if (!expectedType) return this.inferType(value);
1015
- const baseInferred = this.inferType(value);
1016
- if (expectedType.type === "color" && typeof value === "string") {
1017
- return { type: "color" };
1018
- }
1019
- if (expectedType.type === "euler" && Array.isArray(value) && value.length === 3) {
1020
- return { type: "euler" };
1021
- }
1022
- if (expectedType.type === "quat" && Array.isArray(value) && value.length === 4) {
1023
- return { type: "quat" };
1024
- }
1025
- if (expectedType.type === "vec3" && Array.isArray(value) && value.length === 3) {
1026
- return { type: "vec3" };
1027
- }
1028
- return baseInferred;
1029
- }
1030
- /**
1031
- * Parse type string to HoloScriptType
1032
- */
1033
- parseTypeString(typeStr) {
1034
- const normalized = typeStr.toLowerCase().trim();
1035
- const validTypes = [
1036
- "number",
1037
- "string",
1038
- "boolean",
1039
- "array",
1040
- "object",
1041
- "function",
1042
- "void",
1043
- "any",
1044
- "unknown",
1045
- "never",
1046
- "orb",
1047
- "stream",
1048
- "connection",
1049
- "gate",
1050
- "vec2",
1051
- "vec3",
1052
- "vec4",
1053
- "color",
1054
- "euler",
1055
- "quat",
1056
- "mat4"
1057
- ];
1058
- if (validTypes.includes(normalized)) {
1059
- return normalized;
1060
- }
1061
- return "any";
1062
- }
1063
- /**
1064
- * Extract variable names from an expression string
1065
- */
1066
- extractVariables(expr) {
1067
- const varPattern = /\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g;
1068
- const matches = expr.match(varPattern) || [];
1069
- const keywords = ["true", "false", "null", "undefined", "if", "else", "for", "while", "return"];
1070
- return matches.filter((m) => !keywords.includes(m));
1071
- }
1072
- /**
1073
- * Check if string is a literal
1074
- */
1075
- isLiteral(str) {
1076
- if (/^-?\d+(\.\d+)?$/.test(str)) return true;
1077
- if (str === "true" || str === "false") return true;
1078
- if (/^["'].*["']$/.test(str)) return true;
1079
- return false;
1080
- }
1081
- validateTraitConstraints(node) {
1082
- const traitsMap = node.traits;
1083
- if (!traitsMap || traitsMap.size === 0) {
1084
- return;
1085
- }
1086
- const traitNames = Array.from(traitsMap.keys());
1087
- const allConstraints = [...chunk3FXV5S25_cjs.BUILTIN_CONSTRAINTS, ...this.customConstraints];
1088
- for (const constraint of allConstraints) {
1089
- if (constraint.type === "requires") {
1090
- if (traitNames.includes(constraint.source)) {
1091
- for (const target of constraint.targets) {
1092
- if (!traitNames.includes(target)) {
1093
- const suggestions = constraint.suggestion ? [constraint.suggestion] : [`Add @${target} to the same orb as @${constraint.source}.`];
1094
- this.addDiagnostic(
1095
- "error",
1096
- constraint.message || `Trait @${constraint.source} requires @${target}.`,
1097
- "HSP014",
1098
- suggestions
1099
- );
1100
- }
1101
- }
1102
- }
1103
- } else if (constraint.type === "conflicts") {
1104
- if (traitNames.includes(constraint.source)) {
1105
- for (const target of constraint.targets) {
1106
- if (traitNames.includes(target)) {
1107
- const suggestions = constraint.suggestion ? [constraint.suggestion] : [`Remove either @${constraint.source} or @${target} from the orb.`];
1108
- this.addDiagnostic(
1109
- "error",
1110
- constraint.message || `Trait @${constraint.source} conflicts with @${target}.`,
1111
- "HSP014",
1112
- suggestions
1113
- );
1114
- }
1115
- }
1116
- }
1117
- } else if (constraint.type === "oneof") {
1118
- const matches = traitNames.filter((t) => constraint.targets.includes(t));
1119
- if (matches.length > 1) {
1120
- const suggestions = constraint.suggestion ? [constraint.suggestion] : [`Keep only one of: ${matches.map((t) => "@" + t).join(", ")}. Remove the others.`];
1121
- this.addDiagnostic(
1122
- "error",
1123
- constraint.message || `Only one of the following traits can be used at a time: ${constraint.targets.map((t) => "@" + t).join(", ")}.`,
1124
- "HSP014",
1125
- suggestions
1126
- );
1127
- }
1128
- }
1129
- }
1130
- }
1131
- /**
1132
- * Add a diagnostic
1133
- */
1134
- addDiagnostic(severity, message, code, suggestions) {
1135
- this.diagnostics.push({
1136
- severity,
1137
- message,
1138
- line: this.currentLine,
1139
- column: this.currentColumn,
1140
- code,
1141
- suggestions
1142
- });
1143
- }
1144
- /**
1145
- * Get type info for a name
1146
- */
1147
- getType(name) {
1148
- return this.typeMap.get(name);
1149
- }
1150
- /**
1151
- * Get all registered types
1152
- */
1153
- getAllTypes() {
1154
- return new Map(this.typeMap);
1155
- }
1156
- /**
1157
- * Reset the type checker
1158
- */
1159
- reset() {
1160
- this.typeMap.clear();
1161
- this.diagnostics = [];
1162
- this.unionTypes.clear();
1163
- BUILTIN_FUNCTIONS.forEach((type, name) => {
1164
- this.typeMap.set(name, type);
1165
- });
1166
- }
1167
- /**
1168
- * Get all registered union types
1169
- */
1170
- getAllUnionTypes() {
1171
- return new Map(this.unionTypes);
1172
- }
1173
- /**
1174
- * Sprint 5 — String-based type inference.
1175
- *
1176
- * Infers a simplified HoloScript type name from an expression string.
1177
- * This is a lightweight syntactic analysis that does NOT require the AST:
1178
- *
1179
- * | Expression | Inferred type |
1180
- * |---------------------------|---------------|
1181
- * | `[0, 1, 0]` | `'vec3'` |
1182
- * | `[0, 1]` | `'vec2'` |
1183
- * | `3.14` | `'float'` |
1184
- * | `42`, `0` | `'int'` |
1185
- * | `true` / `false` | `'bool'` |
1186
- * | `"hello"` / `'world'` | `'string'` |
1187
- * | anything else | `'any'` |
1188
- *
1189
- * @param expr Raw expression string (trimmed)
1190
- */
1191
- inferTypeExpression(expr) {
1192
- const s = expr.trim();
1193
- if (!s) return "any";
1194
- if (s === "true" || s === "false") return "bool";
1195
- if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'"))
1196
- return "string";
1197
- if (/^-?\d+$/.test(s)) return "int";
1198
- if (/^-?\d+\.\d+$/.test(s)) return "float";
1199
- if (s.startsWith("[") && s.endsWith("]")) {
1200
- const inner = s.slice(1, -1).trim();
1201
- if (!inner) return "any";
1202
- const parts = inner.split(",").map((p) => p.trim());
1203
- const allNumeric = parts.every((p) => /^-?\d+(\.\d+)?$/.test(p));
1204
- if (allNumeric) {
1205
- if (parts.length === 2) return "vec2";
1206
- if (parts.length === 3) return "vec3";
1207
- }
1208
- }
1209
- return "any";
1210
- }
1211
- };
1212
- function createTypeChecker() {
1213
- return new HoloScriptTypeChecker();
1214
- }
1215
-
1216
- exports.HoloScriptTypeChecker = HoloScriptTypeChecker;
1217
- exports.createTypeChecker = createTypeChecker;
1218
- //# sourceMappingURL=chunk-IBDG74G2.cjs.map
1219
- //# sourceMappingURL=chunk-IBDG74G2.cjs.map