starlight-cli 1.0.30 → 1.0.32

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/dist/index.js CHANGED
@@ -1496,6 +1496,35 @@ async evaluate(node, env = this.global) {
1496
1496
  const val = await this.evaluate(node.argument, env);
1497
1497
  return val;
1498
1498
  }
1499
+ case 'NewExpression': {
1500
+ const callee = await this.evaluate(node.callee, env);
1501
+
1502
+ if (typeof callee === 'object' && callee.body) {
1503
+ // This is a Starlight "func" object — wrap it in JS function
1504
+ const Constructor = function(...args) {
1505
+ const newEnv = new Environment(callee.env);
1506
+ newEnv.define('this', this); // bind 'this' for the constructor
1507
+ for (let i = 0; i < callee.params.length; i++) {
1508
+ newEnv.define(callee.params[i], args[i]);
1509
+ }
1510
+ return this.evaluate(callee.body, newEnv);
1511
+ }.bind(this);
1512
+
1513
+ const args = [];
1514
+ for (const a of node.arguments) args.push(await this.evaluate(a, env));
1515
+
1516
+ return new Constructor(...args);
1517
+ }
1518
+
1519
+ if (typeof callee !== 'function') {
1520
+ throw new Error('NewExpression callee is not a function');
1521
+ }
1522
+
1523
+ const args = [];
1524
+ for (const a of node.arguments) args.push(await this.evaluate(a, env));
1525
+ return new callee(...args);
1526
+ }
1527
+
1499
1528
  default:
1500
1529
  throw new Error(`Unknown node type in evaluator: ${node.type}`);
1501
1530
  }
@@ -1919,7 +1948,7 @@ class Lexer {
1919
1948
  'break', 'continue', 'func', 'return',
1920
1949
  'true', 'false', 'null',
1921
1950
  'ask', 'define', 'import', 'from', 'as',
1922
- 'async', 'await'
1951
+ 'async', 'await', 'new'
1923
1952
  ];
1924
1953
 
1925
1954
 
@@ -2444,6 +2473,22 @@ if (t.type === 'AWAIT') {
2444
2473
  const argument = this.expression();
2445
2474
  return { type: 'AwaitExpression', argument };
2446
2475
  }
2476
+ if (t.type === 'NEW') {
2477
+ this.eat('NEW');
2478
+ const callee = this.primary(); // the class or function being called
2479
+ this.eat('LPAREN');
2480
+ const args = [];
2481
+ if (this.current.type !== 'RPAREN') {
2482
+ args.push(this.expression());
2483
+ while (this.current.type === 'COMMA') {
2484
+ this.eat('COMMA');
2485
+ args.push(this.expression());
2486
+ }
2487
+ }
2488
+ this.eat('RPAREN');
2489
+ return { type: 'NewExpression', callee, arguments: args };
2490
+ }
2491
+
2447
2492
  if (t.type === 'ASK') {
2448
2493
  this.eat('ASK');
2449
2494
  this.eat('LPAREN');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "starlight-cli",
3
- "version": "1.0.30",
3
+ "version": "1.0.32",
4
4
  "description": "Starlight Programming Language CLI",
5
5
  "bin": {
6
6
  "starlight": "index.js"
package/src/evaluator.js CHANGED
@@ -153,6 +153,35 @@ async evaluate(node, env = this.global) {
153
153
  const val = await this.evaluate(node.argument, env);
154
154
  return val;
155
155
  }
156
+ case 'NewExpression': {
157
+ const callee = await this.evaluate(node.callee, env);
158
+
159
+ if (typeof callee === 'object' && callee.body) {
160
+ // This is a Starlight "func" object — wrap it in JS function
161
+ const Constructor = function(...args) {
162
+ const newEnv = new Environment(callee.env);
163
+ newEnv.define('this', this); // bind 'this' for the constructor
164
+ for (let i = 0; i < callee.params.length; i++) {
165
+ newEnv.define(callee.params[i], args[i]);
166
+ }
167
+ return this.evaluate(callee.body, newEnv);
168
+ }.bind(this);
169
+
170
+ const args = [];
171
+ for (const a of node.arguments) args.push(await this.evaluate(a, env));
172
+
173
+ return new Constructor(...args);
174
+ }
175
+
176
+ if (typeof callee !== 'function') {
177
+ throw new Error('NewExpression callee is not a function');
178
+ }
179
+
180
+ const args = [];
181
+ for (const a of node.arguments) args.push(await this.evaluate(a, env));
182
+ return new callee(...args);
183
+ }
184
+
156
185
  default:
157
186
  throw new Error(`Unknown node type in evaluator: ${node.type}`);
158
187
  }
package/src/lexer.js CHANGED
@@ -83,7 +83,7 @@ class Lexer {
83
83
  'break', 'continue', 'func', 'return',
84
84
  'true', 'false', 'null',
85
85
  'ask', 'define', 'import', 'from', 'as',
86
- 'async', 'await'
86
+ 'async', 'await', 'new'
87
87
  ];
88
88
 
89
89
 
package/src/parser.js CHANGED
@@ -414,6 +414,22 @@ if (t.type === 'AWAIT') {
414
414
  const argument = this.expression();
415
415
  return { type: 'AwaitExpression', argument };
416
416
  }
417
+ if (t.type === 'NEW') {
418
+ this.eat('NEW');
419
+ const callee = this.primary(); // the class or function being called
420
+ this.eat('LPAREN');
421
+ const args = [];
422
+ if (this.current.type !== 'RPAREN') {
423
+ args.push(this.expression());
424
+ while (this.current.type === 'COMMA') {
425
+ this.eat('COMMA');
426
+ args.push(this.expression());
427
+ }
428
+ }
429
+ this.eat('RPAREN');
430
+ return { type: 'NewExpression', callee, arguments: args };
431
+ }
432
+
417
433
  if (t.type === 'ASK') {
418
434
  this.eat('ASK');
419
435
  this.eat('LPAREN');