starlight-cli 1.1.15 → 1.1.17
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 +608 -16
- package/package.json +1 -1
- package/src/evaluator.js +465 -3
- package/src/parser.js +142 -12
- package/src/starlight.js +1 -1
package/dist/index.js
CHANGED
|
@@ -10213,7 +10213,6 @@ const fs = __nccwpck_require__(896);
|
|
|
10213
10213
|
const Lexer = __nccwpck_require__(211);
|
|
10214
10214
|
const Parser = __nccwpck_require__(222);
|
|
10215
10215
|
const path = __nccwpck_require__(928);
|
|
10216
|
-
|
|
10217
10216
|
class ReturnValue {
|
|
10218
10217
|
constructor(value) { this.value = value; }
|
|
10219
10218
|
}
|
|
@@ -10414,7 +10413,51 @@ formatValue(value, seen = new Set()) {
|
|
|
10414
10413
|
if (arg && typeof arg === 'object') return Object.keys(arg).length;
|
|
10415
10414
|
return 0;
|
|
10416
10415
|
});
|
|
10416
|
+
this.global.define('lower', arg => {
|
|
10417
|
+
if (typeof arg !== 'string') return String(arg).toLowerCase();
|
|
10418
|
+
return arg.toLowerCase();
|
|
10419
|
+
});
|
|
10420
|
+
this.global.define('toStr', arg => String(arg));
|
|
10421
|
+
|
|
10422
|
+
this.global.define('upper', arg => {
|
|
10423
|
+
if (typeof arg !== 'string') return String(arg).toUpperCase();
|
|
10424
|
+
return arg.toUpperCase();
|
|
10425
|
+
});
|
|
10426
|
+
|
|
10427
|
+
this.global.define('trim', arg => {
|
|
10428
|
+
if (typeof arg !== 'string') return String(arg).trim();
|
|
10429
|
+
return arg.trim();
|
|
10430
|
+
});
|
|
10431
|
+
|
|
10432
|
+
this.global.define('startsWith', (str, prefix) => {
|
|
10433
|
+
if (typeof str !== 'string') str = String(str);
|
|
10434
|
+
if (typeof prefix !== 'string') prefix = String(prefix);
|
|
10435
|
+
return str.startsWith(prefix);
|
|
10436
|
+
});
|
|
10437
|
+
|
|
10438
|
+
this.global.define('endsWith', (str, suffix) => {
|
|
10439
|
+
if (typeof str !== 'string') str = String(str);
|
|
10440
|
+
if (typeof suffix !== 'string') suffix = String(suffix);
|
|
10441
|
+
return str.endsWith(suffix);
|
|
10442
|
+
});
|
|
10443
|
+
|
|
10444
|
+
this.global.define('includes', (str, substr) => {
|
|
10445
|
+
if (typeof str !== 'string') str = String(str);
|
|
10446
|
+
if (typeof substr !== 'string') substr = String(substr);
|
|
10447
|
+
return str.includes(substr);
|
|
10448
|
+
});
|
|
10449
|
+
|
|
10450
|
+
this.global.define('repeat', (str, times) => {
|
|
10451
|
+
if (typeof str !== 'string') str = String(str);
|
|
10452
|
+
return str.repeat(Number(times) || 0);
|
|
10453
|
+
});
|
|
10417
10454
|
|
|
10455
|
+
this.global.define('replace', (str, search, replacement) => {
|
|
10456
|
+
if (typeof str !== 'string') str = String(str);
|
|
10457
|
+
if (typeof search !== 'string') search = String(search);
|
|
10458
|
+
if (typeof replacement !== 'string') replacement = String(replacement);
|
|
10459
|
+
return str.split(search).join(replacement);
|
|
10460
|
+
});
|
|
10418
10461
|
this.global.define('print', arg => { console.log(arg); return null; });
|
|
10419
10462
|
this.global.define('type', arg => {
|
|
10420
10463
|
if (Array.isArray(arg)) return 'array';
|
|
@@ -10563,6 +10606,72 @@ this.global.define('range', (...args) => {
|
|
|
10563
10606
|
|
|
10564
10607
|
return result;
|
|
10565
10608
|
});
|
|
10609
|
+
this.global.define('floor', arg => Math.floor(Number(arg)));
|
|
10610
|
+
this.global.define('ceil', arg => Math.ceil(Number(arg)));
|
|
10611
|
+
this.global.define('round', arg => Math.round(Number(arg)));
|
|
10612
|
+
this.global.define('abs', arg => Math.abs(Number(arg)));
|
|
10613
|
+
this.global.define('pow', (base, exp) => Math.pow(Number(base), Number(exp)));
|
|
10614
|
+
this.global.define('sqrt', arg => Math.sqrt(Number(arg)));
|
|
10615
|
+
this.global.define('min', (...args) => Math.min(...args.map(Number)));
|
|
10616
|
+
this.global.define('max', (...args) => Math.max(...args.map(Number)));
|
|
10617
|
+
this.global.define('randomFloat', (min, max) => {
|
|
10618
|
+
min = Number(min); max = Number(max);
|
|
10619
|
+
if (isNaN(min) || isNaN(max)) return 0;
|
|
10620
|
+
return Math.random() * (max - min) + min;
|
|
10621
|
+
});
|
|
10622
|
+
|
|
10623
|
+
this.global.define('push', (arr, val) => {
|
|
10624
|
+
if (!Array.isArray(arr)) throw new RuntimeError('push() expects an array', null, this.source);
|
|
10625
|
+
arr.push(val); return arr.length;
|
|
10626
|
+
});
|
|
10627
|
+
this.global.define('pop', arr => {
|
|
10628
|
+
if (!Array.isArray(arr)) throw new RuntimeError('pop() expects an array', null, this.source);
|
|
10629
|
+
return arr.pop();
|
|
10630
|
+
});
|
|
10631
|
+
this.global.define('shift', arr => {
|
|
10632
|
+
if (!Array.isArray(arr)) throw new RuntimeError('shift() expects an array', null, this.source);
|
|
10633
|
+
return arr.shift();
|
|
10634
|
+
});
|
|
10635
|
+
this.global.define('unshift', (arr, val) => {
|
|
10636
|
+
if (!Array.isArray(arr)) throw new RuntimeError('unshift() expects an array', null, this.source);
|
|
10637
|
+
arr.unshift(val); return arr.length;
|
|
10638
|
+
});
|
|
10639
|
+
this.global.define('sort', (arr, fn) => {
|
|
10640
|
+
if (!Array.isArray(arr)) throw new RuntimeError('sort() expects an array', null, this.source);
|
|
10641
|
+
if (fn && typeof fn === 'function') return arr.sort(fn);
|
|
10642
|
+
return arr.sort();
|
|
10643
|
+
});
|
|
10644
|
+
this.global.define('reverse', arr => {
|
|
10645
|
+
if (!Array.isArray(arr)) throw new RuntimeError('reverse() expects an array', null, this.source);
|
|
10646
|
+
return arr.reverse();
|
|
10647
|
+
});
|
|
10648
|
+
|
|
10649
|
+
this.global.define('has', (obj, key) => obj && typeof obj === 'object' ? obj.hasOwnProperty(key) : false);
|
|
10650
|
+
this.global.define('merge', (obj1, obj2) => {
|
|
10651
|
+
if (!obj1 || typeof obj1 !== 'object') obj1 = {};
|
|
10652
|
+
if (!obj2 || typeof obj2 !== 'object') obj2 = {};
|
|
10653
|
+
return { ...obj1, ...obj2 };
|
|
10654
|
+
});
|
|
10655
|
+
|
|
10656
|
+
this.global.define('uuid', () => {
|
|
10657
|
+
// simple random UUID v4
|
|
10658
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
10659
|
+
const r = Math.random() * 16 | 0;
|
|
10660
|
+
const v = c === 'x' ? r : (r & 0x3 | 0x8);
|
|
10661
|
+
return v.toString(16);
|
|
10662
|
+
});
|
|
10663
|
+
});
|
|
10664
|
+
this.global.define('timestamp', () => Date.now());
|
|
10665
|
+
this.global.define('clone', arg => {
|
|
10666
|
+
if (Array.isArray(arg)) return [...arg];
|
|
10667
|
+
if (arg && typeof arg === 'object') return { ...arg };
|
|
10668
|
+
return arg; // primitive types
|
|
10669
|
+
});
|
|
10670
|
+
this.global.define('typeOf', arg => {
|
|
10671
|
+
if (arg === null) return 'null';
|
|
10672
|
+
if (Array.isArray(arg)) return 'array';
|
|
10673
|
+
return typeof arg;
|
|
10674
|
+
});
|
|
10566
10675
|
|
|
10567
10676
|
this.global.define('ask', prompt => {
|
|
10568
10677
|
const readlineSync = __nccwpck_require__(552);
|
|
@@ -10619,6 +10728,271 @@ this.global.define('sleep', async (ms) => {
|
|
|
10619
10728
|
this.global.define('str', arg => {
|
|
10620
10729
|
return String(arg);
|
|
10621
10730
|
});
|
|
10731
|
+
this.global.define('now', () => Date.now());
|
|
10732
|
+
this.global.define('formatDate', (timestamp, locale = 'en-US', options = {}) => {
|
|
10733
|
+
if (timestamp === null || timestamp === undefined) timestamp = Date.now();
|
|
10734
|
+
const t = typeof timestamp === 'number' ? timestamp : Number(timestamp);
|
|
10735
|
+
if (isNaN(t)) t = Date.now();
|
|
10736
|
+
return new Date(t).toLocaleString(locale, options);
|
|
10737
|
+
});
|
|
10738
|
+
|
|
10739
|
+
this.global.define('readFile', path => {
|
|
10740
|
+
if (typeof path !== 'string') path = String(path);
|
|
10741
|
+
try {
|
|
10742
|
+
return fs.readFileSync(path, 'utf-8');
|
|
10743
|
+
} catch (e) {
|
|
10744
|
+
throw new RuntimeError('readFile error: ' + e.message, null, this.source);
|
|
10745
|
+
}
|
|
10746
|
+
});
|
|
10747
|
+
this.global.define('writeFile', (path, content) => {
|
|
10748
|
+
if (typeof path !== 'string') path = String(path);
|
|
10749
|
+
if (typeof content !== 'string') content = String(content);
|
|
10750
|
+
try {
|
|
10751
|
+
fs.writeFileSync(path, content, 'utf-8');
|
|
10752
|
+
return true;
|
|
10753
|
+
} catch (e) {
|
|
10754
|
+
throw new RuntimeError('writeFile error: ' + e.message, null, this.source);
|
|
10755
|
+
}
|
|
10756
|
+
});
|
|
10757
|
+
|
|
10758
|
+
this.global.define('split', (str, separator) => {
|
|
10759
|
+
if (typeof str !== 'string') str = String(str);
|
|
10760
|
+
if (separator === undefined) separator = '';
|
|
10761
|
+
return str.split(separator);
|
|
10762
|
+
});
|
|
10763
|
+
|
|
10764
|
+
this.global.define('join', (arr, separator = '') => {
|
|
10765
|
+
if (!Array.isArray(arr)) throw new RuntimeError('join() expects an array', null, this.source);
|
|
10766
|
+
return arr.join(separator);
|
|
10767
|
+
});
|
|
10768
|
+
|
|
10769
|
+
this.global.define('substring', (str, start, end) => {
|
|
10770
|
+
if (typeof str !== 'string') str = String(str);
|
|
10771
|
+
start = Number(start) || 0;
|
|
10772
|
+
end = end !== undefined ? Number(end) : undefined;
|
|
10773
|
+
return str.substring(start, end);
|
|
10774
|
+
});
|
|
10775
|
+
|
|
10776
|
+
this.global.define('padStart', (str, targetLength, padString = ' ') => {
|
|
10777
|
+
if (typeof str !== 'string') str = String(str);
|
|
10778
|
+
targetLength = Number(targetLength) || 0;
|
|
10779
|
+
return str.padStart(targetLength, padString);
|
|
10780
|
+
});
|
|
10781
|
+
|
|
10782
|
+
this.global.define('padEnd', (str, targetLength, padString = ' ') => {
|
|
10783
|
+
if (typeof str !== 'string') str = String(str);
|
|
10784
|
+
targetLength = Number(targetLength) || 0;
|
|
10785
|
+
return str.padEnd(targetLength, padString);
|
|
10786
|
+
});
|
|
10787
|
+
this.global.define('unique', arr => {
|
|
10788
|
+
if (!Array.isArray(arr)) throw new RuntimeError('unique() expects an array', null, this.source);
|
|
10789
|
+
return [...new Set(arr)];
|
|
10790
|
+
});
|
|
10791
|
+
|
|
10792
|
+
this.global.define('indexOf', (arr, val) => {
|
|
10793
|
+
if (!Array.isArray(arr)) throw new RuntimeError('indexOf() expects an array', null, this.source);
|
|
10794
|
+
return arr.indexOf(val);
|
|
10795
|
+
});
|
|
10796
|
+
|
|
10797
|
+
this.global.define('includesArr', (arr, val) => {
|
|
10798
|
+
if (!Array.isArray(arr)) throw new RuntimeError('includesArr() expects an array', null, this.source);
|
|
10799
|
+
return arr.includes(val);
|
|
10800
|
+
});
|
|
10801
|
+
|
|
10802
|
+
this.global.define('flatten', arr => {
|
|
10803
|
+
if (!Array.isArray(arr)) throw new RuntimeError('flatten() expects an array', null, this.source);
|
|
10804
|
+
return arr.flat(Infinity);
|
|
10805
|
+
});
|
|
10806
|
+
|
|
10807
|
+
this.global.define('randomChoice', arr => {
|
|
10808
|
+
if (!Array.isArray(arr)) throw new RuntimeError('randomChoice() expects an array', null, this.source);
|
|
10809
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
10810
|
+
});
|
|
10811
|
+
|
|
10812
|
+
this.global.define('entries', obj => {
|
|
10813
|
+
if (!obj || typeof obj !== 'object') throw new RuntimeError('entries() expects an object', null, this.source);
|
|
10814
|
+
return Object.entries(obj);
|
|
10815
|
+
});
|
|
10816
|
+
|
|
10817
|
+
this.global.define('invert', obj => {
|
|
10818
|
+
if (!obj || typeof obj !== 'object') throw new RuntimeError('invert() expects an object', null, this.source);
|
|
10819
|
+
const result = {};
|
|
10820
|
+
for (const key in obj) result[obj[key]] = key;
|
|
10821
|
+
return result;
|
|
10822
|
+
});
|
|
10823
|
+
|
|
10824
|
+
this.global.define('isEmpty', arg => {
|
|
10825
|
+
if (arg == null) return true;
|
|
10826
|
+
if (Array.isArray(arg) || typeof arg === 'string') return arg.length === 0;
|
|
10827
|
+
if (typeof arg === 'object') return Object.keys(arg).length === 0;
|
|
10828
|
+
return false;
|
|
10829
|
+
});
|
|
10830
|
+
|
|
10831
|
+
this.global.define('deepClone', arg => {
|
|
10832
|
+
return JSON.parse(JSON.stringify(arg));
|
|
10833
|
+
});
|
|
10834
|
+
|
|
10835
|
+
this.global.define('capitalize', str => {
|
|
10836
|
+
if (typeof str !== 'string') str = String(str);
|
|
10837
|
+
if (str.length === 0) return '';
|
|
10838
|
+
return str[0].toUpperCase() + str.slice(1);
|
|
10839
|
+
});
|
|
10840
|
+
|
|
10841
|
+
this.global.define('reverseStr', str => {
|
|
10842
|
+
if (typeof str !== 'string') str = String(str);
|
|
10843
|
+
return str.split('').reverse().join('');
|
|
10844
|
+
});
|
|
10845
|
+
|
|
10846
|
+
this.global.define('trimStart', str => {
|
|
10847
|
+
if (typeof str !== 'string') str = String(str);
|
|
10848
|
+
return str.trimStart();
|
|
10849
|
+
});
|
|
10850
|
+
|
|
10851
|
+
this.global.define('trimEnd', str => {
|
|
10852
|
+
if (typeof str !== 'string') str = String(str);
|
|
10853
|
+
return str.trimEnd();
|
|
10854
|
+
});
|
|
10855
|
+
|
|
10856
|
+
this.global.define('clamp', (value, min, max) => {
|
|
10857
|
+
value = Number(value); min = Number(min); max = Number(max);
|
|
10858
|
+
return Math.min(Math.max(value, min), max);
|
|
10859
|
+
});
|
|
10860
|
+
|
|
10861
|
+
this.global.define('sign', value => {
|
|
10862
|
+
value = Number(value);
|
|
10863
|
+
return Math.sign(value);
|
|
10864
|
+
});
|
|
10865
|
+
|
|
10866
|
+
this.global.define('appendFile', (path, content) => {
|
|
10867
|
+
if (typeof path !== 'string') path = String(path);
|
|
10868
|
+
if (typeof content !== 'string') content = String(content);
|
|
10869
|
+
try {
|
|
10870
|
+
fs.appendFileSync(path, content, 'utf-8');
|
|
10871
|
+
return true;
|
|
10872
|
+
} catch (e) {
|
|
10873
|
+
throw new RuntimeError('appendFile error: ' + e.message, null, this.source);
|
|
10874
|
+
}
|
|
10875
|
+
});
|
|
10876
|
+
|
|
10877
|
+
this.global.define('exists', path => {
|
|
10878
|
+
if (typeof path !== 'string') path = String(path);
|
|
10879
|
+
return fs.existsSync(path);
|
|
10880
|
+
});
|
|
10881
|
+
|
|
10882
|
+
this.global.define('mkdir', path => {
|
|
10883
|
+
if (typeof path !== 'string') path = String(path);
|
|
10884
|
+
if (!fs.existsSync(path)) fs.mkdirSync(path, { recursive: true });
|
|
10885
|
+
return true;
|
|
10886
|
+
});
|
|
10887
|
+
this.global.define('count', (arr, value) => {
|
|
10888
|
+
if (!Array.isArray(arr)) throw new RuntimeError('count() expects an array', null, this.source);
|
|
10889
|
+
return arr.filter(x => x === value).length;
|
|
10890
|
+
});
|
|
10891
|
+
|
|
10892
|
+
this.global.define('uniqueBy', (arr, fn) => {
|
|
10893
|
+
if (!Array.isArray(arr)) throw new RuntimeError('uniqueBy() expects an array', null, this.source);
|
|
10894
|
+
const seen = new Set();
|
|
10895
|
+
const result = [];
|
|
10896
|
+
for (const item of arr) {
|
|
10897
|
+
const key = fn ? fn(item) : item;
|
|
10898
|
+
if (!seen.has(key)) {
|
|
10899
|
+
seen.add(key);
|
|
10900
|
+
result.push(item);
|
|
10901
|
+
}
|
|
10902
|
+
}
|
|
10903
|
+
return result;
|
|
10904
|
+
});
|
|
10905
|
+
this.global.define('getProp', (obj, key, defaultValue = null) => {
|
|
10906
|
+
if (!obj || typeof obj !== 'object') return defaultValue;
|
|
10907
|
+
const keys = key.split('.');
|
|
10908
|
+
let current = obj;
|
|
10909
|
+
for (const k of keys) {
|
|
10910
|
+
if (current[k] === undefined) return defaultValue;
|
|
10911
|
+
current = current[k];
|
|
10912
|
+
}
|
|
10913
|
+
return current;
|
|
10914
|
+
});
|
|
10915
|
+
|
|
10916
|
+
this.global.define('setProp', (obj, key, value) => {
|
|
10917
|
+
if (!obj || typeof obj !== 'object') throw new RuntimeError('setProp() expects an object', null, this.source);
|
|
10918
|
+
const keys = key.split('.');
|
|
10919
|
+
let current = obj;
|
|
10920
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
10921
|
+
if (!current[keys[i]] || typeof current[keys[i]] !== 'object') current[keys[i]] = {};
|
|
10922
|
+
current = current[keys[i]];
|
|
10923
|
+
}
|
|
10924
|
+
current[keys[keys.length - 1]] = value;
|
|
10925
|
+
return obj;
|
|
10926
|
+
});
|
|
10927
|
+
|
|
10928
|
+
this.global.define('mergeDeep', (obj1, obj2) => {
|
|
10929
|
+
const isObject = val => val && typeof val === 'object';
|
|
10930
|
+
const result = {...obj1};
|
|
10931
|
+
for (const key in obj2) {
|
|
10932
|
+
if (isObject(obj2[key]) && isObject(result[key])) {
|
|
10933
|
+
result[key] = this.global.get('mergeDeep')(result[key], obj2[key]);
|
|
10934
|
+
} else {
|
|
10935
|
+
result[key] = obj2[key];
|
|
10936
|
+
}
|
|
10937
|
+
}
|
|
10938
|
+
return result;
|
|
10939
|
+
});
|
|
10940
|
+
this.global.define('camelCase', str => {
|
|
10941
|
+
if (typeof str !== 'string') str = String(str);
|
|
10942
|
+
return str
|
|
10943
|
+
.replace(/[-_ ]+./g, s => s.charAt(s.length - 1).toUpperCase())
|
|
10944
|
+
.replace(/^[A-Z]/, s => s.toLowerCase());
|
|
10945
|
+
});
|
|
10946
|
+
|
|
10947
|
+
this.global.define('kebabCase', str => {
|
|
10948
|
+
if (typeof str !== 'string') str = String(str);
|
|
10949
|
+
return str
|
|
10950
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
10951
|
+
.replace(/\s+/g, '-')
|
|
10952
|
+
.replace(/_+/g, '-')
|
|
10953
|
+
.toLowerCase();
|
|
10954
|
+
});
|
|
10955
|
+
|
|
10956
|
+
this.global.define('repeatStr', (str, times) => {
|
|
10957
|
+
if (typeof str !== 'string') str = String(str);
|
|
10958
|
+
return str.repeat(Number(times) || 0);
|
|
10959
|
+
});
|
|
10960
|
+
this.global.define('randomInt', (min, max) => {
|
|
10961
|
+
min = Number(min); max = Number(max);
|
|
10962
|
+
if (isNaN(min) || isNaN(max)) return 0;
|
|
10963
|
+
return Math.floor(Math.random() * (max - min + 1)) + min;
|
|
10964
|
+
});
|
|
10965
|
+
|
|
10966
|
+
this.global.define('lerp', (a, b, t) => {
|
|
10967
|
+
a = Number(a); b = Number(b); t = Number(t);
|
|
10968
|
+
return a + (b - a) * t;
|
|
10969
|
+
});
|
|
10970
|
+
|
|
10971
|
+
this.global.define('degToRad', deg => Number(deg) * (Math.PI / 180));
|
|
10972
|
+
this.global.define('radToDeg', rad => Number(rad) * (180 / Math.PI));
|
|
10973
|
+
this.global.define('readJSON', path => {
|
|
10974
|
+
const content = this.global.get('readFile')(path);
|
|
10975
|
+
return JSON.parse(content);
|
|
10976
|
+
});
|
|
10977
|
+
|
|
10978
|
+
this.global.define('writeJSON', (path, obj) => {
|
|
10979
|
+
const content = JSON.stringify(obj, null, 2);
|
|
10980
|
+
return this.global.get('writeFile')(path, content);
|
|
10981
|
+
});
|
|
10982
|
+
|
|
10983
|
+
this.global.define('deleteFile', path => {
|
|
10984
|
+
if (typeof path !== 'string') path = String(path);
|
|
10985
|
+
if (!fs.existsSync(path)) return false;
|
|
10986
|
+
fs.unlinkSync(path);
|
|
10987
|
+
return true;
|
|
10988
|
+
});
|
|
10989
|
+
|
|
10990
|
+
this.global.define('rmdir', path => {
|
|
10991
|
+
if (typeof path !== 'string') path = String(path);
|
|
10992
|
+
if (!fs.existsSync(path)) return false;
|
|
10993
|
+
fs.rmSync(path, { recursive: true, force: true });
|
|
10994
|
+
return true;
|
|
10995
|
+
});
|
|
10622
10996
|
|
|
10623
10997
|
}
|
|
10624
10998
|
|
|
@@ -10632,10 +11006,17 @@ async evaluate(node, env = this.global) {
|
|
|
10632
11006
|
case 'SldeployStatement': return await this.evalSldeploy(node, env);
|
|
10633
11007
|
case 'AskStatement': return await this.evalAsk(node, env);
|
|
10634
11008
|
case 'DefineStatement': return await this.evalDefine(node, env);
|
|
11009
|
+
case 'FunctionExpression':
|
|
11010
|
+
return this.evalFunctionExpression(node, env);
|
|
11011
|
+
case 'SliceExpression':
|
|
11012
|
+
return await this.evalSlice(node, env);
|
|
11013
|
+
|
|
10635
11014
|
case 'ExpressionStatement': return await this.evaluate(node.expression, env);
|
|
10636
11015
|
case 'BinaryExpression': return await this.evalBinary(node, env);
|
|
10637
11016
|
case 'LogicalExpression': return await this.evalLogical(node, env);
|
|
10638
11017
|
case 'UnaryExpression': return await this.evalUnary(node, env);
|
|
11018
|
+
case 'ConditionalExpression':
|
|
11019
|
+
return await this.evalConditional(node, env);
|
|
10639
11020
|
case 'Literal': return node.value;
|
|
10640
11021
|
case 'Identifier': return env.get(node.name, node, this.source);
|
|
10641
11022
|
case 'IfStatement': return await this.evalIf(node, env);
|
|
@@ -10738,6 +11119,36 @@ async evalProgram(node, env) {
|
|
|
10738
11119
|
}
|
|
10739
11120
|
return result;
|
|
10740
11121
|
}
|
|
11122
|
+
async evalSlice(node, env) {
|
|
11123
|
+
try {
|
|
11124
|
+
const arr = await this.evaluate(node.object, env);
|
|
11125
|
+
const start = node.start ? await this.evaluate(node.start, env) : 0;
|
|
11126
|
+
const end = node.end ? await this.evaluate(node.end, env) : arr.length;
|
|
11127
|
+
|
|
11128
|
+
if (!Array.isArray(arr)) {
|
|
11129
|
+
throw new RuntimeError(
|
|
11130
|
+
'Slice target must be an array',
|
|
11131
|
+
node,
|
|
11132
|
+
this.source,
|
|
11133
|
+
env
|
|
11134
|
+
);
|
|
11135
|
+
}
|
|
11136
|
+
|
|
11137
|
+
const s = start < 0 ? Math.max(arr.length + start, 0) : Math.min(start, arr.length);
|
|
11138
|
+
const e = end < 0 ? Math.max(arr.length + end, 0) : Math.min(end, arr.length);
|
|
11139
|
+
|
|
11140
|
+
return arr.slice(s, e);
|
|
11141
|
+
|
|
11142
|
+
} catch (err) {
|
|
11143
|
+
if (err instanceof RuntimeError) throw err;
|
|
11144
|
+
throw new RuntimeError(
|
|
11145
|
+
err.message || 'Error evaluating slice expression',
|
|
11146
|
+
node,
|
|
11147
|
+
this.source,
|
|
11148
|
+
env
|
|
11149
|
+
);
|
|
11150
|
+
}
|
|
11151
|
+
}
|
|
10741
11152
|
|
|
10742
11153
|
async evalStartStatement(node, env) {
|
|
10743
11154
|
try {
|
|
@@ -10786,6 +11197,24 @@ async evalStartStatement(node, env) {
|
|
|
10786
11197
|
);
|
|
10787
11198
|
}
|
|
10788
11199
|
}
|
|
11200
|
+
async evalConditional(node, env) {
|
|
11201
|
+
try {
|
|
11202
|
+
const test = await this.evaluate(node.test, env);
|
|
11203
|
+
if (test) {
|
|
11204
|
+
return await this.evaluate(node.consequent, env);
|
|
11205
|
+
} else {
|
|
11206
|
+
return await this.evaluate(node.alternate, env);
|
|
11207
|
+
}
|
|
11208
|
+
} catch (e) {
|
|
11209
|
+
if (e instanceof RuntimeError) throw e;
|
|
11210
|
+
throw new RuntimeError(
|
|
11211
|
+
e.message || 'Error evaluating conditional expression',
|
|
11212
|
+
node,
|
|
11213
|
+
this.source,
|
|
11214
|
+
env
|
|
11215
|
+
);
|
|
11216
|
+
}
|
|
11217
|
+
}
|
|
10789
11218
|
|
|
10790
11219
|
async evalRaceClause(node, env) {
|
|
10791
11220
|
try {
|
|
@@ -11396,6 +11825,41 @@ async evalFor(node, env) {
|
|
|
11396
11825
|
);
|
|
11397
11826
|
}
|
|
11398
11827
|
}
|
|
11828
|
+
evalFunctionExpression(node, env) {
|
|
11829
|
+
if (!node.body || !Array.isArray(node.params)) {
|
|
11830
|
+
throw new RuntimeError(
|
|
11831
|
+
'Invalid function expression',
|
|
11832
|
+
node,
|
|
11833
|
+
this.source,
|
|
11834
|
+
env
|
|
11835
|
+
);
|
|
11836
|
+
}
|
|
11837
|
+
|
|
11838
|
+
const evaluator = this;
|
|
11839
|
+
|
|
11840
|
+
const fn = async function (...args) {
|
|
11841
|
+
const localEnv = new Environment(env);
|
|
11842
|
+
|
|
11843
|
+
for (let i = 0; i < node.params.length; i++) {
|
|
11844
|
+
const param = node.params[i];
|
|
11845
|
+
const paramName = typeof param === 'string' ? param : param.name;
|
|
11846
|
+
localEnv.define(paramName, args[i]);
|
|
11847
|
+
}
|
|
11848
|
+
|
|
11849
|
+
try {
|
|
11850
|
+
const result = await evaluator.evaluate(node.body, localEnv);
|
|
11851
|
+
return result === undefined ? null : result;
|
|
11852
|
+
} catch (e) {
|
|
11853
|
+
if (e instanceof ReturnValue) return e.value === undefined ? null : e.value;
|
|
11854
|
+
throw e;
|
|
11855
|
+
}
|
|
11856
|
+
};
|
|
11857
|
+
fn.params = node.params;
|
|
11858
|
+
fn.body = node.body;
|
|
11859
|
+
fn.env = env;
|
|
11860
|
+
|
|
11861
|
+
return fn;
|
|
11862
|
+
}
|
|
11399
11863
|
|
|
11400
11864
|
evalFunctionDeclaration(node, env) {
|
|
11401
11865
|
try {
|
|
@@ -11483,7 +11947,6 @@ async evalCall(node, env) {
|
|
|
11483
11947
|
);
|
|
11484
11948
|
}
|
|
11485
11949
|
}
|
|
11486
|
-
|
|
11487
11950
|
async evalIndex(node, env) {
|
|
11488
11951
|
try {
|
|
11489
11952
|
const obj = await this.evaluate(node.object, env);
|
|
@@ -11516,7 +11979,6 @@ async evalIndex(node, env) {
|
|
|
11516
11979
|
);
|
|
11517
11980
|
}
|
|
11518
11981
|
}
|
|
11519
|
-
|
|
11520
11982
|
async evalObject(node, env) {
|
|
11521
11983
|
try {
|
|
11522
11984
|
const out = {};
|
|
@@ -13161,33 +13623,100 @@ postfix() {
|
|
|
13161
13623
|
while (true) {
|
|
13162
13624
|
const t = this.current;
|
|
13163
13625
|
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
13626
|
+
if (t.type === 'LBRACKET') {
|
|
13627
|
+
const startLine = t.line;
|
|
13628
|
+
const startCol = t.column;
|
|
13629
|
+
this.eat('LBRACKET');
|
|
13630
|
+
|
|
13631
|
+
let start = null;
|
|
13632
|
+
let end = null;
|
|
13633
|
+
let step = null;
|
|
13634
|
+
|
|
13635
|
+
if (this.current.type === 'COLON') {
|
|
13636
|
+
this.eat('COLON');
|
|
13637
|
+
|
|
13638
|
+
if (this.current.type !== 'RBRACKET' && this.current.type !== 'COLON') {
|
|
13639
|
+
end = this.expression();
|
|
13640
|
+
}
|
|
13641
|
+
|
|
13642
|
+
if (this.current.type === 'COLON') {
|
|
13643
|
+
this.eat('COLON');
|
|
13644
|
+
if (this.current.type !== 'RBRACKET') {
|
|
13645
|
+
step = this.expression();
|
|
13646
|
+
}
|
|
13647
|
+
}
|
|
13648
|
+
|
|
13649
|
+
if (this.current.type !== 'RBRACKET') {
|
|
13650
|
+
throw new ParseError(
|
|
13651
|
+
"Expected ']' after slice",
|
|
13652
|
+
this.current,
|
|
13653
|
+
this.source
|
|
13654
|
+
);
|
|
13655
|
+
}
|
|
13656
|
+
|
|
13657
|
+
this.eat('RBRACKET');
|
|
13658
|
+
|
|
13659
|
+
node = {
|
|
13660
|
+
type: 'SliceExpression',
|
|
13661
|
+
object: node,
|
|
13662
|
+
start,
|
|
13663
|
+
end,
|
|
13664
|
+
step,
|
|
13665
|
+
line: startLine,
|
|
13666
|
+
column: startCol
|
|
13667
|
+
};
|
|
13668
|
+
|
|
13669
|
+
} else {
|
|
13670
|
+
start = this.expression();
|
|
13671
|
+
|
|
13672
|
+
if (this.current.type === 'COLON') {
|
|
13673
|
+
this.eat('COLON');
|
|
13168
13674
|
|
|
13169
|
-
|
|
13675
|
+
if (this.current.type !== 'RBRACKET' && this.current.type !== 'COLON') {
|
|
13676
|
+
end = this.expression();
|
|
13677
|
+
}
|
|
13678
|
+
|
|
13679
|
+
if (this.current.type === 'COLON') {
|
|
13680
|
+
this.eat('COLON');
|
|
13681
|
+
if (this.current.type !== 'RBRACKET') {
|
|
13682
|
+
step = this.expression();
|
|
13683
|
+
}
|
|
13684
|
+
}
|
|
13170
13685
|
|
|
13171
13686
|
if (this.current.type !== 'RBRACKET') {
|
|
13172
13687
|
throw new ParseError(
|
|
13173
|
-
"Expected ']' after
|
|
13688
|
+
"Expected ']' after slice",
|
|
13174
13689
|
this.current,
|
|
13175
|
-
this.source
|
|
13176
|
-
"Index access must be closed, e.g. arr[0]"
|
|
13690
|
+
this.source
|
|
13177
13691
|
);
|
|
13178
13692
|
}
|
|
13179
13693
|
|
|
13180
13694
|
this.eat('RBRACKET');
|
|
13181
13695
|
|
|
13696
|
+
node = {
|
|
13697
|
+
type: 'SliceExpression',
|
|
13698
|
+
object: node,
|
|
13699
|
+
start,
|
|
13700
|
+
end,
|
|
13701
|
+
step,
|
|
13702
|
+
line: startLine,
|
|
13703
|
+
column: startCol
|
|
13704
|
+
};
|
|
13705
|
+
|
|
13706
|
+
} else {
|
|
13707
|
+
this.eat('RBRACKET');
|
|
13182
13708
|
node = {
|
|
13183
13709
|
type: 'IndexExpression',
|
|
13184
13710
|
object: node,
|
|
13185
|
-
indexer:
|
|
13711
|
+
indexer: start,
|
|
13186
13712
|
line: startLine,
|
|
13187
13713
|
column: startCol
|
|
13188
13714
|
};
|
|
13189
|
-
continue;
|
|
13190
13715
|
}
|
|
13716
|
+
}
|
|
13717
|
+
}
|
|
13718
|
+
|
|
13719
|
+
|
|
13191
13720
|
|
|
13192
13721
|
if (t.type === 'LPAREN') {
|
|
13193
13722
|
const startLine = t.line;
|
|
@@ -13319,6 +13848,7 @@ arrowFunction(params) {
|
|
|
13319
13848
|
};
|
|
13320
13849
|
}
|
|
13321
13850
|
|
|
13851
|
+
|
|
13322
13852
|
primary() {
|
|
13323
13853
|
const t = this.current;
|
|
13324
13854
|
|
|
@@ -13390,7 +13920,6 @@ primary() {
|
|
|
13390
13920
|
return { type: 'NewExpression', callee, arguments: args, line: t.line, column: t.column };
|
|
13391
13921
|
}
|
|
13392
13922
|
|
|
13393
|
-
// ---- ask(...) function call ----
|
|
13394
13923
|
if (t.type === 'ASK') {
|
|
13395
13924
|
this.eat('ASK');
|
|
13396
13925
|
|
|
@@ -13431,6 +13960,69 @@ primary() {
|
|
|
13431
13960
|
column: t.column
|
|
13432
13961
|
};
|
|
13433
13962
|
}
|
|
13963
|
+
if (t.type === 'FUNC') {
|
|
13964
|
+
const funcToken = t;
|
|
13965
|
+
this.eat('FUNC');
|
|
13966
|
+
|
|
13967
|
+
let params = [];
|
|
13968
|
+
if (this.current.type === 'LPAREN') {
|
|
13969
|
+
this.eat('LPAREN');
|
|
13970
|
+
|
|
13971
|
+
if (this.current.type !== 'RPAREN') {
|
|
13972
|
+
if (this.current.type !== 'IDENTIFIER') {
|
|
13973
|
+
throw new ParseError(
|
|
13974
|
+
"Expected parameter name",
|
|
13975
|
+
this.current,
|
|
13976
|
+
this.source
|
|
13977
|
+
);
|
|
13978
|
+
}
|
|
13979
|
+
|
|
13980
|
+
params.push(this.current.value);
|
|
13981
|
+
this.eat('IDENTIFIER');
|
|
13982
|
+
|
|
13983
|
+
while (this.current.type === 'COMMA') {
|
|
13984
|
+
this.eat('COMMA');
|
|
13985
|
+
if (this.current.type !== 'IDENTIFIER') {
|
|
13986
|
+
throw new ParseError(
|
|
13987
|
+
"Expected parameter name",
|
|
13988
|
+
this.current,
|
|
13989
|
+
this.source
|
|
13990
|
+
);
|
|
13991
|
+
}
|
|
13992
|
+
params.push(this.current.value);
|
|
13993
|
+
this.eat('IDENTIFIER');
|
|
13994
|
+
}
|
|
13995
|
+
}
|
|
13996
|
+
|
|
13997
|
+
if (this.current.type !== 'RPAREN') {
|
|
13998
|
+
throw new ParseError(
|
|
13999
|
+
"Expected ')' after function parameters",
|
|
14000
|
+
this.current,
|
|
14001
|
+
this.source
|
|
14002
|
+
);
|
|
14003
|
+
}
|
|
14004
|
+
|
|
14005
|
+
this.eat('RPAREN');
|
|
14006
|
+
}
|
|
14007
|
+
|
|
14008
|
+
if (this.current.type !== 'LBRACE') {
|
|
14009
|
+
throw new ParseError(
|
|
14010
|
+
"Expected '{' to start function body",
|
|
14011
|
+
this.current,
|
|
14012
|
+
this.source
|
|
14013
|
+
);
|
|
14014
|
+
}
|
|
14015
|
+
|
|
14016
|
+
const body = this.block();
|
|
14017
|
+
|
|
14018
|
+
return {
|
|
14019
|
+
type: 'FunctionExpression',
|
|
14020
|
+
params,
|
|
14021
|
+
body,
|
|
14022
|
+
line: funcToken.line,
|
|
14023
|
+
column: funcToken.column
|
|
14024
|
+
};
|
|
14025
|
+
}
|
|
13434
14026
|
|
|
13435
14027
|
if (t.type === 'IDENTIFIER') {
|
|
13436
14028
|
const name = t.value;
|
|
@@ -13567,7 +14159,7 @@ primary() {
|
|
|
13567
14159
|
t,
|
|
13568
14160
|
this.source
|
|
13569
14161
|
);
|
|
13570
|
-
}
|
|
14162
|
+
}
|
|
13571
14163
|
|
|
13572
14164
|
}
|
|
13573
14165
|
|
|
@@ -13751,7 +14343,7 @@ const Lexer = __nccwpck_require__(211);
|
|
|
13751
14343
|
const Parser = __nccwpck_require__(222);
|
|
13752
14344
|
const Evaluator = __nccwpck_require__(112);
|
|
13753
14345
|
|
|
13754
|
-
const VERSION = '1.1.
|
|
14346
|
+
const VERSION = '1.1.17';
|
|
13755
14347
|
|
|
13756
14348
|
const COLOR = {
|
|
13757
14349
|
reset: '\x1b[0m',
|