starlight-cli 1.0.23 → 1.0.25

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
@@ -1347,421 +1347,394 @@ const Lexer = __nccwpck_require__(211);
1347
1347
  const Parser = __nccwpck_require__(222);
1348
1348
  const path = __nccwpck_require__(928);
1349
1349
 
1350
- class ReturnValue {
1351
- constructor(value) { this.value = value; }
1352
- }
1350
+ class ReturnValue { constructor(value) { this.value = value; } }
1353
1351
  class BreakSignal {}
1354
1352
  class ContinueSignal {}
1355
1353
 
1356
1354
  class Environment {
1357
- constructor(parent = null) {
1358
- this.store = Object.create(null);
1359
- this.parent = parent;
1360
- }
1355
+ constructor(parent = null) {
1356
+ this.store = Object.create(null);
1357
+ this.parent = parent;
1358
+ }
1361
1359
 
1362
- has(name) {
1363
- if (name in this.store) return true;
1364
- if (this.parent) return this.parent.has(name);
1365
- return false;
1366
- }
1360
+ has(name) {
1361
+ if (name in this.store) return true;
1362
+ if (this.parent) return this.parent.has(name);
1363
+ return false;
1364
+ }
1367
1365
 
1368
- get(name) {
1369
- if (name in this.store) return this.store[name];
1370
- if (this.parent) return this.parent.get(name);
1371
- throw new Error(`Undefined variable: ${name}`);
1372
- }
1366
+ get(name) {
1367
+ if (name in this.store) return this.store[name];
1368
+ if (this.parent) return this.parent.get(name);
1369
+ throw new Error(`Undefined variable: ${name}`);
1370
+ }
1373
1371
 
1374
- set(name, value) {
1375
- if (name in this.store) { this.store[name] = value; return value; }
1376
- if (this.parent && this.parent.has(name)) { return this.parent.set(name, value); }
1377
- this.store[name] = value;
1378
- return value;
1379
- }
1372
+ set(name, value) {
1373
+ if (name in this.store) { this.store[name] = value; return value; }
1374
+ if (this.parent && this.parent.has(name)) { return this.parent.set(name, value); }
1375
+ this.store[name] = value;
1376
+ return value;
1377
+ }
1380
1378
 
1381
- define(name, value) {
1382
- this.store[name] = value;
1383
- return value;
1384
- }
1379
+ define(name, value) {
1380
+ this.store[name] = value;
1381
+ return value;
1382
+ }
1385
1383
  }
1386
1384
 
1387
1385
  class Evaluator {
1388
- constructor() {
1389
- this.global = new Environment();
1390
- this.setupBuiltins();
1391
- }
1392
-
1393
- setupBuiltins() {
1394
- this.global.define('len', arg => {
1395
- if (Array.isArray(arg) || typeof arg === 'string') return arg.length;
1396
- if (arg && typeof arg === 'object') return Object.keys(arg).length;
1397
- return 0;
1398
- });
1399
-
1400
- this.global.define('print', arg => { console.log(arg); return null; });
1401
- this.global.define('type', arg => {
1402
- if (Array.isArray(arg)) return 'array';
1403
- return typeof arg;
1404
- });
1405
- this.global.define('keys', arg => arg && typeof arg === 'object' ? Object.keys(arg) : []);
1406
- this.global.define('values', arg => arg && typeof arg === 'object' ? Object.values(arg) : []);
1386
+ constructor() {
1387
+ this.global = new Environment();
1388
+ this.setupBuiltins();
1389
+ }
1407
1390
 
1408
- this.global.define('ask', prompt => {
1409
- const readlineSync = __nccwpck_require__(552);
1410
- return readlineSync.question(prompt + ' ');
1411
- });
1412
- this.global.define('num', arg => {
1413
- const n = Number(arg);
1414
- if (Number.isNaN(n)) {
1415
- throw new Error('Cannot convert value to number');
1391
+ setupBuiltins() {
1392
+ this.global.define('len', arg => {
1393
+ if (Array.isArray(arg) || typeof arg === 'string') return arg.length;
1394
+ if (arg && typeof arg === 'object') return Object.keys(arg).length;
1395
+ return 0;
1396
+ });
1397
+
1398
+ this.global.define('print', arg => { console.log(arg); return null; });
1399
+ this.global.define('type', arg => Array.isArray(arg) ? 'array' : typeof arg);
1400
+ this.global.define('keys', arg => arg && typeof arg === 'object' ? Object.keys(arg) : []);
1401
+ this.global.define('values', arg => arg && typeof arg === 'object' ? Object.values(arg) : []);
1402
+
1403
+ this.global.define('ask', prompt => readlineSync.question(prompt + ' '));
1404
+ this.global.define('num', arg => {
1405
+ const n = Number(arg);
1406
+ if (Number.isNaN(n)) throw new Error('Cannot convert value to number');
1407
+ return n;
1408
+ });
1409
+ this.global.define('str', arg => String(arg));
1410
+
1411
+ // Async fetch built-in for API requests
1412
+ this.global.define('fetch', async (url, options) => {
1413
+ const fetch = __nccwpck_require__(266); // Make sure node-fetch is installed
1414
+ const res = await fetch(url, options);
1415
+ return res;
1416
+ });
1416
1417
  }
1417
- return n;
1418
- });
1419
1418
 
1420
- this.global.define('str', arg => {
1421
- return String(arg);
1422
- });
1419
+ async evaluate(node, env = this.global) {
1420
+ switch (node.type) {
1421
+ case 'Program': return await this.evalProgram(node, env);
1422
+ case 'BlockStatement': return await this.evalBlock(node, new Environment(env));
1423
+ case 'VarDeclaration': return await this.evalVarDeclaration(node, env);
1424
+ case 'AssignmentExpression': return await this.evalAssignment(node, env);
1425
+ case 'CompoundAssignment': return await this.evalCompoundAssignment(node, env);
1426
+ case 'SldeployStatement': return await this.evalSldeploy(node, env);
1427
+ case 'AskStatement': return await this.evalAsk(node, env);
1428
+ case 'DefineStatement': return await this.evalDefine(node, env);
1429
+ case 'ExpressionStatement': return await this.evaluate(node.expression, env);
1430
+ case 'BinaryExpression': return await this.evalBinary(node, env);
1431
+ case 'LogicalExpression': return await this.evalLogical(node, env);
1432
+ case 'UnaryExpression': return await this.evalUnary(node, env);
1433
+ case 'Literal': return node.value;
1434
+ case 'Identifier': return env.get(node.name);
1435
+ case 'IfStatement': return await this.evalIf(node, env);
1436
+ case 'WhileStatement': return await this.evalWhile(node, env);
1437
+ case 'ForStatement': return await this.evalFor(node, env);
1438
+ case 'BreakStatement': throw new BreakSignal();
1439
+ case 'ContinueStatement': throw new ContinueSignal();
1440
+ case 'ImportStatement': return await this.evalImport(node, env);
1441
+ case 'FunctionDeclaration': return await this.evalFunctionDeclaration(node, env);
1442
+ case 'CallExpression': return await this.evalCall(node, env);
1443
+ case 'ArrowFunctionExpression': return await this.evalArrowFunction(node, env);
1444
+ case 'ReturnStatement': {
1445
+ const val = node.argument ? await this.evaluate(node.argument, env) : null;
1446
+ throw new ReturnValue(val);
1447
+ }
1448
+ case 'ArrayExpression': return await Promise.all(node.elements.map(el => this.evaluate(el, env)));
1449
+ case 'IndexExpression': return await this.evalIndex(node, env);
1450
+ case 'ObjectExpression': return await this.evalObject(node, env);
1451
+ case 'MemberExpression': return await this.evalMember(node, env);
1452
+ case 'UpdateExpression': return await this.evalUpdate(node, env);
1453
+ default:
1454
+ throw new Error(`Unknown node type in evaluator: ${node.type}`);
1455
+ }
1456
+ }
1423
1457
 
1424
- }
1458
+ async evalProgram(node, env) {
1459
+ let result = null;
1460
+ for (const stmt of node.body) result = await this.evaluate(stmt, env);
1461
+ return result;
1462
+ }
1425
1463
 
1464
+ async evalBlock(node, env) {
1465
+ let result = null;
1466
+ for (const stmt of node.body) {
1467
+ try { result = await this.evaluate(stmt, env); }
1468
+ catch (e) {
1469
+ if (e instanceof ReturnValue || e instanceof BreakSignal || e instanceof ContinueSignal) throw e;
1470
+ throw e;
1471
+ }
1472
+ }
1473
+ return result;
1474
+ }
1426
1475
 
1427
- evaluate(node, env = this.global) {
1428
- switch (node.type) {
1429
- case 'Program': return this.evalProgram(node, env);
1430
- case 'BlockStatement': return this.evalBlock(node, new Environment(env));
1431
- case 'VarDeclaration': return this.evalVarDeclaration(node, env);
1432
- case 'AssignmentExpression': return this.evalAssignment(node, env);
1433
- case 'CompoundAssignment': return this.evalCompoundAssignment(node, env);
1434
- case 'SldeployStatement': return this.evalSldeploy(node, env);
1435
- case 'AskStatement': return this.evalAsk(node, env);
1436
- case 'DefineStatement': return this.evalDefine(node, env);
1437
- case 'ExpressionStatement': return this.evaluate(node.expression, env);
1438
- case 'BinaryExpression': return this.evalBinary(node, env);
1439
- case 'LogicalExpression': return this.evalLogical(node, env);
1440
- case 'UnaryExpression': return this.evalUnary(node, env);
1441
- case 'Literal': return node.value;
1442
- case 'Identifier': return env.get(node.name);
1443
- case 'IfStatement': return this.evalIf(node, env);
1444
- case 'WhileStatement': return this.evalWhile(node, env);
1445
- case 'ForStatement': return this.evalFor(node, env);
1446
- case 'BreakStatement': throw new BreakSignal();
1447
- case 'ContinueStatement': throw new ContinueSignal();
1448
- case 'ImportStatement': return this.evalImport(node, env);
1449
- case 'FunctionDeclaration': return this.evalFunctionDeclaration(node, env);
1450
- case 'CallExpression': return this.evalCall(node, env);
1451
- case 'ReturnStatement': {
1452
- const val = node.argument ? this.evaluate(node.argument, env) : null;
1453
- throw new ReturnValue(val);
1454
- }
1455
- case 'ArrayExpression': return node.elements.map(el => this.evaluate(el, env));
1456
- case 'IndexExpression': return this.evalIndex(node, env);
1457
- case 'ObjectExpression': return this.evalObject(node, env);
1458
- case 'MemberExpression': return this.evalMember(node, env);
1459
- case 'UpdateExpression': return this.evalUpdate(node, env);
1460
- default:
1461
- throw new Error(`Unknown node type in evaluator: ${node.type}`);
1476
+ async evalVarDeclaration(node, env) {
1477
+ const val = await this.evaluate(node.expr, env);
1478
+ return env.define(node.id, val);
1462
1479
  }
1463
- }
1464
1480
 
1465
- evalProgram(node, env) {
1466
- let result = null;
1467
- for (const stmt of node.body) {
1468
- result = this.evaluate(stmt, env);
1481
+ async evalArrowFunction(node, env) {
1482
+ return { params: node.params, body: node.body, env, arrow: true };
1469
1483
  }
1470
- return result;
1471
- }
1472
- evalImport(node, env) {
1473
- const spec = node.path;
1474
- let lib;
1475
1484
 
1476
- try {
1477
- const resolved = require.resolve(spec, {
1478
- paths: [process.cwd()]
1479
- });
1480
- lib = require(resolved);
1481
- } catch (e) {
1482
- const fullPath = path.isAbsolute(spec)
1483
- ? spec
1484
- : path.join(process.cwd(), spec.endsWith('.sl') ? spec : spec + '.sl');
1485
+ async evalAssignment(node, env) {
1486
+ const rightVal = await this.evaluate(node.right, env);
1487
+ const left = node.left;
1485
1488
 
1486
- if (!fs.existsSync(fullPath)) {
1487
- throw new Error(`Import not found: ${spec}`);
1489
+ if (left.type === 'Identifier') return env.set(left.name, rightVal);
1490
+ if (left.type === 'MemberExpression') {
1491
+ const obj = await this.evalMemberObj(left, env);
1492
+ obj[left.property] = rightVal;
1493
+ return rightVal;
1494
+ }
1495
+ if (left.type === 'IndexExpression') {
1496
+ const obj = await this.evalIndexObj(left, env);
1497
+ const idx = await this.evaluate(left.indexer, env);
1498
+ obj[idx] = rightVal;
1499
+ return rightVal;
1500
+ }
1501
+ throw new Error('Invalid assignment target');
1488
1502
  }
1489
1503
 
1490
- const code = fs.readFileSync(fullPath, 'utf-8');
1491
- const tokens = new Lexer(code).getTokens();
1492
- const ast = new Parser(tokens).parse();
1504
+ async evalCompoundAssignment(node, env) {
1505
+ const left = node.left;
1506
+ let current;
1507
+ if (left.type === 'Identifier') current = env.get(left.name);
1508
+ else if (left.type === 'MemberExpression') current = await this.evalMember(left, env);
1509
+ else if (left.type === 'IndexExpression') current = await this.evalIndex(left, env);
1510
+ else throw new Error('Invalid compound assignment target');
1511
+
1512
+ const rhs = await this.evaluate(node.right, env);
1513
+ let computed;
1514
+ switch (node.operator) {
1515
+ case 'PLUSEQ': computed = current + rhs; break;
1516
+ case 'MINUSEQ': computed = current - rhs; break;
1517
+ case 'STAREQ': computed = current * rhs; break;
1518
+ case 'SLASHEQ': computed = current / rhs; break;
1519
+ case 'MODEQ': computed = current % rhs; break;
1520
+ default: throw new Error('Unknown compound operator');
1521
+ }
1493
1522
 
1494
- const moduleEnv = new Environment(env);
1495
- this.evaluate(ast, moduleEnv);
1523
+ if (left.type === 'Identifier') env.set(left.name, computed);
1524
+ else await this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
1496
1525
 
1497
- lib = {};
1498
- for (const key of Object.keys(moduleEnv.store)) {
1499
- lib[key] = moduleEnv.store[key];
1526
+ return computed;
1500
1527
  }
1501
1528
 
1502
- lib.default = lib;
1503
- }
1504
-
1505
- for (const imp of node.specifiers) {
1506
- if (imp.type === 'DefaultImport') {
1507
- env.define(imp.local, lib.default ?? lib);
1529
+ async evalSldeploy(node, env) {
1530
+ const val = await this.evaluate(node.expr, env);
1531
+ console.log(val);
1532
+ return val;
1508
1533
  }
1509
- if (imp.type === 'NamespaceImport') {
1510
- env.define(imp.local, lib);
1511
- }
1512
- if (imp.type === 'NamedImport') {
1513
- if (!(imp.imported in lib)) {
1514
- throw new Error(`Module '${spec}' has no export '${imp.imported}'`);
1515
- }
1516
- env.define(imp.local, lib[imp.imported]);
1517
- }
1518
- }
1519
1534
 
1520
- return null;
1521
- }
1522
-
1523
-
1524
- evalBlock(node, env) {
1525
- let result = null;
1526
- for (const stmt of node.body) {
1527
- try {
1528
- result = this.evaluate(stmt, env);
1529
- } catch (e) {
1530
- if (e instanceof ReturnValue || e instanceof BreakSignal || e instanceof ContinueSignal) throw e;
1531
- throw e;
1532
- }
1535
+ async evalAsk(node, env) {
1536
+ const prompt = await this.evaluate(node.prompt, env);
1537
+ return readlineSync.question(prompt + ' ');
1533
1538
  }
1534
- return result;
1535
- }
1536
1539
 
1537
- evalVarDeclaration(node, env) {
1538
- const val = this.evaluate(node.expr, env);
1539
- return env.define(node.id, val);
1540
- }
1540
+ async evalDefine(node, env) {
1541
+ const val = node.expr ? await this.evaluate(node.expr, env) : null;
1542
+ return this.global.define(node.id, val);
1543
+ }
1541
1544
 
1542
- evalAssignment(node, env) {
1543
- const rightVal = this.evaluate(node.right, env);
1544
- const left = node.left;
1545
+ async evalBinary(node, env) {
1546
+ const l = await this.evaluate(node.left, env);
1547
+ const r = await this.evaluate(node.right, env);
1548
+
1549
+ if (node.operator === 'SLASH' && r === 0) throw new Error('Division by zero');
1550
+
1551
+ switch (node.operator) {
1552
+ case 'PLUS': return l + r;
1553
+ case 'MINUS': return l - r;
1554
+ case 'STAR': return l * r;
1555
+ case 'SLASH': return l / r;
1556
+ case 'MOD': return l % r;
1557
+ case 'EQEQ': return l === r;
1558
+ case 'NOTEQ': return l !== r;
1559
+ case 'LT': return l < r;
1560
+ case 'LTE': return l <= r;
1561
+ case 'GT': return l > r;
1562
+ case 'GTE': return l >= r;
1563
+ default: throw new Error(`Unknown binary operator ${node.operator}`);
1564
+ }
1565
+ }
1545
1566
 
1546
- if (left.type === 'Identifier') return env.set(left.name, rightVal);
1547
- if (left.type === 'MemberExpression') {
1548
- const obj = this.evaluate(left.object, env);
1549
- obj[left.property] = rightVal;
1550
- return rightVal;
1567
+ async evalLogical(node, env) {
1568
+ const l = await this.evaluate(node.left, env);
1569
+ if (node.operator === 'AND') return l && await this.evaluate(node.right, env);
1570
+ if (node.operator === 'OR') return l || await this.evaluate(node.right, env);
1571
+ throw new Error(`Unknown logical operator ${node.operator}`);
1551
1572
  }
1552
- if (left.type === 'IndexExpression') {
1553
- const obj = this.evaluate(left.object, env);
1554
- const idx = this.evaluate(left.indexer, env);
1555
- obj[idx] = rightVal;
1556
- return rightVal;
1573
+
1574
+ async evalUnary(node, env) {
1575
+ const val = await this.evaluate(node.argument, env);
1576
+ switch (node.operator) {
1577
+ case 'NOT': return !val;
1578
+ case 'MINUS': return -val;
1579
+ case 'PLUS': return +val;
1580
+ default: throw new Error(`Unknown unary operator ${node.operator}`);
1581
+ }
1557
1582
  }
1558
1583
 
1559
- throw new Error('Invalid assignment target');
1560
- }
1584
+ async evalIf(node, env) {
1585
+ const test = await this.evaluate(node.test, env);
1586
+ if (test) return await this.evaluate(node.consequent, env);
1587
+ if (node.alternate) return await this.evaluate(node.alternate, env);
1588
+ return null;
1589
+ }
1561
1590
 
1562
- evalCompoundAssignment(node, env) {
1563
- const left = node.left;
1564
- let current;
1591
+ async evalWhile(node, env) {
1592
+ while (await this.evaluate(node.test, env)) {
1593
+ try { await this.evaluate(node.body, env); }
1594
+ catch (e) { if (e instanceof BreakSignal) break; if (e instanceof ContinueSignal) continue; throw e; }
1595
+ }
1596
+ return null;
1597
+ }
1565
1598
 
1566
- if (left.type === 'Identifier') current = env.get(left.name);
1567
- else if (left.type === 'MemberExpression') current = this.evalMember(left, env);
1568
- else if (left.type === 'IndexExpression') current = this.evalIndex(left, env);
1569
- else throw new Error('Invalid compound assignment target');
1599
+ async evalFor(node, env) {
1600
+ const local = new Environment(env);
1601
+ if (node.init) await this.evaluate(node.init, local);
1602
+ while (!node.test || await this.evaluate(node.test, local)) {
1603
+ try { await this.evaluate(node.body, local); }
1604
+ catch (e) {
1605
+ if (e instanceof BreakSignal) break;
1606
+ if (e instanceof ContinueSignal) { if (node.update) await this.evaluate(node.update, local); continue; }
1607
+ throw e;
1608
+ }
1609
+ if (node.update) await this.evaluate(node.update, local);
1610
+ }
1611
+ return null;
1612
+ }
1570
1613
 
1571
- const rhs = this.evaluate(node.right, env);
1572
- let computed;
1573
- switch (node.operator) {
1574
- case 'PLUSEQ': computed = current + rhs; break;
1575
- case 'MINUSEQ': computed = current - rhs; break;
1576
- case 'STAREQ': computed = current * rhs; break;
1577
- case 'SLASHEQ': computed = current / rhs; break;
1578
- case 'MODEQ': computed = current % rhs; break;
1579
- default: throw new Error('Unknown compound operator');
1614
+ async evalFunctionDeclaration(node, env) {
1615
+ const fn = { params: node.params, body: node.body, env };
1616
+ env.define(node.name, fn);
1617
+ return null;
1580
1618
  }
1581
1619
 
1582
- if (left.type === 'Identifier') env.set(left.name, computed);
1583
- else if (left.type === 'MemberExpression') this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
1584
- else this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
1620
+ async evalCall(node, env) {
1621
+ const calleeEvaluated = await this.evaluate(node.callee, env);
1585
1622
 
1586
- return computed;
1587
- }
1623
+ if (typeof calleeEvaluated === 'function') {
1624
+ const args = [];
1625
+ for (const a of node.arguments) args.push(await this.evaluate(a, env));
1626
+ return await calleeEvaluated(...args);
1627
+ }
1588
1628
 
1589
- evalSldeploy(node, env) {
1590
- const val = this.evaluate(node.expr, env);
1591
- console.log(val);
1592
- return val;
1593
- }
1629
+ if (!calleeEvaluated || typeof calleeEvaluated !== 'object' || !calleeEvaluated.body) throw new Error('Call to non-function');
1594
1630
 
1595
- evalAsk(node, env) {
1596
- const prompt = this.evaluate(node.prompt, env);
1597
- const input = readlineSync.question(prompt + ' ');
1598
- return input;
1599
- }
1631
+ const fn = calleeEvaluated;
1632
+ const callEnv = new Environment(fn.env);
1633
+ for (let i = 0; i < fn.params.length; i++) {
1634
+ const argVal = node.arguments[i] ? await this.evaluate(node.arguments[i], env) : null;
1635
+ callEnv.define(fn.params[i], argVal);
1636
+ }
1600
1637
 
1601
- evalDefine(node, env) {
1602
- const val = node.expr ? this.evaluate(node.expr, env) : null;
1603
- return this.global.define(node.id, val);
1604
- }
1638
+ try {
1639
+ const result = await this.evaluate(fn.body, callEnv);
1640
+ return fn.arrow ? result : result;
1641
+ } catch (e) { if (e instanceof ReturnValue) return e.value; throw e; }
1642
+ }
1605
1643
 
1606
- evalBinary(node, env) {
1607
- const l = this.evaluate(node.left, env);
1608
- const r = this.evaluate(node.right, env);
1644
+ async evalIndex(node, env) {
1645
+ const obj = await this.evaluate(node.object, env);
1646
+ const idx = await this.evaluate(node.indexer, env);
1609
1647
 
1610
- if (node.operator === 'SLASH' && r === 0) {
1611
- throw new Error('Division by zero');
1648
+ if (obj == null) throw new Error('Indexing null or undefined');
1649
+ if (Array.isArray(obj) && (idx < 0 || idx >= obj.length)) throw new Error('Array index out of bounds');
1650
+ if (typeof obj === 'object' && !(idx in obj)) throw new Error(`Property '${idx}' does not exist`);
1651
+ return obj[idx];
1612
1652
  }
1613
1653
 
1614
- switch (node.operator) {
1615
- case 'PLUS': return l + r;
1616
- case 'MINUS': return l - r;
1617
- case 'STAR': return l * r;
1618
- case 'SLASH': return l / r;
1619
- case 'MOD': return l % r;
1620
- case 'EQEQ': return l === r;
1621
- case 'NOTEQ': return l !== r;
1622
- case 'LT': return l < r;
1623
- case 'LTE': return l <= r;
1624
- case 'GT': return l > r;
1625
- case 'GTE': return l >= r;
1626
- default: throw new Error(`Unknown binary operator ${node.operator}`);
1654
+ async evalObject(node, env) {
1655
+ const out = {};
1656
+ for (const p of node.props) out[p.key] = await this.evaluate(p.value, env);
1657
+ return out;
1627
1658
  }
1628
- }
1629
-
1630
1659
 
1631
- evalLogical(node, env) {
1632
- const l = this.evaluate(node.left, env);
1633
- if (node.operator === 'AND') return l && this.evaluate(node.right, env);
1634
- if (node.operator === 'OR') return l || this.evaluate(node.right, env);
1635
- throw new Error(`Unknown logical operator ${node.operator}`);
1636
- }
1637
-
1638
- evalUnary(node, env) {
1639
- const val = this.evaluate(node.argument, env);
1640
- switch (node.operator) {
1641
- case 'NOT': return !val;
1642
- case 'MINUS': return -val;
1643
- case 'PLUS': return +val;
1644
- default: throw new Error(`Unknown unary operator ${node.operator}`);
1660
+ async evalMember(node, env) {
1661
+ const obj = await this.evaluate(node.object, env);
1662
+ if (obj == null) throw new Error('Member access of null or undefined');
1663
+ if (!(node.property in obj)) throw new Error(`Property '${node.property}' does not exist`);
1664
+ return obj[node.property];
1645
1665
  }
1646
- }
1647
-
1648
- evalIf(node, env) {
1649
- const test = this.evaluate(node.test, env);
1650
- if (test) return this.evaluate(node.consequent, env);
1651
- if (node.alternate) return this.evaluate(node.alternate, env);
1652
- return null;
1653
- }
1654
1666
 
1655
- evalWhile(node, env) {
1656
- while (this.evaluate(node.test, env)) {
1657
- try { this.evaluate(node.body, env); }
1658
- catch (e) {
1659
- if (e instanceof BreakSignal) break;
1660
- if (e instanceof ContinueSignal) continue;
1661
- throw e;
1662
- }
1667
+ async evalMemberObj(node, env) {
1668
+ const obj = await this.evaluate(node.object, env);
1669
+ if (obj == null) throw new Error('Member access of null or undefined');
1670
+ return obj;
1663
1671
  }
1664
- return null;
1665
- }
1666
1672
 
1667
- evalFor(node, env) {
1668
- const local = new Environment(env);
1669
- if (node.init) this.evaluate(node.init, local);
1670
- while (!node.test || this.evaluate(node.test, local)) {
1671
- try { this.evaluate(node.body, local); }
1672
- catch (e) {
1673
- if (e instanceof BreakSignal) break;
1674
- if (e instanceof ContinueSignal) { if (node.update) this.evaluate(node.update, local); continue; }
1675
- throw e;
1676
- }
1677
- if (node.update) this.evaluate(node.update, local);
1673
+ async evalIndexObj(node, env) {
1674
+ const obj = await this.evaluate(node.object, env);
1675
+ if (obj == null) throw new Error('Indexing null or undefined');
1676
+ return obj;
1678
1677
  }
1679
- return null;
1680
- }
1681
-
1682
- evalFunctionDeclaration(node, env) {
1683
- const fn = { params: node.params, body: node.body, env };
1684
- env.define(node.name, fn);
1685
- return null;
1686
- }
1687
1678
 
1688
- evalCall(node, env) {
1689
- const calleeEvaluated = this.evaluate(node.callee, env);
1690
- if (typeof calleeEvaluated === 'function') {
1691
- const args = node.arguments.map(a => this.evaluate(a, env));
1692
- return calleeEvaluated(...args);
1693
- }
1694
- if (!calleeEvaluated || typeof calleeEvaluated !== 'object' || !calleeEvaluated.body) {
1695
- throw new Error('Call to non-function');
1679
+ async evalUpdate(node, env) {
1680
+ const arg = node.argument;
1681
+ const getCurrent = async () => {
1682
+ if (arg.type === 'Identifier') return env.get(arg.name);
1683
+ if (arg.type === 'MemberExpression') return await this.evalMember(arg, env);
1684
+ if (arg.type === 'IndexExpression') return await this.evalIndex(arg, env);
1685
+ throw new Error('Invalid update target');
1686
+ };
1687
+ const setValue = async (v) => {
1688
+ if (arg.type === 'Identifier') env.set(arg.name, v);
1689
+ else if (arg.type === 'MemberExpression') { const obj = await this.evalMemberObj(arg, env); obj[arg.property] = v; }
1690
+ else if (arg.type === 'IndexExpression') { const obj = await this.evalIndexObj(arg, env); const idx = await this.evaluate(arg.indexer, env); obj[idx] = v; }
1691
+ };
1692
+
1693
+ const current = await getCurrent();
1694
+ const newVal = (node.operator === 'PLUSPLUS') ? current + 1 : current - 1;
1695
+
1696
+ if (node.prefix) { await setValue(newVal); return newVal; }
1697
+ else { await setValue(newVal); return current; }
1696
1698
  }
1697
- const fn = calleeEvaluated;
1698
- const callEnv = new Environment(fn.env);
1699
- fn.params.forEach((p, i) => {
1700
- const argVal = node.arguments[i] ? this.evaluate(node.arguments[i], env) : null;
1701
- callEnv.define(p, argVal);
1702
- });
1703
- try { return this.evaluate(fn.body, callEnv); }
1704
- catch (e) { if (e instanceof ReturnValue) return e.value; throw e; }
1705
- }
1706
1699
 
1707
- evalIndex(node, env) {
1708
- const obj = this.evaluate(node.object, env);
1709
- const idx = this.evaluate(node.indexer, env);
1710
-
1711
- if (obj == null) throw new Error('Indexing null or undefined');
1712
- if (Array.isArray(obj) && (idx < 0 || idx >= obj.length)) {
1713
- throw new Error('Array index out of bounds');
1714
- }
1715
- if (typeof obj === 'object' && !(idx in obj)) {
1716
- throw new Error(`Property '${idx}' does not exist`);
1717
- }
1700
+ async evalImport(node, env) {
1701
+ const spec = node.path;
1702
+ let lib;
1718
1703
 
1719
- return obj[idx];
1720
- }
1704
+ try {
1705
+ const resolved = require.resolve(spec, { paths: [process.cwd()] });
1706
+ lib = require(resolved);
1707
+ } catch (e) {
1708
+ const fullPath = path.isAbsolute(spec) ? spec : path.join(process.cwd(), spec.endsWith('.sl') ? spec : spec + '.sl');
1709
+ if (!fs.existsSync(fullPath)) throw new Error(`Import not found: ${spec}`);
1721
1710
 
1711
+ const code = fs.readFileSync(fullPath, 'utf-8');
1712
+ const tokens = new Lexer(code).getTokens();
1713
+ const ast = new Parser(tokens).parse();
1722
1714
 
1723
- evalObject(node, env) {
1724
- const out = {};
1725
- for (const p of node.props) out[p.key] = this.evaluate(p.value, env);
1726
- return out;
1727
- }
1715
+ const moduleEnv = new Environment(env);
1716
+ await this.evaluate(ast, moduleEnv);
1728
1717
 
1729
- evalMember(node, env) {
1730
- const obj = this.evaluate(node.object, env);
1731
- if (obj == null) throw new Error('Member access of null or undefined');
1732
- if (!(node.property in obj)) throw new Error(`Property '${node.property}' does not exist`);
1733
- return obj[node.property];
1734
- }
1718
+ lib = {};
1719
+ for (const key of Object.keys(moduleEnv.store)) lib[key] = moduleEnv.store[key];
1720
+ lib.default = lib;
1721
+ }
1735
1722
 
1723
+ for (const imp of node.specifiers) {
1724
+ if (imp.type === 'DefaultImport') env.define(imp.local, lib.default ?? lib);
1725
+ if (imp.type === 'NamespaceImport') env.define(imp.local, lib);
1726
+ if (imp.type === 'NamedImport') {
1727
+ if (!(imp.imported in lib)) throw new Error(`Module '${spec}' has no export '${imp.imported}'`);
1728
+ env.define(imp.local, lib[imp.imported]);
1729
+ }
1730
+ }
1736
1731
 
1737
- evalUpdate(node, env) {
1738
- const arg = node.argument;
1739
- const getCurrent = () => {
1740
- if (arg.type === 'Identifier') return env.get(arg.name);
1741
- if (arg.type === 'MemberExpression') return this.evalMember(arg, env);
1742
- if (arg.type === 'IndexExpression') return this.evalIndex(arg, env);
1743
- throw new Error('Invalid update target');
1744
- };
1745
- const setValue = (v) => {
1746
- if (arg.type === 'Identifier') env.set(arg.name, v);
1747
- else if (arg.type === 'MemberExpression') {
1748
- const obj = this.evaluate(arg.object, env);
1749
- obj[arg.property] = v;
1750
- }
1751
- else if (arg.type === 'IndexExpression') {
1752
- const obj = this.evaluate(arg.object, env);
1753
- const idx = this.evaluate(arg.indexer, env);
1754
- obj[idx] = v;
1755
- }
1756
- };
1757
- const current = getCurrent();
1758
- const newVal = (node.operator === 'PLUSPLUS') ? current + 1 : current - 1;
1759
- if (node.prefix) { setValue(newVal); return newVal; }
1760
- else { setValue(newVal); return current; }
1761
- }
1732
+ return null;
1733
+ }
1762
1734
  }
1763
1735
 
1764
- module.exports = Evaluator;
1736
+ module.exports = Evaluator;
1737
+
1765
1738
 
1766
1739
  /***/ }),
1767
1740
 
@@ -1909,7 +1882,19 @@ class Lexer {
1909
1882
  const startCol = this.column;
1910
1883
 
1911
1884
  if (char === '=' && next === '=') { tokens.push({ type: 'EQEQ', line: startLine, column: startCol }); this.advance(); this.advance(); continue; }
1912
- if (char === '=' && next === '>') { tokens.push({ type: 'ARROW', line: startLine, column: startCol }); this.advance(); this.advance(); continue; }
1885
+
1886
+ if (char === '=' && next === '>') {
1887
+ tokens.push({ type: 'ARROW', line: startLine, column: startCol });
1888
+ this.advance(); this.advance();
1889
+ continue;
1890
+ }
1891
+
1892
+ if (char === '-' && next === '>') {
1893
+ tokens.push({ type: 'ARROW', line: startLine, column: startCol });
1894
+ this.advance(); this.advance();
1895
+ continue;
1896
+ }
1897
+
1913
1898
  if (char === '!' && next === '=') { tokens.push({ type: 'NOTEQ', line: startLine, column: startCol }); this.advance(); this.advance(); continue; }
1914
1899
  if (char === '<' && next === '=') { tokens.push({ type: 'LTE', line: startLine, column: startCol }); this.advance(); this.advance(); continue; }
1915
1900
  if (char === '>' && next === '=') { tokens.push({ type: 'GTE', line: startLine, column: startCol }); this.advance(); this.advance(); continue; }
@@ -2317,6 +2302,15 @@ class Parser {
2317
2302
  }
2318
2303
  return node;
2319
2304
  }
2305
+ arrowFunction(params) {
2306
+ this.eat('ARROW');
2307
+ const body = this.expression();
2308
+ return {
2309
+ type: 'ArrowFunctionExpression',
2310
+ params,
2311
+ body
2312
+ };
2313
+ }
2320
2314
 
2321
2315
  primary() {
2322
2316
  const t = this.current;
@@ -2343,17 +2337,47 @@ class Parser {
2343
2337
  }
2344
2338
 
2345
2339
  if (t.type === 'IDENTIFIER') {
2346
- const name = t.value;
2340
+ const name = t.value;
2341
+ this.eat('IDENTIFIER');
2342
+
2343
+ if (this.current.type === 'ARROW') {
2344
+ return this.arrowFunction([name]);
2345
+ }
2346
+
2347
+ return { type: 'Identifier', name };
2348
+ }
2349
+
2350
+
2351
+ if (t.type === 'LPAREN') {
2352
+ this.eat('LPAREN');
2353
+
2354
+ const params = [];
2355
+
2356
+ if (this.current.type !== 'RPAREN') {
2357
+ params.push(this.current.value);
2358
+ this.eat('IDENTIFIER');
2359
+ while (this.current.type === 'COMMA') {
2360
+ this.eat('COMMA');
2361
+ params.push(this.current.value);
2347
2362
  this.eat('IDENTIFIER');
2348
- return { type: 'Identifier', name };
2349
2363
  }
2364
+ }
2365
+
2366
+ this.eat('RPAREN');
2367
+
2368
+ if (this.current.type === 'ARROW') {
2369
+ return this.arrowFunction(params);
2370
+ }
2371
+
2372
+ if (params.length === 1) {
2373
+ return { type: 'Identifier', name: params[0] };
2374
+ }
2375
+
2376
+ throw new Error(
2377
+ `Invalid grouped expression at line ${this.current.line}, column ${this.current.column}`
2378
+ );
2379
+ }
2350
2380
 
2351
- if (t.type === 'LPAREN') {
2352
- this.eat('LPAREN');
2353
- const expr = this.expression();
2354
- this.eat('RPAREN');
2355
- return expr;
2356
- }
2357
2381
 
2358
2382
  if (t.type === 'LBRACKET') {
2359
2383
  this.eat('LBRACKET');
@@ -2392,6 +2416,14 @@ class Parser {
2392
2416
 
2393
2417
  module.exports = Parser;
2394
2418
 
2419
+ /***/ }),
2420
+
2421
+ /***/ 266:
2422
+ /***/ ((module) => {
2423
+
2424
+ module.exports = eval("require")("node-fetch");
2425
+
2426
+
2395
2427
  /***/ }),
2396
2428
 
2397
2429
  /***/ 317:
@@ -2492,7 +2524,7 @@ const Lexer = __nccwpck_require__(211);
2492
2524
  const Parser = __nccwpck_require__(222);
2493
2525
  const Evaluator = __nccwpck_require__(112);
2494
2526
 
2495
- const VERSION = '1.0.23';
2527
+ const VERSION = '1.0.25';
2496
2528
 
2497
2529
  const COLOR = {
2498
2530
  reset: '\x1b[0m',