@robinpath/robinpath 0.30.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 (65) hide show
  1. package/README.md +856 -0
  2. package/bin/robinpath.js +374 -0
  3. package/dist/classes/ASTSerializer.d.ts +45 -0
  4. package/dist/classes/ExecutionStateTracker.d.ts +30 -0
  5. package/dist/classes/Executor.d.ts +193 -0
  6. package/dist/classes/ExpressionEvaluator.d.ts +20 -0
  7. package/dist/classes/Lexer.d.ts +86 -0
  8. package/dist/classes/Parser.d.ts +71 -0
  9. package/dist/classes/RobinPathThread.d.ts +146 -0
  10. package/dist/classes/TokenStream.d.ts +217 -0
  11. package/dist/classes/code-converter/ASTToCodeConverter.d.ts +178 -0
  12. package/dist/classes/code-converter/LineIndex.d.ts +54 -0
  13. package/dist/classes/code-converter/Printer.d.ts +117 -0
  14. package/dist/classes/code-converter/Writer.d.ts +42 -0
  15. package/dist/classes/code-converter/index.d.ts +8 -0
  16. package/dist/classes/code-converter/types.d.ts +29 -0
  17. package/dist/classes/exceptions.d.ts +26 -0
  18. package/dist/classes/index.d.ts +16 -0
  19. package/dist/index.d.ts +485 -0
  20. package/dist/index.js +13808 -0
  21. package/dist/modules/Array.d.ts +10 -0
  22. package/dist/modules/Core.d.ts +10 -0
  23. package/dist/modules/Dom.d.ts +10 -0
  24. package/dist/modules/Fetch.d.ts +6 -0
  25. package/dist/modules/Json.d.ts +10 -0
  26. package/dist/modules/Math.d.ts +10 -0
  27. package/dist/modules/Object.d.ts +10 -0
  28. package/dist/modules/Random.d.ts +6 -0
  29. package/dist/modules/String.d.ts +10 -0
  30. package/dist/modules/Test.d.ts +10 -0
  31. package/dist/modules/Time.d.ts +10 -0
  32. package/dist/parsers/ArrayLiteralParser.d.ts +17 -0
  33. package/dist/parsers/AssignmentParser.d.ts +37 -0
  34. package/dist/parsers/BracketParser.d.ts +31 -0
  35. package/dist/parsers/BreakParser.d.ts +15 -0
  36. package/dist/parsers/CellBlockParser.d.ts +11 -0
  37. package/dist/parsers/ChunkMarkerParser.d.ts +12 -0
  38. package/dist/parsers/CommandParser.d.ts +56 -0
  39. package/dist/parsers/CommentParser.d.ts +37 -0
  40. package/dist/parsers/ContinueParser.d.ts +15 -0
  41. package/dist/parsers/DecoratorParser.d.ts +29 -0
  42. package/dist/parsers/DefineParser.d.ts +18 -0
  43. package/dist/parsers/EventParser.d.ts +17 -0
  44. package/dist/parsers/ExpressionParser.d.ts +3 -0
  45. package/dist/parsers/FenceClassifier.d.ts +29 -0
  46. package/dist/parsers/ForLoopParser.d.ts +17 -0
  47. package/dist/parsers/IfBlockParser.d.ts +17 -0
  48. package/dist/parsers/ObjectLiteralParser.d.ts +17 -0
  49. package/dist/parsers/ParserUtils.d.ts +15 -0
  50. package/dist/parsers/PromptBlockParser.d.ts +10 -0
  51. package/dist/parsers/ReturnParser.d.ts +16 -0
  52. package/dist/parsers/ScopeParser.d.ts +24 -0
  53. package/dist/parsers/StringTemplateParser.d.ts +31 -0
  54. package/dist/parsers/SubexpressionParser.d.ts +33 -0
  55. package/dist/parsers/TogetherBlockParser.d.ts +18 -0
  56. package/dist/parsers/WithScopeParser.d.ts +24 -0
  57. package/dist/types/Ast.type.d.ts +455 -0
  58. package/dist/types/Environment.type.d.ts +53 -0
  59. package/dist/utils/args.d.ts +24 -0
  60. package/dist/utils/errorFormatter.d.ts +22 -0
  61. package/dist/utils/index.d.ts +8 -0
  62. package/dist/utils/stringParsing.d.ts +41 -0
  63. package/dist/utils/types.d.ts +15 -0
  64. package/dist/utils/valueConversion.d.ts +25 -0
  65. package/package.json +50 -0
@@ -0,0 +1,374 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { createInterface } from 'readline';
4
+ import { RobinPath } from '../dist/index.js';
5
+
6
+ // Create interpreter instance with thread control enabled and start a thread for REPL
7
+ const rp = new RobinPath({ threadControl: true });
8
+ rp.createThread('default'); // Creates and sets as currentThread
9
+
10
+ // Helper function to get the prompt with thread ID and current module
11
+ function getPrompt() {
12
+ if (!rp.currentThread) return '> ';
13
+ const threadId = rp.currentThread.id;
14
+ const currentModule = rp.currentThread.getCurrentModule();
15
+ if (currentModule) {
16
+ return `${threadId}@${currentModule}> `;
17
+ }
18
+ return `${threadId}> `;
19
+ }
20
+
21
+ // Create readline interface (prompt will be updated after thread is ready)
22
+ const rl = createInterface({
23
+ input: process.stdin,
24
+ output: process.stdout,
25
+ prompt: '> '
26
+ });
27
+
28
+ // Set the initial prompt with current module
29
+ rl.setPrompt(getPrompt());
30
+
31
+ // State for multi-line blocks
32
+ let accumulatedLines = [];
33
+
34
+ // Helper function to check if a line ends with backslash (ignoring trailing whitespace)
35
+ function endsWithBackslash(line) {
36
+ const trimmed = line.trimEnd();
37
+ return trimmed.endsWith('\\');
38
+ }
39
+
40
+ // Process a line of input
41
+ async function processLine(line) {
42
+ const trimmed = line.trim();
43
+
44
+ // Skip empty lines
45
+ if (!trimmed) {
46
+ return;
47
+ }
48
+
49
+ // Handle exit commands
50
+ if (trimmed === 'exit' || trimmed === 'quit' || trimmed === '.exit' || trimmed === '.quit') {
51
+ console.log('Goodbye!');
52
+ rl.close();
53
+ process.exit(0);
54
+ return;
55
+ }
56
+
57
+ // Handle help
58
+ if (trimmed === 'help' || trimmed === '.help') {
59
+ console.log(`
60
+ RobinPath REPL Commands:
61
+ exit, quit, .exit, .quit - Exit the REPL
62
+ help, .help - Show this help message
63
+ clear, .clear - Clear the screen
64
+ .. - Show all available commands as JSON
65
+
66
+ Multi-line blocks:
67
+ def <name> ... enddef - Define a function
68
+ if <expr> ... endif - Conditional block
69
+ for $var in <expr> ... endfor - Loop block
70
+ scope ... endscope - Scope block
71
+ fn(...) - Parenthesized function call (multi-line)
72
+ { ... } - Object literal (multi-line)
73
+ [ ... ] - Array literal (multi-line)
74
+ <line> \\ - Backslash line continuation
75
+ `);
76
+ return;
77
+ }
78
+
79
+ // Handle clear
80
+ if (trimmed === 'clear' || trimmed === '.clear') {
81
+ console.clear();
82
+ return;
83
+ }
84
+
85
+ // Handle ".." command - show available commands
86
+ if (trimmed === '..') {
87
+ let commands;
88
+ if (rp.currentThread) {
89
+ commands = rp.currentThread.getAvailableCommands();
90
+ } else {
91
+ commands = rp.getAvailableCommands();
92
+ }
93
+
94
+ // Just show JSON
95
+ console.log(JSON.stringify(commands, null, 2));
96
+ return;
97
+ }
98
+
99
+ // If we have accumulated lines, add this line and check if block is complete
100
+ if (accumulatedLines.length > 0) {
101
+ accumulatedLines.push(line);
102
+ const script = accumulatedLines.join('\n');
103
+
104
+ // Check if line ends with backslash - if so, continue accumulating
105
+ if (endsWithBackslash(line)) {
106
+ // Still in continuation mode, update prompt
107
+ if (!rp.currentThread) {
108
+ rl.setPrompt(`... `);
109
+ } else {
110
+ const threadId = rp.currentThread.id;
111
+ const currentModule = rp.currentThread.getCurrentModule();
112
+ if (currentModule) {
113
+ rl.setPrompt(`[${threadId}]@[${currentModule}]... `);
114
+ } else {
115
+ rl.setPrompt(`[${threadId}]... `);
116
+ }
117
+ }
118
+ return;
119
+ }
120
+
121
+ // Check if the block is now complete using the built-in method
122
+ let needsMore;
123
+ if (rp.currentThread) {
124
+ needsMore = rp.currentThread.needsMoreInput(script);
125
+ } else {
126
+ needsMore = rp.needsMoreInput(script);
127
+ }
128
+
129
+ if (!needsMore.needsMore) {
130
+ // Block is complete, execute it
131
+ const finalScript = accumulatedLines.join('\n');
132
+ accumulatedLines = [];
133
+
134
+ try {
135
+ let result;
136
+ if (rp.currentThread) {
137
+ // Execute in current thread
138
+ result = await rp.currentThread.executeScript(finalScript);
139
+ } else {
140
+ // Execute in global thread (root RobinPath instance)
141
+ result = await rp.executeScript(finalScript);
142
+ }
143
+
144
+ // Check if result is from explain command (structured object)
145
+ if (result && typeof result === 'object' && !Array.isArray(result) && result.type) {
146
+ if (result.type === 'function') {
147
+ // Format function documentation
148
+ console.log(`\nFunction: ${result.name}`);
149
+ console.log(`\nDescription: ${result.description}\n`);
150
+
151
+ if (result.parameters && result.parameters.length > 0) {
152
+ console.log('Parameters:');
153
+ for (const param of result.parameters) {
154
+ let paramLine = ` - ${param.name} (${param.dataType})`;
155
+ if (param.required) {
156
+ paramLine += ' [required]';
157
+ }
158
+ console.log(paramLine);
159
+ console.log(` ${param.description}`);
160
+ if (param.formInputType) {
161
+ console.log(` Input type: ${param.formInputType}`);
162
+ }
163
+ if (param.defaultValue !== undefined) {
164
+ console.log(` Default: ${JSON.stringify(param.defaultValue)}`);
165
+ }
166
+ }
167
+ } else {
168
+ console.log('Parameters: None');
169
+ }
170
+
171
+ console.log(`\nReturns: ${result.returnType}`);
172
+ if (result.returnDescription) {
173
+ console.log(` ${result.returnDescription}`);
174
+ }
175
+ console.log('');
176
+ } else if (result.type === 'module') {
177
+ // Format module documentation
178
+ console.log(`\nModule: ${result.name}`);
179
+ console.log(`\nDescription: ${result.description}\n`);
180
+
181
+ if (result.methods && result.methods.length > 0) {
182
+ console.log('Available Methods:');
183
+ for (const method of result.methods) {
184
+ console.log(` - ${method}`);
185
+ }
186
+ } else {
187
+ console.log('Available Methods: None');
188
+ }
189
+ console.log('');
190
+ } else if (result.error) {
191
+ console.log(result.error);
192
+ }
193
+ } else if (result && typeof result === 'object' && result.error) {
194
+ // Handle error objects
195
+ console.log(result.error);
196
+ } else if (result !== null && result !== undefined) {
197
+ // Only show result if it's meaningful
198
+ // (log commands already print, so we don't need to show null)
199
+ }
200
+ } catch (error) {
201
+ console.error(`Error: ${error.message}`);
202
+ }
203
+
204
+ // Reset prompt after block execution
205
+ rl.setPrompt(getPrompt());
206
+ } else {
207
+ // Still in block mode, update prompt to show continuation
208
+ if (!rp.currentThread) {
209
+ rl.setPrompt(`... `);
210
+ } else {
211
+ const threadId = rp.currentThread.id;
212
+ const currentModule = rp.currentThread.getCurrentModule();
213
+ if (currentModule) {
214
+ rl.setPrompt(`[${threadId}]@[${currentModule}]... `);
215
+ } else {
216
+ rl.setPrompt(`[${threadId}]... `);
217
+ }
218
+ }
219
+ }
220
+
221
+ return;
222
+ }
223
+
224
+ // Check if this line ends with backslash - if so, enter continuation mode
225
+ if (endsWithBackslash(line)) {
226
+ accumulatedLines = [line];
227
+ if (!rp.currentThread) {
228
+ rl.setPrompt(`... `);
229
+ } else {
230
+ const threadId = rp.currentThread.id;
231
+ const currentModule = rp.currentThread.getCurrentModule();
232
+ if (currentModule) {
233
+ rl.setPrompt(`[${threadId}]@[${currentModule}]... `);
234
+ } else {
235
+ rl.setPrompt(`[${threadId}]... `);
236
+ }
237
+ }
238
+ return;
239
+ }
240
+
241
+ // Check if this line starts an incomplete block using the built-in method
242
+ let needsMore;
243
+ if (rp.currentThread) {
244
+ needsMore = rp.currentThread.needsMoreInput(line);
245
+ } else {
246
+ needsMore = rp.needsMoreInput(line);
247
+ }
248
+
249
+ if (needsMore.needsMore) {
250
+ // This line starts an incomplete block, enter block mode
251
+ accumulatedLines = [line];
252
+ if (!rp.currentThread) {
253
+ rl.setPrompt(`... `);
254
+ } else {
255
+ const threadId = rp.currentThread.id;
256
+ const currentModule = rp.currentThread.getCurrentModule();
257
+ if (currentModule) {
258
+ rl.setPrompt(`[${threadId}]@[${currentModule}]... `);
259
+ } else {
260
+ rl.setPrompt(`[${threadId}]... `);
261
+ }
262
+ }
263
+ return;
264
+ }
265
+
266
+ // Regular single-line command - use executeLine for persistent state
267
+ try {
268
+ let result;
269
+ if (rp.currentThread) {
270
+ // Execute in current thread
271
+ result = await rp.currentThread.executeLine(line);
272
+ } else {
273
+ // Execute in global thread (root RobinPath instance)
274
+ result = await rp.executeLine(line);
275
+ }
276
+
277
+ // Check if result is from explain command (structured object)
278
+ if (result && typeof result === 'object' && !Array.isArray(result) && result.type) {
279
+ if (result.type === 'function') {
280
+ // Format function documentation
281
+ console.log(`\nFunction: ${result.name}`);
282
+ console.log(`\nDescription: ${result.description}\n`);
283
+
284
+ if (result.parameters && result.parameters.length > 0) {
285
+ console.log('Parameters:');
286
+ for (const param of result.parameters) {
287
+ let paramLine = ` - ${param.name} (${param.dataType})`;
288
+ if (param.required) {
289
+ paramLine += ' [required]';
290
+ }
291
+ console.log(paramLine);
292
+ console.log(` ${param.description}`);
293
+ if (param.formInputType) {
294
+ console.log(` Input type: ${param.formInputType}`);
295
+ }
296
+ if (param.defaultValue !== undefined) {
297
+ console.log(` Default: ${JSON.stringify(param.defaultValue)}`);
298
+ }
299
+ }
300
+ } else {
301
+ console.log('Parameters: None');
302
+ }
303
+
304
+ console.log(`\nReturns: ${result.returnType}`);
305
+ if (result.returnDescription) {
306
+ console.log(` ${result.returnDescription}`);
307
+ }
308
+ console.log('');
309
+ } else if (result.type === 'module') {
310
+ // Format module documentation
311
+ console.log(`\nModule: ${result.name}`);
312
+ console.log(`\nDescription: ${result.description}\n`);
313
+
314
+ if (result.methods && result.methods.length > 0) {
315
+ console.log('Available Methods:');
316
+ for (const method of result.methods) {
317
+ console.log(` - ${method}`);
318
+ }
319
+ } else {
320
+ console.log('Available Methods: None');
321
+ }
322
+ console.log('');
323
+ } else if (result.error) {
324
+ console.log(result.error);
325
+ }
326
+ } else if (result && typeof result === 'object' && result.error) {
327
+ // Handle error objects
328
+ console.log(result.error);
329
+ }
330
+
331
+ // Update prompt in case module context changed (e.g., "use" command)
332
+ rl.setPrompt(getPrompt());
333
+ // Don't print null/undefined results (log commands handle their own output)
334
+ if (result !== null && result !== undefined && result !== '' &&
335
+ (!result || typeof result !== 'object' || (!result.type && !result.error))) {
336
+ // Only print if it's a meaningful value and not a structured object
337
+ // Most commands use log for output, so we skip printing here
338
+ }
339
+ } catch (error) {
340
+ console.error(`Error: ${error.message}`);
341
+ }
342
+ }
343
+
344
+ // Start the REPL
345
+ console.log('RobinPath REPL');
346
+ console.log('Type "help" for commands, "exit" to quit');
347
+ console.log('');
348
+
349
+ rl.prompt();
350
+
351
+ rl.on('line', async (line) => {
352
+ await processLine(line);
353
+ rl.prompt();
354
+ });
355
+
356
+ rl.on('close', () => {
357
+ console.log('\nGoodbye!');
358
+ process.exit(0);
359
+ });
360
+
361
+ // Handle Ctrl+C gracefully
362
+ process.on('SIGINT', () => {
363
+ if (accumulatedLines.length > 0) {
364
+ console.log('\nBlock cancelled. Returning to normal mode.');
365
+ accumulatedLines = [];
366
+ rl.setPrompt(getPrompt());
367
+ rl.prompt();
368
+ } else {
369
+ console.log('\nGoodbye!');
370
+ rl.close();
371
+ process.exit(0);
372
+ }
373
+ });
374
+
@@ -0,0 +1,45 @@
1
+ import { Environment } from '../types/Environment.type';
2
+ import { Statement, Arg } from '../types/Ast.type';
3
+ import { Value } from '../utils';
4
+ export declare class ASTSerializer {
5
+ private environment;
6
+ constructor(environment: Environment);
7
+ /**
8
+ * Find the module name for a given function name
9
+ * Returns the module name if found, null otherwise
10
+ */
11
+ findModuleName(functionName: string, currentModuleContext?: string | null): string | null;
12
+ /**
13
+
14
+ * Get a simplified tree structure of the AST for navigation
15
+
16
+ */
17
+ getStructure(statements: Statement[], nodeKeyPrefix?: string): any[];
18
+ /**
19
+
20
+ * Generate a human-readable label for a statement
21
+
22
+ */
23
+ private getNodeLabel;
24
+ /**
25
+
26
+ * Serialize a statement to a JSON-serializable object
27
+
28
+ * @param stmt The statement to serialize
29
+
30
+ * @param currentModuleContext Optional module context from "use" command
31
+
32
+ * @param lastValue Optional last value (execution state) - can be a Value or a state object with lastValue and beforeValue
33
+
34
+ * @param nodeKey Optional key for the node
35
+
36
+ */
37
+ serializeStatement(stmt: Statement, currentModuleContext?: string | null, lastValue?: Value | {
38
+ lastValue: Value;
39
+ beforeValue: Value;
40
+ } | null, nodeKey?: string): any;
41
+ /**
42
+ * Serialize an argument to a JSON-serializable object
43
+ */
44
+ serializeArg(arg: Arg, currentModuleContext?: string | null, nodeKey?: string): any;
45
+ }
@@ -0,0 +1,30 @@
1
+ import { Value } from '../utils';
2
+ export interface ExecutionStepInfo {
3
+ nodeKey: string;
4
+ variables: Record<string, Value>;
5
+ result: Value;
6
+ timestamp: number;
7
+ }
8
+ export interface ExecutionLog {
9
+ message: string;
10
+ nodeKey?: string;
11
+ timestamp: number;
12
+ source?: 'log' | 'say' | string;
13
+ }
14
+ export type LogCallback = (log: ExecutionLog) => void;
15
+ export declare class ExecutionStateTracker {
16
+ private steps;
17
+ private logs;
18
+ private nodeStates;
19
+ private indexedStates;
20
+ private onLog;
21
+ setLogCallback(callback: LogCallback | null): void;
22
+ addStep(step: ExecutionStepInfo): void;
23
+ addLog(log: ExecutionLog): void;
24
+ getSteps(): ExecutionStepInfo[];
25
+ getLogs(): ExecutionLog[];
26
+ getNodeState(nodeKey: string): ExecutionStepInfo | undefined;
27
+ getState(index: number): any;
28
+ setState(index: number, state: any): void;
29
+ clear(): void;
30
+ }
@@ -0,0 +1,193 @@
1
+ import { Value } from '../utils';
2
+ import { Environment, Frame } from '../index';
3
+ import { Statement, Arg, DefineFunction, OnBlock, DecoratorCall, Expression } from '../types/Ast.type';
4
+ import { RobinPathThread } from './RobinPathThread';
5
+ export declare class Executor {
6
+ private environment;
7
+ private callStack;
8
+ private parentThread;
9
+ private sourceCode;
10
+ private recursionDepth;
11
+ private currentStatement;
12
+ private static readonly MAX_RECURSION_DEPTH;
13
+ /**
14
+ * Debug mode flag - set to true to enable logging
15
+ * Can be controlled via VITE_DEBUG environment variable or set programmatically
16
+ */
17
+ static debug: boolean;
18
+ constructor(environment: Environment, parentThread?: RobinPathThread | null, sourceCode?: string | null);
19
+ getCurrentFrame(frameOverride?: Frame): Frame;
20
+ getCurrentStatement(): Statement | null;
21
+ getEnvironment(): Environment;
22
+ getCallStack(): Frame[];
23
+ /**
24
+ * Compute Levenshtein distance between two strings
25
+ */
26
+ private levenshteinDistance;
27
+ /**
28
+ * Find similar function names for "did you mean?" suggestions
29
+ */
30
+ private findSimilarFunctions;
31
+ /**
32
+ * Format "Unknown function" error with suggestions
33
+ */
34
+ private unknownFunctionError;
35
+ /**
36
+ * Creates a new Executor instance that shares the same environment and call stack,
37
+ * but has its own call stack array to allow parallel execution without stack corruption.
38
+ * The frames themselves (locals Maps) are shared.
39
+ */
40
+ spawnChild(): Executor;
41
+ /**
42
+ * Execute an event handler with the provided arguments
43
+ * Arguments are available as $1, $2, $3, etc. in the handler body
44
+ */
45
+ executeEventHandler(handler: OnBlock, args: Value[]): Promise<void>;
46
+ /**
47
+ * Execute a single statement (public method for state tracking)
48
+ */
49
+ executeStatementPublic(stmt: Statement): Promise<void>;
50
+ /**
51
+ * Execute a function call and return the result (public method for expression evaluation)
52
+ */
53
+ executeFunctionCall(funcName: string, args: Arg[]): Promise<Value>;
54
+ execute(statements: Statement[]): Promise<Value>;
55
+ private executeStatement;
56
+ /**
57
+ * Get all variables visible in the current frame
58
+ */
59
+ private getVariableStateInternal;
60
+ /**
61
+ * Reconstructs the original input string from an Arg object.
62
+ * This is useful for commands that need to preserve the original input
63
+ * (e.g., variable/function names) rather than evaluating them.
64
+ *
65
+ * Examples:
66
+ * - { type: 'var', name: 'a' } -> '$a'
67
+ * - { type: 'var', name: 'a', path: [{ type: 'property', name: 'b' }] } -> '$a.b'
68
+ * - { type: 'var', name: 'a', path: [{ type: 'index', index: 0 }] } -> '$a[0]'
69
+ * - { type: 'string', value: 'hello' } -> 'hello'
70
+ *
71
+ * @param arg The Arg object to reconstruct
72
+ * @returns The original input string, or null if the arg type cannot be reconstructed
73
+ */
74
+ private reconstructOriginalInput;
75
+ private executeCommand;
76
+ /**
77
+ * Execute decorators for a target (function or variable)
78
+ * @param decorators Array of decorator calls
79
+ * @param targetName Name of the target (function or variable)
80
+ * @param func Function object (null for variables)
81
+ * @param originalArgs Original arguments (for functions, empty array for variables)
82
+ * @returns Modified arguments (for functions) or original args unchanged
83
+ */
84
+ executeDecorators(decorators: DecoratorCall[], targetName: string, func: DefineFunction | null, originalArgs: Value[], frameOverride?: Frame): Promise<Value[]>;
85
+ private callFunction;
86
+ private executeAssignment;
87
+ private executeShorthandAssignment;
88
+ private executeInlineIf;
89
+ private executeIfBlock;
90
+ private executeIfTrue;
91
+ private executeIfFalse;
92
+ private executeReturn;
93
+ private executeBreak;
94
+ private executeContinue;
95
+ private registerFunction;
96
+ private registerEventHandler;
97
+ private executeScope;
98
+ private executeTogether;
99
+ /**
100
+ * Set a variable at a path in the parent scope (for together blocks)
101
+ */
102
+ private setVariableAtPathInParentScope;
103
+ private executeForLoop;
104
+ private evaluateArg;
105
+ /**
106
+ * Interpolate variables and subexpressions in object literal code
107
+ * Replaces $var, $(expr), $ (last value), and [$key] with their actual values
108
+ *
109
+ * TODO: AST Refactor - This method will be removed once ObjectLiteralExpression
110
+ * is used. Object literals will be evaluated by walking the properties AST nodes.
111
+ */
112
+ private interpolateObjectLiteral;
113
+ /**
114
+ * Execute a subexpression from code string with frame override support
115
+ *
116
+ * @param code - The subexpression code to execute
117
+ * @param frameOverride - Optional frame override for variable resolution
118
+ */
119
+ private executeSubexpressionWithFrame;
120
+ /**
121
+ * Execute a subexpression from code string
122
+ *
123
+ * TODO: AST Refactor - This will be replaced with executeSubexpressionStatements()
124
+ * which takes Statement[] directly, eliminating runtime parsing.
125
+ */
126
+ executeSubexpression(code: string): Promise<Value>;
127
+ /**
128
+ * Execute subexpression statements directly (for Expression-based AST)
129
+ *
130
+ * @param statements - Pre-parsed statements from SubexpressionExpression.body
131
+ * @param frameOverride - Optional frame override for parallel execution
132
+ * @returns The lastValue after executing the statements
133
+ */
134
+ executeSubexpressionStatements(statements: Statement[], frameOverride?: Frame): Promise<Value>;
135
+ /**
136
+ * Evaluate an Expression node
137
+ *
138
+ * @param expr - The Expression node to evaluate
139
+ * @param frameOverride - Optional frame override
140
+ * @returns The evaluated value
141
+ */
142
+ evaluateExpression(expr: Expression, frameOverride?: Frame): Promise<Value>;
143
+ /**
144
+ * Evaluate an ObjectLiteralExpression
145
+ *
146
+ * @param expr - The ObjectLiteralExpression node
147
+ * @param frameOverride - Optional frame override
148
+ * @returns The evaluated object
149
+ */
150
+ evaluateObjectLiteral(expr: import('../types/Ast.type').ObjectLiteralExpression, frameOverride?: Frame): Promise<Record<string, Value>>;
151
+ /**
152
+ * Evaluate an ArrayLiteralExpression
153
+ *
154
+ * @param expr - The ArrayLiteralExpression node
155
+ * @param frameOverride - Optional frame override
156
+ * @returns The evaluated array
157
+ */
158
+ evaluateArrayLiteral(expr: import('../types/Ast.type').ArrayLiteralExpression, frameOverride?: Frame): Promise<Value[]>;
159
+ /**
160
+ * Evaluate a BinaryExpression
161
+ *
162
+ * @param expr - The BinaryExpression node
163
+ * @param frameOverride - Optional frame override
164
+ * @returns The evaluated value
165
+ */
166
+ evaluateBinaryExpression(expr: import('../types/Ast.type').BinaryExpression, frameOverride?: Frame): Promise<Value>;
167
+ /**
168
+ * Evaluate a UnaryExpression
169
+ *
170
+ * @param expr - The UnaryExpression node
171
+ * @param frameOverride - Optional frame override
172
+ * @returns The evaluated value
173
+ */
174
+ evaluateUnaryExpression(expr: import('../types/Ast.type').UnaryExpression, frameOverride?: Frame): Promise<Value>;
175
+ /**
176
+ * Evaluate a CallExpression
177
+ *
178
+ * @param expr - The CallExpression node
179
+ * @param frameOverride - Optional frame override
180
+ * @returns The evaluated value
181
+ */
182
+ evaluateCallExpression(expr: import('../types/Ast.type').CallExpression, frameOverride?: Frame): Promise<Value>;
183
+ private resolveVariable;
184
+ private setVariable;
185
+ /**
186
+ * Set a value at an attribute path (e.g., $animal.cat = 5 or $.property = value)
187
+ */
188
+ private setVariableAtPath;
189
+ /**
190
+ * Resolve a dynamic key segment to its actual key value
191
+ */
192
+ private resolveDynamicKey;
193
+ }
@@ -0,0 +1,20 @@
1
+ import { Frame, Environment } from '../index';
2
+ import { Executor } from './Executor';
3
+ export declare class ExpressionEvaluator {
4
+ private frame;
5
+ private globals;
6
+ private executor;
7
+ constructor(frame: Frame, globals: Environment, executor?: Executor | null);
8
+ evaluate(expr: string): Promise<boolean>;
9
+ /**
10
+ * Replace all subexpressions $(...) in an expression string with their evaluated values
11
+ */
12
+ private replaceSubexpressions;
13
+ /**
14
+ * Extract a subexpression $(...) from a string, starting at the given position
15
+ * Returns null if no valid subexpression is found
16
+ */
17
+ private extractSubexpressionFromString;
18
+ private executeFunctionCall;
19
+ private resolveVariable;
20
+ }