starlight-cli 1.0.24 → 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,438 +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 'ArrowFunctionExpression':
1452
- return this.evalArrowFunction(node, env);
1453
-
1454
- case 'ReturnStatement': {
1455
- const val = node.argument ? this.evaluate(node.argument, env) : null;
1456
- throw new ReturnValue(val);
1457
- }
1458
- case 'ArrayExpression': return node.elements.map(el => this.evaluate(el, env));
1459
- case 'IndexExpression': return this.evalIndex(node, env);
1460
- case 'ObjectExpression': return this.evalObject(node, env);
1461
- case 'MemberExpression': return this.evalMember(node, env);
1462
- case 'UpdateExpression': return this.evalUpdate(node, env);
1463
- default:
1464
- 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);
1465
1479
  }
1466
- }
1467
1480
 
1468
- evalProgram(node, env) {
1469
- let result = null;
1470
- for (const stmt of node.body) {
1471
- result = this.evaluate(stmt, env);
1481
+ async evalArrowFunction(node, env) {
1482
+ return { params: node.params, body: node.body, env, arrow: true };
1472
1483
  }
1473
- return result;
1474
- }
1475
- evalImport(node, env) {
1476
- const spec = node.path;
1477
- let lib;
1478
1484
 
1479
- try {
1480
- const resolved = require.resolve(spec, {
1481
- paths: [process.cwd()]
1482
- });
1483
- lib = require(resolved);
1484
- } catch (e) {
1485
- const fullPath = path.isAbsolute(spec)
1486
- ? spec
1487
- : 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;
1488
1488
 
1489
- if (!fs.existsSync(fullPath)) {
1490
- 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');
1491
1502
  }
1492
1503
 
1493
- const code = fs.readFileSync(fullPath, 'utf-8');
1494
- const tokens = new Lexer(code).getTokens();
1495
- 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
+ }
1496
1522
 
1497
- const moduleEnv = new Environment(env);
1498
- 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);
1499
1525
 
1500
- lib = {};
1501
- for (const key of Object.keys(moduleEnv.store)) {
1502
- lib[key] = moduleEnv.store[key];
1526
+ return computed;
1503
1527
  }
1504
1528
 
1505
- lib.default = lib;
1506
- }
1507
-
1508
- for (const imp of node.specifiers) {
1509
- if (imp.type === 'DefaultImport') {
1510
- 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;
1511
1533
  }
1512
- if (imp.type === 'NamespaceImport') {
1513
- env.define(imp.local, lib);
1514
- }
1515
- if (imp.type === 'NamedImport') {
1516
- if (!(imp.imported in lib)) {
1517
- throw new Error(`Module '${spec}' has no export '${imp.imported}'`);
1518
- }
1519
- env.define(imp.local, lib[imp.imported]);
1520
- }
1521
- }
1522
1534
 
1523
- return null;
1524
- }
1525
-
1526
-
1527
- evalBlock(node, env) {
1528
- let result = null;
1529
- for (const stmt of node.body) {
1530
- try {
1531
- result = this.evaluate(stmt, env);
1532
- } catch (e) {
1533
- if (e instanceof ReturnValue || e instanceof BreakSignal || e instanceof ContinueSignal) throw e;
1534
- throw e;
1535
- }
1535
+ async evalAsk(node, env) {
1536
+ const prompt = await this.evaluate(node.prompt, env);
1537
+ return readlineSync.question(prompt + ' ');
1536
1538
  }
1537
- return result;
1538
- }
1539
1539
 
1540
- evalVarDeclaration(node, env) {
1541
- const val = this.evaluate(node.expr, env);
1542
- return env.define(node.id, val);
1543
- }
1544
- evalArrowFunction(node, env) {
1545
- return {
1546
- params: node.params,
1547
- body: node.body,
1548
- env: env,
1549
- arrow: true
1550
- };
1551
- }
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
+ }
1552
1544
 
1553
- evalAssignment(node, env) {
1554
- const rightVal = this.evaluate(node.right, env);
1555
- 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
+ }
1556
1566
 
1557
- if (left.type === 'Identifier') return env.set(left.name, rightVal);
1558
- if (left.type === 'MemberExpression') {
1559
- const obj = this.evaluate(left.object, env);
1560
- obj[left.property] = rightVal;
1561
- 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}`);
1562
1572
  }
1563
- if (left.type === 'IndexExpression') {
1564
- const obj = this.evaluate(left.object, env);
1565
- const idx = this.evaluate(left.indexer, env);
1566
- obj[idx] = rightVal;
1567
- 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
+ }
1568
1582
  }
1569
1583
 
1570
- throw new Error('Invalid assignment target');
1571
- }
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
+ }
1572
1590
 
1573
- evalCompoundAssignment(node, env) {
1574
- const left = node.left;
1575
- 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
+ }
1576
1598
 
1577
- if (left.type === 'Identifier') current = env.get(left.name);
1578
- else if (left.type === 'MemberExpression') current = this.evalMember(left, env);
1579
- else if (left.type === 'IndexExpression') current = this.evalIndex(left, env);
1580
- 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
+ }
1581
1613
 
1582
- const rhs = this.evaluate(node.right, env);
1583
- let computed;
1584
- switch (node.operator) {
1585
- case 'PLUSEQ': computed = current + rhs; break;
1586
- case 'MINUSEQ': computed = current - rhs; break;
1587
- case 'STAREQ': computed = current * rhs; break;
1588
- case 'SLASHEQ': computed = current / rhs; break;
1589
- case 'MODEQ': computed = current % rhs; break;
1590
- 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;
1591
1618
  }
1592
1619
 
1593
- if (left.type === 'Identifier') env.set(left.name, computed);
1594
- else if (left.type === 'MemberExpression') this.evalAssignment({ left, right: { type: 'Literal', value: computed }, type: 'AssignmentExpression' }, env);
1595
- 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);
1596
1622
 
1597
- return computed;
1598
- }
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
+ }
1599
1628
 
1600
- evalSldeploy(node, env) {
1601
- const val = this.evaluate(node.expr, env);
1602
- console.log(val);
1603
- return val;
1604
- }
1629
+ if (!calleeEvaluated || typeof calleeEvaluated !== 'object' || !calleeEvaluated.body) throw new Error('Call to non-function');
1605
1630
 
1606
- evalAsk(node, env) {
1607
- const prompt = this.evaluate(node.prompt, env);
1608
- const input = readlineSync.question(prompt + ' ');
1609
- return input;
1610
- }
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
+ }
1611
1637
 
1612
- evalDefine(node, env) {
1613
- const val = node.expr ? this.evaluate(node.expr, env) : null;
1614
- return this.global.define(node.id, val);
1615
- }
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
+ }
1616
1643
 
1617
- evalBinary(node, env) {
1618
- const l = this.evaluate(node.left, env);
1619
- 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);
1620
1647
 
1621
- if (node.operator === 'SLASH' && r === 0) {
1622
- 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];
1623
1652
  }
1624
1653
 
1625
- switch (node.operator) {
1626
- case 'PLUS': return l + r;
1627
- case 'MINUS': return l - r;
1628
- case 'STAR': return l * r;
1629
- case 'SLASH': return l / r;
1630
- case 'MOD': return l % r;
1631
- case 'EQEQ': return l === r;
1632
- case 'NOTEQ': return l !== r;
1633
- case 'LT': return l < r;
1634
- case 'LTE': return l <= r;
1635
- case 'GT': return l > r;
1636
- case 'GTE': return l >= r;
1637
- 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;
1638
1658
  }
1639
- }
1640
1659
 
1641
-
1642
- evalLogical(node, env) {
1643
- const l = this.evaluate(node.left, env);
1644
- if (node.operator === 'AND') return l && this.evaluate(node.right, env);
1645
- if (node.operator === 'OR') return l || this.evaluate(node.right, env);
1646
- throw new Error(`Unknown logical operator ${node.operator}`);
1647
- }
1648
-
1649
- evalUnary(node, env) {
1650
- const val = this.evaluate(node.argument, env);
1651
- switch (node.operator) {
1652
- case 'NOT': return !val;
1653
- case 'MINUS': return -val;
1654
- case 'PLUS': return +val;
1655
- 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];
1656
1665
  }
1657
- }
1658
1666
 
1659
- evalIf(node, env) {
1660
- const test = this.evaluate(node.test, env);
1661
- if (test) return this.evaluate(node.consequent, env);
1662
- if (node.alternate) return this.evaluate(node.alternate, env);
1663
- return null;
1664
- }
1665
-
1666
- evalWhile(node, env) {
1667
- while (this.evaluate(node.test, env)) {
1668
- try { this.evaluate(node.body, env); }
1669
- catch (e) {
1670
- if (e instanceof BreakSignal) break;
1671
- if (e instanceof ContinueSignal) continue;
1672
- throw e;
1673
- }
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;
1674
1671
  }
1675
- return null;
1676
- }
1677
1672
 
1678
- evalFor(node, env) {
1679
- const local = new Environment(env);
1680
- if (node.init) this.evaluate(node.init, local);
1681
- while (!node.test || this.evaluate(node.test, local)) {
1682
- try { this.evaluate(node.body, local); }
1683
- catch (e) {
1684
- if (e instanceof BreakSignal) break;
1685
- if (e instanceof ContinueSignal) { if (node.update) this.evaluate(node.update, local); continue; }
1686
- throw e;
1687
- }
1688
- 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;
1689
1677
  }
1690
- return null;
1691
- }
1692
-
1693
- evalFunctionDeclaration(node, env) {
1694
- const fn = { params: node.params, body: node.body, env };
1695
- env.define(node.name, fn);
1696
- return null;
1697
- }
1698
1678
 
1699
- evalCall(node, env) {
1700
- const calleeEvaluated = this.evaluate(node.callee, env);
1701
- if (typeof calleeEvaluated === 'function') {
1702
- const args = node.arguments.map(a => this.evaluate(a, env));
1703
- return calleeEvaluated(...args);
1704
- }
1705
- if (!calleeEvaluated || typeof calleeEvaluated !== 'object' || !calleeEvaluated.body) {
1706
- 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; }
1707
1698
  }
1708
- const fn = calleeEvaluated;
1709
- const callEnv = new Environment(fn.env);
1710
- fn.params.forEach((p, i) => {
1711
- const argVal = node.arguments[i] ? this.evaluate(node.arguments[i], env) : null;
1712
- callEnv.define(p, argVal);
1713
- });
1714
- try {
1715
- const result = this.evaluate(fn.body, callEnv);
1716
- return fn.arrow ? result : result;
1717
- } catch (e) {
1718
- if (e instanceof ReturnValue) return e.value;
1719
- throw e;
1720
- }
1721
-
1722
- }
1723
1699
 
1724
- evalIndex(node, env) {
1725
- const obj = this.evaluate(node.object, env);
1726
- const idx = this.evaluate(node.indexer, env);
1700
+ async evalImport(node, env) {
1701
+ const spec = node.path;
1702
+ let lib;
1727
1703
 
1728
- if (obj == null) throw new Error('Indexing null or undefined');
1729
- if (Array.isArray(obj) && (idx < 0 || idx >= obj.length)) {
1730
- throw new Error('Array index out of bounds');
1731
- }
1732
- if (typeof obj === 'object' && !(idx in obj)) {
1733
- throw new Error(`Property '${idx}' does not exist`);
1734
- }
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}`);
1735
1710
 
1736
- return obj[idx];
1737
- }
1711
+ const code = fs.readFileSync(fullPath, 'utf-8');
1712
+ const tokens = new Lexer(code).getTokens();
1713
+ const ast = new Parser(tokens).parse();
1738
1714
 
1715
+ const moduleEnv = new Environment(env);
1716
+ await this.evaluate(ast, moduleEnv);
1739
1717
 
1740
- evalObject(node, env) {
1741
- const out = {};
1742
- for (const p of node.props) out[p.key] = this.evaluate(p.value, env);
1743
- return out;
1744
- }
1745
-
1746
- evalMember(node, env) {
1747
- const obj = this.evaluate(node.object, env);
1748
- if (obj == null) throw new Error('Member access of null or undefined');
1749
- if (!(node.property in obj)) throw new Error(`Property '${node.property}' does not exist`);
1750
- return obj[node.property];
1751
- }
1718
+ lib = {};
1719
+ for (const key of Object.keys(moduleEnv.store)) lib[key] = moduleEnv.store[key];
1720
+ lib.default = lib;
1721
+ }
1752
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
+ }
1753
1731
 
1754
- evalUpdate(node, env) {
1755
- const arg = node.argument;
1756
- const getCurrent = () => {
1757
- if (arg.type === 'Identifier') return env.get(arg.name);
1758
- if (arg.type === 'MemberExpression') return this.evalMember(arg, env);
1759
- if (arg.type === 'IndexExpression') return this.evalIndex(arg, env);
1760
- throw new Error('Invalid update target');
1761
- };
1762
- const setValue = (v) => {
1763
- if (arg.type === 'Identifier') env.set(arg.name, v);
1764
- else if (arg.type === 'MemberExpression') {
1765
- const obj = this.evaluate(arg.object, env);
1766
- obj[arg.property] = v;
1767
- }
1768
- else if (arg.type === 'IndexExpression') {
1769
- const obj = this.evaluate(arg.object, env);
1770
- const idx = this.evaluate(arg.indexer, env);
1771
- obj[idx] = v;
1772
- }
1773
- };
1774
- const current = getCurrent();
1775
- const newVal = (node.operator === 'PLUSPLUS') ? current + 1 : current - 1;
1776
- if (node.prefix) { setValue(newVal); return newVal; }
1777
- else { setValue(newVal); return current; }
1778
- }
1732
+ return null;
1733
+ }
1779
1734
  }
1780
1735
 
1781
- module.exports = Evaluator;
1736
+ module.exports = Evaluator;
1737
+
1782
1738
 
1783
1739
  /***/ }),
1784
1740
 
@@ -2460,6 +2416,14 @@ arrowFunction(params) {
2460
2416
 
2461
2417
  module.exports = Parser;
2462
2418
 
2419
+ /***/ }),
2420
+
2421
+ /***/ 266:
2422
+ /***/ ((module) => {
2423
+
2424
+ module.exports = eval("require")("node-fetch");
2425
+
2426
+
2463
2427
  /***/ }),
2464
2428
 
2465
2429
  /***/ 317:
@@ -2560,7 +2524,7 @@ const Lexer = __nccwpck_require__(211);
2560
2524
  const Parser = __nccwpck_require__(222);
2561
2525
  const Evaluator = __nccwpck_require__(112);
2562
2526
 
2563
- const VERSION = '1.0.24';
2527
+ const VERSION = '1.0.25';
2564
2528
 
2565
2529
  const COLOR = {
2566
2530
  reset: '\x1b[0m',