littlewing 0.5.3 → 0.6.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.
- package/README.md +145 -682
- package/dist/index.d.ts +35 -61
- package/dist/index.js +78 -516
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
declare namespace exports_ast {
|
|
2
|
-
export { unaryOp, subtract,
|
|
2
|
+
export { unaryOp, subtract, program, number, notEquals, negate, multiply, modulo, logicalOr, logicalAnd, lessThan, lessEqual, identifier, greaterThan, greaterEqual, functionCall, exponentiate, equals, divide, conditional, binaryOp, assign, add };
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
5
5
|
* Runtime value type - only numbers
|
|
@@ -44,7 +44,6 @@ declare enum TokenType {
|
|
|
44
44
|
COMMA = "COMMA",
|
|
45
45
|
QUESTION = "QUESTION",
|
|
46
46
|
COLON = "COLON",
|
|
47
|
-
NULLISH_ASSIGN = "NULLISH_ASSIGN",
|
|
48
47
|
EOF = "EOF"
|
|
49
48
|
}
|
|
50
49
|
/**
|
|
@@ -58,7 +57,7 @@ interface Token {
|
|
|
58
57
|
/**
|
|
59
58
|
* AST Node - base type
|
|
60
59
|
*/
|
|
61
|
-
type ASTNode = Program | NumberLiteral | Identifier | BinaryOp | UnaryOp | FunctionCall | Assignment | ConditionalExpression
|
|
60
|
+
type ASTNode = Program | NumberLiteral | Identifier | BinaryOp | UnaryOp | FunctionCall | Assignment | ConditionalExpression;
|
|
62
61
|
/**
|
|
63
62
|
* Program node (multiple statements)
|
|
64
63
|
*/
|
|
@@ -124,16 +123,6 @@ interface ConditionalExpression {
|
|
|
124
123
|
alternate: ASTNode;
|
|
125
124
|
}
|
|
126
125
|
/**
|
|
127
|
-
* Nullish assignment (x ??= 5)
|
|
128
|
-
* Assigns value only if variable is undefined (not provided in context)
|
|
129
|
-
* Used for providing defaults for external variables
|
|
130
|
-
*/
|
|
131
|
-
interface NullishAssignment {
|
|
132
|
-
type: "NullishAssignment";
|
|
133
|
-
name: string;
|
|
134
|
-
value: ASTNode;
|
|
135
|
-
}
|
|
136
|
-
/**
|
|
137
126
|
* Type guard functions for discriminated union narrowing
|
|
138
127
|
*/
|
|
139
128
|
declare function isNumberLiteral(node: ASTNode): node is NumberLiteral;
|
|
@@ -144,11 +133,14 @@ declare function isFunctionCall(node: ASTNode): node is FunctionCall;
|
|
|
144
133
|
declare function isAssignment(node: ASTNode): node is Assignment;
|
|
145
134
|
declare function isProgram(node: ASTNode): node is Program;
|
|
146
135
|
declare function isConditionalExpression(node: ASTNode): node is ConditionalExpression;
|
|
147
|
-
declare function isNullishAssignment(node: ASTNode): node is NullishAssignment;
|
|
148
136
|
/**
|
|
149
137
|
* Builder functions for creating AST nodes manually
|
|
150
138
|
*/
|
|
151
139
|
/**
|
|
140
|
+
* Create a program node
|
|
141
|
+
*/
|
|
142
|
+
declare function program(statements: ASTNode[]): Program;
|
|
143
|
+
/**
|
|
152
144
|
* Create a number literal node
|
|
153
145
|
*/
|
|
154
146
|
declare function number(value: number): NumberLiteral;
|
|
@@ -173,11 +165,6 @@ declare function functionCall(name: string, args?: ASTNode[]): FunctionCall;
|
|
|
173
165
|
*/
|
|
174
166
|
declare function assign(name: string, value: ASTNode): Assignment;
|
|
175
167
|
/**
|
|
176
|
-
* Create a nullish assignment node (x ??= 5)
|
|
177
|
-
* Assigns only if variable is undefined
|
|
178
|
-
*/
|
|
179
|
-
declare function nullishAssign(name: string, value: ASTNode): NullishAssignment;
|
|
180
|
-
/**
|
|
181
168
|
* Create a conditional expression node (ternary operator)
|
|
182
169
|
*/
|
|
183
170
|
declare function conditional(condition: ASTNode, consequent: ASTNode, alternate: ASTNode): ConditionalExpression;
|
|
@@ -287,10 +274,6 @@ declare class CodeGenerator {
|
|
|
287
274
|
*/
|
|
288
275
|
private generateAssignment;
|
|
289
276
|
/**
|
|
290
|
-
* Generate code for a nullish assignment
|
|
291
|
-
*/
|
|
292
|
-
private generateNullishAssignment;
|
|
293
|
-
/**
|
|
294
277
|
* Generate code for a conditional expression (ternary operator)
|
|
295
278
|
*/
|
|
296
279
|
private generateConditionalExpression;
|
|
@@ -337,10 +320,12 @@ declare function generate(node: ASTNode): string;
|
|
|
337
320
|
declare const defaultContext: ExecutionContext;
|
|
338
321
|
/**
|
|
339
322
|
* Executor - evaluates an AST with given context
|
|
323
|
+
* Uses a tree-walk interpreter with O(n) execution time where n is the number of AST nodes
|
|
340
324
|
*/
|
|
341
325
|
declare class Executor {
|
|
342
326
|
private context;
|
|
343
327
|
private variables;
|
|
328
|
+
private externalVariables;
|
|
344
329
|
constructor(context?: ExecutionContext);
|
|
345
330
|
/**
|
|
346
331
|
* Execute an AST node and return the result
|
|
@@ -372,15 +357,11 @@ declare class Executor {
|
|
|
372
357
|
private executeFunctionCall;
|
|
373
358
|
/**
|
|
374
359
|
* Execute a variable assignment
|
|
360
|
+
* External variables (from context) take precedence over script assignments
|
|
361
|
+
* This allows scripts to define defaults that can be overridden at runtime
|
|
375
362
|
*/
|
|
376
363
|
private executeAssignment;
|
|
377
364
|
/**
|
|
378
|
-
* Execute a nullish assignment (??=)
|
|
379
|
-
* Only assigns if the variable is undefined (not in variables map)
|
|
380
|
-
* Returns the existing value if defined, otherwise evaluates and assigns the value
|
|
381
|
-
*/
|
|
382
|
-
private executeNullishAssignment;
|
|
383
|
-
/**
|
|
384
365
|
* Execute a conditional expression (ternary operator)
|
|
385
366
|
* Returns consequent if condition !== 0, otherwise returns alternate
|
|
386
367
|
*/
|
|
@@ -392,10 +373,12 @@ declare class Executor {
|
|
|
392
373
|
declare function execute(source: string, context?: ExecutionContext): RuntimeValue;
|
|
393
374
|
/**
|
|
394
375
|
* Lexer - converts source code into tokens
|
|
376
|
+
* Implements a single-pass O(n) tokenization algorithm
|
|
395
377
|
*/
|
|
396
378
|
declare class Lexer {
|
|
397
379
|
private source;
|
|
398
380
|
private position;
|
|
381
|
+
private length;
|
|
399
382
|
constructor(source: string);
|
|
400
383
|
/**
|
|
401
384
|
* Tokenize the entire source and return all tokens
|
|
@@ -419,23 +402,11 @@ declare class Lexer {
|
|
|
419
402
|
*/
|
|
420
403
|
private readIdentifier;
|
|
421
404
|
/**
|
|
422
|
-
*
|
|
423
|
-
*/
|
|
424
|
-
private getCharAt;
|
|
425
|
-
/**
|
|
426
|
-
* Peek at the next character without consuming it
|
|
427
|
-
*/
|
|
428
|
-
private peek;
|
|
429
|
-
/**
|
|
430
|
-
* Peek ahead n positions without consuming
|
|
431
|
-
*/
|
|
432
|
-
private peekAhead;
|
|
433
|
-
/**
|
|
434
|
-
* Check if character is a digit
|
|
405
|
+
* Check if character is a digit (0-9)
|
|
435
406
|
*/
|
|
436
407
|
private isDigit;
|
|
437
408
|
/**
|
|
438
|
-
* Check if character is a letter
|
|
409
|
+
* Check if character is a letter (a-z, A-Z)
|
|
439
410
|
*/
|
|
440
411
|
private isLetter;
|
|
441
412
|
/**
|
|
@@ -444,25 +415,25 @@ declare class Lexer {
|
|
|
444
415
|
private isWhitespace;
|
|
445
416
|
}
|
|
446
417
|
/**
|
|
447
|
-
* Optimize an AST using
|
|
418
|
+
* Optimize an AST using constant folding and expression simplification.
|
|
448
419
|
*
|
|
449
|
-
* This optimizer
|
|
450
|
-
*
|
|
451
|
-
*
|
|
452
|
-
*
|
|
453
|
-
*
|
|
420
|
+
* This optimizer performs LOCAL, SAFE optimizations that preserve program semantics:
|
|
421
|
+
* - Constant folding: Evaluates arithmetic with literal operands at compile-time
|
|
422
|
+
* - Function argument pre-evaluation: Simplifies expressions passed to functions
|
|
423
|
+
* - Conditional folding: Evaluates ternary with constant condition
|
|
424
|
+
*
|
|
425
|
+
* Optimizations that are NOT performed (because they're unsafe with context variables):
|
|
426
|
+
* - Variable propagation: Variables can be overridden by ExecutionContext
|
|
427
|
+
* - Dead code elimination: Cannot determine if variables are "dead" without knowing context
|
|
428
|
+
* - Cross-statement analysis: Each statement may affect external state
|
|
454
429
|
*
|
|
455
430
|
* Time complexity: O(n) where n is the number of AST nodes
|
|
456
|
-
* Space complexity: O(
|
|
431
|
+
* Space complexity: O(d) where d is the max depth (recursion stack)
|
|
457
432
|
*
|
|
458
433
|
* Algorithm properties:
|
|
459
434
|
* - Sound: Preserves program semantics exactly
|
|
460
|
-
* -
|
|
461
|
-
* -
|
|
462
|
-
*
|
|
463
|
-
* Based on classical compiler optimization theory:
|
|
464
|
-
* - Cytron et al. "Efficiently Computing Static Single Assignment Form" (1991)
|
|
465
|
-
* - Wegman & Zadeck "Constant Propagation with Conditional Branches" (1991)
|
|
435
|
+
* - Safe: No assumptions about variable values or liveness
|
|
436
|
+
* - Local: Only optimizes within individual expressions
|
|
466
437
|
*
|
|
467
438
|
* @param node - The AST node to optimize
|
|
468
439
|
* @returns Optimized AST node
|
|
@@ -470,6 +441,7 @@ declare class Lexer {
|
|
|
470
441
|
declare function optimize(node: ASTNode): ASTNode;
|
|
471
442
|
/**
|
|
472
443
|
* Parser using Pratt parsing (top-down operator precedence)
|
|
444
|
+
* Implements an efficient O(n) parsing algorithm
|
|
473
445
|
*/
|
|
474
446
|
declare class Parser {
|
|
475
447
|
private tokens;
|
|
@@ -477,11 +449,12 @@ declare class Parser {
|
|
|
477
449
|
constructor(tokens: Token[]);
|
|
478
450
|
/**
|
|
479
451
|
* Parse tokens into an AST
|
|
480
|
-
* Supports multiple statements separated by semicolons
|
|
452
|
+
* Supports multiple statements separated by semicolons or newlines
|
|
481
453
|
*/
|
|
482
454
|
parse(): ASTNode;
|
|
483
455
|
/**
|
|
484
456
|
* Parse an expression with Pratt parsing (precedence climbing)
|
|
457
|
+
* This is the core of the parser - handles infix operators with proper precedence
|
|
485
458
|
*/
|
|
486
459
|
private parseExpression;
|
|
487
460
|
/**
|
|
@@ -496,15 +469,15 @@ declare class Parser {
|
|
|
496
469
|
* Get unary operator precedence
|
|
497
470
|
* Returns 6 which is higher than add/sub (6) but lower than exponentiation (8)
|
|
498
471
|
* This means: -2^2 parses as -(2^2) = -4, not (-2)^2 = 4
|
|
499
|
-
*
|
|
472
|
+
* Matches the behavior of Python, Ruby, and most languages
|
|
500
473
|
*/
|
|
501
474
|
private getUnaryPrecedence;
|
|
502
475
|
/**
|
|
503
|
-
* Check if token is a binary operator
|
|
476
|
+
* Check if token is a binary operator (O(1) Set lookup)
|
|
504
477
|
*/
|
|
505
478
|
private isBinaryOperator;
|
|
506
479
|
/**
|
|
507
|
-
* Get current token
|
|
480
|
+
* Get current token without advancing
|
|
508
481
|
*/
|
|
509
482
|
private peek;
|
|
510
483
|
/**
|
|
@@ -514,9 +487,10 @@ declare class Parser {
|
|
|
514
487
|
}
|
|
515
488
|
/**
|
|
516
489
|
* Parse source code string into AST
|
|
490
|
+
* Convenience function that creates lexer and parser
|
|
517
491
|
*
|
|
518
492
|
* @param source - The source code to parse
|
|
519
493
|
* @returns Parsed AST
|
|
520
494
|
*/
|
|
521
495
|
declare function parseSource(source: string): ASTNode;
|
|
522
|
-
export { parseSource, optimize, isUnaryOp, isProgram, isNumberLiteral,
|
|
496
|
+
export { parseSource, optimize, isUnaryOp, isProgram, isNumberLiteral, isIdentifier, isFunctionCall, isConditionalExpression, isBinaryOp, isAssignment, generate, execute, defaultContext, exports_ast as ast, TokenType, Token, RuntimeValue, Parser, Lexer, Executor, ExecutionContext, CodeGenerator, ASTNode };
|