@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,2522 +0,0 @@
1
- import { logger } from './chunk-PHENW4MQ.js';
2
-
3
- // src/HoloScriptPersistenceParser.ts
4
- var HoloScriptPersistenceParser = class {
5
- constructor(context) {
6
- this.ctx = context;
7
- }
8
- /**
9
- * Parse memory primitive block
10
- * memory <Name> { semantic: SemanticMemory { ... }, episodic: EpisodicMemory { ... }, procedural: ProceduralMemory { ... } }
11
- */
12
- parseMemory() {
13
- const startToken = this.ctx.check("keyword", "memory");
14
- if (!startToken) {
15
- return null;
16
- }
17
- this.ctx.advance();
18
- const name = this.ctx.expectIdentifier() || "UnnamedMemory";
19
- const node = {
20
- type: "memory",
21
- name,
22
- position: { x: 0, y: 0, z: 0 }
23
- };
24
- if (this.ctx.check("punctuation", "{")) {
25
- this.ctx.advance();
26
- while (!this.ctx.check("punctuation", "}") && this.ctx.position < this.ctx.tokens.length) {
27
- this.ctx.skipNewlines();
28
- if (this.ctx.check("punctuation", "}")) break;
29
- const keyToken = this.ctx.currentToken();
30
- if (!keyToken || keyToken.type !== "identifier" && keyToken.type !== "keyword") {
31
- this.ctx.advance();
32
- continue;
33
- }
34
- const key = keyToken.value;
35
- this.ctx.advance();
36
- if (this.ctx.check("punctuation", ":")) {
37
- this.ctx.advance();
38
- }
39
- const typeToken = this.ctx.currentToken();
40
- if (typeToken && (typeToken.type === "identifier" || typeToken.type === "keyword")) {
41
- this.ctx.advance();
42
- if (this.ctx.check("punctuation", "{")) {
43
- const properties = this.ctx.parseObject();
44
- if (key === "semantic" && typeToken.value === "SemanticMemory") {
45
- node.semantic = {
46
- type: "semantic-memory",
47
- properties,
48
- position: { x: 0, y: 0, z: 0 }
49
- };
50
- } else if (key === "episodic" && typeToken.value === "EpisodicMemory") {
51
- node.episodic = {
52
- type: "episodic-memory",
53
- properties,
54
- position: { x: 0, y: 0, z: 0 }
55
- };
56
- } else if (key === "procedural" && typeToken.value === "ProceduralMemory") {
57
- node.procedural = {
58
- type: "procedural-memory",
59
- properties,
60
- position: { x: 0, y: 0, z: 0 }
61
- };
62
- }
63
- }
64
- }
65
- if (this.ctx.check("punctuation", ",")) {
66
- this.ctx.advance();
67
- }
68
- }
69
- this.ctx.expect("punctuation", "}");
70
- }
71
- return node;
72
- }
73
- };
74
-
75
- // src/HoloScriptCodeParser.ts
76
- var ObjectPool = class {
77
- constructor(createFn, resetFn, maxSize = 100) {
78
- this.pool = [];
79
- this.createFn = createFn;
80
- this.resetFn = resetFn;
81
- this.maxSize = maxSize;
82
- }
83
- /** Get an object from pool or create new one */
84
- acquire() {
85
- if (this.pool.length > 0) {
86
- return this.pool.pop();
87
- }
88
- return this.createFn();
89
- }
90
- /** Return object to pool for reuse */
91
- release(obj) {
92
- if (this.pool.length < this.maxSize) {
93
- this.resetFn(obj);
94
- this.pool.push(obj);
95
- }
96
- }
97
- /** Clear the pool */
98
- clear() {
99
- this.pool.length = 0;
100
- }
101
- /** Get pool statistics */
102
- get stats() {
103
- return { pooled: this.pool.length, maxSize: this.maxSize };
104
- }
105
- };
106
- var tokenPool = new ObjectPool(
107
- () => ({ type: "", value: "", line: 0, column: 0 }),
108
- (t) => {
109
- t.type = "";
110
- t.value = "";
111
- t.line = 0;
112
- t.column = 0;
113
- }
114
- );
115
- var arrayPool = new ObjectPool(
116
- () => [],
117
- (arr) => {
118
- arr.length = 0;
119
- },
120
- 50
121
- );
122
- var ParserPools = {
123
- token: tokenPool,
124
- array: arrayPool,
125
- clearAll: () => {
126
- tokenPool.clear();
127
- arrayPool.clear();
128
- },
129
- getStats: () => ({
130
- token: tokenPool.stats,
131
- array: arrayPool.stats
132
- })
133
- };
134
- var CODE_SECURITY_CONFIG = {
135
- maxCodeLength: 5e4,
136
- maxBlocks: 100,
137
- suspiciousKeywords: [
138
- "process",
139
- "require",
140
- "eval",
141
- "constructor",
142
- "prototype",
143
- "__proto__",
144
- "fs",
145
- "child_process",
146
- "exec",
147
- "spawn"
148
- ]
149
- };
150
- function stripCommentsAndStrings(code) {
151
- let result = "";
152
- let i = 0;
153
- while (i < code.length) {
154
- if (code[i] === "/" && code[i + 1] === "/") {
155
- while (i < code.length && code[i] !== "\n") i++;
156
- continue;
157
- }
158
- if (code[i] === "/" && code[i + 1] === "*") {
159
- i += 2;
160
- while (i < code.length - 1 && !(code[i] === "*" && code[i + 1] === "/")) i++;
161
- i += 2;
162
- continue;
163
- }
164
- if (code[i] === '"') {
165
- i++;
166
- while (i < code.length && code[i] !== '"') {
167
- if (code[i] === "\\" && i + 1 < code.length) i++;
168
- i++;
169
- }
170
- i++;
171
- continue;
172
- }
173
- if (code[i] === "'") {
174
- i++;
175
- while (i < code.length && code[i] !== "'") {
176
- if (code[i] === "\\" && i + 1 < code.length) i++;
177
- i++;
178
- }
179
- i++;
180
- continue;
181
- }
182
- result += code[i];
183
- i++;
184
- }
185
- return result;
186
- }
187
- var ERROR_CODES = {
188
- HS001: "Expected keyword - a required keyword is missing",
189
- HS002: "Expected identifier - a name is required here",
190
- HS003: "Expected operator - an operator like = or : is required",
191
- HS004: "Unexpected token - this token is not valid in this context",
192
- HS005: "Unclosed block - missing closing brace }",
193
- HS006: "Unclosed string - missing closing quote",
194
- HS007: "Invalid number - numeric literal is malformed",
195
- HS008: "Unknown keyword - this keyword is not recognized",
196
- HS009: "Too many items - limit exceeded for performance",
197
- HS010: "Security violation - blocked for security reasons"
198
- };
199
- var HoloScriptCodeParser = class {
200
- constructor() {
201
- this.errors = [];
202
- this.warnings = [];
203
- this.tokens = [];
204
- this.position = 0;
205
- /** Source code lines for error context */
206
- this.sourceLines = [];
207
- this.persistenceParser = new HoloScriptPersistenceParser(this);
208
- this.keywordSet = /* @__PURE__ */ new Set([
209
- "orb",
210
- "function",
211
- "connect",
212
- "to",
213
- "as",
214
- "gate",
215
- "stream",
216
- "from",
217
- "through",
218
- "return",
219
- "if",
220
- "else",
221
- "nexus",
222
- "building",
223
- "pillar",
224
- "foundation",
225
- "for",
226
- "while",
227
- "forEach",
228
- "in",
229
- "of",
230
- "break",
231
- "continue",
232
- "import",
233
- "export",
234
- "module",
235
- "use",
236
- "type",
237
- "interface",
238
- "extends",
239
- "implements",
240
- "is",
241
- "async",
242
- "await",
243
- "spawn",
244
- "parallel",
245
- "class",
246
- "new",
247
- "this",
248
- "super",
249
- "static",
250
- "private",
251
- "public",
252
- "try",
253
- "catch",
254
- "finally",
255
- "throw",
256
- "const",
257
- "let",
258
- "var",
259
- "animate",
260
- "modify",
261
- "pulse",
262
- "move",
263
- "show",
264
- "hide",
265
- "scale",
266
- "focus",
267
- "environment",
268
- "composition",
269
- "template",
270
- "settings",
271
- "chat",
272
- "migrate",
273
- // Shape keywords for 3D objects
274
- "cube",
275
- "sphere",
276
- "plane",
277
- "cylinder",
278
- "cone",
279
- "torus",
280
- "pyramid",
281
- "box",
282
- "mesh",
283
- "model",
284
- "object",
285
- "light",
286
- "camera",
287
- // System and component keywords (Phase 0: Hololand Bootstrap)
288
- "system",
289
- "component",
290
- "action",
291
- "props",
292
- // Additional scene keywords
293
- "npc",
294
- "player",
295
- "entity",
296
- "trigger",
297
- "zone",
298
- "portal",
299
- "spatial_group",
300
- "interactive",
301
- "traits",
302
- "on_interact",
303
- "on_collision",
304
- "on_enter",
305
- "on_exit",
306
- "using",
307
- "memory",
308
- "semantic",
309
- "episodic",
310
- "procedural"
311
- ]);
312
- }
313
- /**
314
- * Create a rich error with context and suggestions
315
- */
316
- createError(code, message, token, suggestion) {
317
- const line = token?.line || 0;
318
- const column = token?.column || 0;
319
- let context = "";
320
- if (this.sourceLines.length > 0 && line > 0) {
321
- const lines = [];
322
- if (line > 1) lines.push(`${line - 1} | ${this.sourceLines[line - 2] || ""}`);
323
- lines.push(`${line} | ${this.sourceLines[line - 1] || ""}`);
324
- lines.push(` ${" ".repeat(column)}^`);
325
- if (line < this.sourceLines.length)
326
- lines.push(`${line + 1} | ${this.sourceLines[line] || ""}`);
327
- context = lines.join("\n");
328
- }
329
- return {
330
- line,
331
- column,
332
- message,
333
- code,
334
- context,
335
- suggestion,
336
- severity: "error"
337
- };
338
- }
339
- /**
340
- * Find similar keywords for "did you mean" suggestions
341
- */
342
- findSimilarKeyword(word) {
343
- if (!word) return void 0;
344
- const lower = word.toLowerCase();
345
- let bestMatch;
346
- let bestScore = 0;
347
- for (const keyword of this.keywordSet) {
348
- const score = this.similarity(lower, keyword);
349
- if (score > bestScore && score > 0.6) {
350
- bestScore = score;
351
- bestMatch = keyword;
352
- }
353
- }
354
- return bestMatch;
355
- }
356
- /**
357
- * Simple Levenshtein-based similarity (0-1)
358
- */
359
- similarity(a, b) {
360
- if (a === b) return 1;
361
- if (a.length === 0 || b.length === 0) return 0;
362
- const len = Math.max(a.length, b.length);
363
- let matches = 0;
364
- for (let i = 0; i < Math.min(a.length, b.length); i++) {
365
- if (a[i] === b[i]) matches++;
366
- }
367
- if (a.startsWith(b) || b.startsWith(a)) {
368
- matches = Math.max(matches, Math.min(a.length, b.length));
369
- }
370
- return matches / len;
371
- }
372
- /**
373
- * Add error and continue parsing (error recovery)
374
- */
375
- addError(error) {
376
- if (!this.errors.some((e) => e.line === error.line && e.message === error.message)) {
377
- this.errors.push(error);
378
- }
379
- }
380
- /**
381
- * Recover from error by skipping to next statement boundary
382
- */
383
- synchronize() {
384
- while (this.position < this.tokens.length) {
385
- const token = this.currentToken();
386
- if (!token) break;
387
- if (token.type === "newline") {
388
- this.advance();
389
- break;
390
- }
391
- if (token.type === "keyword" && [
392
- "orb",
393
- "function",
394
- "gate",
395
- "for",
396
- "while",
397
- "if",
398
- "return",
399
- "object",
400
- "template",
401
- "composition",
402
- "spatial_group",
403
- "logic"
404
- ].includes(token.value)) {
405
- break;
406
- }
407
- if (token.type === "punctuation" && ["}", ";"].includes(token.value)) {
408
- this.advance();
409
- break;
410
- }
411
- this.advance();
412
- }
413
- }
414
- /**
415
- * Parse HoloScript code string into AST
416
- */
417
- parse(code) {
418
- this.errors = [];
419
- this.warnings = [];
420
- this.tokens = [];
421
- this.position = 0;
422
- this.sourceLines = code.split("\n");
423
- if (code.length > CODE_SECURITY_CONFIG.maxCodeLength) {
424
- return {
425
- success: false,
426
- ast: [],
427
- errors: [
428
- {
429
- line: 0,
430
- column: 0,
431
- message: `Code exceeds max length (${CODE_SECURITY_CONFIG.maxCodeLength})`,
432
- code: "HS009",
433
- severity: "error"
434
- }
435
- ],
436
- warnings: []
437
- };
438
- }
439
- const strippedCode = stripCommentsAndStrings(code).toLowerCase();
440
- for (const keyword of CODE_SECURITY_CONFIG.suspiciousKeywords) {
441
- const regex = new RegExp(`\\b${keyword}\\b`, "i");
442
- if (regex.test(strippedCode)) {
443
- logger.warn("Suspicious keyword detected", { keyword });
444
- return {
445
- success: false,
446
- ast: [],
447
- errors: [
448
- {
449
- line: 0,
450
- column: 0,
451
- message: `Suspicious keyword detected: ${keyword}`,
452
- code: "HS010",
453
- severity: "error"
454
- }
455
- ],
456
- warnings: []
457
- };
458
- }
459
- }
460
- try {
461
- this.tokens = this.tokenize(code);
462
- const ast = this.parseProgram();
463
- return {
464
- success: this.errors.length === 0,
465
- ast,
466
- errors: this.errors,
467
- warnings: this.warnings
468
- };
469
- } catch (error) {
470
- this.addError({
471
- line: 0,
472
- column: 0,
473
- message: String(error),
474
- code: "HS004",
475
- severity: "error"
476
- });
477
- return {
478
- success: false,
479
- ast: [],
480
- errors: this.errors,
481
- warnings: this.warnings
482
- };
483
- }
484
- }
485
- /**
486
- * Tokenize code into tokens
487
- */
488
- tokenize(code) {
489
- const tokens = [];
490
- let line = 1;
491
- let column = 1;
492
- let i = 0;
493
- while (i < code.length) {
494
- const char = code[i];
495
- if (char === " " || char === " " || char === "\r") {
496
- i++;
497
- column++;
498
- continue;
499
- }
500
- if (char === "\n") {
501
- tokens.push({ type: "newline", value: "\n", line, column });
502
- line++;
503
- column = 1;
504
- i++;
505
- continue;
506
- }
507
- if (char === "/" && code[i + 1] === "/") {
508
- while (i < code.length && code[i] !== "\n") {
509
- i++;
510
- }
511
- continue;
512
- }
513
- if (char === '"' || char === "'") {
514
- const quote = char;
515
- let str = "";
516
- const startCol = column;
517
- i++;
518
- column++;
519
- while (i < code.length && code[i] !== quote) {
520
- if (code[i] === "\\" && i + 1 < code.length) {
521
- str += code[i + 1];
522
- i += 2;
523
- column += 2;
524
- } else {
525
- str += code[i];
526
- i++;
527
- column++;
528
- }
529
- }
530
- i++;
531
- column++;
532
- tokens.push({ type: "string", value: str, line, column: startCol });
533
- continue;
534
- }
535
- if (/[0-9]/.test(char) || char === "-" && /[0-9]/.test(code[i + 1])) {
536
- let num = "";
537
- const startCol = column;
538
- while (i < code.length && /[0-9.\-]/.test(code[i])) {
539
- num += code[i];
540
- i++;
541
- column++;
542
- }
543
- tokens.push({ type: "number", value: num, line, column: startCol });
544
- continue;
545
- }
546
- if (/[a-zA-Z_]/.test(char)) {
547
- let ident = "";
548
- const startCol = column;
549
- while (i < code.length && /[a-zA-Z0-9_]/.test(code[i])) {
550
- ident += code[i];
551
- i++;
552
- column++;
553
- }
554
- const isKeyword = this.keywordSet.has(ident.toLowerCase());
555
- tokens.push({
556
- type: isKeyword ? "keyword" : "identifier",
557
- value: ident,
558
- line,
559
- column: startCol
560
- });
561
- continue;
562
- }
563
- const multiCharOps = [
564
- "===",
565
- "!==",
566
- "==",
567
- "!=",
568
- ">=",
569
- "<=",
570
- "&&",
571
- "||",
572
- "??",
573
- "?.",
574
- "++",
575
- "--",
576
- "+=",
577
- "-=",
578
- "*=",
579
- "/=",
580
- "%=",
581
- "=>",
582
- "->"
583
- ];
584
- let foundMultiOp = false;
585
- for (const op of multiCharOps) {
586
- if (code.substring(i, i + op.length) === op) {
587
- tokens.push({ type: "operator", value: op, line, column });
588
- i += op.length;
589
- column += op.length;
590
- foundMultiOp = true;
591
- break;
592
- }
593
- }
594
- if (foundMultiOp) continue;
595
- const punctuation = [
596
- "{",
597
- "}",
598
- "(",
599
- ")",
600
- "[",
601
- "]",
602
- ":",
603
- ",",
604
- ".",
605
- ";",
606
- "=",
607
- "<",
608
- ">",
609
- "+",
610
- "-",
611
- "*",
612
- "/",
613
- "%",
614
- "!",
615
- "&",
616
- "|",
617
- "?",
618
- "#",
619
- "@"
620
- ];
621
- if (punctuation.includes(char)) {
622
- tokens.push({ type: "punctuation", value: char, line, column });
623
- i++;
624
- column++;
625
- continue;
626
- }
627
- i++;
628
- column++;
629
- }
630
- return tokens;
631
- }
632
- /**
633
- * Parse program (list of declarations)
634
- */
635
- parseProgram() {
636
- const nodes = [];
637
- let blockCount = 0;
638
- const maxErrors = 50;
639
- while (this.position < this.tokens.length) {
640
- if (this.errors.length >= maxErrors) {
641
- this.addError({
642
- line: 0,
643
- column: 0,
644
- message: `Too many errors (${maxErrors}+), stopping parse`,
645
- code: "HS009",
646
- severity: "error"
647
- });
648
- break;
649
- }
650
- while (this.currentToken()?.type === "newline") {
651
- this.advance();
652
- }
653
- if (this.position >= this.tokens.length) break;
654
- blockCount++;
655
- if (blockCount > CODE_SECURITY_CONFIG.maxBlocks) {
656
- this.addError({
657
- line: 0,
658
- column: 0,
659
- message: "Too many blocks in program",
660
- code: "HS009",
661
- severity: "error"
662
- });
663
- break;
664
- }
665
- const errorCountBefore = this.errors.length;
666
- const node = this.parseDeclaration();
667
- if (node) {
668
- nodes.push(node);
669
- } else if (this.errors.length > errorCountBefore) {
670
- this.synchronize();
671
- }
672
- }
673
- return nodes;
674
- }
675
- /**
676
- * Parse a single declaration
677
- */
678
- parseDeclaration() {
679
- const token = this.currentToken();
680
- if (!token) return null;
681
- if (token.type === "keyword") {
682
- switch (token.value.toLowerCase()) {
683
- case "orb":
684
- case "object":
685
- return this.parseOrb();
686
- case "function":
687
- return this.parseFunction();
688
- case "connect":
689
- return this.parseConnection();
690
- case "gate":
691
- case "if":
692
- return this.parseGate();
693
- case "return":
694
- return this.parseReturn();
695
- case "stream":
696
- return this.parseStream();
697
- case "nexus":
698
- return this.parseNexus();
699
- case "building":
700
- case "class":
701
- return this.parseBuilding();
702
- // Phase 2: Loop constructs
703
- case "for":
704
- return this.parseForLoop();
705
- case "while":
706
- return this.parseWhileLoop();
707
- case "foreach":
708
- return this.parseForEachLoop();
709
- // Phase 2: Module system
710
- case "import":
711
- return this.parseImport();
712
- case "export":
713
- return this.parseExport();
714
- // Phase 2: Variable declarations
715
- // UI Extensions
716
- case "ui2d":
717
- case "card":
718
- case "metric":
719
- case "button":
720
- case "row":
721
- case "col":
722
- case "text":
723
- return this.parseUIElement();
724
- case "const":
725
- case "let":
726
- case "var":
727
- return this.parseVariableDeclaration();
728
- // DSL-first commands (Phase 54)
729
- case "animate":
730
- return this.parseAnimate();
731
- case "modify":
732
- return this.parseModify();
733
- case "scale":
734
- return this.parseScale();
735
- case "focus":
736
- return this.parseFocus();
737
- case "environment":
738
- return this.parseEnvironment();
739
- case "composition":
740
- return this.parseComposition();
741
- case "template":
742
- return this.parseTemplate();
743
- case "system":
744
- return this.parseSystem();
745
- case "component":
746
- return this.parseComponent();
747
- case "migrate":
748
- return this.parseMigration();
749
- case "settings":
750
- return this.parseSettings();
751
- case "chat":
752
- return this.parseChat();
753
- // Primitive 3D shapes (Phase 55)
754
- case "cube":
755
- case "sphere":
756
- case "plane":
757
- case "cylinder":
758
- case "cone":
759
- case "torus":
760
- case "pyramid":
761
- case "box":
762
- case "mesh":
763
- case "model":
764
- case "light":
765
- case "camera":
766
- return this.parsePrimitive();
767
- case "zone":
768
- return this.parseZone();
769
- case "memory":
770
- return this.parseMemory();
771
- default:
772
- return this.parseExpressionStatement();
773
- }
774
- }
775
- this.advance();
776
- return null;
777
- }
778
- /**
779
- * Parse for loop: for (init; condition; update) { body }
780
- */
781
- parseForLoop() {
782
- this.expect("keyword", "for");
783
- if (!this.check("punctuation", "(")) {
784
- this.errors.push({ line: 0, column: 0, message: "Expected ( after for" });
785
- return null;
786
- }
787
- this.advance();
788
- let init = "", condition = "", update = "";
789
- let depth = 0;
790
- while (this.position < this.tokens.length) {
791
- const t = this.currentToken();
792
- if (!t) break;
793
- if (t.value === ";" && depth === 0) {
794
- this.advance();
795
- break;
796
- }
797
- if (t.value === "(") depth++;
798
- if (t.value === ")") depth--;
799
- init += t.value + " ";
800
- this.advance();
801
- }
802
- depth = 0;
803
- while (this.position < this.tokens.length) {
804
- const t = this.currentToken();
805
- if (!t) break;
806
- if (t.value === ";" && depth === 0) {
807
- this.advance();
808
- break;
809
- }
810
- if (t.value === "(") depth++;
811
- if (t.value === ")") depth--;
812
- condition += t.value + " ";
813
- this.advance();
814
- }
815
- depth = 0;
816
- while (this.position < this.tokens.length) {
817
- const t = this.currentToken();
818
- if (!t) break;
819
- if (t.value === ")" && depth === 0) {
820
- this.advance();
821
- break;
822
- }
823
- if (t.value === "(") depth++;
824
- if (t.value === ")") depth--;
825
- update += t.value + " ";
826
- this.advance();
827
- }
828
- const body = [];
829
- if (this.check("punctuation", "{")) {
830
- this.advance();
831
- let braceDepth = 1;
832
- while (braceDepth > 0 && this.position < this.tokens.length) {
833
- if (this.check("punctuation", "{")) braceDepth++;
834
- if (this.check("punctuation", "}")) braceDepth--;
835
- this.advance();
836
- }
837
- }
838
- return {
839
- type: "for-loop",
840
- init: init.trim(),
841
- condition: this.parseConditionExpression(condition.trim()),
842
- update: update.trim(),
843
- body,
844
- position: { x: 0, y: 0, z: 0 }
845
- };
846
- }
847
- /**
848
- * Parse while loop: while (condition) { body }
849
- */
850
- parseWhileLoop() {
851
- this.expect("keyword", "while");
852
- let condition = "";
853
- if (this.check("punctuation", "(")) {
854
- this.advance();
855
- let depth = 1;
856
- while (depth > 0 && this.position < this.tokens.length) {
857
- const t = this.currentToken();
858
- if (!t) break;
859
- if (t.value === "(") depth++;
860
- if (t.value === ")") {
861
- depth--;
862
- if (depth === 0) {
863
- this.advance();
864
- break;
865
- }
866
- }
867
- condition += t.value + " ";
868
- this.advance();
869
- }
870
- }
871
- if (this.check("punctuation", "{")) {
872
- this.advance();
873
- let braceDepth = 1;
874
- while (braceDepth > 0 && this.position < this.tokens.length) {
875
- if (this.check("punctuation", "{")) braceDepth++;
876
- if (this.check("punctuation", "}")) braceDepth--;
877
- this.advance();
878
- }
879
- }
880
- return {
881
- type: "while-loop",
882
- condition: this.parseConditionExpression(condition.trim()),
883
- body: [],
884
- position: { x: 0, y: 0, z: 0 }
885
- };
886
- }
887
- /**
888
- * Parse forEach loop: forEach item in collection { body }
889
- */
890
- parseForEachLoop() {
891
- this.expect("keyword", "forEach");
892
- const variable = this.expectIdentifier();
893
- this.expect("keyword", "in");
894
- const collection = this.expectIdentifier();
895
- if (this.check("punctuation", "{")) {
896
- this.advance();
897
- let braceDepth = 1;
898
- while (braceDepth > 0 && this.position < this.tokens.length) {
899
- if (this.check("punctuation", "{")) braceDepth++;
900
- if (this.check("punctuation", "}")) braceDepth--;
901
- this.advance();
902
- }
903
- }
904
- return {
905
- type: "foreach-loop",
906
- variable: variable || "item",
907
- collection: collection || "items",
908
- body: [],
909
- position: { x: 0, y: 0, z: 0 }
910
- };
911
- }
912
- /**
913
- * Parse import: import { x, y } from "module"
914
- */
915
- parseImport() {
916
- this.expect("keyword", "import");
917
- const imports = [];
918
- let modulePath = "";
919
- let defaultImport;
920
- const current = this.currentToken();
921
- if (current?.type === "string") {
922
- modulePath = current.value;
923
- this.advance();
924
- return {
925
- type: "import",
926
- imports: [],
927
- modulePath,
928
- position: { x: 0, y: 0, z: 0 }
929
- };
930
- }
931
- if (this.check("punctuation", "{")) {
932
- this.advance();
933
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
934
- const name = this.expectIdentifier();
935
- if (name) imports.push(name);
936
- if (this.check("punctuation", ",")) this.advance();
937
- }
938
- this.expect("punctuation", "}");
939
- } else {
940
- defaultImport = this.expectIdentifier() || void 0;
941
- }
942
- if (this.check("keyword", "from")) {
943
- this.advance();
944
- const pathToken = this.currentToken();
945
- if (pathToken?.type === "string") {
946
- modulePath = pathToken.value;
947
- this.advance();
948
- }
949
- }
950
- return {
951
- type: "import",
952
- imports,
953
- defaultImport,
954
- modulePath,
955
- position: { x: 0, y: 0, z: 0 }
956
- };
957
- }
958
- /**
959
- * Parse export: export { x, y } or export function/orb
960
- */
961
- parseExport() {
962
- this.expect("keyword", "export");
963
- const next = this.currentToken();
964
- if (next?.type === "keyword") {
965
- const declaration = this.parseDeclaration();
966
- return {
967
- type: "export",
968
- declaration: declaration || void 0,
969
- position: { x: 0, y: 0, z: 0 }
970
- };
971
- }
972
- const exports$1 = [];
973
- if (this.check("punctuation", "{")) {
974
- this.advance();
975
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
976
- const name = this.expectIdentifier();
977
- if (name) exports$1.push(name);
978
- if (this.check("punctuation", ",")) this.advance();
979
- }
980
- this.expect("punctuation", "}");
981
- }
982
- return {
983
- type: "export",
984
- exports: exports$1,
985
- position: { x: 0, y: 0, z: 0 }
986
- };
987
- }
988
- /**
989
- * Parse variable declaration: const/let/var name = value
990
- */
991
- parseVariableDeclaration() {
992
- const kindToken = this.currentToken()?.value.toLowerCase();
993
- const kind = kindToken === "let" ? "let" : kindToken === "var" ? "var" : "const";
994
- this.advance();
995
- const name = this.expectIdentifier();
996
- if (!name) return null;
997
- let dataType;
998
- if (this.check("punctuation", ":")) {
999
- this.advance();
1000
- dataType = this.expectIdentifier() || void 0;
1001
- }
1002
- const result = {
1003
- type: "variable-declaration",
1004
- kind,
1005
- name,
1006
- dataType,
1007
- value: void 0,
1008
- position: { x: 0, y: 0, z: 0 }
1009
- };
1010
- if (this.check("punctuation", "=")) {
1011
- this.advance();
1012
- const valueToken = this.currentToken();
1013
- if (valueToken?.type === "string") {
1014
- result.value = valueToken.value;
1015
- this.advance();
1016
- } else if (valueToken?.type === "number") {
1017
- result.value = parseFloat(valueToken.value);
1018
- this.advance();
1019
- } else if (this.check("punctuation", "[")) {
1020
- result.value = this.parseArray();
1021
- } else if (this.check("punctuation", "{")) {
1022
- result.value = this.parseObject();
1023
- } else if (valueToken?.type === "identifier") {
1024
- if (valueToken.value === "true") {
1025
- result.value = true;
1026
- this.advance();
1027
- } else if (valueToken.value === "false") {
1028
- result.value = false;
1029
- this.advance();
1030
- } else {
1031
- let expression = "";
1032
- while (this.position < this.tokens.length) {
1033
- const t = this.currentToken();
1034
- if (!t || t.type === "newline" || t.type === "punctuation" && t.value === ";") break;
1035
- expression += t.value + " ";
1036
- this.advance();
1037
- }
1038
- result.value = expression.trim();
1039
- result.isExpression = true;
1040
- }
1041
- }
1042
- }
1043
- return result;
1044
- }
1045
- /**
1046
- * Parse orb declaration
1047
- */
1048
- parseOrb() {
1049
- const startToken = this.currentToken();
1050
- if (this.check("keyword", "orb") || this.check("keyword", "object")) {
1051
- this.advance();
1052
- } else {
1053
- this.expect("keyword", "orb");
1054
- }
1055
- let name = "";
1056
- if (this.check("punctuation", "#")) {
1057
- this.advance();
1058
- name = this.expectName() || `orb_${Date.now()}`;
1059
- } else {
1060
- name = this.expectName() || `orb_${Date.now()}`;
1061
- }
1062
- let template;
1063
- if (this.check("keyword", "using")) {
1064
- this.advance();
1065
- template = this.expectName() || void 0;
1066
- }
1067
- const properties = {};
1068
- const directives = [];
1069
- let position;
1070
- let hologram;
1071
- if (this.check("punctuation", "{")) {
1072
- this.advance();
1073
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1074
- this.skipNewlines();
1075
- if (this.check("punctuation", "}")) break;
1076
- if (this.check("punctuation", ",") || this.check("punctuation", ";")) {
1077
- this.advance();
1078
- continue;
1079
- }
1080
- const token = this.currentToken();
1081
- if (token?.type === "punctuation" && token.value === "@") {
1082
- const directive = this.parseDirective();
1083
- if (directive) directives.push(directive);
1084
- } else {
1085
- const prop = this.parseProperty();
1086
- if (prop) {
1087
- if (prop.key === "position" || prop.key === "at") {
1088
- position = this.parsePosition(prop.value);
1089
- } else if (prop.key === "color" || prop.key === "glow" || prop.key === "size") {
1090
- hologram = hologram || {
1091
- shape: "orb",
1092
- color: "#00ffff",
1093
- size: 0.5,
1094
- glow: true,
1095
- interactive: true
1096
- };
1097
- if (prop.key === "color") hologram.color = String(prop.value);
1098
- if (prop.key === "glow") hologram.glow = Boolean(prop.value);
1099
- if (prop.key === "size") hologram.size = Number(prop.value);
1100
- } else {
1101
- properties[prop.key] = prop.value;
1102
- }
1103
- } else {
1104
- this.advance();
1105
- }
1106
- }
1107
- this.skipNewlines();
1108
- }
1109
- this.expect("punctuation", "}");
1110
- }
1111
- return {
1112
- type: "orb",
1113
- name,
1114
- position: position || { x: 0, y: 0, z: 0 },
1115
- hologram: hologram || {
1116
- shape: "orb",
1117
- color: "#00ffff",
1118
- size: 0.5,
1119
- glow: true,
1120
- interactive: true
1121
- },
1122
- properties,
1123
- directives,
1124
- template,
1125
- methods: [],
1126
- children: [],
1127
- line: startToken?.line || 0
1128
- };
1129
- }
1130
- /**
1131
- * Parse HoloScript+ directive: @name(...) or @name { ... }
1132
- */
1133
- parseDirective() {
1134
- this.expect("punctuation", "@");
1135
- const name = this.expectIdentifier();
1136
- if (!name) return null;
1137
- if (name === "state") {
1138
- const body = this.parseObject();
1139
- return { type: "state", body };
1140
- }
1141
- if (name === "bindings") {
1142
- const bindings = this.parseBindingsBlock();
1143
- return { type: "bindings", bindings };
1144
- }
1145
- if (name.startsWith("on_")) {
1146
- let body = "";
1147
- if (this.check("punctuation", "{")) {
1148
- this.advance();
1149
- let braceDepth = 1;
1150
- while (braceDepth > 0 && this.position < this.tokens.length) {
1151
- const t = this.advance();
1152
- if (t.value === "{") braceDepth++;
1153
- if (t.value === "}") braceDepth--;
1154
- if (braceDepth > 0) {
1155
- const val = t.type === "string" ? JSON.stringify(t.value) : t.value;
1156
- body += val + " ";
1157
- } else if (braceDepth < 0) break;
1158
- }
1159
- } else {
1160
- const t = this.advance();
1161
- if (t) body = t.value;
1162
- }
1163
- return { type: "lifecycle", hook: name, body };
1164
- }
1165
- let config = {};
1166
- if (this.check("punctuation", "(")) {
1167
- this.advance();
1168
- while (!this.check("punctuation", ")") && this.position < this.tokens.length) {
1169
- const prop = this.parseProperty();
1170
- if (prop) {
1171
- config[prop.key] = prop.value;
1172
- }
1173
- if (this.check("punctuation", ",")) {
1174
- this.advance();
1175
- }
1176
- }
1177
- this.expect("punctuation", ")");
1178
- } else if (this.check("punctuation", "{")) {
1179
- config = this.parseObject();
1180
- }
1181
- return { type: "trait", name, config };
1182
- }
1183
- /**
1184
- * Parse @bindings { bind(expr) -> target.prop, ... }
1185
- */
1186
- parseBindingsBlock() {
1187
- const bindings = [];
1188
- if (!this.check("punctuation", "{")) {
1189
- return bindings;
1190
- }
1191
- this.advance();
1192
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1193
- this.skipNewlines();
1194
- if (this.check("identifier") && this.currentToken()?.value === "bind") {
1195
- this.advance();
1196
- let expression = "";
1197
- if (this.check("punctuation", "(")) {
1198
- this.advance();
1199
- let parenDepth = 1;
1200
- while (parenDepth > 0 && this.position < this.tokens.length) {
1201
- const t = this.advance();
1202
- if (t.value === "(") parenDepth++;
1203
- if (t.value === ")") parenDepth--;
1204
- if (parenDepth > 0) {
1205
- expression += t.value + " ";
1206
- }
1207
- }
1208
- expression = expression.trim();
1209
- }
1210
- if (this.check("punctuation", "-")) {
1211
- this.advance();
1212
- if (this.check("punctuation", ">")) {
1213
- this.advance();
1214
- }
1215
- }
1216
- const target = this.expectIdentifier() || "";
1217
- let property = "";
1218
- if (this.check("punctuation", ".")) {
1219
- this.advance();
1220
- property = this.expectIdentifier() || "";
1221
- }
1222
- if (expression && target && property) {
1223
- bindings.push({ expression, target, property });
1224
- }
1225
- } else {
1226
- this.advance();
1227
- }
1228
- this.skipNewlines();
1229
- }
1230
- this.expect("punctuation", "}");
1231
- return bindings;
1232
- }
1233
- // ============================================================================
1234
- // Phase 7: AI Persistence Memory Syntax
1235
- // ============================================================================
1236
- /**
1237
- * Parse memory primitive block
1238
- * memory <Name> { semantic: SemanticMemory { ... }, episodic: EpisodicMemory { ... }, procedural: ProceduralMemory { ... } }
1239
- *
1240
- * Defers to the modular HoloScriptPersistenceParser
1241
- */
1242
- parseMemory() {
1243
- return this.persistenceParser.parseMemory();
1244
- }
1245
- /**
1246
- * Parse function declaration
1247
- */
1248
- parseFunction() {
1249
- this.expect("keyword", "function");
1250
- const name = this.expectIdentifier();
1251
- if (!name) return null;
1252
- const parameters = [];
1253
- let returnType;
1254
- if (this.check("punctuation", "(")) {
1255
- this.advance();
1256
- while (!this.check("punctuation", ")") && this.position < this.tokens.length) {
1257
- const paramName = this.expectIdentifier();
1258
- if (!paramName) break;
1259
- let paramType = "any";
1260
- if (this.check("punctuation", ":")) {
1261
- this.advance();
1262
- paramType = this.expectIdentifier() || "any";
1263
- }
1264
- parameters.push({
1265
- type: "parameter",
1266
- name: paramName,
1267
- dataType: paramType
1268
- });
1269
- if (this.check("punctuation", ",")) {
1270
- this.advance();
1271
- }
1272
- }
1273
- this.expect("punctuation", ")");
1274
- }
1275
- if (this.check("punctuation", ":")) {
1276
- this.advance();
1277
- returnType = this.expectIdentifier() || void 0;
1278
- }
1279
- const body = [];
1280
- if (this.check("punctuation", "{")) {
1281
- this.advance();
1282
- let depth = 1;
1283
- while (depth > 0 && this.position < this.tokens.length) {
1284
- if (this.check("punctuation", "{")) depth++;
1285
- if (this.check("punctuation", "}")) depth--;
1286
- this.advance();
1287
- }
1288
- }
1289
- return {
1290
- type: "method",
1291
- name,
1292
- parameters,
1293
- body,
1294
- returnType,
1295
- position: { x: 0, y: 0, z: 0 },
1296
- hologram: { shape: "cube", color: "#ff6b35", size: 1.5, glow: true, interactive: true }
1297
- };
1298
- }
1299
- /**
1300
- * Parse connection
1301
- */
1302
- parseConnection() {
1303
- this.expect("keyword", "connect");
1304
- const from = this.expectIdentifier();
1305
- if (!from) return null;
1306
- this.expect("keyword", "to");
1307
- const to = this.expectIdentifier();
1308
- if (!to) return null;
1309
- let dataType = "any";
1310
- if (this.check("keyword", "as")) {
1311
- this.advance();
1312
- const typeStr = this.currentToken();
1313
- if (typeStr?.type === "string" || typeStr?.type === "identifier") {
1314
- dataType = typeStr.value;
1315
- this.advance();
1316
- }
1317
- }
1318
- return {
1319
- type: "connection",
1320
- from,
1321
- to,
1322
- dataType,
1323
- bidirectional: false
1324
- };
1325
- }
1326
- /**
1327
- * Parse scale block: scale <magnitude> { body }
1328
- */
1329
- parseScale() {
1330
- this.expect("keyword", "scale");
1331
- const magnitude = this.expectIdentifier() || "standard";
1332
- const multipliers = {
1333
- galactic: 1e6,
1334
- macro: 1e3,
1335
- standard: 1,
1336
- micro: 1e-3,
1337
- atomic: 1e-6
1338
- };
1339
- const body = [];
1340
- if (this.check("punctuation", "{")) {
1341
- this.advance();
1342
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1343
- this.skipNewlines();
1344
- const node = this.parseDeclaration();
1345
- if (node) body.push(node);
1346
- this.skipNewlines();
1347
- }
1348
- this.expect("punctuation", "}");
1349
- }
1350
- return {
1351
- type: "scale",
1352
- magnitude,
1353
- multiplier: multipliers[magnitude] || 1,
1354
- body,
1355
- position: { x: 0, y: 0, z: 0 }
1356
- };
1357
- }
1358
- /**
1359
- * Parse focus block: focus <target> { body }
1360
- */
1361
- parseFocus() {
1362
- this.expect("keyword", "focus");
1363
- const target = this.expectIdentifier() || "origin";
1364
- const body = [];
1365
- if (this.check("punctuation", "{")) {
1366
- this.advance();
1367
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1368
- this.skipNewlines();
1369
- const node = this.parseDeclaration();
1370
- if (node) body.push(node);
1371
- this.skipNewlines();
1372
- }
1373
- this.expect("punctuation", "}");
1374
- }
1375
- return {
1376
- type: "focus",
1377
- target,
1378
- body,
1379
- position: { x: 0, y: 0, z: 0 }
1380
- };
1381
- }
1382
- /**
1383
- * Parse environment declaration
1384
- * Supports: environment { ... } or environment #id { ... }
1385
- */
1386
- parseEnvironment() {
1387
- this.expect("keyword", "environment");
1388
- const settings = {};
1389
- let envId;
1390
- if (this.check("punctuation", "#")) {
1391
- this.advance();
1392
- envId = this.expectIdentifier() || void 0;
1393
- }
1394
- if (this.check("punctuation", "{")) {
1395
- this.advance();
1396
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1397
- this.skipNewlines();
1398
- if (this.check("punctuation", "}")) break;
1399
- if (this.check("punctuation", "@")) {
1400
- const directive = this.parseDirective();
1401
- if (directive) {
1402
- const dir = directive;
1403
- settings[`@${directive.type}`] = dir.args || dir.config || [];
1404
- }
1405
- continue;
1406
- }
1407
- const prop = this.parseProperty();
1408
- if (prop) {
1409
- settings[prop.key] = prop.value;
1410
- }
1411
- this.skipNewlines();
1412
- }
1413
- this.expect("punctuation", "}");
1414
- } else {
1415
- while (this.position < this.tokens.length && this.currentToken()?.type !== "newline" && !this.check("punctuation", "}")) {
1416
- const key = this.expectIdentifier();
1417
- if (!key) break;
1418
- settings[key] = this.parseLiteral();
1419
- }
1420
- }
1421
- if (envId) {
1422
- settings["id"] = envId;
1423
- }
1424
- return {
1425
- type: "environment",
1426
- settings
1427
- };
1428
- }
1429
- /**
1430
- * Parse primitive 3D shape declaration
1431
- * Supports: cylinder #id { ... }, sphere "name" { ... }, etc.
1432
- */
1433
- parsePrimitive() {
1434
- const startToken = this.currentToken();
1435
- const primitiveType = startToken?.value || "object";
1436
- this.advance();
1437
- let name = "";
1438
- let elementId;
1439
- if (this.check("punctuation", "#")) {
1440
- this.advance();
1441
- elementId = this.expectIdentifier() || void 0;
1442
- name = elementId || `${primitiveType}_${Date.now()}`;
1443
- } else {
1444
- name = this.expectName() || `${primitiveType}_${Date.now()}`;
1445
- }
1446
- let template;
1447
- if (this.check("keyword", "using")) {
1448
- this.advance();
1449
- template = this.expectName() || void 0;
1450
- }
1451
- const properties = {};
1452
- const directives = [];
1453
- let position;
1454
- if (this.check("punctuation", "{")) {
1455
- this.advance();
1456
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1457
- this.skipNewlines();
1458
- if (this.check("punctuation", "}")) break;
1459
- if (this.check("punctuation", ",") || this.check("punctuation", ";")) {
1460
- this.advance();
1461
- continue;
1462
- }
1463
- const token = this.currentToken();
1464
- if (token?.type === "punctuation" && token.value === "@") {
1465
- const directive = this.parseDirective();
1466
- if (directive) directives.push(directive);
1467
- } else {
1468
- const prop = this.parseProperty();
1469
- if (prop) {
1470
- if (prop.key === "position" || prop.key === "at") {
1471
- position = this.parsePosition(prop.value);
1472
- } else {
1473
- properties[prop.key] = prop.value;
1474
- }
1475
- } else {
1476
- this.advance();
1477
- }
1478
- }
1479
- this.skipNewlines();
1480
- }
1481
- this.expect("punctuation", "}");
1482
- }
1483
- properties["_primitiveType"] = primitiveType;
1484
- if (elementId) {
1485
- properties["id"] = elementId;
1486
- }
1487
- return {
1488
- type: "orb",
1489
- name,
1490
- position: position || { x: 0, y: 0, z: 0 },
1491
- hologram: {
1492
- shape: primitiveType,
1493
- color: "#00d4ff",
1494
- size: 1,
1495
- glow: false,
1496
- interactive: true
1497
- },
1498
- properties,
1499
- directives,
1500
- template,
1501
- methods: [],
1502
- children: [],
1503
- line: startToken?.line || 0
1504
- };
1505
- }
1506
- /**
1507
- * Parse zone declaration: zone "Name" { ... } or zone #id { ... }
1508
- */
1509
- parseZone() {
1510
- this.expect("keyword", "zone");
1511
- let name = "";
1512
- let zoneId;
1513
- if (this.check("punctuation", "#")) {
1514
- this.advance();
1515
- zoneId = this.expectIdentifier() || void 0;
1516
- name = zoneId || `zone_${Date.now()}`;
1517
- } else {
1518
- name = this.expectName() || `zone_${Date.now()}`;
1519
- }
1520
- const properties = {};
1521
- let position;
1522
- if (this.check("punctuation", "{")) {
1523
- this.advance();
1524
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1525
- this.skipNewlines();
1526
- if (this.check("punctuation", "}")) break;
1527
- const prop = this.parseProperty();
1528
- if (prop) {
1529
- if (prop.key === "position") {
1530
- position = this.parsePosition(prop.value);
1531
- properties["position"] = prop.value;
1532
- } else {
1533
- properties[prop.key] = prop.value;
1534
- }
1535
- } else {
1536
- const token = this.currentToken();
1537
- this.addError(
1538
- this.createError(
1539
- "HS004",
1540
- `Unexpected token in zone: ${token?.type || "unknown"}`,
1541
- token
1542
- )
1543
- );
1544
- this.advance();
1545
- }
1546
- this.skipNewlines();
1547
- }
1548
- this.expect("punctuation", "}");
1549
- }
1550
- return {
1551
- type: "zone",
1552
- name,
1553
- id: zoneId,
1554
- position,
1555
- events: {},
1556
- // Events are stored in properties for now
1557
- properties
1558
- };
1559
- }
1560
- /**
1561
- * Parse composition block
1562
- */
1563
- parseComposition() {
1564
- this.expect("keyword", "composition");
1565
- const name = this.expectName() || "unnamed";
1566
- const children = [];
1567
- if (this.check("punctuation", "{")) {
1568
- this.advance();
1569
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1570
- this.skipNewlines();
1571
- const node = this.parseDeclaration();
1572
- if (node) children.push(node);
1573
- this.skipNewlines();
1574
- }
1575
- this.expect("punctuation", "}");
1576
- }
1577
- return {
1578
- type: "composition",
1579
- name,
1580
- children
1581
- };
1582
- }
1583
- /**
1584
- * Parse template declaration
1585
- */
1586
- parseTemplate() {
1587
- this.expect("keyword", "template");
1588
- const name = this.expectName() || "template";
1589
- let version;
1590
- const params = [];
1591
- if (this.check("punctuation", "(")) {
1592
- this.advance();
1593
- while (!this.check("punctuation", ")") && this.position < this.tokens.length) {
1594
- const p = this.expectIdentifier();
1595
- if (p) params.push(p);
1596
- if (this.check("punctuation", ",")) this.advance();
1597
- }
1598
- this.expect("punctuation", ")");
1599
- }
1600
- const children = [];
1601
- const migrations = [];
1602
- const directives = [];
1603
- const properties = {};
1604
- if (this.check("punctuation", "{")) {
1605
- this.advance();
1606
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1607
- this.skipNewlines();
1608
- const token = this.currentToken();
1609
- if (token?.type === "punctuation" && token.value === "@") {
1610
- const startPos2 = this.position;
1611
- this.advance();
1612
- const dirName = this.expectIdentifier();
1613
- if (dirName === "version") {
1614
- this.expect("punctuation", "(");
1615
- const vStr = this.currentToken();
1616
- if (vStr?.type === "number") {
1617
- version = parseInt(vStr.value, 10);
1618
- this.advance();
1619
- }
1620
- this.expect("punctuation", ")");
1621
- directives.push({ type: "version", version });
1622
- this.skipNewlines();
1623
- continue;
1624
- } else {
1625
- this.position = startPos2;
1626
- const dir = this.parseDirective();
1627
- if (dir) directives.push(dir);
1628
- this.skipNewlines();
1629
- continue;
1630
- }
1631
- }
1632
- const startPos = this.position;
1633
- const errorCount = this.errors.length;
1634
- const node = this.parseDeclaration();
1635
- if (node && node.type !== "expression") {
1636
- if (node.type === "migration") {
1637
- migrations.push(node);
1638
- } else {
1639
- children.push(node);
1640
- }
1641
- this.skipNewlines();
1642
- continue;
1643
- }
1644
- this.position = startPos;
1645
- this.errors.length = errorCount;
1646
- const prop = this.parseProperty();
1647
- if (prop) {
1648
- properties[prop.key] = prop.value;
1649
- this.skipNewlines();
1650
- continue;
1651
- }
1652
- this.advance();
1653
- }
1654
- this.expect("punctuation", "}");
1655
- }
1656
- return {
1657
- type: "template",
1658
- name,
1659
- parameters: params,
1660
- children,
1661
- properties,
1662
- directives,
1663
- version,
1664
- migrations
1665
- };
1666
- }
1667
- /**
1668
- * Parse system declaration: system Name { state {}, on_start {}, action name() {}, ui {} }
1669
- *
1670
- * Systems are named trait+logic containers that auto-initialize within a composition.
1671
- * They encapsulate state, lifecycle hooks, actions, and optional UI.
1672
- *
1673
- * Syntax:
1674
- * system TutorialSystem {
1675
- * state { currentStep: 0, completed: false }
1676
- * on_start { ... }
1677
- * on_update { ... }
1678
- * action next() { ... }
1679
- * action skip() { ... }
1680
- * ui { ... }
1681
- * }
1682
- */
1683
- parseSystem() {
1684
- this.expect("keyword", "system");
1685
- const name = this.expectName() || "unnamed_system";
1686
- const state = {};
1687
- const actions = [];
1688
- const hooks = [];
1689
- const directives = [];
1690
- const properties = {};
1691
- const children = [];
1692
- const uiNodes = [];
1693
- if (this.check("punctuation", "{")) {
1694
- this.advance();
1695
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1696
- this.skipNewlines();
1697
- if (this.check("punctuation", "}")) break;
1698
- const token = this.currentToken();
1699
- if (token?.type === "punctuation" && token.value === "@") {
1700
- const directive = this.parseDirective();
1701
- if (directive) directives.push(directive);
1702
- this.skipNewlines();
1703
- continue;
1704
- }
1705
- if (token?.type === "keyword" || token?.type === "identifier") {
1706
- const val = token.value.toLowerCase();
1707
- if (val === "state") {
1708
- this.advance();
1709
- if (this.check("punctuation", "{")) {
1710
- const stateObj = this.parseObject();
1711
- Object.assign(state, stateObj);
1712
- }
1713
- this.skipNewlines();
1714
- continue;
1715
- }
1716
- if (val === "action") {
1717
- this.advance();
1718
- const actionName = this.expectIdentifier();
1719
- if (actionName) {
1720
- const params = [];
1721
- if (this.check("punctuation", "(")) {
1722
- this.advance();
1723
- while (!this.check("punctuation", ")") && this.position < this.tokens.length) {
1724
- const p = this.expectIdentifier();
1725
- if (p) params.push(p);
1726
- if (this.check("punctuation", ",")) this.advance();
1727
- }
1728
- this.expect("punctuation", ")");
1729
- }
1730
- const body = this.parseBlockBody();
1731
- actions.push({ name: actionName, params, body });
1732
- }
1733
- this.skipNewlines();
1734
- continue;
1735
- }
1736
- if (val.startsWith("on_")) {
1737
- this.advance();
1738
- const body = this.parseBlockBody();
1739
- hooks.push({ name: val, body });
1740
- this.skipNewlines();
1741
- continue;
1742
- }
1743
- if (val === "ui") {
1744
- this.advance();
1745
- if (this.check("punctuation", "{")) {
1746
- this.advance();
1747
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1748
- this.skipNewlines();
1749
- const node2 = this.parseDeclaration();
1750
- if (node2) uiNodes.push(node2);
1751
- this.skipNewlines();
1752
- }
1753
- this.expect("punctuation", "}");
1754
- }
1755
- this.skipNewlines();
1756
- continue;
1757
- }
1758
- const startPos = this.position;
1759
- const errorCount = this.errors.length;
1760
- const node = this.parseDeclaration();
1761
- if (node && node.type !== "expression") {
1762
- children.push(node);
1763
- this.skipNewlines();
1764
- continue;
1765
- }
1766
- this.position = startPos;
1767
- this.errors.length = errorCount;
1768
- const prop = this.parseProperty();
1769
- if (prop) {
1770
- properties[prop.key] = prop.value;
1771
- this.skipNewlines();
1772
- continue;
1773
- }
1774
- }
1775
- this.advance();
1776
- }
1777
- this.expect("punctuation", "}");
1778
- }
1779
- return {
1780
- type: "system",
1781
- id: name,
1782
- properties,
1783
- state: Object.keys(state).length > 0 ? state : void 0,
1784
- actions: actions.length > 0 ? actions : void 0,
1785
- hooks: hooks.length > 0 ? hooks : void 0,
1786
- ui: uiNodes.length > 0 ? uiNodes : void 0,
1787
- children: children.length > 0 ? children : void 0,
1788
- directives: directives.length > 0 ? directives : void 0
1789
- };
1790
- }
1791
- /**
1792
- * Parse component declaration: component Name { props {}, state {}, ui {}, action name() {} }
1793
- *
1794
- * Components are UI-focused declarations with props, state, and render/ui blocks.
1795
- *
1796
- * Syntax:
1797
- * component MobileControls {
1798
- * props { visible: true, joystickSize: 120 }
1799
- * state { isMoving: false }
1800
- * ui { ... }
1801
- * }
1802
- */
1803
- parseComponent() {
1804
- this.expect("keyword", "component");
1805
- const name = this.expectName() || "unnamed_component";
1806
- const props = {};
1807
- const state = {};
1808
- const actions = [];
1809
- const hooks = [];
1810
- const directives = [];
1811
- const properties = {};
1812
- const children = [];
1813
- const uiNodes = [];
1814
- if (this.check("punctuation", "{")) {
1815
- this.advance();
1816
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1817
- this.skipNewlines();
1818
- if (this.check("punctuation", "}")) break;
1819
- const token = this.currentToken();
1820
- if (token?.type === "punctuation" && token.value === "@") {
1821
- const directive = this.parseDirective();
1822
- if (directive) directives.push(directive);
1823
- this.skipNewlines();
1824
- continue;
1825
- }
1826
- if (token?.type === "keyword" || token?.type === "identifier") {
1827
- const val = token.value.toLowerCase();
1828
- if (val === "props") {
1829
- this.advance();
1830
- if (this.check("punctuation", "{")) {
1831
- const propsObj = this.parseObject();
1832
- Object.assign(props, propsObj);
1833
- }
1834
- this.skipNewlines();
1835
- continue;
1836
- }
1837
- if (val === "state") {
1838
- this.advance();
1839
- if (this.check("punctuation", "{")) {
1840
- const stateObj = this.parseObject();
1841
- Object.assign(state, stateObj);
1842
- }
1843
- this.skipNewlines();
1844
- continue;
1845
- }
1846
- if (val === "action") {
1847
- this.advance();
1848
- const actionName = this.expectIdentifier();
1849
- if (actionName) {
1850
- const params = [];
1851
- if (this.check("punctuation", "(")) {
1852
- this.advance();
1853
- while (!this.check("punctuation", ")") && this.position < this.tokens.length) {
1854
- const p = this.expectIdentifier();
1855
- if (p) params.push(p);
1856
- if (this.check("punctuation", ",")) this.advance();
1857
- }
1858
- this.expect("punctuation", ")");
1859
- }
1860
- const body = this.parseBlockBody();
1861
- actions.push({ name: actionName, params, body });
1862
- }
1863
- this.skipNewlines();
1864
- continue;
1865
- }
1866
- if (val.startsWith("on_")) {
1867
- this.advance();
1868
- const body = this.parseBlockBody();
1869
- hooks.push({ name: val, body });
1870
- this.skipNewlines();
1871
- continue;
1872
- }
1873
- if (val === "ui") {
1874
- this.advance();
1875
- if (this.check("punctuation", "{")) {
1876
- this.advance();
1877
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
1878
- this.skipNewlines();
1879
- const node2 = this.parseDeclaration();
1880
- if (node2) uiNodes.push(node2);
1881
- this.skipNewlines();
1882
- }
1883
- this.expect("punctuation", "}");
1884
- }
1885
- this.skipNewlines();
1886
- continue;
1887
- }
1888
- const startPos = this.position;
1889
- const errorCount = this.errors.length;
1890
- const node = this.parseDeclaration();
1891
- if (node && node.type !== "expression") {
1892
- children.push(node);
1893
- this.skipNewlines();
1894
- continue;
1895
- }
1896
- this.position = startPos;
1897
- this.errors.length = errorCount;
1898
- const prop = this.parseProperty();
1899
- if (prop) {
1900
- properties[prop.key] = prop.value;
1901
- this.skipNewlines();
1902
- continue;
1903
- }
1904
- }
1905
- this.advance();
1906
- }
1907
- this.expect("punctuation", "}");
1908
- }
1909
- return {
1910
- type: "component",
1911
- name,
1912
- props: Object.keys(props).length > 0 ? props : void 0,
1913
- state: Object.keys(state).length > 0 ? state : void 0,
1914
- actions: actions.length > 0 ? actions : void 0,
1915
- hooks: hooks.length > 0 ? hooks : void 0,
1916
- ui: uiNodes.length > 0 ? uiNodes : void 0,
1917
- children: children.length > 0 ? children : void 0,
1918
- directives: directives.length > 0 ? directives : void 0,
1919
- properties: Object.keys(properties).length > 0 ? properties : void 0
1920
- };
1921
- }
1922
- /**
1923
- * Parse a block body { ... } — captures everything between braces as a string.
1924
- * Used for action bodies and lifecycle hooks where we capture the raw body.
1925
- */
1926
- parseBlockBody() {
1927
- let body = "";
1928
- if (this.check("punctuation", "{")) {
1929
- this.advance();
1930
- let braceDepth = 1;
1931
- while (braceDepth > 0 && this.position < this.tokens.length) {
1932
- const t = this.advance();
1933
- if (t.value === "{") braceDepth++;
1934
- if (t.value === "}") braceDepth--;
1935
- if (braceDepth > 0) {
1936
- const val = t.type === "string" ? JSON.stringify(t.value) : t.value;
1937
- body += val + " ";
1938
- }
1939
- }
1940
- }
1941
- return body.trim();
1942
- }
1943
- /**
1944
- * Parse migration block: migrate from(n) { body }
1945
- */
1946
- parseMigration() {
1947
- this.expect("keyword", "migrate");
1948
- this.expect("keyword", "from");
1949
- this.expect("punctuation", "(");
1950
- let fromVersion = 0;
1951
- const vStr = this.currentToken();
1952
- if (vStr?.type === "number") {
1953
- fromVersion = parseInt(vStr.value, 10);
1954
- this.advance();
1955
- }
1956
- this.expect("punctuation", ")");
1957
- let body = "";
1958
- if (this.check("punctuation", "{")) {
1959
- this.advance();
1960
- let braceDepth = 1;
1961
- this.position;
1962
- while (braceDepth > 0 && this.position < this.tokens.length) {
1963
- const t = this.advance();
1964
- if (t.value === "{") braceDepth++;
1965
- if (t.value === "}") braceDepth--;
1966
- if (braceDepth > 0) {
1967
- const val = t.type === "string" ? JSON.stringify(t.value) : t.value;
1968
- body += val + " ";
1969
- }
1970
- }
1971
- }
1972
- return {
1973
- type: "migration",
1974
- fromVersion,
1975
- body: body.trim(),
1976
- position: { x: 0, y: 0, z: 0 }
1977
- };
1978
- }
1979
- /**
1980
- * Parse gate (conditional)
1981
- */
1982
- parseGate() {
1983
- const isIf = this.check("keyword", "if");
1984
- if (isIf) {
1985
- this.advance();
1986
- } else {
1987
- this.expect("keyword", "gate");
1988
- this.expectIdentifier();
1989
- }
1990
- let condition = "";
1991
- if (this.check("punctuation", "(")) {
1992
- this.advance();
1993
- while (!this.check("punctuation", ")") && this.position < this.tokens.length) {
1994
- const token = this.currentToken();
1995
- if (token) condition += token.value + " ";
1996
- this.advance();
1997
- }
1998
- this.expect("punctuation", ")");
1999
- }
2000
- const truePath = [];
2001
- if (this.check("punctuation", "{")) {
2002
- this.advance();
2003
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
2004
- const node = this.parseDeclaration();
2005
- if (node) truePath.push(node);
2006
- else this.advance();
2007
- }
2008
- this.expect("punctuation", "}");
2009
- }
2010
- const falsePath = [];
2011
- if (this.check("keyword", "else")) {
2012
- this.advance();
2013
- if (this.check("punctuation", "{")) {
2014
- this.advance();
2015
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
2016
- const node = this.parseDeclaration();
2017
- if (node) falsePath.push(node);
2018
- else this.advance();
2019
- }
2020
- this.expect("punctuation", "}");
2021
- } else {
2022
- const node = this.parseDeclaration();
2023
- if (node) falsePath.push(node);
2024
- }
2025
- }
2026
- return {
2027
- type: "gate",
2028
- condition: this.parseConditionExpression(condition.trim()),
2029
- truePath,
2030
- falsePath,
2031
- position: { x: 0, y: 0, z: 0 },
2032
- hologram: { shape: "pyramid", color: "#4ecdc4", size: 1, glow: true, interactive: true }
2033
- };
2034
- }
2035
- /**
2036
- * Parse return statement
2037
- */
2038
- parseReturn() {
2039
- this.expect("keyword", "return");
2040
- let expression = "";
2041
- let parenDepth = 0;
2042
- let braceDepth = 0;
2043
- let bracketDepth = 0;
2044
- while (this.position < this.tokens.length) {
2045
- const t = this.currentToken();
2046
- if (!t) break;
2047
- if (t.type === "newline" && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) break;
2048
- if (t.type === "punctuation" && t.value === ";" && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0)
2049
- break;
2050
- if (t.type === "punctuation") {
2051
- if (t.value === "(") parenDepth++;
2052
- else if (t.value === ")") parenDepth--;
2053
- else if (t.value === "{") braceDepth++;
2054
- else if (t.value === "}") braceDepth--;
2055
- else if (t.value === "[") bracketDepth++;
2056
- else if (t.value === "]") bracketDepth--;
2057
- }
2058
- expression += t.value + " ";
2059
- this.advance();
2060
- }
2061
- return {
2062
- type: "return",
2063
- value: expression.trim(),
2064
- // Use 'value' to match runtime's executeReturn
2065
- position: { x: 0, y: 0, z: 0 }
2066
- };
2067
- }
2068
- /**
2069
- * Parse generic expression statement (e.g. function call or assignment)
2070
- */
2071
- parseExpressionStatement() {
2072
- let expression = "";
2073
- let parenDepth = 0;
2074
- let braceDepth = 0;
2075
- let bracketDepth = 0;
2076
- while (this.position < this.tokens.length) {
2077
- const t = this.currentToken();
2078
- if (!t) break;
2079
- if (t.type === "newline" && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) break;
2080
- if (t.type === "punctuation" && t.value === ";" && parenDepth === 0 && braceDepth === 0 && bracketDepth === 0)
2081
- break;
2082
- if (t.type === "punctuation") {
2083
- if (t.value === "(") parenDepth++;
2084
- else if (t.value === ")") parenDepth--;
2085
- else if (t.value === "{") braceDepth++;
2086
- else if (t.value === "}") braceDepth--;
2087
- else if (t.value === "[") bracketDepth++;
2088
- else if (t.value === "]") bracketDepth--;
2089
- }
2090
- expression += t.value + " ";
2091
- this.advance();
2092
- }
2093
- if (expression.trim().length === 0) {
2094
- this.advance();
2095
- return null;
2096
- }
2097
- return {
2098
- type: "expression-statement",
2099
- expression: expression.trim(),
2100
- position: { x: 0, y: 0, z: 0 }
2101
- };
2102
- }
2103
- /**
2104
- * Parse stream
2105
- */
2106
- parseStream() {
2107
- this.expect("keyword", "stream");
2108
- const name = this.expectIdentifier();
2109
- if (!name) return null;
2110
- let source = "unknown";
2111
- if (this.check("keyword", "from")) {
2112
- this.advance();
2113
- source = this.expectIdentifier() || "unknown";
2114
- }
2115
- if (this.check("punctuation", "{")) {
2116
- this.advance();
2117
- let depth = 1;
2118
- while (depth > 0 && this.position < this.tokens.length) {
2119
- if (this.check("punctuation", "{")) depth++;
2120
- if (this.check("punctuation", "}")) depth--;
2121
- this.advance();
2122
- }
2123
- }
2124
- return {
2125
- type: "stream",
2126
- name,
2127
- source,
2128
- transformations: [],
2129
- position: { x: 0, y: 0, z: 0 },
2130
- hologram: { shape: "cylinder", color: "#45b7d1", size: 2, glow: true, interactive: true }
2131
- };
2132
- }
2133
- /**
2134
- * Parse nexus (multi-agent hub)
2135
- */
2136
- parseNexus() {
2137
- this.expect("keyword", "nexus");
2138
- const name = this.expectIdentifier();
2139
- if (!name) return null;
2140
- if (this.check("punctuation", "{")) {
2141
- this.advance();
2142
- let depth = 1;
2143
- while (depth > 0 && this.position < this.tokens.length) {
2144
- if (this.check("punctuation", "{")) depth++;
2145
- if (this.check("punctuation", "}")) depth--;
2146
- this.advance();
2147
- }
2148
- }
2149
- return {
2150
- type: "nexus",
2151
- position: { x: 0, y: 0, z: 0 },
2152
- hologram: { shape: "sphere", color: "#9b59b6", size: 3, glow: true, interactive: true }
2153
- };
2154
- }
2155
- /**
2156
- * Parse building (class-like)
2157
- */
2158
- parseBuilding() {
2159
- this.expect("keyword", "building");
2160
- const name = this.expectName();
2161
- if (!name) return null;
2162
- if (this.check("punctuation", "{")) {
2163
- this.advance();
2164
- let depth = 1;
2165
- while (depth > 0 && this.position < this.tokens.length) {
2166
- if (this.check("punctuation", "{")) depth++;
2167
- if (this.check("punctuation", "}")) depth--;
2168
- this.advance();
2169
- }
2170
- }
2171
- return {
2172
- type: "building",
2173
- position: { x: 0, y: 0, z: 0 },
2174
- hologram: { shape: "cube", color: "#e74c3c", size: 4, glow: true, interactive: true }
2175
- };
2176
- }
2177
- /**
2178
- * Parse a literal value (string, number, boolean, array, or object)
2179
- */
2180
- parseLiteral() {
2181
- const token = this.currentToken();
2182
- if (!token) return null;
2183
- if (token.type === "string") {
2184
- this.advance();
2185
- return token.value;
2186
- }
2187
- if (token.type === "number") {
2188
- this.advance();
2189
- return parseFloat(token.value);
2190
- }
2191
- if (token.type === "identifier") {
2192
- const val = token.value.toLowerCase();
2193
- this.advance();
2194
- if (val === "true") return true;
2195
- if (val === "false") return false;
2196
- if (val === "null") return null;
2197
- return token.value;
2198
- }
2199
- if (this.check("punctuation", "[")) {
2200
- return this.parseArray();
2201
- }
2202
- if (this.check("punctuation", "{")) {
2203
- return this.parseObject();
2204
- }
2205
- this.advance();
2206
- return token.value;
2207
- }
2208
- /**
2209
- * Parse a property (key: value)
2210
- */
2211
- parseProperty() {
2212
- const key = this.expectIdentifier();
2213
- if (!key) return null;
2214
- if (!this.check("punctuation", ":")) {
2215
- return { key, value: true };
2216
- }
2217
- this.advance();
2218
- const value = this.parseLiteral();
2219
- return { key, value };
2220
- }
2221
- /**
2222
- * Parse array [...]
2223
- */
2224
- parseArray() {
2225
- const arr = [];
2226
- this.expect("punctuation", "[");
2227
- while (!this.check("punctuation", "]") && this.position < this.tokens.length) {
2228
- const token = this.currentToken();
2229
- if (token?.type === "string" || token?.type === "number" || token?.type === "identifier") {
2230
- if (token.type === "number") {
2231
- arr.push(parseFloat(token.value));
2232
- } else {
2233
- arr.push(token.value);
2234
- }
2235
- this.advance();
2236
- } else if (this.check("punctuation", ",")) {
2237
- this.advance();
2238
- } else {
2239
- this.addError(
2240
- this.createError("HS004", `Unexpected token in array: ${token?.type || "unknown"}`, token)
2241
- );
2242
- this.advance();
2243
- }
2244
- }
2245
- this.expect("punctuation", "]");
2246
- return arr;
2247
- }
2248
- /**
2249
- * Parse object {...}
2250
- */
2251
- parseObject() {
2252
- const obj = {};
2253
- this.expect("punctuation", "{");
2254
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
2255
- this.skipNewlines();
2256
- if (this.check("punctuation", "}")) break;
2257
- const prop = this.parseProperty();
2258
- if (prop) {
2259
- obj[prop.key] = prop.value;
2260
- } else {
2261
- const token = this.currentToken();
2262
- this.addError(
2263
- this.createError(
2264
- "HS004",
2265
- `Unexpected token in object: ${token?.type || "unknown"}`,
2266
- token
2267
- )
2268
- );
2269
- this.advance();
2270
- }
2271
- this.skipNewlines();
2272
- if (this.check("punctuation", ",")) {
2273
- this.advance();
2274
- }
2275
- }
2276
- this.expect("punctuation", "}");
2277
- return obj;
2278
- }
2279
- /**
2280
- * Parse position from value
2281
- */
2282
- parsePosition(value) {
2283
- if (Array.isArray(value)) {
2284
- return {
2285
- x: Number(value[0]) || 0,
2286
- y: Number(value[1]) || 0,
2287
- z: Number(value[2]) || 0
2288
- };
2289
- }
2290
- if (typeof value === "object" && value !== null) {
2291
- const v = value;
2292
- return {
2293
- x: Number(v.x) || 0,
2294
- y: Number(v.y) || 0,
2295
- z: Number(v.z) || 0
2296
- };
2297
- }
2298
- return { x: 0, y: 0, z: 0 };
2299
- }
2300
- // Helper methods
2301
- currentToken() {
2302
- return this.tokens[this.position];
2303
- }
2304
- advance() {
2305
- return this.tokens[this.position++];
2306
- }
2307
- check(type, value) {
2308
- const token = this.currentToken();
2309
- if (!token) return false;
2310
- if (token.type !== type) return false;
2311
- if (value !== void 0 && token.value.toLowerCase() !== value.toLowerCase()) return false;
2312
- return true;
2313
- }
2314
- expect(type, value) {
2315
- if (this.check(type, value)) {
2316
- this.advance();
2317
- return true;
2318
- }
2319
- const token = this.currentToken();
2320
- let suggestion;
2321
- if (type === "keyword" && value && token?.type === "identifier") {
2322
- const similar = this.findSimilarKeyword(token.value);
2323
- if (similar) {
2324
- suggestion = `Did you mean '${similar}'?`;
2325
- }
2326
- }
2327
- this.addError(
2328
- this.createError(
2329
- type === "keyword" ? "HS001" : type === "identifier" ? "HS002" : "HS003",
2330
- `Expected ${type}${value ? ` '${value}'` : ""}, got ${token?.type || "EOF"} '${token?.value || ""}'`,
2331
- token,
2332
- suggestion
2333
- )
2334
- );
2335
- return false;
2336
- }
2337
- expectIdentifier() {
2338
- const token = this.currentToken();
2339
- if (token && (token.type === "identifier" || token.type === "keyword")) {
2340
- this.advance();
2341
- return token.value;
2342
- }
2343
- this.addError(
2344
- this.createError(
2345
- "HS002",
2346
- `Expected identifier, got ${token?.type || "EOF"}`,
2347
- token,
2348
- token?.type === "number" ? "Identifiers cannot start with a number" : void 0
2349
- )
2350
- );
2351
- return null;
2352
- }
2353
- /**
2354
- * Expect an identifier OR a string literal for named declarations
2355
- * Allows both: composition MyScene { } and composition "MyScene" { }
2356
- */
2357
- expectName() {
2358
- const token = this.currentToken();
2359
- if (token?.type === "identifier" || token?.type === "keyword") {
2360
- this.advance();
2361
- return token.value;
2362
- }
2363
- if (token?.type === "string") {
2364
- this.advance();
2365
- const val = token.value;
2366
- if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
2367
- return val.slice(1, -1);
2368
- }
2369
- return val;
2370
- }
2371
- this.addError(
2372
- this.createError(
2373
- "HS002",
2374
- `Expected name (identifier or string), got ${token?.type || "EOF"}`,
2375
- token
2376
- )
2377
- );
2378
- return null;
2379
- }
2380
- /**
2381
- * Parse animate command: animate target property: "..." from: 0 to: 1 duration: 1000
2382
- */
2383
- parseAnimate() {
2384
- this.expect("keyword", "animate");
2385
- const target = this.expectIdentifier();
2386
- if (!target) return null;
2387
- const properties = {};
2388
- while (this.position < this.tokens.length) {
2389
- this.skipNewlines();
2390
- const t = this.currentToken();
2391
- if (!t || t.type === "newline" || t.type === "keyword" && this.keywordSet.has(t.value.toLowerCase()))
2392
- break;
2393
- const prop = this.parseProperty();
2394
- if (prop) {
2395
- properties[prop.key] = prop.value;
2396
- } else {
2397
- break;
2398
- }
2399
- }
2400
- return {
2401
- type: "expression-statement",
2402
- expression: `animate("${target}", ${JSON.stringify(properties)})`,
2403
- position: { x: 0, y: 0, z: 0 }
2404
- };
2405
- }
2406
- /**
2407
- * Parse modify command: modify target { prop: value }
2408
- */
2409
- parseModify() {
2410
- this.expect("keyword", "modify");
2411
- const target = this.expectIdentifier();
2412
- if (!target) return null;
2413
- const properties = {};
2414
- if (this.check("punctuation", "{")) {
2415
- this.advance();
2416
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
2417
- this.skipNewlines();
2418
- if (this.check("punctuation", "}")) break;
2419
- const prop = this.parseProperty();
2420
- if (prop) {
2421
- properties[prop.key] = prop.value;
2422
- }
2423
- this.skipNewlines();
2424
- }
2425
- this.expect("punctuation", "}");
2426
- }
2427
- return {
2428
- type: "expression-statement",
2429
- expression: `modify("${target}", ${JSON.stringify(properties)})`,
2430
- position: { x: 0, y: 0, z: 0 }
2431
- };
2432
- }
2433
- /**
2434
- * Parse UI Element: ui2d dashboard#id { ... }
2435
- */
2436
- parseUIElement() {
2437
- const typeToken = this.currentToken();
2438
- if (!typeToken) return null;
2439
- const elementType = typeToken.value;
2440
- this.advance();
2441
- let elementId = `${elementType}_${Date.now()}`;
2442
- const token = this.currentToken();
2443
- if (token?.type === "punctuation" && token.value === "#") {
2444
- this.advance();
2445
- const idToken = this.currentToken();
2446
- if (idToken) {
2447
- elementId = idToken.value;
2448
- this.advance();
2449
- }
2450
- } else if (token?.type === "identifier" && token.value.startsWith("#")) {
2451
- elementId = token.value.slice(1) || elementId;
2452
- this.advance();
2453
- }
2454
- const properties = {};
2455
- if (this.check("punctuation", "{")) {
2456
- this.advance();
2457
- while (!this.check("punctuation", "}") && this.position < this.tokens.length) {
2458
- this.skipNewlines();
2459
- if (this.check("punctuation", "}")) break;
2460
- const prop = this.parseProperty();
2461
- if (prop) {
2462
- properties[prop.key] = prop.value;
2463
- }
2464
- this.skipNewlines();
2465
- }
2466
- this.expect("punctuation", "}");
2467
- }
2468
- return {
2469
- type: "ui2d",
2470
- name: elementType,
2471
- properties: { id: elementId, ...properties },
2472
- position: { x: 0, y: 0, z: 0 }
2473
- };
2474
- }
2475
- /**
2476
- * Parse settings command: settings
2477
- */
2478
- parseSettings() {
2479
- this.expect("keyword", "settings");
2480
- return {
2481
- type: "expression-statement",
2482
- expression: "showSettings()",
2483
- position: { x: 0, y: 0, z: 0 }
2484
- };
2485
- }
2486
- parseChat() {
2487
- this.expect("keyword", "chat");
2488
- return {
2489
- type: "expression-statement",
2490
- expression: "openChat()",
2491
- position: { x: 0, y: 0, z: 0 }
2492
- };
2493
- }
2494
- /**
2495
- * Parse a condition string into a structured TypeGuardExpression if applicable,
2496
- * otherwise returns the string as-is.
2497
- */
2498
- parseConditionExpression(condition) {
2499
- const isPattern = /^([a-zA-Z_][a-zA-Z0-9_]*)\s+is\s+["']([^"']+)["']$/;
2500
- const match = condition.match(isPattern);
2501
- if (match) {
2502
- return {
2503
- type: "type-guard",
2504
- subject: match[1],
2505
- guardType: match[2],
2506
- line: 0,
2507
- // Simplified for now
2508
- column: 0
2509
- };
2510
- }
2511
- return condition;
2512
- }
2513
- skipNewlines() {
2514
- while (this.currentToken()?.type === "newline") {
2515
- this.advance();
2516
- }
2517
- }
2518
- };
2519
-
2520
- export { ERROR_CODES, HoloScriptCodeParser, ParserPools };
2521
- //# sourceMappingURL=chunk-EPWRXL6S.js.map
2522
- //# sourceMappingURL=chunk-EPWRXL6S.js.map