@holoscript/core 1.0.0-alpha.1 → 2.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 (127) hide show
  1. package/package.json +10 -9
  2. package/src/HoloScript2DParser.js +227 -0
  3. package/src/HoloScript2DParser.ts +5 -0
  4. package/src/HoloScriptCodeParser.js +1102 -0
  5. package/src/HoloScriptCodeParser.ts +145 -20
  6. package/src/HoloScriptDebugger.js +458 -0
  7. package/src/HoloScriptParser.js +338 -0
  8. package/src/HoloScriptPlusParser.js +371 -0
  9. package/src/HoloScriptPlusParser.ts +543 -0
  10. package/src/HoloScriptRuntime.js +1399 -0
  11. package/src/HoloScriptRuntime.test.js +351 -0
  12. package/src/HoloScriptRuntime.ts +257 -3
  13. package/src/HoloScriptTypeChecker.js +356 -0
  14. package/src/__tests__/GraphicsServices.test.js +357 -0
  15. package/src/__tests__/GraphicsServices.test.ts +427 -0
  16. package/src/__tests__/HoloScriptPlusParser.test.js +317 -0
  17. package/src/__tests__/HoloScriptPlusParser.test.ts +392 -0
  18. package/src/__tests__/integration.test.js +336 -0
  19. package/src/__tests__/performance.bench.js +218 -0
  20. package/src/__tests__/type-checker.test.js +60 -0
  21. package/src/__tests__/type-checker.test.ts +73 -0
  22. package/src/index.js +217 -0
  23. package/src/index.ts +158 -18
  24. package/src/interop/Interoperability.js +413 -0
  25. package/src/interop/Interoperability.ts +494 -0
  26. package/src/logger.js +42 -0
  27. package/src/parser/EnhancedParser.js +205 -0
  28. package/src/parser/EnhancedParser.ts +251 -0
  29. package/src/parser/HoloScriptPlusParser.js +928 -0
  30. package/src/parser/HoloScriptPlusParser.ts +1089 -0
  31. package/src/runtime/HoloScriptPlusRuntime.js +674 -0
  32. package/src/runtime/HoloScriptPlusRuntime.ts +861 -0
  33. package/src/runtime/PerformanceTelemetry.js +323 -0
  34. package/src/runtime/PerformanceTelemetry.ts +467 -0
  35. package/src/runtime/RuntimeOptimization.js +361 -0
  36. package/src/runtime/RuntimeOptimization.ts +416 -0
  37. package/src/services/HololandGraphicsPipelineService.js +506 -0
  38. package/src/services/HololandGraphicsPipelineService.ts +662 -0
  39. package/src/services/PlatformPerformanceOptimizer.js +356 -0
  40. package/src/services/PlatformPerformanceOptimizer.ts +503 -0
  41. package/src/state/ReactiveState.js +427 -0
  42. package/src/state/ReactiveState.ts +572 -0
  43. package/src/tools/DeveloperExperience.js +376 -0
  44. package/src/tools/DeveloperExperience.ts +438 -0
  45. package/src/traits/AIDriverTrait.js +322 -0
  46. package/src/traits/AIDriverTrait.test.js +329 -0
  47. package/src/traits/AIDriverTrait.test.ts +357 -0
  48. package/src/traits/AIDriverTrait.ts +474 -0
  49. package/src/traits/LightingTrait.js +313 -0
  50. package/src/traits/LightingTrait.test.js +410 -0
  51. package/src/traits/LightingTrait.test.ts +462 -0
  52. package/src/traits/LightingTrait.ts +505 -0
  53. package/src/traits/MaterialTrait.js +194 -0
  54. package/src/traits/MaterialTrait.test.js +286 -0
  55. package/src/traits/MaterialTrait.test.ts +329 -0
  56. package/src/traits/MaterialTrait.ts +324 -0
  57. package/src/traits/RenderingTrait.js +356 -0
  58. package/src/traits/RenderingTrait.test.js +363 -0
  59. package/src/traits/RenderingTrait.test.ts +427 -0
  60. package/src/traits/RenderingTrait.ts +555 -0
  61. package/src/traits/VRTraitSystem.js +740 -0
  62. package/src/traits/VRTraitSystem.ts +1040 -0
  63. package/src/traits/VoiceInputTrait.js +284 -0
  64. package/src/traits/VoiceInputTrait.test.js +226 -0
  65. package/src/traits/VoiceInputTrait.test.ts +252 -0
  66. package/src/traits/VoiceInputTrait.ts +401 -0
  67. package/src/types/AdvancedTypeSystem.js +226 -0
  68. package/src/types/AdvancedTypeSystem.ts +494 -0
  69. package/src/types/HoloScriptPlus.d.ts +853 -0
  70. package/src/types.js +6 -0
  71. package/src/types.ts +96 -1
  72. package/tsconfig.json +1 -1
  73. package/tsup.config.d.ts +2 -0
  74. package/tsup.config.js +18 -0
  75. package/LICENSE +0 -21
  76. package/dist/chunk-3X2EGU7Z.cjs +0 -52
  77. package/dist/chunk-3X2EGU7Z.cjs.map +0 -1
  78. package/dist/chunk-723TPVHD.js +0 -1074
  79. package/dist/chunk-723TPVHD.js.map +0 -1
  80. package/dist/chunk-EOKNAVDO.cjs +0 -424
  81. package/dist/chunk-EOKNAVDO.cjs.map +0 -1
  82. package/dist/chunk-HQZ3HUMY.js +0 -1087
  83. package/dist/chunk-HQZ3HUMY.js.map +0 -1
  84. package/dist/chunk-KWYIVRIH.js +0 -344
  85. package/dist/chunk-KWYIVRIH.js.map +0 -1
  86. package/dist/chunk-LKH4ZAN6.js +0 -421
  87. package/dist/chunk-LKH4ZAN6.js.map +0 -1
  88. package/dist/chunk-SATNCODL.js +0 -45
  89. package/dist/chunk-SATNCODL.js.map +0 -1
  90. package/dist/chunk-VMZN4EVR.cjs +0 -347
  91. package/dist/chunk-VMZN4EVR.cjs.map +0 -1
  92. package/dist/chunk-VV3UUUYP.cjs +0 -1089
  93. package/dist/chunk-VV3UUUYP.cjs.map +0 -1
  94. package/dist/chunk-XRYTSQHZ.cjs +0 -1076
  95. package/dist/chunk-XRYTSQHZ.cjs.map +0 -1
  96. package/dist/debugger.cjs +0 -19
  97. package/dist/debugger.cjs.map +0 -1
  98. package/dist/debugger.d.cts +0 -171
  99. package/dist/debugger.d.ts +0 -171
  100. package/dist/debugger.js +0 -6
  101. package/dist/debugger.js.map +0 -1
  102. package/dist/index.cjs +0 -755
  103. package/dist/index.cjs.map +0 -1
  104. package/dist/index.d.cts +0 -169
  105. package/dist/index.d.ts +0 -169
  106. package/dist/index.js +0 -699
  107. package/dist/index.js.map +0 -1
  108. package/dist/parser.cjs +0 -13
  109. package/dist/parser.cjs.map +0 -1
  110. package/dist/parser.d.cts +0 -154
  111. package/dist/parser.d.ts +0 -154
  112. package/dist/parser.js +0 -4
  113. package/dist/parser.js.map +0 -1
  114. package/dist/runtime.cjs +0 -13
  115. package/dist/runtime.cjs.map +0 -1
  116. package/dist/runtime.d.cts +0 -147
  117. package/dist/runtime.d.ts +0 -147
  118. package/dist/runtime.js +0 -4
  119. package/dist/runtime.js.map +0 -1
  120. package/dist/type-checker.cjs +0 -16
  121. package/dist/type-checker.cjs.map +0 -1
  122. package/dist/type-checker.d.cts +0 -105
  123. package/dist/type-checker.d.ts +0 -105
  124. package/dist/type-checker.js +0 -3
  125. package/dist/type-checker.js.map +0 -1
  126. package/dist/types-WQSk1Qs2.d.cts +0 -238
  127. package/dist/types-WQSk1Qs2.d.ts +0 -238
@@ -1,1087 +0,0 @@
1
- import { logger } from './chunk-SATNCODL.js';
2
-
3
- // src/HoloScriptRuntime.ts
4
- var RUNTIME_SECURITY_LIMITS = {
5
- maxExecutionDepth: 50,
6
- maxTotalNodes: 1e3,
7
- maxExecutionTimeMs: 5e3,
8
- maxParticlesPerSystem: 1e3,
9
- maxCallStackDepth: 100
10
- };
11
- var HoloScriptRuntime = class {
12
- constructor() {
13
- this.particleSystems = /* @__PURE__ */ new Map();
14
- this.executionHistory = [];
15
- this.startTime = 0;
16
- this.nodeCount = 0;
17
- this.callStack = [];
18
- this.eventHandlers = /* @__PURE__ */ new Map();
19
- this.animations = /* @__PURE__ */ new Map();
20
- this.uiElements = /* @__PURE__ */ new Map();
21
- this.context = this.createEmptyContext();
22
- this.currentScope = { variables: this.context.variables };
23
- this.builtinFunctions = this.initBuiltins();
24
- }
25
- /**
26
- * Initialize built-in functions
27
- */
28
- initBuiltins() {
29
- const builtins = /* @__PURE__ */ new Map();
30
- builtins.set("show", (args) => {
31
- const target = String(args[0]);
32
- const element = this.uiElements.get(target);
33
- if (element) element.visible = true;
34
- const hologram = this.context.hologramState.get(target);
35
- if (hologram) {
36
- this.createParticleEffect(`${target}_show`, { x: 0, y: 0, z: 0 }, hologram.color, 15);
37
- }
38
- logger.info("show", { target });
39
- return { shown: target };
40
- });
41
- builtins.set("hide", (args) => {
42
- const target = String(args[0]);
43
- const element = this.uiElements.get(target);
44
- if (element) element.visible = false;
45
- logger.info("hide", { target });
46
- return { hidden: target };
47
- });
48
- builtins.set("pulse", (args) => {
49
- const target = String(args[0]);
50
- const options = args[1] || {};
51
- const duration = Number(options.duration) || 1e3;
52
- const color = String(options.color || "#ffffff");
53
- const position = this.context.spatialMemory.get(target) || { x: 0, y: 0, z: 0 };
54
- this.createParticleEffect(`${target}_pulse`, position, color, 30);
55
- return { pulsing: target, duration };
56
- });
57
- builtins.set("animate", (args) => {
58
- const target = String(args[0]);
59
- const options = args[1] || {};
60
- const animation = {
61
- target,
62
- property: String(options.property || "position.y"),
63
- from: Number(options.from || 0),
64
- to: Number(options.to || 1),
65
- duration: Number(options.duration || 1e3),
66
- startTime: Date.now(),
67
- easing: String(options.easing || "linear"),
68
- loop: Boolean(options.loop),
69
- yoyo: Boolean(options.yoyo)
70
- };
71
- this.animations.set(`${target}_${animation.property}`, animation);
72
- return { animating: target, animation };
73
- });
74
- builtins.set("spawn", (args) => {
75
- const target = String(args[0]);
76
- const position = args[1] || { x: 0, y: 0, z: 0 };
77
- this.context.spatialMemory.set(target, position);
78
- this.createParticleEffect(`${target}_spawn`, position, "#00ff00", 25);
79
- return { spawned: target, at: position };
80
- });
81
- builtins.set("move", (args) => {
82
- const target = String(args[0]);
83
- const position = args[1] || { x: 0, y: 0, z: 0 };
84
- const current = this.context.spatialMemory.get(target);
85
- if (current) {
86
- this.context.spatialMemory.set(target, position);
87
- this.createConnectionStream(target, `${target}_dest`, current, position, "move");
88
- }
89
- return { moved: target, to: position };
90
- });
91
- builtins.set("set", (args) => {
92
- const target = String(args[0]);
93
- const value = args[1];
94
- this.setVariable(target, value);
95
- return { set: target, value };
96
- });
97
- builtins.set("get", (args) => {
98
- const target = String(args[0]);
99
- return this.getVariable(target);
100
- });
101
- builtins.set("add", (args) => Number(args[0]) + Number(args[1]));
102
- builtins.set("subtract", (args) => Number(args[0]) - Number(args[1]));
103
- builtins.set("multiply", (args) => Number(args[0]) * Number(args[1]));
104
- builtins.set("divide", (args) => Number(args[1]) !== 0 ? Number(args[0]) / Number(args[1]) : 0);
105
- builtins.set("mod", (args) => Number(args[0]) % Number(args[1]));
106
- builtins.set("abs", (args) => Math.abs(Number(args[0])));
107
- builtins.set("floor", (args) => Math.floor(Number(args[0])));
108
- builtins.set("ceil", (args) => Math.ceil(Number(args[0])));
109
- builtins.set("round", (args) => Math.round(Number(args[0])));
110
- builtins.set("min", (args) => Math.min(...args.map(Number)));
111
- builtins.set("max", (args) => Math.max(...args.map(Number)));
112
- builtins.set("random", () => Math.random());
113
- builtins.set("concat", (args) => args.map(String).join(""));
114
- builtins.set("length", (args) => {
115
- const val = args[0];
116
- if (typeof val === "string") return val.length;
117
- if (Array.isArray(val)) return val.length;
118
- return 0;
119
- });
120
- builtins.set("substring", (args) => String(args[0]).substring(Number(args[1]), Number(args[2])));
121
- builtins.set("uppercase", (args) => String(args[0]).toUpperCase());
122
- builtins.set("lowercase", (args) => String(args[0]).toLowerCase());
123
- builtins.set("push", (args) => {
124
- const arr = args[0];
125
- if (Array.isArray(arr)) {
126
- arr.push(args[1]);
127
- return arr;
128
- }
129
- return [args[0], args[1]];
130
- });
131
- builtins.set("pop", (args) => {
132
- const arr = args[0];
133
- if (Array.isArray(arr)) return arr.pop();
134
- return void 0;
135
- });
136
- builtins.set("at", (args) => {
137
- const arr = args[0];
138
- const index = Number(args[1]);
139
- if (Array.isArray(arr)) return arr[index];
140
- return void 0;
141
- });
142
- builtins.set("log", (args) => {
143
- logger.info("HoloScript log", { args });
144
- return args[0];
145
- });
146
- builtins.set("print", (args) => {
147
- const message = args.map(String).join(" ");
148
- logger.info("print", { message });
149
- return message;
150
- });
151
- builtins.set("typeof", (args) => typeof args[0]);
152
- builtins.set("isArray", (args) => Array.isArray(args[0]));
153
- builtins.set("isNumber", (args) => typeof args[0] === "number" && !isNaN(args[0]));
154
- builtins.set("isString", (args) => typeof args[0] === "string");
155
- return builtins;
156
- }
157
- /**
158
- * Execute a single AST node
159
- */
160
- async executeNode(node) {
161
- const startTime = Date.now();
162
- try {
163
- this.context.executionStack.push(node);
164
- let result;
165
- switch (node.type) {
166
- case "orb":
167
- result = await this.executeOrb(node);
168
- break;
169
- case "method":
170
- case "function":
171
- result = await this.executeFunction(node);
172
- break;
173
- case "connection":
174
- result = await this.executeConnection(node);
175
- break;
176
- case "gate":
177
- result = await this.executeGate(node);
178
- break;
179
- case "stream":
180
- result = await this.executeStream(node);
181
- break;
182
- case "execute":
183
- case "call":
184
- result = await this.executeCall(node);
185
- break;
186
- case "debug":
187
- result = await this.executeDebug(node);
188
- break;
189
- case "visualize":
190
- result = await this.executeVisualize(node);
191
- break;
192
- case "2d-element":
193
- result = await this.executeUIElement(node);
194
- break;
195
- case "nexus":
196
- case "building":
197
- result = await this.executeStructure(node);
198
- break;
199
- case "assignment":
200
- result = await this.executeAssignment(node);
201
- break;
202
- case "return":
203
- result = await this.executeReturn(node);
204
- break;
205
- default:
206
- result = {
207
- success: false,
208
- error: `Unknown node type: ${node.type}`,
209
- executionTime: Date.now() - startTime
210
- };
211
- }
212
- result.executionTime = Date.now() - startTime;
213
- this.executionHistory.push(result);
214
- this.context.executionStack.pop();
215
- return result;
216
- } catch (error) {
217
- const execTime = Date.now() - startTime;
218
- const errorResult = {
219
- success: false,
220
- error: error instanceof Error ? error.message : String(error),
221
- executionTime: execTime
222
- };
223
- this.executionHistory.push(errorResult);
224
- this.context.executionStack.pop();
225
- return errorResult;
226
- }
227
- }
228
- /**
229
- * Execute multiple nodes in sequence
230
- */
231
- async executeProgram(nodes, depth = 0) {
232
- if (depth === 0) {
233
- this.startTime = Date.now();
234
- this.nodeCount = 0;
235
- }
236
- if (depth > RUNTIME_SECURITY_LIMITS.maxExecutionDepth) {
237
- logger.error("Max execution depth exceeded", { depth });
238
- return [{
239
- success: false,
240
- error: `Max execution depth exceeded (${RUNTIME_SECURITY_LIMITS.maxExecutionDepth})`,
241
- executionTime: 0
242
- }];
243
- }
244
- const results = [];
245
- for (const node of nodes) {
246
- this.nodeCount++;
247
- if (this.nodeCount > RUNTIME_SECURITY_LIMITS.maxTotalNodes) {
248
- logger.error("Max total nodes exceeded", { count: this.nodeCount });
249
- results.push({
250
- success: false,
251
- error: "Max total nodes exceeded",
252
- executionTime: Date.now() - this.startTime
253
- });
254
- break;
255
- }
256
- if (Date.now() - this.startTime > RUNTIME_SECURITY_LIMITS.maxExecutionTimeMs) {
257
- logger.error("Execution timeout", { duration: Date.now() - this.startTime });
258
- results.push({
259
- success: false,
260
- error: "Execution timeout",
261
- executionTime: Date.now() - this.startTime
262
- });
263
- break;
264
- }
265
- const result = await this.executeNode(node);
266
- results.push(result);
267
- if (!result.success && node.type !== "visualize") {
268
- break;
269
- }
270
- if (node.type === "return") {
271
- break;
272
- }
273
- }
274
- return results;
275
- }
276
- /**
277
- * Call a function with arguments
278
- */
279
- async callFunction(name, args = []) {
280
- const builtin = this.builtinFunctions.get(name);
281
- if (builtin) {
282
- try {
283
- const result = builtin(args);
284
- return {
285
- success: true,
286
- output: result
287
- };
288
- } catch (error) {
289
- return {
290
- success: false,
291
- error: `Built-in function ${name} failed: ${error}`
292
- };
293
- }
294
- }
295
- const func = this.context.functions.get(name);
296
- if (!func) {
297
- return {
298
- success: false,
299
- error: `Function '${name}' not found`
300
- };
301
- }
302
- if (this.callStack.length >= RUNTIME_SECURITY_LIMITS.maxCallStackDepth) {
303
- return {
304
- success: false,
305
- error: `Max call stack depth exceeded (${RUNTIME_SECURITY_LIMITS.maxCallStackDepth})`
306
- };
307
- }
308
- const parentScope = this.currentScope;
309
- this.currentScope = {
310
- variables: /* @__PURE__ */ new Map(),
311
- parent: parentScope
312
- };
313
- func.parameters.forEach((param, index) => {
314
- const value = index < args.length ? args[index] : param.defaultValue;
315
- this.currentScope.variables.set(param.name, value);
316
- });
317
- this.callStack.push(name);
318
- let returnValue = void 0;
319
- try {
320
- const results = await this.executeProgram(func.body, this.callStack.length);
321
- const lastResult = results[results.length - 1];
322
- if (lastResult?.output !== void 0) {
323
- returnValue = lastResult.output;
324
- }
325
- this.createExecutionEffect(name, func.position || { x: 0, y: 0, z: 0 });
326
- return {
327
- success: results.every((r) => r.success),
328
- output: returnValue,
329
- hologram: func.hologram,
330
- spatialPosition: func.position
331
- };
332
- } finally {
333
- this.currentScope = parentScope;
334
- this.callStack.pop();
335
- }
336
- }
337
- /**
338
- * Set a variable in current scope
339
- */
340
- setVariable(name, value) {
341
- if (name.includes(".")) {
342
- const parts = name.split(".");
343
- const objName = parts[0];
344
- const propPath = parts.slice(1);
345
- let obj = this.getVariable(objName);
346
- if (obj === void 0 || typeof obj !== "object" || obj === null) {
347
- obj = {};
348
- this.currentScope.variables.set(objName, obj);
349
- }
350
- let current = obj;
351
- for (let i = 0; i < propPath.length - 1; i++) {
352
- if (current[propPath[i]] === void 0 || typeof current[propPath[i]] !== "object") {
353
- current[propPath[i]] = {};
354
- }
355
- current = current[propPath[i]];
356
- }
357
- current[propPath[propPath.length - 1]] = value;
358
- } else {
359
- this.currentScope.variables.set(name, value);
360
- }
361
- }
362
- /**
363
- * Get a variable from scope chain
364
- */
365
- getVariable(name) {
366
- if (name.includes(".")) {
367
- const parts = name.split(".");
368
- let value = this.getVariable(parts[0]);
369
- for (let i = 1; i < parts.length && value !== void 0; i++) {
370
- if (typeof value === "object" && value !== null) {
371
- value = value[parts[i]];
372
- } else {
373
- return void 0;
374
- }
375
- }
376
- return value;
377
- }
378
- let scope = this.currentScope;
379
- while (scope) {
380
- if (scope.variables.has(name)) {
381
- return scope.variables.get(name);
382
- }
383
- scope = scope.parent;
384
- }
385
- return this.context.variables.get(name);
386
- }
387
- /**
388
- * Evaluate an expression
389
- */
390
- evaluateExpression(expr) {
391
- if (!expr || typeof expr !== "string") return expr;
392
- expr = expr.trim();
393
- const suspicious = ["eval", "process", "require", "__proto__", "constructor", "Function"];
394
- if (suspicious.some((kw) => expr.toLowerCase().includes(kw))) {
395
- logger.warn("Suspicious expression blocked", { expr });
396
- return void 0;
397
- }
398
- if (expr.startsWith('"') && expr.endsWith('"') || expr.startsWith("'") && expr.endsWith("'")) {
399
- return expr.slice(1, -1);
400
- }
401
- if (/^-?\d+(\.\d+)?$/.test(expr)) {
402
- return parseFloat(expr);
403
- }
404
- if (expr === "true") return true;
405
- if (expr === "false") return false;
406
- if (expr === "null") return null;
407
- if (expr === "undefined") return void 0;
408
- if (expr.startsWith("[") && expr.endsWith("]")) {
409
- const inner = expr.slice(1, -1);
410
- if (!inner.trim()) return [];
411
- const elements = this.splitByComma(inner);
412
- return elements.map((e) => this.evaluateExpression(e.trim()));
413
- }
414
- if (expr.startsWith("{") && expr.endsWith("}")) {
415
- const inner = expr.slice(1, -1);
416
- if (!inner.trim()) return {};
417
- const pairs = this.splitByComma(inner);
418
- const obj = {};
419
- for (const pair of pairs) {
420
- const colonIndex = pair.indexOf(":");
421
- if (colonIndex > 0) {
422
- const key = pair.slice(0, colonIndex).trim();
423
- const value = pair.slice(colonIndex + 1).trim();
424
- obj[key] = this.evaluateExpression(value);
425
- }
426
- }
427
- return obj;
428
- }
429
- const funcMatch = expr.match(/^(\w+)\s*\((.*)?\)$/);
430
- if (funcMatch) {
431
- const [, funcName, argsStr] = funcMatch;
432
- const args = argsStr ? this.splitByComma(argsStr).map((a) => this.evaluateExpression(a.trim())) : [];
433
- const builtin = this.builtinFunctions.get(funcName);
434
- if (builtin) {
435
- return builtin(args);
436
- }
437
- if (this.context.functions.has(funcName)) {
438
- return { __holoCall: funcName, args };
439
- }
440
- return void 0;
441
- }
442
- const binaryOps = [
443
- { pattern: /(.+)\s*\+\s*(.+)/, op: (a, b) => Number(a) + Number(b) },
444
- { pattern: /(.+)\s*-\s*(.+)/, op: (a, b) => Number(a) - Number(b) },
445
- { pattern: /(.+)\s*\*\s*(.+)/, op: (a, b) => Number(a) * Number(b) },
446
- { pattern: /(.+)\s*\/\s*(.+)/, op: (a, b) => Number(b) !== 0 ? Number(a) / Number(b) : 0 },
447
- { pattern: /(.+)\s*%\s*(.+)/, op: (a, b) => Number(a) % Number(b) }
448
- ];
449
- for (const { pattern, op } of binaryOps) {
450
- const match = expr.match(pattern);
451
- if (match) {
452
- const left = this.evaluateExpression(match[1]);
453
- const right = this.evaluateExpression(match[2]);
454
- return op(left, right);
455
- }
456
- }
457
- return this.getVariable(expr);
458
- }
459
- /**
460
- * Split string by comma, respecting nesting
461
- */
462
- splitByComma(str) {
463
- const parts = [];
464
- let current = "";
465
- let depth = 0;
466
- let inString = false;
467
- let stringChar = "";
468
- for (let i = 0; i < str.length; i++) {
469
- const char = str[i];
470
- if (!inString && (char === '"' || char === "'")) {
471
- inString = true;
472
- stringChar = char;
473
- } else if (inString && char === stringChar && str[i - 1] !== "\\") {
474
- inString = false;
475
- }
476
- if (!inString) {
477
- if (char === "(" || char === "[" || char === "{") depth++;
478
- if (char === ")" || char === "]" || char === "}") depth--;
479
- if (char === "," && depth === 0) {
480
- parts.push(current.trim());
481
- current = "";
482
- continue;
483
- }
484
- }
485
- current += char;
486
- }
487
- if (current.trim()) {
488
- parts.push(current.trim());
489
- }
490
- return parts;
491
- }
492
- // ============================================================================
493
- // Node Executors
494
- // ============================================================================
495
- async executeOrb(node) {
496
- if (node.position) {
497
- this.context.spatialMemory.set(node.name, node.position);
498
- }
499
- const orbData = {
500
- __type: "orb",
501
- name: node.name,
502
- properties: { ...node.properties },
503
- position: node.position || { x: 0, y: 0, z: 0 },
504
- hologram: node.hologram,
505
- created: Date.now(),
506
- // Methods bound to this orb
507
- show: () => this.builtinFunctions.get("show")([node.name]),
508
- hide: () => this.builtinFunctions.get("hide")([node.name]),
509
- pulse: (opts) => this.builtinFunctions.get("pulse")([node.name, opts])
510
- };
511
- this.context.variables.set(node.name, orbData);
512
- if (node.hologram) {
513
- this.context.hologramState.set(node.name, node.hologram);
514
- }
515
- this.createParticleEffect(`${node.name}_creation`, node.position || { x: 0, y: 0, z: 0 }, "#00ffff", 20);
516
- logger.info("Orb created", { name: node.name, properties: Object.keys(node.properties) });
517
- return {
518
- success: true,
519
- output: orbData,
520
- hologram: node.hologram,
521
- spatialPosition: node.position
522
- };
523
- }
524
- async executeFunction(node) {
525
- this.context.functions.set(node.name, node);
526
- const hologram = {
527
- shape: "cube",
528
- color: "#ff6b35",
529
- size: 1.5,
530
- glow: true,
531
- interactive: true,
532
- ...node.hologram
533
- };
534
- this.context.hologramState.set(node.name, hologram);
535
- logger.info("Function defined", { name: node.name, params: node.parameters.map((p) => p.name) });
536
- return {
537
- success: true,
538
- output: `Function '${node.name}' defined with ${node.parameters.length} parameter(s)`,
539
- hologram,
540
- spatialPosition: node.position
541
- };
542
- }
543
- async executeConnection(node) {
544
- this.context.connections.push(node);
545
- const fromPos = this.context.spatialMemory.get(node.from);
546
- const toPos = this.context.spatialMemory.get(node.to);
547
- if (fromPos && toPos) {
548
- this.createConnectionStream(node.from, node.to, fromPos, toPos, node.dataType);
549
- }
550
- if (node.bidirectional) {
551
- this.on(`${node.from}.changed`, async (data) => {
552
- this.setVariable(node.to, data);
553
- this.emit(`${node.to}.changed`, data);
554
- });
555
- this.on(`${node.to}.changed`, async (data) => {
556
- this.setVariable(node.from, data);
557
- this.emit(`${node.from}.changed`, data);
558
- });
559
- }
560
- logger.info("Connection created", { from: node.from, to: node.to, dataType: node.dataType });
561
- return {
562
- success: true,
563
- output: `Connected '${node.from}' to '${node.to}' (${node.dataType})`,
564
- hologram: {
565
- shape: "cylinder",
566
- color: this.getDataTypeColor(node.dataType),
567
- size: 0.1,
568
- glow: true,
569
- interactive: false
570
- }
571
- };
572
- }
573
- async executeGate(node) {
574
- try {
575
- const condition = this.evaluateCondition(node.condition);
576
- const path = condition ? node.truePath : node.falsePath;
577
- logger.info("Gate evaluation", { condition: node.condition, result: condition });
578
- if (path.length > 0) {
579
- await this.executeProgram(path, this.callStack.length + 1);
580
- }
581
- return {
582
- success: true,
583
- output: `Gate: took ${condition ? "true" : "false"} path`,
584
- hologram: {
585
- shape: "pyramid",
586
- color: condition ? "#00ff00" : "#ff0000",
587
- size: 1,
588
- glow: true,
589
- interactive: true
590
- }
591
- };
592
- } catch (error) {
593
- return {
594
- success: false,
595
- error: `Gate execution failed: ${error}`
596
- };
597
- }
598
- }
599
- async executeStream(node) {
600
- let data = this.getVariable(node.source);
601
- logger.info("Stream processing", { name: node.name, source: node.source, transforms: node.transformations.length });
602
- for (const transform of node.transformations) {
603
- data = await this.applyTransformation(data, transform);
604
- }
605
- this.setVariable(`${node.name}_result`, data);
606
- this.createFlowingStream(node.name, node.position || { x: 0, y: 0, z: 0 }, data);
607
- return {
608
- success: true,
609
- output: `Stream '${node.name}' processed ${Array.isArray(data) ? data.length : 1} item(s)`,
610
- hologram: node.hologram,
611
- spatialPosition: node.position
612
- };
613
- }
614
- async executeCall(node) {
615
- const funcName = node.target || "";
616
- const args = node.args || [];
617
- return this.callFunction(funcName, args);
618
- }
619
- async executeDebug(node) {
620
- const debugInfo = {
621
- variables: Object.fromEntries(this.currentScope.variables),
622
- contextVariables: Object.fromEntries(this.context.variables),
623
- functions: Array.from(this.context.functions.keys()),
624
- connections: this.context.connections.length,
625
- callStack: [...this.callStack],
626
- uiElements: Array.from(this.uiElements.keys()),
627
- animations: Array.from(this.animations.keys()),
628
- executionHistory: this.executionHistory.slice(-10)
629
- };
630
- const debugOrb = {
631
- shape: "pyramid",
632
- color: "#ff1493",
633
- size: 0.8,
634
- glow: true,
635
- interactive: true
636
- };
637
- this.context.hologramState.set(`debug_${node.target || "program"}`, debugOrb);
638
- logger.info("Debug info", debugInfo);
639
- return {
640
- success: true,
641
- output: debugInfo,
642
- hologram: debugOrb
643
- };
644
- }
645
- async executeVisualize(node) {
646
- const target = node.target || "";
647
- const data = this.getVariable(target);
648
- if (data === void 0) {
649
- return {
650
- success: false,
651
- error: `No data found for '${target}'`
652
- };
653
- }
654
- const visHologram = {
655
- shape: "cylinder",
656
- color: "#32cd32",
657
- size: 1.5,
658
- glow: true,
659
- interactive: true
660
- };
661
- this.createDataVisualization(target, data, node.position || { x: 0, y: 0, z: 0 });
662
- return {
663
- success: true,
664
- output: { visualizing: target, data },
665
- hologram: visHologram
666
- };
667
- }
668
- async executeUIElement(node) {
669
- const element = {
670
- type: node.elementType,
671
- name: node.name,
672
- properties: { ...node.properties },
673
- visible: true,
674
- enabled: true
675
- };
676
- if (node.elementType === "textinput") {
677
- element.value = node.properties.value || "";
678
- } else if (node.elementType === "slider") {
679
- element.value = node.properties.value || node.properties.min || 0;
680
- } else if (node.elementType === "toggle") {
681
- element.value = node.properties.checked || false;
682
- }
683
- this.uiElements.set(node.name, element);
684
- if (node.events) {
685
- for (const [eventName, handlerName] of Object.entries(node.events)) {
686
- this.on(`${node.name}.${eventName}`, async () => {
687
- await this.callFunction(handlerName);
688
- });
689
- }
690
- }
691
- logger.info("UI element created", { type: node.elementType, name: node.name });
692
- return {
693
- success: true,
694
- output: element
695
- };
696
- }
697
- async executeStructure(node) {
698
- const hologram = node.hologram || {
699
- shape: node.type === "nexus" ? "sphere" : "cube",
700
- color: node.type === "nexus" ? "#9b59b6" : "#e74c3c",
701
- size: node.type === "nexus" ? 3 : 4,
702
- glow: true,
703
- interactive: true
704
- };
705
- return {
706
- success: true,
707
- output: { type: node.type, created: true },
708
- hologram,
709
- spatialPosition: node.position
710
- };
711
- }
712
- async executeAssignment(node) {
713
- const value = this.evaluateExpression(String(node.value));
714
- this.setVariable(node.name, value);
715
- return {
716
- success: true,
717
- output: { assigned: node.name, value }
718
- };
719
- }
720
- async executeReturn(node) {
721
- const value = this.evaluateExpression(String(node.value));
722
- return {
723
- success: true,
724
- output: value
725
- };
726
- }
727
- // ============================================================================
728
- // Condition Evaluation
729
- // ============================================================================
730
- evaluateCondition(condition) {
731
- if (!condition) return false;
732
- const suspiciousKeywords = ["eval", "process", "require", "__proto__", "constructor"];
733
- if (suspiciousKeywords.some((kw) => condition.toLowerCase().includes(kw))) {
734
- logger.warn("Suspicious condition blocked", { condition });
735
- return false;
736
- }
737
- try {
738
- if (condition.trim().toLowerCase() === "true") return true;
739
- if (condition.trim().toLowerCase() === "false") return false;
740
- const comparisonPatterns = [
741
- { regex: /^(.+?)\s*(===|!==)\s*(.+)$/ },
742
- { regex: /^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/ },
743
- { regex: /^(.+?)\s*(&&)\s*(.+)$/, logical: "and" },
744
- { regex: /^(.+?)\s*(\|\|)\s*(.+)$/, logical: "or" }
745
- ];
746
- for (const { regex, logical } of comparisonPatterns) {
747
- const match = condition.match(regex);
748
- if (match) {
749
- const [, leftExpr, operator, rightExpr] = match;
750
- const left = this.evaluateExpression(leftExpr.trim());
751
- const right = this.evaluateExpression(rightExpr.trim());
752
- if (logical === "and") return Boolean(left) && Boolean(right);
753
- if (logical === "or") return Boolean(left) || Boolean(right);
754
- switch (operator) {
755
- case "===":
756
- return left === right;
757
- case "!==":
758
- return left !== right;
759
- case "==":
760
- return left == right;
761
- case "!=":
762
- return left != right;
763
- case ">=":
764
- return Number(left) >= Number(right);
765
- case "<=":
766
- return Number(left) <= Number(right);
767
- case ">":
768
- return Number(left) > Number(right);
769
- case "<":
770
- return Number(left) < Number(right);
771
- }
772
- }
773
- }
774
- if (condition.startsWith("!")) {
775
- return !this.evaluateCondition(condition.slice(1).trim());
776
- }
777
- const value = this.evaluateExpression(condition.trim());
778
- return Boolean(value);
779
- } catch (error) {
780
- logger.error("Condition evaluation error", { condition, error });
781
- return false;
782
- }
783
- }
784
- // ============================================================================
785
- // Transformation
786
- // ============================================================================
787
- async applyTransformation(data, transform) {
788
- const params = transform.parameters || {};
789
- switch (transform.operation) {
790
- case "filter": {
791
- if (!Array.isArray(data)) return data;
792
- const predicate = params.predicate;
793
- if (predicate) {
794
- return data.filter((item) => {
795
- this.setVariable("_item", item);
796
- return this.evaluateCondition(predicate);
797
- });
798
- }
799
- return data.filter((item) => item !== null && item !== void 0);
800
- }
801
- case "map": {
802
- if (!Array.isArray(data)) return data;
803
- const mapper = params.mapper;
804
- if (mapper) {
805
- return data.map((item) => {
806
- this.setVariable("_item", item);
807
- return this.evaluateExpression(mapper);
808
- });
809
- }
810
- return data.map((item) => ({ value: item, processed: true }));
811
- }
812
- case "reduce": {
813
- if (!Array.isArray(data)) return data;
814
- const initial = params.initial ?? 0;
815
- const reducer = params.reducer;
816
- if (reducer) {
817
- return data.reduce((acc, item) => {
818
- this.setVariable("_acc", acc);
819
- this.setVariable("_item", item);
820
- return this.evaluateExpression(reducer);
821
- }, initial);
822
- }
823
- return data.reduce((acc, item) => acc + (typeof item === "number" ? item : 0), 0);
824
- }
825
- case "sort": {
826
- if (!Array.isArray(data)) return data;
827
- const key = params.key;
828
- const desc = params.descending;
829
- const sorted = [...data].sort((a, b) => {
830
- const aVal = key ? a[key] : a;
831
- const bVal = key ? b[key] : b;
832
- if (aVal < bVal) return desc ? 1 : -1;
833
- if (aVal > bVal) return desc ? -1 : 1;
834
- return 0;
835
- });
836
- return sorted;
837
- }
838
- case "sum":
839
- return Array.isArray(data) ? data.reduce((sum, item) => sum + (typeof item === "number" ? item : 0), 0) : data;
840
- case "count":
841
- return Array.isArray(data) ? data.length : 1;
842
- case "unique":
843
- return Array.isArray(data) ? [...new Set(data)] : data;
844
- case "flatten":
845
- return Array.isArray(data) ? data.flat() : data;
846
- case "reverse":
847
- return Array.isArray(data) ? [...data].reverse() : data;
848
- case "take": {
849
- if (!Array.isArray(data)) return data;
850
- const count = Number(params.count) || 10;
851
- return data.slice(0, count);
852
- }
853
- case "skip": {
854
- if (!Array.isArray(data)) return data;
855
- const count = Number(params.count) || 0;
856
- return data.slice(count);
857
- }
858
- default:
859
- logger.warn("Unknown transformation", { operation: transform.operation });
860
- return data;
861
- }
862
- }
863
- // ============================================================================
864
- // Event System
865
- // ============================================================================
866
- /**
867
- * Register event handler
868
- */
869
- on(event, handler) {
870
- const handlers = this.eventHandlers.get(event) || [];
871
- handlers.push(handler);
872
- this.eventHandlers.set(event, handlers);
873
- }
874
- /**
875
- * Remove event handler
876
- */
877
- off(event, handler) {
878
- if (!handler) {
879
- this.eventHandlers.delete(event);
880
- } else {
881
- const handlers = this.eventHandlers.get(event) || [];
882
- this.eventHandlers.set(event, handlers.filter((h) => h !== handler));
883
- }
884
- }
885
- /**
886
- * Emit event
887
- */
888
- async emit(event, data) {
889
- const handlers = this.eventHandlers.get(event) || [];
890
- for (const handler of handlers) {
891
- try {
892
- await handler(data);
893
- } catch (error) {
894
- logger.error("Event handler error", { event, error });
895
- }
896
- }
897
- }
898
- /**
899
- * Trigger UI event
900
- */
901
- async triggerUIEvent(elementName, eventType, data) {
902
- const element = this.uiElements.get(elementName);
903
- if (!element) {
904
- logger.warn("UI element not found", { elementName });
905
- return;
906
- }
907
- if (eventType === "change" && data !== void 0) {
908
- element.value = data;
909
- }
910
- await this.emit(`${elementName}.${eventType}`, data);
911
- }
912
- // ============================================================================
913
- // Animation System
914
- // ============================================================================
915
- /**
916
- * Update all animations
917
- */
918
- updateAnimations() {
919
- const now = Date.now();
920
- for (const [key, anim] of this.animations) {
921
- const elapsed = now - anim.startTime;
922
- let progress = Math.min(elapsed / anim.duration, 1);
923
- progress = this.applyEasing(progress, anim.easing);
924
- let currentValue = anim.from + (anim.to - anim.from) * progress;
925
- if (anim.yoyo && progress >= 1) {
926
- anim.startTime = now;
927
- [anim.from, anim.to] = [anim.to, anim.from];
928
- }
929
- this.setVariable(`${anim.target}.${anim.property}`, currentValue);
930
- if (progress >= 1 && !anim.loop && !anim.yoyo) {
931
- this.animations.delete(key);
932
- } else if (progress >= 1 && anim.loop) {
933
- anim.startTime = now;
934
- }
935
- }
936
- }
937
- applyEasing(t, easing) {
938
- switch (easing) {
939
- case "easeIn":
940
- return t * t;
941
- case "easeOut":
942
- return t * (2 - t);
943
- case "easeInOut":
944
- return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
945
- case "easeInQuad":
946
- return t * t;
947
- case "easeOutQuad":
948
- return t * (2 - t);
949
- case "easeInOutQuad":
950
- return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
951
- case "linear":
952
- default:
953
- return t;
954
- }
955
- }
956
- // ============================================================================
957
- // Particle Effects
958
- // ============================================================================
959
- createParticleEffect(name, position, color, count) {
960
- const limitedCount = Math.min(count, RUNTIME_SECURITY_LIMITS.maxParticlesPerSystem);
961
- const particles = [];
962
- for (let i = 0; i < limitedCount; i++) {
963
- particles.push({
964
- x: position.x + (Math.random() - 0.5) * 2,
965
- y: position.y + (Math.random() - 0.5) * 2,
966
- z: position.z + (Math.random() - 0.5) * 2
967
- });
968
- }
969
- this.particleSystems.set(name, {
970
- particles,
971
- color,
972
- lifetime: 3e3,
973
- speed: 0.01
974
- });
975
- }
976
- createConnectionStream(from, to, fromPos, toPos, dataType) {
977
- const streamName = `connection_${from}_${to}`;
978
- const particles = [];
979
- const steps = 20;
980
- for (let i = 0; i <= steps; i++) {
981
- const t = i / steps;
982
- particles.push({
983
- x: fromPos.x + (toPos.x - fromPos.x) * t,
984
- y: fromPos.y + (toPos.y - fromPos.y) * t,
985
- z: fromPos.z + (toPos.z - fromPos.z) * t
986
- });
987
- }
988
- this.particleSystems.set(streamName, {
989
- particles,
990
- color: this.getDataTypeColor(dataType),
991
- lifetime: 5e3,
992
- speed: 0.02
993
- });
994
- }
995
- createFlowingStream(name, position, data) {
996
- const count = Array.isArray(data) ? Math.min(data.length, 50) : 10;
997
- this.createParticleEffect(`${name}_flow`, position, "#45b7d1", count);
998
- }
999
- createExecutionEffect(name, position) {
1000
- this.createParticleEffect(`${name}_execution`, position, "#ff4500", 30);
1001
- }
1002
- createDataVisualization(name, data, position) {
1003
- let count = 10;
1004
- if (Array.isArray(data)) {
1005
- count = Math.min(data.length, 100);
1006
- } else if (typeof data === "object" && data !== null) {
1007
- count = Math.min(Object.keys(data).length * 5, 50);
1008
- }
1009
- this.createParticleEffect(`${name}_visualization`, position, "#32cd32", count);
1010
- }
1011
- getDataTypeColor(dataType) {
1012
- const colors = {
1013
- "string": "#ff6b35",
1014
- "number": "#4ecdc4",
1015
- "boolean": "#45b7d1",
1016
- "object": "#96ceb4",
1017
- "array": "#ffeaa7",
1018
- "any": "#dda0dd",
1019
- "move": "#ff69b4"
1020
- };
1021
- return colors[dataType] || "#ffffff";
1022
- }
1023
- // ============================================================================
1024
- // Public API
1025
- // ============================================================================
1026
- getParticleSystems() {
1027
- return new Map(this.particleSystems);
1028
- }
1029
- updateParticles(deltaTime) {
1030
- for (const [name, system] of this.particleSystems) {
1031
- system.lifetime -= deltaTime;
1032
- system.particles.forEach((particle) => {
1033
- particle.x += (Math.random() - 0.5) * system.speed;
1034
- particle.y += (Math.random() - 0.5) * system.speed;
1035
- particle.z += (Math.random() - 0.5) * system.speed;
1036
- });
1037
- if (system.lifetime <= 0) {
1038
- this.particleSystems.delete(name);
1039
- }
1040
- }
1041
- }
1042
- getContext() {
1043
- return { ...this.context };
1044
- }
1045
- getUIElements() {
1046
- return new Map(this.uiElements);
1047
- }
1048
- getUIElement(name) {
1049
- return this.uiElements.get(name);
1050
- }
1051
- getAnimations() {
1052
- return new Map(this.animations);
1053
- }
1054
- reset() {
1055
- this.context = this.createEmptyContext();
1056
- this.currentScope = { variables: this.context.variables };
1057
- this.callStack = [];
1058
- this.particleSystems.clear();
1059
- this.executionHistory = [];
1060
- this.eventHandlers.clear();
1061
- this.animations.clear();
1062
- this.uiElements.clear();
1063
- }
1064
- createEmptyContext() {
1065
- return {
1066
- variables: /* @__PURE__ */ new Map(),
1067
- functions: /* @__PURE__ */ new Map(),
1068
- connections: [],
1069
- spatialMemory: /* @__PURE__ */ new Map(),
1070
- hologramState: /* @__PURE__ */ new Map(),
1071
- executionStack: []
1072
- };
1073
- }
1074
- getExecutionHistory() {
1075
- return [...this.executionHistory];
1076
- }
1077
- getHologramStates() {
1078
- return new Map(this.context.hologramState);
1079
- }
1080
- getCallStack() {
1081
- return [...this.callStack];
1082
- }
1083
- };
1084
-
1085
- export { HoloScriptRuntime };
1086
- //# sourceMappingURL=chunk-HQZ3HUMY.js.map
1087
- //# sourceMappingURL=chunk-HQZ3HUMY.js.map