@holoscript/core 2.0.1 → 2.0.2
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.
- package/LICENSE +21 -0
- package/dist/chunk-3N67RLQP.cjs +1298 -0
- package/dist/chunk-3N67RLQP.cjs.map +1 -0
- package/dist/chunk-3X2EGU7Z.cjs +52 -0
- package/dist/chunk-3X2EGU7Z.cjs.map +1 -0
- package/dist/chunk-4CV4JOE5.js +24 -0
- package/dist/chunk-4CV4JOE5.js.map +1 -0
- package/dist/chunk-4OHVW4XR.cjs +1027 -0
- package/dist/chunk-4OHVW4XR.cjs.map +1 -0
- package/dist/chunk-CZLDE2OZ.cjs +28 -0
- package/dist/chunk-CZLDE2OZ.cjs.map +1 -0
- package/{src/HoloScriptRuntime.ts → dist/chunk-EU6CZMGJ.js} +437 -794
- package/dist/chunk-EU6CZMGJ.js.map +1 -0
- package/dist/chunk-KWYIVRIH.js +344 -0
- package/dist/chunk-KWYIVRIH.js.map +1 -0
- package/dist/chunk-MCP6D4LT.js +1025 -0
- package/dist/chunk-MCP6D4LT.js.map +1 -0
- package/dist/chunk-SATNCODL.js +45 -0
- package/dist/chunk-SATNCODL.js.map +1 -0
- package/dist/chunk-VMZN4EVR.cjs +347 -0
- package/dist/chunk-VMZN4EVR.cjs.map +1 -0
- package/{src/HoloScriptDebugger.ts → dist/chunk-VYIDLUCV.js} +118 -257
- package/dist/chunk-VYIDLUCV.js.map +1 -0
- package/dist/chunk-WFI4T3XB.cjs +424 -0
- package/dist/chunk-WFI4T3XB.cjs.map +1 -0
- package/dist/debugger.cjs +20 -0
- package/dist/debugger.cjs.map +1 -0
- package/dist/debugger.d.cts +171 -0
- package/dist/debugger.d.ts +171 -0
- package/dist/debugger.js +7 -0
- package/dist/debugger.js.map +1 -0
- package/dist/index.cjs +6006 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2482 -0
- package/dist/index.d.ts +2482 -0
- package/dist/index.js +5926 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.cjs +14 -0
- package/dist/parser.cjs.map +1 -0
- package/dist/parser.d.cts +139 -0
- package/dist/parser.d.ts +139 -0
- package/dist/parser.js +5 -0
- package/dist/parser.js.map +1 -0
- package/dist/runtime.cjs +14 -0
- package/dist/runtime.cjs.map +1 -0
- package/dist/runtime.d.cts +180 -0
- package/dist/runtime.d.ts +180 -0
- package/dist/runtime.js +5 -0
- package/dist/runtime.js.map +1 -0
- package/dist/type-checker.cjs +17 -0
- package/dist/type-checker.cjs.map +1 -0
- package/dist/type-checker.d.cts +105 -0
- package/dist/type-checker.d.ts +105 -0
- package/dist/type-checker.js +4 -0
- package/dist/type-checker.js.map +1 -0
- package/dist/types-D6g4ACjP.d.cts +262 -0
- package/dist/types-D6g4ACjP.d.ts +262 -0
- package/package.json +11 -8
- package/src/HoloScript2DParser.js +0 -227
- package/src/HoloScript2DParser.ts +0 -261
- package/src/HoloScriptCodeParser.js +0 -1102
- package/src/HoloScriptCodeParser.ts +0 -1188
- package/src/HoloScriptDebugger.js +0 -458
- package/src/HoloScriptParser.js +0 -338
- package/src/HoloScriptParser.ts +0 -397
- package/src/HoloScriptPlusParser.js +0 -371
- package/src/HoloScriptPlusParser.ts +0 -543
- package/src/HoloScriptRuntime.js +0 -1399
- package/src/HoloScriptRuntime.test.js +0 -351
- package/src/HoloScriptRuntime.test.ts +0 -436
- package/src/HoloScriptTypeChecker.js +0 -356
- package/src/HoloScriptTypeChecker.ts +0 -475
- package/src/__tests__/GraphicsServices.test.js +0 -357
- package/src/__tests__/GraphicsServices.test.ts +0 -427
- package/src/__tests__/HoloScriptPlusParser.test.js +0 -317
- package/src/__tests__/HoloScriptPlusParser.test.ts +0 -392
- package/src/__tests__/integration.test.js +0 -336
- package/src/__tests__/integration.test.ts +0 -416
- package/src/__tests__/performance.bench.js +0 -218
- package/src/__tests__/performance.bench.ts +0 -262
- package/src/__tests__/type-checker.test.js +0 -60
- package/src/__tests__/type-checker.test.ts +0 -73
- package/src/index.js +0 -217
- package/src/index.ts +0 -426
- package/src/interop/Interoperability.js +0 -413
- package/src/interop/Interoperability.ts +0 -494
- package/src/logger.js +0 -42
- package/src/logger.ts +0 -57
- package/src/parser/EnhancedParser.js +0 -205
- package/src/parser/EnhancedParser.ts +0 -251
- package/src/parser/HoloScriptPlusParser.js +0 -928
- package/src/parser/HoloScriptPlusParser.ts +0 -1089
- package/src/runtime/HoloScriptPlusRuntime.js +0 -674
- package/src/runtime/HoloScriptPlusRuntime.ts +0 -861
- package/src/runtime/PerformanceTelemetry.js +0 -323
- package/src/runtime/PerformanceTelemetry.ts +0 -467
- package/src/runtime/RuntimeOptimization.js +0 -361
- package/src/runtime/RuntimeOptimization.ts +0 -416
- package/src/services/HololandGraphicsPipelineService.js +0 -506
- package/src/services/HololandGraphicsPipelineService.ts +0 -662
- package/src/services/PlatformPerformanceOptimizer.js +0 -356
- package/src/services/PlatformPerformanceOptimizer.ts +0 -503
- package/src/state/ReactiveState.js +0 -427
- package/src/state/ReactiveState.ts +0 -572
- package/src/tools/DeveloperExperience.js +0 -376
- package/src/tools/DeveloperExperience.ts +0 -438
- package/src/traits/AIDriverTrait.js +0 -322
- package/src/traits/AIDriverTrait.test.js +0 -329
- package/src/traits/AIDriverTrait.test.ts +0 -357
- package/src/traits/AIDriverTrait.ts +0 -474
- package/src/traits/LightingTrait.js +0 -313
- package/src/traits/LightingTrait.test.js +0 -410
- package/src/traits/LightingTrait.test.ts +0 -462
- package/src/traits/LightingTrait.ts +0 -505
- package/src/traits/MaterialTrait.js +0 -194
- package/src/traits/MaterialTrait.test.js +0 -286
- package/src/traits/MaterialTrait.test.ts +0 -329
- package/src/traits/MaterialTrait.ts +0 -324
- package/src/traits/RenderingTrait.js +0 -356
- package/src/traits/RenderingTrait.test.js +0 -363
- package/src/traits/RenderingTrait.test.ts +0 -427
- package/src/traits/RenderingTrait.ts +0 -555
- package/src/traits/VRTraitSystem.js +0 -740
- package/src/traits/VRTraitSystem.ts +0 -1040
- package/src/traits/VoiceInputTrait.js +0 -284
- package/src/traits/VoiceInputTrait.test.js +0 -226
- package/src/traits/VoiceInputTrait.test.ts +0 -252
- package/src/traits/VoiceInputTrait.ts +0 -401
- package/src/types/AdvancedTypeSystem.js +0 -226
- package/src/types/AdvancedTypeSystem.ts +0 -494
- package/src/types/HoloScriptPlus.d.ts +0 -853
- package/src/types.js +0 -6
- package/src/types.ts +0 -369
- package/tsconfig.json +0 -23
- package/tsup.config.d.ts +0 -2
- package/tsup.config.js +0 -18
- package/tsup.config.ts +0 -19
|
@@ -1,116 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
* HoloScript Runtime Engine
|
|
3
|
-
*
|
|
4
|
-
* Executes HoloScript AST in VR environment with spatial computation.
|
|
5
|
-
* Supports:
|
|
6
|
-
* - Orb creation and manipulation
|
|
7
|
-
* - Function definition and invocation with arguments
|
|
8
|
-
* - Connections and reactive data flow
|
|
9
|
-
* - Gates (conditionals)
|
|
10
|
-
* - Streams (data pipelines)
|
|
11
|
-
* - 2D UI elements
|
|
12
|
-
* - Built-in commands (show, hide, animate, pulse)
|
|
13
|
-
* - Expression evaluation
|
|
14
|
-
* - Event system
|
|
15
|
-
*/
|
|
1
|
+
import { logger } from './chunk-SATNCODL.js';
|
|
16
2
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ASTNode,
|
|
20
|
-
OrbNode,
|
|
21
|
-
MethodNode,
|
|
22
|
-
ConnectionNode,
|
|
23
|
-
GateNode,
|
|
24
|
-
StreamNode,
|
|
25
|
-
SpatialPosition,
|
|
26
|
-
HologramProperties,
|
|
27
|
-
HologramShape,
|
|
28
|
-
RuntimeContext,
|
|
29
|
-
ExecutionResult,
|
|
30
|
-
ParticleSystem,
|
|
31
|
-
TransformationNode,
|
|
32
|
-
UI2DNode,
|
|
33
|
-
} from './types';
|
|
34
|
-
import type { ImportLoader } from './types';
|
|
35
|
-
|
|
36
|
-
const RUNTIME_SECURITY_LIMITS = {
|
|
3
|
+
// src/HoloScriptRuntime.ts
|
|
4
|
+
var RUNTIME_SECURITY_LIMITS = {
|
|
37
5
|
maxExecutionDepth: 50,
|
|
38
|
-
maxTotalNodes:
|
|
39
|
-
maxExecutionTimeMs:
|
|
40
|
-
maxParticlesPerSystem:
|
|
41
|
-
|
|
42
|
-
maxCallStackDepth: 100,
|
|
6
|
+
maxTotalNodes: 1e3,
|
|
7
|
+
maxExecutionTimeMs: 5e3,
|
|
8
|
+
maxParticlesPerSystem: 1e3,
|
|
9
|
+
maxCallStackDepth: 100
|
|
43
10
|
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
variables: Map<string, unknown>;
|
|
55
|
-
parent?: Scope;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Animation state
|
|
60
|
-
*/
|
|
61
|
-
interface Animation {
|
|
62
|
-
target: string;
|
|
63
|
-
property: string;
|
|
64
|
-
from: number;
|
|
65
|
-
to: number;
|
|
66
|
-
duration: number;
|
|
67
|
-
startTime: number;
|
|
68
|
-
easing: string;
|
|
69
|
-
loop?: boolean;
|
|
70
|
-
yoyo?: boolean;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* UI Element state
|
|
75
|
-
*/
|
|
76
|
-
interface UIElementState {
|
|
77
|
-
type: string;
|
|
78
|
-
name: string;
|
|
79
|
-
properties: Record<string, unknown>;
|
|
80
|
-
value?: unknown;
|
|
81
|
-
visible: boolean;
|
|
82
|
-
enabled: boolean;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export class HoloScriptRuntime {
|
|
86
|
-
private context: RuntimeContext;
|
|
87
|
-
private particleSystems: Map<string, ParticleSystem> = new Map();
|
|
88
|
-
private executionHistory: ExecutionResult[] = [];
|
|
89
|
-
private startTime: number = 0;
|
|
90
|
-
private nodeCount: number = 0;
|
|
91
|
-
|
|
92
|
-
// Enhanced runtime state
|
|
93
|
-
private currentScope: Scope;
|
|
94
|
-
private callStack: string[] = [];
|
|
95
|
-
private eventHandlers: Map<string, EventHandler[]> = new Map();
|
|
96
|
-
private animations: Map<string, Animation> = new Map();
|
|
97
|
-
private uiElements: Map<string, UIElementState> = new Map();
|
|
98
|
-
private builtinFunctions: Map<string, (args: unknown[]) => unknown>;
|
|
99
|
-
|
|
100
|
-
constructor(_importLoader?: ImportLoader) {
|
|
11
|
+
var HoloScriptRuntime = class {
|
|
12
|
+
constructor(_importLoader) {
|
|
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();
|
|
101
21
|
this.context = this.createEmptyContext();
|
|
102
22
|
this.currentScope = { variables: this.context.variables };
|
|
103
23
|
this.builtinFunctions = this.initBuiltins();
|
|
104
24
|
}
|
|
105
|
-
|
|
106
25
|
/**
|
|
107
26
|
* Initialize built-in functions
|
|
108
27
|
*/
|
|
109
|
-
|
|
110
|
-
const builtins =
|
|
111
|
-
|
|
112
|
-
// Display commands
|
|
113
|
-
builtins.set('show', (args) => {
|
|
28
|
+
initBuiltins() {
|
|
29
|
+
const builtins = /* @__PURE__ */ new Map();
|
|
30
|
+
builtins.set("show", (args) => {
|
|
114
31
|
const target = String(args[0]);
|
|
115
32
|
const element = this.uiElements.get(target);
|
|
116
33
|
if (element) element.visible = true;
|
|
@@ -118,116 +35,92 @@ export class HoloScriptRuntime {
|
|
|
118
35
|
if (hologram) {
|
|
119
36
|
this.createParticleEffect(`${target}_show`, { x: 0, y: 0, z: 0 }, hologram.color, 15);
|
|
120
37
|
}
|
|
121
|
-
logger.info(
|
|
38
|
+
logger.info("show", { target });
|
|
122
39
|
return { shown: target };
|
|
123
40
|
});
|
|
124
|
-
|
|
125
|
-
builtins.set('hide', (args) => {
|
|
41
|
+
builtins.set("hide", (args) => {
|
|
126
42
|
const target = String(args[0]);
|
|
127
43
|
const element = this.uiElements.get(target);
|
|
128
44
|
if (element) element.visible = false;
|
|
129
|
-
logger.info(
|
|
45
|
+
logger.info("hide", { target });
|
|
130
46
|
return { hidden: target };
|
|
131
47
|
});
|
|
132
|
-
|
|
133
|
-
// Animation commands
|
|
134
|
-
builtins.set('pulse', (args) => {
|
|
48
|
+
builtins.set("pulse", (args) => {
|
|
135
49
|
const target = String(args[0]);
|
|
136
|
-
const options =
|
|
137
|
-
const duration = Number(options.duration) ||
|
|
138
|
-
const color = String(options.color ||
|
|
139
|
-
|
|
50
|
+
const options = args[1] || {};
|
|
51
|
+
const duration = Number(options.duration) || 1e3;
|
|
52
|
+
const color = String(options.color || "#ffffff");
|
|
140
53
|
const position = this.context.spatialMemory.get(target) || { x: 0, y: 0, z: 0 };
|
|
141
54
|
this.createParticleEffect(`${target}_pulse`, position, color, 30);
|
|
142
|
-
|
|
143
55
|
return { pulsing: target, duration };
|
|
144
56
|
});
|
|
145
|
-
|
|
146
|
-
builtins.set('animate', (args) => {
|
|
57
|
+
builtins.set("animate", (args) => {
|
|
147
58
|
const target = String(args[0]);
|
|
148
|
-
const options =
|
|
149
|
-
|
|
150
|
-
const animation: Animation = {
|
|
59
|
+
const options = args[1] || {};
|
|
60
|
+
const animation = {
|
|
151
61
|
target,
|
|
152
|
-
property: String(options.property ||
|
|
62
|
+
property: String(options.property || "position.y"),
|
|
153
63
|
from: Number(options.from || 0),
|
|
154
64
|
to: Number(options.to || 1),
|
|
155
|
-
duration: Number(options.duration ||
|
|
65
|
+
duration: Number(options.duration || 1e3),
|
|
156
66
|
startTime: Date.now(),
|
|
157
|
-
easing: String(options.easing ||
|
|
67
|
+
easing: String(options.easing || "linear"),
|
|
158
68
|
loop: Boolean(options.loop),
|
|
159
|
-
yoyo: Boolean(options.yoyo)
|
|
69
|
+
yoyo: Boolean(options.yoyo)
|
|
160
70
|
};
|
|
161
|
-
|
|
162
71
|
this.animations.set(`${target}_${animation.property}`, animation);
|
|
163
72
|
return { animating: target, animation };
|
|
164
73
|
});
|
|
165
|
-
|
|
166
|
-
// Spatial commands
|
|
167
|
-
builtins.set('spawn', (args) => {
|
|
74
|
+
builtins.set("spawn", (args) => {
|
|
168
75
|
const target = String(args[0]);
|
|
169
|
-
const position =
|
|
170
|
-
|
|
76
|
+
const position = args[1] || { x: 0, y: 0, z: 0 };
|
|
171
77
|
this.context.spatialMemory.set(target, position);
|
|
172
|
-
this.createParticleEffect(`${target}_spawn`, position,
|
|
173
|
-
|
|
78
|
+
this.createParticleEffect(`${target}_spawn`, position, "#00ff00", 25);
|
|
174
79
|
return { spawned: target, at: position };
|
|
175
80
|
});
|
|
176
|
-
|
|
177
|
-
builtins.set('move', (args) => {
|
|
81
|
+
builtins.set("move", (args) => {
|
|
178
82
|
const target = String(args[0]);
|
|
179
|
-
const position =
|
|
180
|
-
|
|
83
|
+
const position = args[1] || { x: 0, y: 0, z: 0 };
|
|
181
84
|
const current = this.context.spatialMemory.get(target);
|
|
182
85
|
if (current) {
|
|
183
86
|
this.context.spatialMemory.set(target, position);
|
|
184
|
-
this.createConnectionStream(target, `${target}_dest`, current, position,
|
|
87
|
+
this.createConnectionStream(target, `${target}_dest`, current, position, "move");
|
|
185
88
|
}
|
|
186
|
-
|
|
187
89
|
return { moved: target, to: position };
|
|
188
90
|
});
|
|
189
|
-
|
|
190
|
-
// Data commands
|
|
191
|
-
builtins.set('set', (args) => {
|
|
91
|
+
builtins.set("set", (args) => {
|
|
192
92
|
const target = String(args[0]);
|
|
193
93
|
const value = args[1];
|
|
194
94
|
this.setVariable(target, value);
|
|
195
95
|
return { set: target, value };
|
|
196
96
|
});
|
|
197
|
-
|
|
198
|
-
builtins.set('get', (args) => {
|
|
97
|
+
builtins.set("get", (args) => {
|
|
199
98
|
const target = String(args[0]);
|
|
200
99
|
return this.getVariable(target);
|
|
201
100
|
});
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
builtins.set(
|
|
205
|
-
builtins.set(
|
|
206
|
-
builtins.set(
|
|
207
|
-
builtins.set(
|
|
208
|
-
builtins.set(
|
|
209
|
-
builtins.set(
|
|
210
|
-
builtins.set(
|
|
211
|
-
builtins.set(
|
|
212
|
-
builtins.set(
|
|
213
|
-
builtins.set(
|
|
214
|
-
builtins.set(
|
|
215
|
-
builtins.set(
|
|
216
|
-
|
|
217
|
-
// String functions
|
|
218
|
-
builtins.set('concat', (args) => args.map(String).join(''));
|
|
219
|
-
builtins.set('length', (args) => {
|
|
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) => {
|
|
220
115
|
const val = args[0];
|
|
221
|
-
if (typeof val ===
|
|
116
|
+
if (typeof val === "string") return val.length;
|
|
222
117
|
if (Array.isArray(val)) return val.length;
|
|
223
118
|
return 0;
|
|
224
119
|
});
|
|
225
|
-
builtins.set(
|
|
226
|
-
builtins.set(
|
|
227
|
-
builtins.set(
|
|
228
|
-
|
|
229
|
-
// Array functions
|
|
230
|
-
builtins.set('push', (args) => {
|
|
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) => {
|
|
231
124
|
const arr = args[0];
|
|
232
125
|
if (Array.isArray(arr)) {
|
|
233
126
|
arr.push(args[1]);
|
|
@@ -235,377 +128,308 @@ export class HoloScriptRuntime {
|
|
|
235
128
|
}
|
|
236
129
|
return [args[0], args[1]];
|
|
237
130
|
});
|
|
238
|
-
builtins.set(
|
|
131
|
+
builtins.set("pop", (args) => {
|
|
239
132
|
const arr = args[0];
|
|
240
133
|
if (Array.isArray(arr)) return arr.pop();
|
|
241
|
-
return
|
|
134
|
+
return void 0;
|
|
242
135
|
});
|
|
243
|
-
builtins.set(
|
|
136
|
+
builtins.set("at", (args) => {
|
|
244
137
|
const arr = args[0];
|
|
245
138
|
const index = Number(args[1]);
|
|
246
139
|
if (Array.isArray(arr)) return arr[index];
|
|
247
|
-
return
|
|
140
|
+
return void 0;
|
|
248
141
|
});
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
builtins.set('log', (args) => {
|
|
252
|
-
logger.info('HoloScript log', { args });
|
|
142
|
+
builtins.set("log", (args) => {
|
|
143
|
+
logger.info("HoloScript log", { args });
|
|
253
144
|
return args[0];
|
|
254
145
|
});
|
|
255
|
-
builtins.set(
|
|
256
|
-
const message = args.map(String).join(
|
|
257
|
-
logger.info(
|
|
146
|
+
builtins.set("print", (args) => {
|
|
147
|
+
const message = args.map(String).join(" ");
|
|
148
|
+
logger.info("print", { message });
|
|
258
149
|
return message;
|
|
259
150
|
});
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
builtins.set(
|
|
263
|
-
builtins.set(
|
|
264
|
-
builtins.set('isNumber', (args) => typeof args[0] === 'number' && !isNaN(args[0] as number));
|
|
265
|
-
builtins.set('isString', (args) => typeof args[0] === 'string');
|
|
266
|
-
|
|
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");
|
|
267
155
|
return builtins;
|
|
268
156
|
}
|
|
269
|
-
|
|
270
157
|
/**
|
|
271
158
|
* Execute a single AST node
|
|
272
159
|
*/
|
|
273
|
-
async executeNode(node
|
|
160
|
+
async executeNode(node) {
|
|
274
161
|
const startTime = Date.now();
|
|
275
|
-
|
|
276
162
|
try {
|
|
277
163
|
this.context.executionStack.push(node);
|
|
278
|
-
|
|
279
|
-
let result: ExecutionResult;
|
|
280
|
-
|
|
164
|
+
let result;
|
|
281
165
|
switch (node.type) {
|
|
282
|
-
case
|
|
283
|
-
result = await this.executeOrb(node
|
|
166
|
+
case "orb":
|
|
167
|
+
result = await this.executeOrb(node);
|
|
284
168
|
break;
|
|
285
|
-
case
|
|
286
|
-
case
|
|
287
|
-
result = await this.executeFunction(node
|
|
169
|
+
case "method":
|
|
170
|
+
case "function":
|
|
171
|
+
result = await this.executeFunction(node);
|
|
288
172
|
break;
|
|
289
|
-
case
|
|
290
|
-
result = await this.executeConnection(node
|
|
173
|
+
case "connection":
|
|
174
|
+
result = await this.executeConnection(node);
|
|
291
175
|
break;
|
|
292
|
-
case
|
|
293
|
-
result = await this.executeGate(node
|
|
176
|
+
case "gate":
|
|
177
|
+
result = await this.executeGate(node);
|
|
294
178
|
break;
|
|
295
|
-
case
|
|
296
|
-
result = await this.executeStream(node
|
|
179
|
+
case "stream":
|
|
180
|
+
result = await this.executeStream(node);
|
|
297
181
|
break;
|
|
298
|
-
case
|
|
299
|
-
case
|
|
300
|
-
result = await this.executeCall(node
|
|
182
|
+
case "execute":
|
|
183
|
+
case "call":
|
|
184
|
+
result = await this.executeCall(node);
|
|
301
185
|
break;
|
|
302
|
-
case
|
|
186
|
+
case "debug":
|
|
303
187
|
result = await this.executeDebug(node);
|
|
304
188
|
break;
|
|
305
|
-
case
|
|
189
|
+
case "visualize":
|
|
306
190
|
result = await this.executeVisualize(node);
|
|
307
191
|
break;
|
|
308
|
-
case
|
|
309
|
-
result = await this.executeUIElement(node
|
|
192
|
+
case "2d-element":
|
|
193
|
+
result = await this.executeUIElement(node);
|
|
310
194
|
break;
|
|
311
|
-
case
|
|
312
|
-
case
|
|
195
|
+
case "nexus":
|
|
196
|
+
case "building":
|
|
313
197
|
result = await this.executeStructure(node);
|
|
314
198
|
break;
|
|
315
|
-
case
|
|
316
|
-
result = await this.executeAssignment(node
|
|
199
|
+
case "assignment":
|
|
200
|
+
result = await this.executeAssignment(node);
|
|
317
201
|
break;
|
|
318
|
-
case
|
|
319
|
-
result = await this.executeReturn(node
|
|
202
|
+
case "return":
|
|
203
|
+
result = await this.executeReturn(node);
|
|
320
204
|
break;
|
|
321
|
-
case
|
|
205
|
+
case "generic":
|
|
322
206
|
result = await this.executeGeneric(node);
|
|
323
207
|
break;
|
|
324
|
-
case
|
|
208
|
+
case "expression-statement":
|
|
325
209
|
result = await this.executeCall(node);
|
|
326
210
|
break;
|
|
327
211
|
default:
|
|
328
212
|
result = {
|
|
329
213
|
success: false,
|
|
330
214
|
error: `Unknown node type: ${node.type}`,
|
|
331
|
-
executionTime: Date.now() - startTime
|
|
215
|
+
executionTime: Date.now() - startTime
|
|
332
216
|
};
|
|
333
217
|
}
|
|
334
|
-
|
|
335
218
|
result.executionTime = Date.now() - startTime;
|
|
336
219
|
this.executionHistory.push(result);
|
|
337
220
|
this.context.executionStack.pop();
|
|
338
|
-
|
|
339
221
|
return result;
|
|
340
222
|
} catch (error) {
|
|
341
223
|
const execTime = Date.now() - startTime;
|
|
342
|
-
const errorResult
|
|
224
|
+
const errorResult = {
|
|
343
225
|
success: false,
|
|
344
226
|
error: error instanceof Error ? error.message : String(error),
|
|
345
|
-
executionTime: execTime
|
|
227
|
+
executionTime: execTime
|
|
346
228
|
};
|
|
347
|
-
|
|
348
229
|
this.executionHistory.push(errorResult);
|
|
349
230
|
this.context.executionStack.pop();
|
|
350
|
-
|
|
351
231
|
return errorResult;
|
|
352
232
|
}
|
|
353
233
|
}
|
|
354
|
-
|
|
355
234
|
/**
|
|
356
235
|
* Execute multiple nodes in sequence
|
|
357
236
|
*/
|
|
358
|
-
async executeProgram(nodes
|
|
237
|
+
async executeProgram(nodes, depth = 0) {
|
|
359
238
|
if (depth === 0) {
|
|
360
239
|
this.startTime = Date.now();
|
|
361
240
|
this.nodeCount = 0;
|
|
362
241
|
}
|
|
363
|
-
|
|
364
242
|
if (depth > RUNTIME_SECURITY_LIMITS.maxExecutionDepth) {
|
|
365
|
-
logger.error(
|
|
243
|
+
logger.error("Max execution depth exceeded", { depth });
|
|
366
244
|
return [{
|
|
367
245
|
success: false,
|
|
368
246
|
error: `Max execution depth exceeded (${RUNTIME_SECURITY_LIMITS.maxExecutionDepth})`,
|
|
369
|
-
executionTime: 0
|
|
247
|
+
executionTime: 0
|
|
370
248
|
}];
|
|
371
249
|
}
|
|
372
|
-
|
|
373
|
-
const results: ExecutionResult[] = [];
|
|
374
|
-
|
|
250
|
+
const results = [];
|
|
375
251
|
for (const node of nodes) {
|
|
376
252
|
this.nodeCount++;
|
|
377
253
|
if (this.nodeCount > RUNTIME_SECURITY_LIMITS.maxTotalNodes) {
|
|
378
|
-
logger.error(
|
|
254
|
+
logger.error("Max total nodes exceeded", { count: this.nodeCount });
|
|
379
255
|
results.push({
|
|
380
256
|
success: false,
|
|
381
|
-
error:
|
|
382
|
-
executionTime: Date.now() - this.startTime
|
|
257
|
+
error: "Max total nodes exceeded",
|
|
258
|
+
executionTime: Date.now() - this.startTime
|
|
383
259
|
});
|
|
384
260
|
break;
|
|
385
261
|
}
|
|
386
|
-
|
|
387
262
|
if (Date.now() - this.startTime > RUNTIME_SECURITY_LIMITS.maxExecutionTimeMs) {
|
|
388
|
-
logger.error(
|
|
263
|
+
logger.error("Execution timeout", { duration: Date.now() - this.startTime });
|
|
389
264
|
results.push({
|
|
390
265
|
success: false,
|
|
391
|
-
error:
|
|
392
|
-
executionTime: Date.now() - this.startTime
|
|
266
|
+
error: "Execution timeout",
|
|
267
|
+
executionTime: Date.now() - this.startTime
|
|
393
268
|
});
|
|
394
269
|
break;
|
|
395
270
|
}
|
|
396
|
-
|
|
397
271
|
const result = await this.executeNode(node);
|
|
398
272
|
results.push(result);
|
|
399
|
-
|
|
400
|
-
// Stop on error (except visualize) or return statement
|
|
401
|
-
if (!result.success && node.type !== 'visualize') {
|
|
273
|
+
if (!result.success && node.type !== "visualize") {
|
|
402
274
|
break;
|
|
403
275
|
}
|
|
404
|
-
if (node.type ===
|
|
276
|
+
if (node.type === "return") {
|
|
405
277
|
break;
|
|
406
278
|
}
|
|
407
279
|
}
|
|
408
|
-
|
|
409
280
|
return results;
|
|
410
281
|
}
|
|
411
|
-
|
|
412
282
|
/**
|
|
413
283
|
* Call a function with arguments
|
|
414
284
|
*/
|
|
415
|
-
async callFunction(name
|
|
416
|
-
// Check built-in functions first
|
|
285
|
+
async callFunction(name, args = []) {
|
|
417
286
|
const builtin = this.builtinFunctions.get(name);
|
|
418
287
|
if (builtin) {
|
|
419
288
|
try {
|
|
420
289
|
const result = builtin(args);
|
|
421
290
|
return {
|
|
422
291
|
success: true,
|
|
423
|
-
output: result
|
|
292
|
+
output: result
|
|
424
293
|
};
|
|
425
294
|
} catch (error) {
|
|
426
295
|
return {
|
|
427
296
|
success: false,
|
|
428
|
-
error: `Built-in function ${name} failed: ${error}
|
|
297
|
+
error: `Built-in function ${name} failed: ${error}`
|
|
429
298
|
};
|
|
430
299
|
}
|
|
431
300
|
}
|
|
432
|
-
|
|
433
|
-
// Check user-defined functions
|
|
434
301
|
const func = this.context.functions.get(name);
|
|
435
302
|
if (!func) {
|
|
436
303
|
return {
|
|
437
304
|
success: false,
|
|
438
|
-
error: `Function '${name}' not found
|
|
305
|
+
error: `Function '${name}' not found`
|
|
439
306
|
};
|
|
440
307
|
}
|
|
441
|
-
|
|
442
|
-
// Check call stack depth
|
|
443
308
|
if (this.callStack.length >= RUNTIME_SECURITY_LIMITS.maxCallStackDepth) {
|
|
444
309
|
return {
|
|
445
310
|
success: false,
|
|
446
|
-
error: `Max call stack depth exceeded (${RUNTIME_SECURITY_LIMITS.maxCallStackDepth})
|
|
311
|
+
error: `Max call stack depth exceeded (${RUNTIME_SECURITY_LIMITS.maxCallStackDepth})`
|
|
447
312
|
};
|
|
448
313
|
}
|
|
449
|
-
|
|
450
|
-
// Create new scope
|
|
451
314
|
const parentScope = this.currentScope;
|
|
452
315
|
this.currentScope = {
|
|
453
|
-
variables: new Map(),
|
|
454
|
-
parent: parentScope
|
|
316
|
+
variables: /* @__PURE__ */ new Map(),
|
|
317
|
+
parent: parentScope
|
|
455
318
|
};
|
|
456
|
-
|
|
457
|
-
// Bind parameters
|
|
458
319
|
func.parameters.forEach((param, index) => {
|
|
459
320
|
const value = index < args.length ? args[index] : param.defaultValue;
|
|
460
321
|
this.currentScope.variables.set(param.name, value);
|
|
461
322
|
});
|
|
462
|
-
|
|
463
|
-
// Push to call stack
|
|
464
323
|
this.callStack.push(name);
|
|
465
|
-
|
|
466
|
-
// Execute function body
|
|
467
|
-
let returnValue: unknown = undefined;
|
|
324
|
+
let returnValue = void 0;
|
|
468
325
|
try {
|
|
469
326
|
const results = await this.executeProgram(func.body, this.callStack.length);
|
|
470
327
|
const lastResult = results[results.length - 1];
|
|
471
|
-
|
|
472
|
-
if (lastResult?.output !== undefined) {
|
|
328
|
+
if (lastResult?.output !== void 0) {
|
|
473
329
|
returnValue = lastResult.output;
|
|
474
330
|
}
|
|
475
|
-
|
|
476
|
-
// Visual effect
|
|
477
331
|
this.createExecutionEffect(name, func.position || { x: 0, y: 0, z: 0 });
|
|
478
|
-
|
|
479
332
|
return {
|
|
480
|
-
success: results.every(r => r.success),
|
|
333
|
+
success: results.every((r) => r.success),
|
|
481
334
|
output: returnValue,
|
|
482
335
|
hologram: func.hologram,
|
|
483
|
-
spatialPosition: func.position
|
|
336
|
+
spatialPosition: func.position
|
|
484
337
|
};
|
|
485
338
|
} finally {
|
|
486
|
-
// Restore scope
|
|
487
339
|
this.currentScope = parentScope;
|
|
488
340
|
this.callStack.pop();
|
|
489
341
|
}
|
|
490
342
|
}
|
|
491
|
-
|
|
492
343
|
/**
|
|
493
344
|
* Set a variable in current scope
|
|
494
345
|
*/
|
|
495
|
-
setVariable(name
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
const parts = name.split('.');
|
|
346
|
+
setVariable(name, value) {
|
|
347
|
+
if (name.includes(".")) {
|
|
348
|
+
const parts = name.split(".");
|
|
499
349
|
const objName = parts[0];
|
|
500
350
|
const propPath = parts.slice(1);
|
|
501
|
-
|
|
502
351
|
let obj = this.getVariable(objName);
|
|
503
|
-
if (obj ===
|
|
352
|
+
if (obj === void 0 || typeof obj !== "object" || obj === null) {
|
|
504
353
|
obj = {};
|
|
505
354
|
this.currentScope.variables.set(objName, obj);
|
|
506
355
|
}
|
|
507
|
-
|
|
508
|
-
let current = obj as Record<string, unknown>;
|
|
356
|
+
let current = obj;
|
|
509
357
|
for (let i = 0; i < propPath.length - 1; i++) {
|
|
510
|
-
if (current[propPath[i]] ===
|
|
358
|
+
if (current[propPath[i]] === void 0 || typeof current[propPath[i]] !== "object") {
|
|
511
359
|
current[propPath[i]] = {};
|
|
512
360
|
}
|
|
513
|
-
current = current[propPath[i]]
|
|
361
|
+
current = current[propPath[i]];
|
|
514
362
|
}
|
|
515
363
|
current[propPath[propPath.length - 1]] = value;
|
|
516
364
|
} else {
|
|
517
365
|
this.currentScope.variables.set(name, value);
|
|
518
366
|
}
|
|
519
367
|
}
|
|
520
|
-
|
|
521
368
|
/**
|
|
522
369
|
* Get a variable from scope chain
|
|
523
370
|
*/
|
|
524
|
-
getVariable(name
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
const parts = name.split('.');
|
|
371
|
+
getVariable(name) {
|
|
372
|
+
if (name.includes(".")) {
|
|
373
|
+
const parts = name.split(".");
|
|
528
374
|
let value = this.getVariable(parts[0]);
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
value = (value as Record<string, unknown>)[parts[i]];
|
|
375
|
+
for (let i = 1; i < parts.length && value !== void 0; i++) {
|
|
376
|
+
if (typeof value === "object" && value !== null) {
|
|
377
|
+
value = value[parts[i]];
|
|
533
378
|
} else {
|
|
534
|
-
return
|
|
379
|
+
return void 0;
|
|
535
380
|
}
|
|
536
381
|
}
|
|
537
382
|
return value;
|
|
538
383
|
}
|
|
539
|
-
|
|
540
|
-
// Walk scope chain
|
|
541
|
-
let scope: Scope | undefined = this.currentScope;
|
|
384
|
+
let scope = this.currentScope;
|
|
542
385
|
while (scope) {
|
|
543
386
|
if (scope.variables.has(name)) {
|
|
544
387
|
return scope.variables.get(name);
|
|
545
388
|
}
|
|
546
389
|
scope = scope.parent;
|
|
547
390
|
}
|
|
548
|
-
|
|
549
|
-
// Check context variables
|
|
550
391
|
if (this.context.variables.has(name)) {
|
|
551
392
|
return this.context.variables.get(name);
|
|
552
393
|
}
|
|
553
|
-
|
|
554
|
-
// Fallback to functions map (for imported functions)
|
|
555
394
|
if (this.context.functions.has(name)) {
|
|
556
395
|
return this.context.functions.get(name);
|
|
557
396
|
}
|
|
558
|
-
|
|
559
|
-
return undefined;
|
|
397
|
+
return void 0;
|
|
560
398
|
}
|
|
561
|
-
|
|
562
399
|
/**
|
|
563
400
|
* Evaluate an expression
|
|
564
401
|
*/
|
|
565
|
-
evaluateExpression(expr
|
|
566
|
-
if (!expr || typeof expr !==
|
|
567
|
-
|
|
402
|
+
evaluateExpression(expr) {
|
|
403
|
+
if (!expr || typeof expr !== "string") return expr;
|
|
568
404
|
expr = expr.trim();
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
logger.warn('Suspicious expression blocked', { expr });
|
|
574
|
-
return undefined;
|
|
405
|
+
const suspicious = ["eval", "process", "require", "__proto__", "constructor", "Function"];
|
|
406
|
+
if (suspicious.some((kw) => expr.toLowerCase().includes(kw))) {
|
|
407
|
+
logger.warn("Suspicious expression blocked", { expr });
|
|
408
|
+
return void 0;
|
|
575
409
|
}
|
|
576
|
-
|
|
577
|
-
// String literal
|
|
578
|
-
if ((expr.startsWith('"') && expr.endsWith('"')) || (expr.startsWith("'") && expr.endsWith("'"))) {
|
|
410
|
+
if (expr.startsWith('"') && expr.endsWith('"') || expr.startsWith("'") && expr.endsWith("'")) {
|
|
579
411
|
return expr.slice(1, -1);
|
|
580
412
|
}
|
|
581
|
-
|
|
582
|
-
// Number literal
|
|
583
413
|
if (/^-?\d+(\.\d+)?$/.test(expr)) {
|
|
584
414
|
return parseFloat(expr);
|
|
585
415
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
if (expr ===
|
|
589
|
-
if (expr ===
|
|
590
|
-
if (expr
|
|
591
|
-
if (expr === 'undefined') return undefined;
|
|
592
|
-
|
|
593
|
-
// Array literal [a, b, c]
|
|
594
|
-
if (expr.startsWith('[') && expr.endsWith(']')) {
|
|
416
|
+
if (expr === "true") return true;
|
|
417
|
+
if (expr === "false") return false;
|
|
418
|
+
if (expr === "null") return null;
|
|
419
|
+
if (expr === "undefined") return void 0;
|
|
420
|
+
if (expr.startsWith("[") && expr.endsWith("]")) {
|
|
595
421
|
const inner = expr.slice(1, -1);
|
|
596
422
|
if (!inner.trim()) return [];
|
|
597
423
|
const elements = this.splitByComma(inner);
|
|
598
|
-
return elements.map(e => this.evaluateExpression(e.trim()));
|
|
424
|
+
return elements.map((e) => this.evaluateExpression(e.trim()));
|
|
599
425
|
}
|
|
600
|
-
|
|
601
|
-
// Object literal {a: 1, b: 2}
|
|
602
|
-
if (expr.startsWith('{') && expr.endsWith('}')) {
|
|
426
|
+
if (expr.startsWith("{") && expr.endsWith("}")) {
|
|
603
427
|
const inner = expr.slice(1, -1);
|
|
604
428
|
if (!inner.trim()) return {};
|
|
605
429
|
const pairs = this.splitByComma(inner);
|
|
606
|
-
const obj
|
|
430
|
+
const obj = {};
|
|
607
431
|
for (const pair of pairs) {
|
|
608
|
-
const colonIndex = pair.indexOf(
|
|
432
|
+
const colonIndex = pair.indexOf(":");
|
|
609
433
|
if (colonIndex > 0) {
|
|
610
434
|
const key = pair.slice(0, colonIndex).trim();
|
|
611
435
|
const value = pair.slice(colonIndex + 1).trim();
|
|
@@ -614,37 +438,26 @@ export class HoloScriptRuntime {
|
|
|
614
438
|
}
|
|
615
439
|
return obj;
|
|
616
440
|
}
|
|
617
|
-
|
|
618
|
-
// Function call: name(args)
|
|
619
441
|
const funcMatch = expr.match(/^(\w+)\s*\((.*)?\)$/);
|
|
620
442
|
if (funcMatch) {
|
|
621
443
|
const [, funcName, argsStr] = funcMatch;
|
|
622
|
-
const args = argsStr ? this.splitByComma(argsStr).map(a => this.evaluateExpression(a.trim())) : [];
|
|
623
|
-
|
|
624
|
-
// Check builtins
|
|
444
|
+
const args = argsStr ? this.splitByComma(argsStr).map((a) => this.evaluateExpression(a.trim())) : [];
|
|
625
445
|
const builtin = this.builtinFunctions.get(funcName);
|
|
626
446
|
if (builtin) {
|
|
627
447
|
return builtin(args);
|
|
628
448
|
}
|
|
629
|
-
|
|
630
|
-
// Check user functions (but don't execute - just reference)
|
|
631
449
|
if (this.context.functions.has(funcName)) {
|
|
632
|
-
// For async execution, return a promise marker
|
|
633
450
|
return { __holoCall: funcName, args };
|
|
634
451
|
}
|
|
635
|
-
|
|
636
|
-
return undefined;
|
|
452
|
+
return void 0;
|
|
637
453
|
}
|
|
638
|
-
|
|
639
|
-
// Binary operations: a + b, a - b, etc.
|
|
640
454
|
const binaryOps = [
|
|
641
|
-
{ pattern: /(.+)\s*\+\s*(.+)/, op: (a
|
|
642
|
-
{ pattern: /(.+)\s*-\s*(.+)/, op: (a
|
|
643
|
-
{ pattern: /(.+)\s*\*\s*(.+)/, op: (a
|
|
644
|
-
{ pattern: /(.+)\s*\/\s*(.+)/, op: (a
|
|
645
|
-
{ pattern: /(.+)\s*%\s*(.+)/, op: (a
|
|
455
|
+
{ pattern: /(.+)\s*\+\s*(.+)/, op: (a, b) => typeof a === "string" || typeof b === "string" ? String(a) + String(b) : Number(a) + Number(b) },
|
|
456
|
+
{ pattern: /(.+)\s*-\s*(.+)/, op: (a, b) => Number(a) - Number(b) },
|
|
457
|
+
{ pattern: /(.+)\s*\*\s*(.+)/, op: (a, b) => Number(a) * Number(b) },
|
|
458
|
+
{ pattern: /(.+)\s*\/\s*(.+)/, op: (a, b) => Number(b) !== 0 ? Number(a) / Number(b) : 0 },
|
|
459
|
+
{ pattern: /(.+)\s*%\s*(.+)/, op: (a, b) => Number(a) % Number(b) }
|
|
646
460
|
];
|
|
647
|
-
|
|
648
461
|
for (const { pattern, op } of binaryOps) {
|
|
649
462
|
const match = expr.match(pattern);
|
|
650
463
|
if (match) {
|
|
@@ -653,214 +466,169 @@ export class HoloScriptRuntime {
|
|
|
653
466
|
return op(left, right);
|
|
654
467
|
}
|
|
655
468
|
}
|
|
656
|
-
|
|
657
|
-
// Variable reference
|
|
658
469
|
return this.getVariable(expr);
|
|
659
470
|
}
|
|
660
|
-
|
|
661
471
|
/**
|
|
662
472
|
* Split string by comma, respecting nesting
|
|
663
473
|
*/
|
|
664
|
-
|
|
665
|
-
const parts
|
|
666
|
-
let current =
|
|
474
|
+
splitByComma(str) {
|
|
475
|
+
const parts = [];
|
|
476
|
+
let current = "";
|
|
667
477
|
let depth = 0;
|
|
668
478
|
let inString = false;
|
|
669
|
-
let stringChar =
|
|
670
|
-
|
|
479
|
+
let stringChar = "";
|
|
671
480
|
for (let i = 0; i < str.length; i++) {
|
|
672
481
|
const char = str[i];
|
|
673
|
-
|
|
674
482
|
if (!inString && (char === '"' || char === "'")) {
|
|
675
483
|
inString = true;
|
|
676
484
|
stringChar = char;
|
|
677
|
-
} else if (inString && char === stringChar && str[i - 1] !==
|
|
485
|
+
} else if (inString && char === stringChar && str[i - 1] !== "\\") {
|
|
678
486
|
inString = false;
|
|
679
487
|
}
|
|
680
|
-
|
|
681
488
|
if (!inString) {
|
|
682
|
-
if (char ===
|
|
683
|
-
if (char ===
|
|
684
|
-
|
|
685
|
-
if (char === ',' && depth === 0) {
|
|
489
|
+
if (char === "(" || char === "[" || char === "{") depth++;
|
|
490
|
+
if (char === ")" || char === "]" || char === "}") depth--;
|
|
491
|
+
if (char === "," && depth === 0) {
|
|
686
492
|
parts.push(current.trim());
|
|
687
|
-
current =
|
|
493
|
+
current = "";
|
|
688
494
|
continue;
|
|
689
495
|
}
|
|
690
496
|
}
|
|
691
|
-
|
|
692
497
|
current += char;
|
|
693
498
|
}
|
|
694
|
-
|
|
695
499
|
if (current.trim()) {
|
|
696
500
|
parts.push(current.trim());
|
|
697
501
|
}
|
|
698
|
-
|
|
699
502
|
return parts;
|
|
700
503
|
}
|
|
701
|
-
|
|
702
504
|
// ============================================================================
|
|
703
505
|
// Node Executors
|
|
704
506
|
// ============================================================================
|
|
705
|
-
|
|
706
|
-
private async executeOrb(node: OrbNode): Promise<ExecutionResult> {
|
|
507
|
+
async executeOrb(node) {
|
|
707
508
|
if (node.position) {
|
|
708
509
|
this.context.spatialMemory.set(node.name, node.position);
|
|
709
510
|
}
|
|
710
|
-
|
|
711
|
-
// Create orb object with reactive properties
|
|
712
511
|
const orbData = {
|
|
713
|
-
__type:
|
|
512
|
+
__type: "orb",
|
|
714
513
|
name: node.name,
|
|
715
514
|
properties: { ...node.properties },
|
|
716
515
|
position: node.position || { x: 0, y: 0, z: 0 },
|
|
717
516
|
hologram: node.hologram,
|
|
718
517
|
created: Date.now(),
|
|
719
518
|
// Methods bound to this orb
|
|
720
|
-
show: () => this.builtinFunctions.get(
|
|
721
|
-
hide: () => this.builtinFunctions.get(
|
|
722
|
-
pulse: (opts
|
|
519
|
+
show: () => this.builtinFunctions.get("show")([node.name]),
|
|
520
|
+
hide: () => this.builtinFunctions.get("hide")([node.name]),
|
|
521
|
+
pulse: (opts) => this.builtinFunctions.get("pulse")([node.name, opts])
|
|
723
522
|
};
|
|
724
|
-
|
|
725
523
|
this.context.variables.set(node.name, orbData);
|
|
726
|
-
|
|
727
524
|
if (node.hologram) {
|
|
728
525
|
this.context.hologramState.set(node.name, node.hologram);
|
|
729
526
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
logger.info('Orb created', { name: node.name, properties: Object.keys(node.properties) });
|
|
734
|
-
|
|
527
|
+
this.createParticleEffect(`${node.name}_creation`, node.position || { x: 0, y: 0, z: 0 }, "#00ffff", 20);
|
|
528
|
+
logger.info("Orb created", { name: node.name, properties: Object.keys(node.properties) });
|
|
735
529
|
return {
|
|
736
530
|
success: true,
|
|
737
531
|
output: orbData,
|
|
738
532
|
hologram: node.hologram,
|
|
739
|
-
spatialPosition: node.position
|
|
533
|
+
spatialPosition: node.position
|
|
740
534
|
};
|
|
741
535
|
}
|
|
742
|
-
|
|
743
|
-
private async executeFunction(node: MethodNode): Promise<ExecutionResult> {
|
|
536
|
+
async executeFunction(node) {
|
|
744
537
|
this.context.functions.set(node.name, node);
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
color: '#ff6b35',
|
|
538
|
+
const hologram = {
|
|
539
|
+
shape: "cube",
|
|
540
|
+
color: "#ff6b35",
|
|
749
541
|
size: 1.5,
|
|
750
542
|
glow: true,
|
|
751
543
|
interactive: true,
|
|
752
|
-
...node.hologram
|
|
544
|
+
...node.hologram
|
|
753
545
|
};
|
|
754
|
-
|
|
755
546
|
this.context.hologramState.set(node.name, hologram);
|
|
756
|
-
|
|
757
|
-
logger.info('Function defined', { name: node.name, params: node.parameters.map(p => p.name) });
|
|
758
|
-
|
|
547
|
+
logger.info("Function defined", { name: node.name, params: node.parameters.map((p) => p.name) });
|
|
759
548
|
return {
|
|
760
549
|
success: true,
|
|
761
550
|
output: `Function '${node.name}' defined with ${node.parameters.length} parameter(s)`,
|
|
762
551
|
hologram,
|
|
763
|
-
spatialPosition: node.position
|
|
552
|
+
spatialPosition: node.position
|
|
764
553
|
};
|
|
765
554
|
}
|
|
766
|
-
|
|
767
|
-
private async executeConnection(node: ConnectionNode): Promise<ExecutionResult> {
|
|
555
|
+
async executeConnection(node) {
|
|
768
556
|
this.context.connections.push(node);
|
|
769
|
-
|
|
770
557
|
const fromPos = this.context.spatialMemory.get(node.from);
|
|
771
558
|
const toPos = this.context.spatialMemory.get(node.to);
|
|
772
|
-
|
|
773
559
|
if (fromPos && toPos) {
|
|
774
560
|
this.createConnectionStream(node.from, node.to, fromPos, toPos, node.dataType);
|
|
775
561
|
}
|
|
776
|
-
|
|
777
|
-
// Set up reactive binding if bidirectional
|
|
778
562
|
if (node.bidirectional) {
|
|
779
|
-
// When 'from' changes, update 'to'
|
|
780
563
|
this.on(`${node.from}.changed`, async (data) => {
|
|
781
564
|
this.setVariable(node.to, data);
|
|
782
565
|
this.emit(`${node.to}.changed`, data);
|
|
783
566
|
});
|
|
784
|
-
// When 'to' changes, update 'from'
|
|
785
567
|
this.on(`${node.to}.changed`, async (data) => {
|
|
786
568
|
this.setVariable(node.from, data);
|
|
787
569
|
this.emit(`${node.from}.changed`, data);
|
|
788
570
|
});
|
|
789
571
|
}
|
|
790
|
-
|
|
791
|
-
logger.info('Connection created', { from: node.from, to: node.to, dataType: node.dataType });
|
|
792
|
-
|
|
572
|
+
logger.info("Connection created", { from: node.from, to: node.to, dataType: node.dataType });
|
|
793
573
|
return {
|
|
794
574
|
success: true,
|
|
795
575
|
output: `Connected '${node.from}' to '${node.to}' (${node.dataType})`,
|
|
796
576
|
hologram: {
|
|
797
|
-
shape:
|
|
577
|
+
shape: "cylinder",
|
|
798
578
|
color: this.getDataTypeColor(node.dataType),
|
|
799
579
|
size: 0.1,
|
|
800
580
|
glow: true,
|
|
801
|
-
interactive: false
|
|
802
|
-
}
|
|
581
|
+
interactive: false
|
|
582
|
+
}
|
|
803
583
|
};
|
|
804
584
|
}
|
|
805
|
-
|
|
806
|
-
private async executeGate(node: GateNode): Promise<ExecutionResult> {
|
|
585
|
+
async executeGate(node) {
|
|
807
586
|
try {
|
|
808
587
|
const condition = this.evaluateCondition(node.condition);
|
|
809
588
|
const path = condition ? node.truePath : node.falsePath;
|
|
810
|
-
|
|
811
|
-
logger.info('Gate evaluation', { condition: node.condition, result: condition });
|
|
812
|
-
|
|
589
|
+
logger.info("Gate evaluation", { condition: node.condition, result: condition });
|
|
813
590
|
if (path.length > 0) {
|
|
814
591
|
await this.executeProgram(path, this.callStack.length + 1);
|
|
815
592
|
}
|
|
816
|
-
|
|
817
593
|
return {
|
|
818
594
|
success: true,
|
|
819
|
-
output: `Gate: took ${condition ?
|
|
595
|
+
output: `Gate: took ${condition ? "true" : "false"} path`,
|
|
820
596
|
hologram: {
|
|
821
|
-
shape:
|
|
822
|
-
color: condition ?
|
|
597
|
+
shape: "pyramid",
|
|
598
|
+
color: condition ? "#00ff00" : "#ff0000",
|
|
823
599
|
size: 1,
|
|
824
600
|
glow: true,
|
|
825
|
-
interactive: true
|
|
826
|
-
}
|
|
601
|
+
interactive: true
|
|
602
|
+
}
|
|
827
603
|
};
|
|
828
604
|
} catch (error) {
|
|
829
605
|
return {
|
|
830
606
|
success: false,
|
|
831
|
-
error: `Gate execution failed: ${error}
|
|
607
|
+
error: `Gate execution failed: ${error}`
|
|
832
608
|
};
|
|
833
609
|
}
|
|
834
610
|
}
|
|
835
|
-
|
|
836
|
-
private async executeStream(node: StreamNode): Promise<ExecutionResult> {
|
|
611
|
+
async executeStream(node) {
|
|
837
612
|
let data = this.getVariable(node.source);
|
|
838
|
-
|
|
839
|
-
logger.info('Stream processing', { name: node.name, source: node.source, transforms: node.transformations.length });
|
|
840
|
-
|
|
613
|
+
logger.info("Stream processing", { name: node.name, source: node.source, transforms: node.transformations.length });
|
|
841
614
|
for (const transform of node.transformations) {
|
|
842
615
|
data = await this.applyTransformation(data, transform);
|
|
843
616
|
}
|
|
844
|
-
|
|
845
617
|
this.setVariable(`${node.name}_result`, data);
|
|
846
618
|
this.createFlowingStream(node.name, node.position || { x: 0, y: 0, z: 0 }, data);
|
|
847
|
-
|
|
848
619
|
return {
|
|
849
620
|
success: true,
|
|
850
621
|
output: `Stream '${node.name}' processed ${Array.isArray(data) ? data.length : 1} item(s)`,
|
|
851
622
|
hologram: node.hologram,
|
|
852
|
-
spatialPosition: node.position
|
|
623
|
+
spatialPosition: node.position
|
|
853
624
|
};
|
|
854
625
|
}
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
const funcName = node.target || '';
|
|
626
|
+
async executeCall(node) {
|
|
627
|
+
const funcName = node.target || "";
|
|
858
628
|
const args = node.args || [];
|
|
859
|
-
|
|
860
629
|
return this.callFunction(funcName, args);
|
|
861
630
|
}
|
|
862
|
-
|
|
863
|
-
private async executeDebug(node: ASTNode & { target?: string }): Promise<ExecutionResult> {
|
|
631
|
+
async executeDebug(node) {
|
|
864
632
|
const debugInfo = {
|
|
865
633
|
variables: Object.fromEntries(this.currentScope.variables),
|
|
866
634
|
contextVariables: Object.fromEntries(this.context.variables),
|
|
@@ -869,77 +637,62 @@ export class HoloScriptRuntime {
|
|
|
869
637
|
callStack: [...this.callStack],
|
|
870
638
|
uiElements: Array.from(this.uiElements.keys()),
|
|
871
639
|
animations: Array.from(this.animations.keys()),
|
|
872
|
-
executionHistory: this.executionHistory.slice(-10)
|
|
640
|
+
executionHistory: this.executionHistory.slice(-10)
|
|
873
641
|
};
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
color: '#ff1493',
|
|
642
|
+
const debugOrb = {
|
|
643
|
+
shape: "pyramid",
|
|
644
|
+
color: "#ff1493",
|
|
878
645
|
size: 0.8,
|
|
879
646
|
glow: true,
|
|
880
|
-
interactive: true
|
|
647
|
+
interactive: true
|
|
881
648
|
};
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
logger.info('Debug info', debugInfo);
|
|
886
|
-
|
|
649
|
+
this.context.hologramState.set(`debug_${node.target || "program"}`, debugOrb);
|
|
650
|
+
logger.info("Debug info", debugInfo);
|
|
887
651
|
return {
|
|
888
652
|
success: true,
|
|
889
653
|
output: debugInfo,
|
|
890
|
-
hologram: debugOrb
|
|
654
|
+
hologram: debugOrb
|
|
891
655
|
};
|
|
892
656
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
const target = node.target || '';
|
|
657
|
+
async executeVisualize(node) {
|
|
658
|
+
const target = node.target || "";
|
|
896
659
|
const data = this.getVariable(target);
|
|
897
|
-
|
|
898
|
-
if (data === undefined) {
|
|
660
|
+
if (data === void 0) {
|
|
899
661
|
return {
|
|
900
662
|
success: false,
|
|
901
|
-
error: `No data found for '${target}'
|
|
663
|
+
error: `No data found for '${target}'`
|
|
902
664
|
};
|
|
903
665
|
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
color: '#32cd32',
|
|
666
|
+
const visHologram = {
|
|
667
|
+
shape: "cylinder",
|
|
668
|
+
color: "#32cd32",
|
|
908
669
|
size: 1.5,
|
|
909
670
|
glow: true,
|
|
910
|
-
interactive: true
|
|
671
|
+
interactive: true
|
|
911
672
|
};
|
|
912
|
-
|
|
913
673
|
this.createDataVisualization(target, data, node.position || { x: 0, y: 0, z: 0 });
|
|
914
|
-
|
|
915
674
|
return {
|
|
916
675
|
success: true,
|
|
917
676
|
output: { visualizing: target, data },
|
|
918
|
-
hologram: visHologram
|
|
677
|
+
hologram: visHologram
|
|
919
678
|
};
|
|
920
679
|
}
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
const element: UIElementState = {
|
|
680
|
+
async executeUIElement(node) {
|
|
681
|
+
const element = {
|
|
924
682
|
type: node.elementType,
|
|
925
683
|
name: node.name,
|
|
926
684
|
properties: { ...node.properties },
|
|
927
685
|
visible: true,
|
|
928
|
-
enabled: true
|
|
686
|
+
enabled: true
|
|
929
687
|
};
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
if (node.elementType ===
|
|
933
|
-
element.value = node.properties.value || '';
|
|
934
|
-
} else if (node.elementType === 'slider') {
|
|
688
|
+
if (node.elementType === "textinput") {
|
|
689
|
+
element.value = node.properties.value || "";
|
|
690
|
+
} else if (node.elementType === "slider") {
|
|
935
691
|
element.value = node.properties.value || node.properties.min || 0;
|
|
936
|
-
} else if (node.elementType ===
|
|
692
|
+
} else if (node.elementType === "toggle") {
|
|
937
693
|
element.value = node.properties.checked || false;
|
|
938
694
|
}
|
|
939
|
-
|
|
940
695
|
this.uiElements.set(node.name, element);
|
|
941
|
-
|
|
942
|
-
// Register event handlers
|
|
943
696
|
if (node.events) {
|
|
944
697
|
for (const [eventName, handlerName] of Object.entries(node.events)) {
|
|
945
698
|
this.on(`${node.name}.${eventName}`, async () => {
|
|
@@ -947,531 +700,441 @@ export class HoloScriptRuntime {
|
|
|
947
700
|
});
|
|
948
701
|
}
|
|
949
702
|
}
|
|
950
|
-
|
|
951
|
-
logger.info('UI element created', { type: node.elementType, name: node.name });
|
|
952
|
-
|
|
703
|
+
logger.info("UI element created", { type: node.elementType, name: node.name });
|
|
953
704
|
return {
|
|
954
705
|
success: true,
|
|
955
|
-
output: element
|
|
706
|
+
output: element
|
|
956
707
|
};
|
|
957
708
|
}
|
|
958
|
-
|
|
959
709
|
/**
|
|
960
710
|
* Execute generic voice commands
|
|
961
711
|
* Handles commands like: show, hide, animate, pulse, create
|
|
962
712
|
*/
|
|
963
|
-
|
|
964
|
-
const genericNode = _node
|
|
965
|
-
const command = String(genericNode.command ||
|
|
713
|
+
async executeGeneric(_node) {
|
|
714
|
+
const genericNode = _node;
|
|
715
|
+
const command = String(genericNode.command || "").trim().toLowerCase();
|
|
966
716
|
const tokens = command.split(/\s+/);
|
|
967
717
|
const action = tokens[0];
|
|
968
718
|
const target = tokens[1];
|
|
969
|
-
|
|
970
|
-
logger.info('Executing generic command', { command, action, target });
|
|
971
|
-
|
|
719
|
+
logger.info("Executing generic command", { command, action, target });
|
|
972
720
|
try {
|
|
973
|
-
let result
|
|
974
|
-
|
|
721
|
+
let result;
|
|
975
722
|
switch (action) {
|
|
976
|
-
case
|
|
723
|
+
case "show":
|
|
977
724
|
result = await this.executeShowCommand(target, genericNode);
|
|
978
725
|
break;
|
|
979
|
-
case
|
|
726
|
+
case "hide":
|
|
980
727
|
result = await this.executeHideCommand(target, genericNode);
|
|
981
728
|
break;
|
|
982
|
-
case
|
|
983
|
-
case
|
|
729
|
+
case "create":
|
|
730
|
+
case "summon":
|
|
984
731
|
result = await this.executeCreateCommand(tokens.slice(1), genericNode);
|
|
985
732
|
break;
|
|
986
|
-
case
|
|
733
|
+
case "animate":
|
|
987
734
|
result = await this.executeAnimateCommand(target, tokens.slice(2), genericNode);
|
|
988
735
|
break;
|
|
989
|
-
case
|
|
736
|
+
case "pulse":
|
|
990
737
|
result = await this.executePulseCommand(target, tokens.slice(2), genericNode);
|
|
991
738
|
break;
|
|
992
|
-
case
|
|
739
|
+
case "move":
|
|
993
740
|
result = await this.executeMoveCommand(target, tokens.slice(2), genericNode);
|
|
994
741
|
break;
|
|
995
|
-
case
|
|
996
|
-
case
|
|
742
|
+
case "delete":
|
|
743
|
+
case "remove":
|
|
997
744
|
result = await this.executeDeleteCommand(target, genericNode);
|
|
998
745
|
break;
|
|
999
746
|
default:
|
|
1000
|
-
|
|
1001
|
-
logger.warn('Unknown voice command action', { action, command });
|
|
747
|
+
logger.warn("Unknown voice command action", { action, command });
|
|
1002
748
|
result = {
|
|
1003
749
|
executed: false,
|
|
1004
|
-
message: `Unknown command: ${action}
|
|
750
|
+
message: `Unknown command: ${action}`
|
|
1005
751
|
};
|
|
1006
752
|
}
|
|
1007
|
-
|
|
1008
753
|
return {
|
|
1009
754
|
success: true,
|
|
1010
|
-
output: result
|
|
755
|
+
output: result
|
|
1011
756
|
};
|
|
1012
757
|
} catch (error) {
|
|
1013
758
|
return {
|
|
1014
759
|
success: false,
|
|
1015
|
-
error: `Generic command execution failed: ${String(error)}
|
|
760
|
+
error: `Generic command execution failed: ${String(error)}`
|
|
1016
761
|
};
|
|
1017
762
|
}
|
|
1018
763
|
}
|
|
1019
|
-
|
|
1020
764
|
/**
|
|
1021
765
|
* Execute 'show' command
|
|
1022
766
|
*/
|
|
1023
|
-
|
|
1024
|
-
// Create or show orb for this target
|
|
767
|
+
async executeShowCommand(target, _node) {
|
|
1025
768
|
const hologram = _node.hologram || {
|
|
1026
|
-
shape:
|
|
1027
|
-
color:
|
|
769
|
+
shape: "orb",
|
|
770
|
+
color: "#00ffff",
|
|
1028
771
|
size: 0.8,
|
|
1029
772
|
glow: true,
|
|
1030
|
-
interactive: true
|
|
773
|
+
interactive: true
|
|
1031
774
|
};
|
|
1032
|
-
|
|
1033
775
|
const position = _node.position || { x: 0, y: 0, z: 0 };
|
|
1034
776
|
this.context.spatialMemory.set(target, position);
|
|
1035
777
|
this.createParticleEffect(`${target}_show`, position, hologram.color, 15);
|
|
1036
|
-
|
|
1037
|
-
logger.info('Show command executed', { target, position });
|
|
1038
|
-
|
|
778
|
+
logger.info("Show command executed", { target, position });
|
|
1039
779
|
return {
|
|
1040
780
|
showed: target,
|
|
1041
781
|
hologram,
|
|
1042
|
-
position
|
|
782
|
+
position
|
|
1043
783
|
};
|
|
1044
784
|
}
|
|
1045
|
-
|
|
1046
785
|
/**
|
|
1047
786
|
* Execute 'hide' command
|
|
1048
787
|
*/
|
|
1049
|
-
|
|
788
|
+
async executeHideCommand(target, _node) {
|
|
1050
789
|
const position = this.context.spatialMemory.get(target) || { x: 0, y: 0, z: 0 };
|
|
1051
|
-
this.createParticleEffect(`${target}_hide`, position,
|
|
1052
|
-
|
|
1053
|
-
logger.info('Hide command executed', { target });
|
|
1054
|
-
|
|
790
|
+
this.createParticleEffect(`${target}_hide`, position, "#ff0000", 10);
|
|
791
|
+
logger.info("Hide command executed", { target });
|
|
1055
792
|
return {
|
|
1056
|
-
hidden: target
|
|
793
|
+
hidden: target
|
|
1057
794
|
};
|
|
1058
795
|
}
|
|
1059
|
-
|
|
1060
796
|
/**
|
|
1061
797
|
* Execute 'create' command
|
|
1062
798
|
*/
|
|
1063
|
-
|
|
799
|
+
async executeCreateCommand(tokens, _node) {
|
|
1064
800
|
if (tokens.length < 2) {
|
|
1065
|
-
return { error:
|
|
801
|
+
return { error: "Create command requires shape and name" };
|
|
1066
802
|
}
|
|
1067
|
-
|
|
1068
803
|
const shape = tokens[0];
|
|
1069
804
|
const name = tokens[1];
|
|
1070
805
|
const position = _node.position || { x: 0, y: 0, z: 0 };
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
color: _node.hologram?.color || '#00ffff',
|
|
806
|
+
const hologram = {
|
|
807
|
+
shape,
|
|
808
|
+
color: _node.hologram?.color || "#00ffff",
|
|
1075
809
|
size: _node.hologram?.size || 1,
|
|
1076
810
|
glow: _node.hologram?.glow !== false,
|
|
1077
|
-
interactive: _node.hologram?.interactive !== false
|
|
811
|
+
interactive: _node.hologram?.interactive !== false
|
|
1078
812
|
};
|
|
1079
|
-
|
|
1080
813
|
this.context.spatialMemory.set(name, position);
|
|
1081
814
|
this.createParticleEffect(`${name}_create`, position, hologram.color, 20);
|
|
1082
|
-
|
|
1083
|
-
logger.info('Create command executed', { shape, name, position });
|
|
1084
|
-
|
|
815
|
+
logger.info("Create command executed", { shape, name, position });
|
|
1085
816
|
return {
|
|
1086
817
|
created: name,
|
|
1087
818
|
shape,
|
|
1088
819
|
hologram,
|
|
1089
|
-
position
|
|
820
|
+
position
|
|
1090
821
|
};
|
|
1091
822
|
}
|
|
1092
|
-
|
|
1093
823
|
/**
|
|
1094
824
|
* Execute 'animate' command
|
|
1095
825
|
*/
|
|
1096
|
-
|
|
1097
|
-
const property = tokens[0] ||
|
|
1098
|
-
const duration = parseInt(tokens[1] ||
|
|
1099
|
-
|
|
1100
|
-
const animation: Animation = {
|
|
826
|
+
async executeAnimateCommand(target, tokens, _node) {
|
|
827
|
+
const property = tokens[0] || "position.y";
|
|
828
|
+
const duration = parseInt(tokens[1] || "1000", 10);
|
|
829
|
+
const animation = {
|
|
1101
830
|
target,
|
|
1102
831
|
property,
|
|
1103
832
|
from: 0,
|
|
1104
833
|
to: 1,
|
|
1105
834
|
duration,
|
|
1106
835
|
startTime: Date.now(),
|
|
1107
|
-
easing:
|
|
836
|
+
easing: "ease-in-out"
|
|
1108
837
|
};
|
|
1109
|
-
|
|
1110
838
|
this.animations.set(`${target}_${property}`, animation);
|
|
1111
|
-
|
|
1112
|
-
logger.info('Animate command executed', { target, property, duration });
|
|
1113
|
-
|
|
839
|
+
logger.info("Animate command executed", { target, property, duration });
|
|
1114
840
|
return {
|
|
1115
841
|
animating: target,
|
|
1116
|
-
animation
|
|
842
|
+
animation
|
|
1117
843
|
};
|
|
1118
844
|
}
|
|
1119
|
-
|
|
1120
845
|
/**
|
|
1121
846
|
* Execute 'pulse' command
|
|
1122
847
|
*/
|
|
1123
|
-
|
|
1124
|
-
const duration = parseInt(tokens[0] ||
|
|
848
|
+
async executePulseCommand(target, tokens, _node) {
|
|
849
|
+
const duration = parseInt(tokens[0] || "500", 10);
|
|
1125
850
|
const position = this.context.spatialMemory.get(target) || { x: 0, y: 0, z: 0 };
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
this.createParticleEffect(`${target}_pulse`, position, '#ffff00', 30);
|
|
1129
|
-
|
|
1130
|
-
// Create animation for scale
|
|
1131
|
-
const animation: Animation = {
|
|
851
|
+
this.createParticleEffect(`${target}_pulse`, position, "#ffff00", 30);
|
|
852
|
+
const animation = {
|
|
1132
853
|
target,
|
|
1133
|
-
property:
|
|
854
|
+
property: "scale",
|
|
1134
855
|
from: 1,
|
|
1135
856
|
to: 1.5,
|
|
1136
857
|
duration,
|
|
1137
858
|
startTime: Date.now(),
|
|
1138
|
-
easing:
|
|
859
|
+
easing: "sine",
|
|
1139
860
|
yoyo: true,
|
|
1140
|
-
loop: true
|
|
861
|
+
loop: true
|
|
1141
862
|
};
|
|
1142
|
-
|
|
1143
863
|
this.animations.set(`${target}_pulse`, animation);
|
|
1144
|
-
|
|
1145
|
-
logger.info('Pulse command executed', { target, duration });
|
|
1146
|
-
|
|
864
|
+
logger.info("Pulse command executed", { target, duration });
|
|
1147
865
|
return {
|
|
1148
866
|
pulsing: target,
|
|
1149
|
-
duration
|
|
867
|
+
duration
|
|
1150
868
|
};
|
|
1151
869
|
}
|
|
1152
|
-
|
|
1153
870
|
/**
|
|
1154
871
|
* Execute 'move' command
|
|
1155
872
|
*/
|
|
1156
|
-
|
|
1157
|
-
const x = parseFloat(tokens[0] ||
|
|
1158
|
-
const y = parseFloat(tokens[1] ||
|
|
1159
|
-
const z = parseFloat(tokens[2] ||
|
|
1160
|
-
const position
|
|
1161
|
-
|
|
873
|
+
async executeMoveCommand(target, tokens, _node) {
|
|
874
|
+
const x = parseFloat(tokens[0] || "0");
|
|
875
|
+
const y = parseFloat(tokens[1] || "0");
|
|
876
|
+
const z = parseFloat(tokens[2] || "0");
|
|
877
|
+
const position = { x, y, z };
|
|
1162
878
|
const current = this.context.spatialMemory.get(target);
|
|
1163
879
|
if (current) {
|
|
1164
880
|
this.context.spatialMemory.set(target, position);
|
|
1165
|
-
this.createConnectionStream(target, `${target}_move`, current, position,
|
|
881
|
+
this.createConnectionStream(target, `${target}_move`, current, position, "movement");
|
|
1166
882
|
} else {
|
|
1167
883
|
this.context.spatialMemory.set(target, position);
|
|
1168
884
|
}
|
|
1169
|
-
|
|
1170
|
-
logger.info('Move command executed', { target, position });
|
|
1171
|
-
|
|
885
|
+
logger.info("Move command executed", { target, position });
|
|
1172
886
|
return {
|
|
1173
887
|
moved: target,
|
|
1174
|
-
to: position
|
|
888
|
+
to: position
|
|
1175
889
|
};
|
|
1176
890
|
}
|
|
1177
|
-
|
|
1178
891
|
/**
|
|
1179
892
|
* Execute 'delete' command
|
|
1180
893
|
*/
|
|
1181
|
-
|
|
894
|
+
async executeDeleteCommand(target, _node) {
|
|
1182
895
|
const position = this.context.spatialMemory.get(target);
|
|
1183
896
|
if (position) {
|
|
1184
|
-
this.createParticleEffect(`${target}_delete`, position,
|
|
897
|
+
this.createParticleEffect(`${target}_delete`, position, "#ff0000", 15);
|
|
1185
898
|
this.context.spatialMemory.delete(target);
|
|
1186
899
|
}
|
|
1187
|
-
|
|
1188
|
-
logger.info('Delete command executed', { target });
|
|
1189
|
-
|
|
900
|
+
logger.info("Delete command executed", { target });
|
|
1190
901
|
return {
|
|
1191
|
-
deleted: target
|
|
902
|
+
deleted: target
|
|
1192
903
|
};
|
|
1193
904
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
color: node.type === 'nexus' ? '#9b59b6' : '#e74c3c',
|
|
1200
|
-
size: node.type === 'nexus' ? 3 : 4,
|
|
905
|
+
async executeStructure(node) {
|
|
906
|
+
const hologram = node.hologram || {
|
|
907
|
+
shape: node.type === "nexus" ? "sphere" : "cube",
|
|
908
|
+
color: node.type === "nexus" ? "#9b59b6" : "#e74c3c",
|
|
909
|
+
size: node.type === "nexus" ? 3 : 4,
|
|
1201
910
|
glow: true,
|
|
1202
|
-
interactive: true
|
|
911
|
+
interactive: true
|
|
1203
912
|
};
|
|
1204
|
-
|
|
1205
913
|
return {
|
|
1206
914
|
success: true,
|
|
1207
915
|
output: { type: node.type, created: true },
|
|
1208
916
|
hologram,
|
|
1209
|
-
spatialPosition: node.position
|
|
917
|
+
spatialPosition: node.position
|
|
1210
918
|
};
|
|
1211
919
|
}
|
|
1212
|
-
|
|
1213
|
-
private async executeAssignment(node: ASTNode & { name: string; value: unknown }): Promise<ExecutionResult> {
|
|
920
|
+
async executeAssignment(node) {
|
|
1214
921
|
const value = this.evaluateExpression(String(node.value));
|
|
1215
922
|
this.setVariable(node.name, value);
|
|
1216
|
-
|
|
1217
923
|
return {
|
|
1218
924
|
success: true,
|
|
1219
|
-
output: { assigned: node.name, value }
|
|
925
|
+
output: { assigned: node.name, value }
|
|
1220
926
|
};
|
|
1221
927
|
}
|
|
1222
|
-
|
|
1223
|
-
private async executeReturn(node: ASTNode & { value: unknown }): Promise<ExecutionResult> {
|
|
928
|
+
async executeReturn(node) {
|
|
1224
929
|
const value = this.evaluateExpression(String(node.value));
|
|
1225
|
-
|
|
1226
930
|
return {
|
|
1227
931
|
success: true,
|
|
1228
|
-
output: value
|
|
932
|
+
output: value
|
|
1229
933
|
};
|
|
1230
934
|
}
|
|
1231
|
-
|
|
1232
935
|
// ============================================================================
|
|
1233
936
|
// Condition Evaluation
|
|
1234
937
|
// ============================================================================
|
|
1235
|
-
|
|
1236
|
-
private evaluateCondition(condition: string): boolean {
|
|
938
|
+
evaluateCondition(condition) {
|
|
1237
939
|
if (!condition) return false;
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
logger.warn('Suspicious condition blocked', { condition });
|
|
940
|
+
const suspiciousKeywords = ["eval", "process", "require", "__proto__", "constructor"];
|
|
941
|
+
if (suspiciousKeywords.some((kw) => condition.toLowerCase().includes(kw))) {
|
|
942
|
+
logger.warn("Suspicious condition blocked", { condition });
|
|
1242
943
|
return false;
|
|
1243
944
|
}
|
|
1244
|
-
|
|
1245
945
|
try {
|
|
1246
|
-
|
|
1247
|
-
if (condition.trim().toLowerCase() ===
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
// Comparison operators
|
|
1251
|
-
const comparisonPatterns: Array<{ regex: RegExp; logical?: string }> = [
|
|
946
|
+
if (condition.trim().toLowerCase() === "true") return true;
|
|
947
|
+
if (condition.trim().toLowerCase() === "false") return false;
|
|
948
|
+
const comparisonPatterns = [
|
|
1252
949
|
{ regex: /^(.+?)\s*(===|!==)\s*(.+)$/ },
|
|
1253
950
|
{ regex: /^(.+?)\s*(==|!=|>=|<=|>|<)\s*(.+)$/ },
|
|
1254
|
-
{ regex: /^(.+?)\s*(&&)\s*(.+)$/, logical:
|
|
1255
|
-
{ regex: /^(.+?)\s*(\|\|)\s*(.+)$/, logical:
|
|
951
|
+
{ regex: /^(.+?)\s*(&&)\s*(.+)$/, logical: "and" },
|
|
952
|
+
{ regex: /^(.+?)\s*(\|\|)\s*(.+)$/, logical: "or" }
|
|
1256
953
|
];
|
|
1257
|
-
|
|
1258
954
|
for (const { regex, logical } of comparisonPatterns) {
|
|
1259
955
|
const match = condition.match(regex);
|
|
1260
956
|
if (match) {
|
|
1261
957
|
const [, leftExpr, operator, rightExpr] = match;
|
|
1262
958
|
const left = this.evaluateExpression(leftExpr.trim());
|
|
1263
959
|
const right = this.evaluateExpression(rightExpr.trim());
|
|
1264
|
-
|
|
1265
|
-
if (logical ===
|
|
1266
|
-
if (logical === 'or') return Boolean(left) || Boolean(right);
|
|
1267
|
-
|
|
960
|
+
if (logical === "and") return Boolean(left) && Boolean(right);
|
|
961
|
+
if (logical === "or") return Boolean(left) || Boolean(right);
|
|
1268
962
|
switch (operator) {
|
|
1269
|
-
case
|
|
1270
|
-
|
|
1271
|
-
case
|
|
1272
|
-
|
|
1273
|
-
case
|
|
1274
|
-
|
|
1275
|
-
case
|
|
1276
|
-
|
|
963
|
+
case "===":
|
|
964
|
+
return left === right;
|
|
965
|
+
case "!==":
|
|
966
|
+
return left !== right;
|
|
967
|
+
case "==":
|
|
968
|
+
return left == right;
|
|
969
|
+
case "!=":
|
|
970
|
+
return left != right;
|
|
971
|
+
case ">=":
|
|
972
|
+
return Number(left) >= Number(right);
|
|
973
|
+
case "<=":
|
|
974
|
+
return Number(left) <= Number(right);
|
|
975
|
+
case ">":
|
|
976
|
+
return Number(left) > Number(right);
|
|
977
|
+
case "<":
|
|
978
|
+
return Number(left) < Number(right);
|
|
1277
979
|
}
|
|
1278
980
|
}
|
|
1279
981
|
}
|
|
1280
|
-
|
|
1281
|
-
// Negation
|
|
1282
|
-
if (condition.startsWith('!')) {
|
|
982
|
+
if (condition.startsWith("!")) {
|
|
1283
983
|
return !this.evaluateCondition(condition.slice(1).trim());
|
|
1284
984
|
}
|
|
1285
|
-
|
|
1286
|
-
// Variable truthiness
|
|
1287
985
|
const value = this.evaluateExpression(condition.trim());
|
|
1288
986
|
return Boolean(value);
|
|
1289
987
|
} catch (error) {
|
|
1290
|
-
logger.error(
|
|
988
|
+
logger.error("Condition evaluation error", { condition, error });
|
|
1291
989
|
return false;
|
|
1292
990
|
}
|
|
1293
991
|
}
|
|
1294
|
-
|
|
1295
992
|
// ============================================================================
|
|
1296
993
|
// Transformation
|
|
1297
994
|
// ============================================================================
|
|
1298
|
-
|
|
1299
|
-
private async applyTransformation(data: unknown, transform: TransformationNode): Promise<unknown> {
|
|
995
|
+
async applyTransformation(data, transform) {
|
|
1300
996
|
const params = transform.parameters || {};
|
|
1301
|
-
|
|
1302
997
|
switch (transform.operation) {
|
|
1303
|
-
case
|
|
998
|
+
case "filter": {
|
|
1304
999
|
if (!Array.isArray(data)) return data;
|
|
1305
|
-
const predicate = params.predicate
|
|
1000
|
+
const predicate = params.predicate;
|
|
1306
1001
|
if (predicate) {
|
|
1307
|
-
return data.filter(item => {
|
|
1308
|
-
this.setVariable(
|
|
1002
|
+
return data.filter((item) => {
|
|
1003
|
+
this.setVariable("_item", item);
|
|
1309
1004
|
return this.evaluateCondition(predicate);
|
|
1310
1005
|
});
|
|
1311
1006
|
}
|
|
1312
|
-
return data.filter(item => item !== null && item !==
|
|
1007
|
+
return data.filter((item) => item !== null && item !== void 0);
|
|
1313
1008
|
}
|
|
1314
|
-
|
|
1315
|
-
case 'map': {
|
|
1009
|
+
case "map": {
|
|
1316
1010
|
if (!Array.isArray(data)) return data;
|
|
1317
|
-
const mapper = params.mapper
|
|
1011
|
+
const mapper = params.mapper;
|
|
1318
1012
|
if (mapper) {
|
|
1319
|
-
return data.map(item => {
|
|
1320
|
-
this.setVariable(
|
|
1013
|
+
return data.map((item) => {
|
|
1014
|
+
this.setVariable("_item", item);
|
|
1321
1015
|
return this.evaluateExpression(mapper);
|
|
1322
1016
|
});
|
|
1323
1017
|
}
|
|
1324
|
-
return data.map(item => ({ value: item, processed: true }));
|
|
1018
|
+
return data.map((item) => ({ value: item, processed: true }));
|
|
1325
1019
|
}
|
|
1326
|
-
|
|
1327
|
-
case 'reduce': {
|
|
1020
|
+
case "reduce": {
|
|
1328
1021
|
if (!Array.isArray(data)) return data;
|
|
1329
1022
|
const initial = params.initial ?? 0;
|
|
1330
|
-
const reducer = params.reducer
|
|
1023
|
+
const reducer = params.reducer;
|
|
1331
1024
|
if (reducer) {
|
|
1332
1025
|
return data.reduce((acc, item) => {
|
|
1333
|
-
this.setVariable(
|
|
1334
|
-
this.setVariable(
|
|
1026
|
+
this.setVariable("_acc", acc);
|
|
1027
|
+
this.setVariable("_item", item);
|
|
1335
1028
|
return this.evaluateExpression(reducer);
|
|
1336
1029
|
}, initial);
|
|
1337
1030
|
}
|
|
1338
|
-
return data.reduce((acc, item) => acc + (typeof item ===
|
|
1031
|
+
return data.reduce((acc, item) => acc + (typeof item === "number" ? item : 0), 0);
|
|
1339
1032
|
}
|
|
1340
|
-
|
|
1341
|
-
case 'sort': {
|
|
1033
|
+
case "sort": {
|
|
1342
1034
|
if (!Array.isArray(data)) return data;
|
|
1343
|
-
const key = params.key
|
|
1344
|
-
const desc = params.descending
|
|
1035
|
+
const key = params.key;
|
|
1036
|
+
const desc = params.descending;
|
|
1345
1037
|
const sorted = [...data].sort((a, b) => {
|
|
1346
|
-
const aVal = key ?
|
|
1347
|
-
const bVal = key ?
|
|
1038
|
+
const aVal = key ? a[key] : a;
|
|
1039
|
+
const bVal = key ? b[key] : b;
|
|
1348
1040
|
if (aVal < bVal) return desc ? 1 : -1;
|
|
1349
1041
|
if (aVal > bVal) return desc ? -1 : 1;
|
|
1350
1042
|
return 0;
|
|
1351
1043
|
});
|
|
1352
1044
|
return sorted;
|
|
1353
1045
|
}
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
case 'count':
|
|
1046
|
+
case "sum":
|
|
1047
|
+
return Array.isArray(data) ? data.reduce((sum, item) => sum + (typeof item === "number" ? item : 0), 0) : data;
|
|
1048
|
+
case "count":
|
|
1359
1049
|
return Array.isArray(data) ? data.length : 1;
|
|
1360
|
-
|
|
1361
|
-
case 'unique':
|
|
1050
|
+
case "unique":
|
|
1362
1051
|
return Array.isArray(data) ? [...new Set(data)] : data;
|
|
1363
|
-
|
|
1364
|
-
case 'flatten':
|
|
1052
|
+
case "flatten":
|
|
1365
1053
|
return Array.isArray(data) ? data.flat() : data;
|
|
1366
|
-
|
|
1367
|
-
case 'reverse':
|
|
1054
|
+
case "reverse":
|
|
1368
1055
|
return Array.isArray(data) ? [...data].reverse() : data;
|
|
1369
|
-
|
|
1370
|
-
case 'take': {
|
|
1056
|
+
case "take": {
|
|
1371
1057
|
if (!Array.isArray(data)) return data;
|
|
1372
1058
|
const count = Number(params.count) || 10;
|
|
1373
1059
|
return data.slice(0, count);
|
|
1374
1060
|
}
|
|
1375
|
-
|
|
1376
|
-
case 'skip': {
|
|
1061
|
+
case "skip": {
|
|
1377
1062
|
if (!Array.isArray(data)) return data;
|
|
1378
1063
|
const count = Number(params.count) || 0;
|
|
1379
1064
|
return data.slice(count);
|
|
1380
1065
|
}
|
|
1381
|
-
|
|
1382
1066
|
default:
|
|
1383
|
-
logger.warn(
|
|
1067
|
+
logger.warn("Unknown transformation", { operation: transform.operation });
|
|
1384
1068
|
return data;
|
|
1385
1069
|
}
|
|
1386
1070
|
}
|
|
1387
|
-
|
|
1388
1071
|
// ============================================================================
|
|
1389
1072
|
// Event System
|
|
1390
1073
|
// ============================================================================
|
|
1391
|
-
|
|
1392
1074
|
/**
|
|
1393
1075
|
* Register event handler
|
|
1394
1076
|
*/
|
|
1395
|
-
on(event
|
|
1077
|
+
on(event, handler) {
|
|
1396
1078
|
const handlers = this.eventHandlers.get(event) || [];
|
|
1397
1079
|
handlers.push(handler);
|
|
1398
1080
|
this.eventHandlers.set(event, handlers);
|
|
1399
1081
|
}
|
|
1400
|
-
|
|
1401
1082
|
/**
|
|
1402
1083
|
* Remove event handler
|
|
1403
1084
|
*/
|
|
1404
|
-
off(event
|
|
1085
|
+
off(event, handler) {
|
|
1405
1086
|
if (!handler) {
|
|
1406
1087
|
this.eventHandlers.delete(event);
|
|
1407
1088
|
} else {
|
|
1408
1089
|
const handlers = this.eventHandlers.get(event) || [];
|
|
1409
|
-
this.eventHandlers.set(event, handlers.filter(h => h !== handler));
|
|
1090
|
+
this.eventHandlers.set(event, handlers.filter((h) => h !== handler));
|
|
1410
1091
|
}
|
|
1411
1092
|
}
|
|
1412
|
-
|
|
1413
1093
|
/**
|
|
1414
1094
|
* Emit event
|
|
1415
1095
|
*/
|
|
1416
|
-
async emit(event
|
|
1096
|
+
async emit(event, data) {
|
|
1417
1097
|
const handlers = this.eventHandlers.get(event) || [];
|
|
1418
1098
|
for (const handler of handlers) {
|
|
1419
1099
|
try {
|
|
1420
1100
|
await handler(data);
|
|
1421
1101
|
} catch (error) {
|
|
1422
|
-
logger.error(
|
|
1102
|
+
logger.error("Event handler error", { event, error });
|
|
1423
1103
|
}
|
|
1424
1104
|
}
|
|
1425
1105
|
}
|
|
1426
|
-
|
|
1427
1106
|
/**
|
|
1428
1107
|
* Trigger UI event
|
|
1429
1108
|
*/
|
|
1430
|
-
async triggerUIEvent(elementName
|
|
1109
|
+
async triggerUIEvent(elementName, eventType, data) {
|
|
1431
1110
|
const element = this.uiElements.get(elementName);
|
|
1432
1111
|
if (!element) {
|
|
1433
|
-
logger.warn(
|
|
1112
|
+
logger.warn("UI element not found", { elementName });
|
|
1434
1113
|
return;
|
|
1435
1114
|
}
|
|
1436
|
-
|
|
1437
|
-
// Update element state based on event
|
|
1438
|
-
if (eventType === 'change' && data !== undefined) {
|
|
1115
|
+
if (eventType === "change" && data !== void 0) {
|
|
1439
1116
|
element.value = data;
|
|
1440
1117
|
}
|
|
1441
|
-
|
|
1442
1118
|
await this.emit(`${elementName}.${eventType}`, data);
|
|
1443
1119
|
}
|
|
1444
|
-
|
|
1445
1120
|
// ============================================================================
|
|
1446
1121
|
// Animation System
|
|
1447
1122
|
// ============================================================================
|
|
1448
|
-
|
|
1449
1123
|
/**
|
|
1450
1124
|
* Update all animations
|
|
1451
1125
|
*/
|
|
1452
|
-
updateAnimations()
|
|
1126
|
+
updateAnimations() {
|
|
1453
1127
|
const now = Date.now();
|
|
1454
|
-
|
|
1455
1128
|
for (const [key, anim] of this.animations) {
|
|
1456
1129
|
const elapsed = now - anim.startTime;
|
|
1457
1130
|
let progress = Math.min(elapsed / anim.duration, 1);
|
|
1458
|
-
|
|
1459
|
-
// Apply easing
|
|
1460
1131
|
progress = this.applyEasing(progress, anim.easing);
|
|
1461
|
-
|
|
1462
|
-
// Calculate current value
|
|
1463
1132
|
let currentValue = anim.from + (anim.to - anim.from) * progress;
|
|
1464
|
-
|
|
1465
|
-
// Handle yoyo
|
|
1466
1133
|
if (anim.yoyo && progress >= 1) {
|
|
1467
1134
|
anim.startTime = now;
|
|
1468
1135
|
[anim.from, anim.to] = [anim.to, anim.from];
|
|
1469
1136
|
}
|
|
1470
|
-
|
|
1471
|
-
// Update the property
|
|
1472
1137
|
this.setVariable(`${anim.target}.${anim.property}`, currentValue);
|
|
1473
|
-
|
|
1474
|
-
// Remove completed non-looping animations
|
|
1475
1138
|
if (progress >= 1 && !anim.loop && !anim.yoyo) {
|
|
1476
1139
|
this.animations.delete(key);
|
|
1477
1140
|
} else if (progress >= 1 && anim.loop) {
|
|
@@ -1479,117 +1142,102 @@ export class HoloScriptRuntime {
|
|
|
1479
1142
|
}
|
|
1480
1143
|
}
|
|
1481
1144
|
}
|
|
1482
|
-
|
|
1483
|
-
private applyEasing(t: number, easing: string): number {
|
|
1145
|
+
applyEasing(t, easing) {
|
|
1484
1146
|
switch (easing) {
|
|
1485
|
-
case
|
|
1147
|
+
case "easeIn":
|
|
1486
1148
|
return t * t;
|
|
1487
|
-
case
|
|
1149
|
+
case "easeOut":
|
|
1488
1150
|
return t * (2 - t);
|
|
1489
|
-
case
|
|
1151
|
+
case "easeInOut":
|
|
1490
1152
|
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
1491
|
-
case
|
|
1153
|
+
case "easeInQuad":
|
|
1492
1154
|
return t * t;
|
|
1493
|
-
case
|
|
1155
|
+
case "easeOutQuad":
|
|
1494
1156
|
return t * (2 - t);
|
|
1495
|
-
case
|
|
1157
|
+
case "easeInOutQuad":
|
|
1496
1158
|
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
|
|
1497
|
-
case
|
|
1159
|
+
case "linear":
|
|
1498
1160
|
default:
|
|
1499
1161
|
return t;
|
|
1500
1162
|
}
|
|
1501
1163
|
}
|
|
1502
|
-
|
|
1503
1164
|
// ============================================================================
|
|
1504
1165
|
// Particle Effects
|
|
1505
1166
|
// ============================================================================
|
|
1506
|
-
|
|
1507
|
-
private createParticleEffect(name: string, position: SpatialPosition, color: string, count: number): void {
|
|
1167
|
+
createParticleEffect(name, position, color, count) {
|
|
1508
1168
|
const limitedCount = Math.min(count, RUNTIME_SECURITY_LIMITS.maxParticlesPerSystem);
|
|
1509
|
-
const particles
|
|
1510
|
-
|
|
1169
|
+
const particles = [];
|
|
1511
1170
|
for (let i = 0; i < limitedCount; i++) {
|
|
1512
1171
|
particles.push({
|
|
1513
1172
|
x: position.x + (Math.random() - 0.5) * 2,
|
|
1514
1173
|
y: position.y + (Math.random() - 0.5) * 2,
|
|
1515
|
-
z: position.z + (Math.random() - 0.5) * 2
|
|
1174
|
+
z: position.z + (Math.random() - 0.5) * 2
|
|
1516
1175
|
});
|
|
1517
1176
|
}
|
|
1518
|
-
|
|
1519
1177
|
this.particleSystems.set(name, {
|
|
1520
1178
|
particles,
|
|
1521
1179
|
color,
|
|
1522
|
-
lifetime:
|
|
1523
|
-
speed: 0.01
|
|
1180
|
+
lifetime: 3e3,
|
|
1181
|
+
speed: 0.01
|
|
1524
1182
|
});
|
|
1525
1183
|
}
|
|
1526
|
-
|
|
1527
|
-
private createConnectionStream(from: string, to: string, fromPos: SpatialPosition, toPos: SpatialPosition, dataType: string): void {
|
|
1184
|
+
createConnectionStream(from, to, fromPos, toPos, dataType) {
|
|
1528
1185
|
const streamName = `connection_${from}_${to}`;
|
|
1529
|
-
const particles
|
|
1186
|
+
const particles = [];
|
|
1530
1187
|
const steps = 20;
|
|
1531
|
-
|
|
1532
1188
|
for (let i = 0; i <= steps; i++) {
|
|
1533
1189
|
const t = i / steps;
|
|
1534
1190
|
particles.push({
|
|
1535
1191
|
x: fromPos.x + (toPos.x - fromPos.x) * t,
|
|
1536
1192
|
y: fromPos.y + (toPos.y - fromPos.y) * t,
|
|
1537
|
-
z: fromPos.z + (toPos.z - fromPos.z) * t
|
|
1193
|
+
z: fromPos.z + (toPos.z - fromPos.z) * t
|
|
1538
1194
|
});
|
|
1539
1195
|
}
|
|
1540
|
-
|
|
1541
1196
|
this.particleSystems.set(streamName, {
|
|
1542
1197
|
particles,
|
|
1543
1198
|
color: this.getDataTypeColor(dataType),
|
|
1544
|
-
lifetime:
|
|
1545
|
-
speed: 0.02
|
|
1199
|
+
lifetime: 5e3,
|
|
1200
|
+
speed: 0.02
|
|
1546
1201
|
});
|
|
1547
1202
|
}
|
|
1548
|
-
|
|
1549
|
-
private createFlowingStream(name: string, position: SpatialPosition, data: unknown): void {
|
|
1203
|
+
createFlowingStream(name, position, data) {
|
|
1550
1204
|
const count = Array.isArray(data) ? Math.min(data.length, 50) : 10;
|
|
1551
|
-
this.createParticleEffect(`${name}_flow`, position,
|
|
1205
|
+
this.createParticleEffect(`${name}_flow`, position, "#45b7d1", count);
|
|
1552
1206
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
this.createParticleEffect(`${name}_execution`, position, '#ff4500', 30);
|
|
1207
|
+
createExecutionEffect(name, position) {
|
|
1208
|
+
this.createParticleEffect(`${name}_execution`, position, "#ff4500", 30);
|
|
1556
1209
|
}
|
|
1557
|
-
|
|
1558
|
-
private createDataVisualization(name: string, data: unknown, position: SpatialPosition): void {
|
|
1210
|
+
createDataVisualization(name, data, position) {
|
|
1559
1211
|
let count = 10;
|
|
1560
1212
|
if (Array.isArray(data)) {
|
|
1561
1213
|
count = Math.min(data.length, 100);
|
|
1562
|
-
} else if (typeof data ===
|
|
1214
|
+
} else if (typeof data === "object" && data !== null) {
|
|
1563
1215
|
count = Math.min(Object.keys(data).length * 5, 50);
|
|
1564
1216
|
}
|
|
1565
|
-
this.createParticleEffect(`${name}_visualization`, position,
|
|
1217
|
+
this.createParticleEffect(`${name}_visualization`, position, "#32cd32", count);
|
|
1566
1218
|
}
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
'move': '#ff69b4',
|
|
1219
|
+
getDataTypeColor(dataType) {
|
|
1220
|
+
const colors = {
|
|
1221
|
+
"string": "#ff6b35",
|
|
1222
|
+
"number": "#4ecdc4",
|
|
1223
|
+
"boolean": "#45b7d1",
|
|
1224
|
+
"object": "#96ceb4",
|
|
1225
|
+
"array": "#ffeaa7",
|
|
1226
|
+
"any": "#dda0dd",
|
|
1227
|
+
"move": "#ff69b4"
|
|
1577
1228
|
};
|
|
1578
|
-
return colors[dataType] ||
|
|
1229
|
+
return colors[dataType] || "#ffffff";
|
|
1579
1230
|
}
|
|
1580
|
-
|
|
1581
1231
|
// ============================================================================
|
|
1582
1232
|
// Public API
|
|
1583
1233
|
// ============================================================================
|
|
1584
|
-
|
|
1585
|
-
getParticleSystems(): Map<string, ParticleSystem> {
|
|
1234
|
+
getParticleSystems() {
|
|
1586
1235
|
return new Map(this.particleSystems);
|
|
1587
1236
|
}
|
|
1588
|
-
|
|
1589
|
-
updateParticles(deltaTime: number): void {
|
|
1237
|
+
updateParticles(deltaTime) {
|
|
1590
1238
|
for (const [name, system] of this.particleSystems) {
|
|
1591
1239
|
system.lifetime -= deltaTime;
|
|
1592
|
-
system.particles.forEach(particle => {
|
|
1240
|
+
system.particles.forEach((particle) => {
|
|
1593
1241
|
particle.x += (Math.random() - 0.5) * system.speed;
|
|
1594
1242
|
particle.y += (Math.random() - 0.5) * system.speed;
|
|
1595
1243
|
particle.z += (Math.random() - 0.5) * system.speed;
|
|
@@ -1599,24 +1247,19 @@ export class HoloScriptRuntime {
|
|
|
1599
1247
|
}
|
|
1600
1248
|
}
|
|
1601
1249
|
}
|
|
1602
|
-
|
|
1603
|
-
getContext(): RuntimeContext {
|
|
1250
|
+
getContext() {
|
|
1604
1251
|
return { ...this.context };
|
|
1605
1252
|
}
|
|
1606
|
-
|
|
1607
|
-
getUIElements(): Map<string, UIElementState> {
|
|
1253
|
+
getUIElements() {
|
|
1608
1254
|
return new Map(this.uiElements);
|
|
1609
1255
|
}
|
|
1610
|
-
|
|
1611
|
-
getUIElement(name: string): UIElementState | undefined {
|
|
1256
|
+
getUIElement(name) {
|
|
1612
1257
|
return this.uiElements.get(name);
|
|
1613
1258
|
}
|
|
1614
|
-
|
|
1615
|
-
getAnimations(): Map<string, Animation> {
|
|
1259
|
+
getAnimations() {
|
|
1616
1260
|
return new Map(this.animations);
|
|
1617
1261
|
}
|
|
1618
|
-
|
|
1619
|
-
reset(): void {
|
|
1262
|
+
reset() {
|
|
1620
1263
|
this.context = this.createEmptyContext();
|
|
1621
1264
|
this.currentScope = { variables: this.context.variables };
|
|
1622
1265
|
this.callStack = [];
|
|
@@ -1626,28 +1269,28 @@ export class HoloScriptRuntime {
|
|
|
1626
1269
|
this.animations.clear();
|
|
1627
1270
|
this.uiElements.clear();
|
|
1628
1271
|
}
|
|
1629
|
-
|
|
1630
|
-
private createEmptyContext(): RuntimeContext {
|
|
1272
|
+
createEmptyContext() {
|
|
1631
1273
|
return {
|
|
1632
|
-
variables: new Map(),
|
|
1633
|
-
functions: new Map(),
|
|
1634
|
-
exports: new Map(),
|
|
1274
|
+
variables: /* @__PURE__ */ new Map(),
|
|
1275
|
+
functions: /* @__PURE__ */ new Map(),
|
|
1276
|
+
exports: /* @__PURE__ */ new Map(),
|
|
1635
1277
|
connections: [],
|
|
1636
|
-
spatialMemory: new Map(),
|
|
1637
|
-
hologramState: new Map(),
|
|
1638
|
-
executionStack: []
|
|
1278
|
+
spatialMemory: /* @__PURE__ */ new Map(),
|
|
1279
|
+
hologramState: /* @__PURE__ */ new Map(),
|
|
1280
|
+
executionStack: []
|
|
1639
1281
|
};
|
|
1640
1282
|
}
|
|
1641
|
-
|
|
1642
|
-
getExecutionHistory(): ExecutionResult[] {
|
|
1283
|
+
getExecutionHistory() {
|
|
1643
1284
|
return [...this.executionHistory];
|
|
1644
1285
|
}
|
|
1645
|
-
|
|
1646
|
-
getHologramStates(): Map<string, HologramProperties> {
|
|
1286
|
+
getHologramStates() {
|
|
1647
1287
|
return new Map(this.context.hologramState);
|
|
1648
1288
|
}
|
|
1649
|
-
|
|
1650
|
-
getCallStack(): string[] {
|
|
1289
|
+
getCallStack() {
|
|
1651
1290
|
return [...this.callStack];
|
|
1652
1291
|
}
|
|
1653
|
-
}
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
export { HoloScriptRuntime };
|
|
1295
|
+
//# sourceMappingURL=chunk-EU6CZMGJ.js.map
|
|
1296
|
+
//# sourceMappingURL=chunk-EU6CZMGJ.js.map
|