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