@forthic/interp 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/forthic/errors.d.ts +1 -0
- package/dist/cjs/forthic/errors.js +6 -0
- package/dist/cjs/forthic/errors.js.map +1 -1
- package/dist/cjs/forthic/interpreter.d.ts +1 -1
- package/dist/cjs/forthic/interpreter.js +4 -1
- package/dist/cjs/forthic/interpreter.js.map +1 -1
- package/dist/esm/forthic/errors.d.ts +1 -0
- package/dist/esm/forthic/errors.js +20 -31
- package/dist/esm/forthic/errors.js.map +1 -1
- package/dist/esm/forthic/global_module/map_word.js +3 -7
- package/dist/esm/forthic/global_module/map_word.js.map +1 -1
- package/dist/esm/forthic/global_module.js +44 -48
- package/dist/esm/forthic/global_module.js.map +1 -1
- package/dist/esm/forthic/interpreter.d.ts +1 -1
- package/dist/esm/forthic/interpreter.js +57 -60
- package/dist/esm/forthic/interpreter.js.map +1 -1
- package/dist/esm/forthic/module.js +15 -28
- package/dist/esm/forthic/module.js.map +1 -1
- package/dist/esm/forthic/tokenizer.js +10 -20
- package/dist/esm/forthic/tokenizer.js.map +1 -1
- package/dist/esm/forthic/utils.js +16 -28
- package/dist/esm/forthic/utils.js.map +1 -1
- package/dist/esm/index.js +4 -20
- package/dist/esm/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const map_word_1 = require("./global_module/map_word");
|
|
8
|
-
const tokenizer_1 = require("./tokenizer");
|
|
9
|
-
const errors_1 = require("./errors");
|
|
1
|
+
import { Module, PushValueWord } from "./module";
|
|
2
|
+
import { is_array, is_record, is_string, pretty_print, to_date, date_to_string, date_to_int, } from "./utils";
|
|
3
|
+
import { Temporal } from "temporal-polyfill";
|
|
4
|
+
import { MapWord } from "./global_module/map_word";
|
|
5
|
+
import { CodeLocation } from "./tokenizer";
|
|
6
|
+
import { IntentionalStopError, InvalidVariableNameError } from "./errors";
|
|
10
7
|
const DLE = String.fromCharCode(16); // ASCII char for "Data Link Escape" used as an untypeable quote
|
|
11
|
-
class GlobalModule extends
|
|
8
|
+
export class GlobalModule extends Module {
|
|
12
9
|
literal_handlers;
|
|
13
10
|
constructor(interp) {
|
|
14
11
|
super("<GLOBAL>", interp);
|
|
@@ -226,7 +223,7 @@ class GlobalModule extends module_1.Module {
|
|
|
226
223
|
for (let i = 0; i < self.literal_handlers.length; i++) {
|
|
227
224
|
value = self.literal_handlers[i](string);
|
|
228
225
|
if (value !== null)
|
|
229
|
-
return new
|
|
226
|
+
return new PushValueWord(string, value);
|
|
230
227
|
}
|
|
231
228
|
return null;
|
|
232
229
|
}
|
|
@@ -262,7 +259,7 @@ class GlobalModule extends module_1.Module {
|
|
|
262
259
|
let month;
|
|
263
260
|
let day;
|
|
264
261
|
const date_parts = str_val.split("-");
|
|
265
|
-
const zonedDateTime =
|
|
262
|
+
const zonedDateTime = Temporal.Now.zonedDateTimeISO(this.interp?.get_timezone() ?? "UTC");
|
|
266
263
|
// Case 1: If time is like "YYYY-MM-DD"
|
|
267
264
|
if (str_val.match(/^YYYY-MM-DD$/)) {
|
|
268
265
|
year = zonedDateTime.year;
|
|
@@ -307,7 +304,7 @@ class GlobalModule extends module_1.Module {
|
|
|
307
304
|
else {
|
|
308
305
|
return null;
|
|
309
306
|
}
|
|
310
|
-
const result =
|
|
307
|
+
const result = Temporal.PlainDate.from({
|
|
311
308
|
year: year,
|
|
312
309
|
month: month,
|
|
313
310
|
day: day,
|
|
@@ -324,7 +321,7 @@ class GlobalModule extends module_1.Module {
|
|
|
324
321
|
return null;
|
|
325
322
|
if (minutes >= 60)
|
|
326
323
|
return null;
|
|
327
|
-
const result =
|
|
324
|
+
const result = Temporal.PlainTime.from({
|
|
328
325
|
hour: hours,
|
|
329
326
|
minute: minutes,
|
|
330
327
|
});
|
|
@@ -349,7 +346,7 @@ class GlobalModule extends module_1.Module {
|
|
|
349
346
|
const module = interp.cur_module();
|
|
350
347
|
varnames.forEach((v) => {
|
|
351
348
|
if (v.match(/__.*/)) {
|
|
352
|
-
throw new
|
|
349
|
+
throw new InvalidVariableNameError(interp.get_top_input_string(), v, "Variable names cannot begin with '__'", interp.get_string_location());
|
|
353
350
|
}
|
|
354
351
|
module.add_variable(v);
|
|
355
352
|
});
|
|
@@ -698,7 +695,7 @@ class GlobalModule extends module_1.Module {
|
|
|
698
695
|
const string_location = interp.get_string_location();
|
|
699
696
|
const items = interp.stack_pop();
|
|
700
697
|
const flags = interp.get_flags(this.module_id);
|
|
701
|
-
const map_word = new
|
|
698
|
+
const map_word = new MapWord(items, forthic, string_location, flags);
|
|
702
699
|
await map_word.execute(interp);
|
|
703
700
|
}
|
|
704
701
|
// ( items word -- ? )
|
|
@@ -1631,11 +1628,11 @@ class GlobalModule extends module_1.Module {
|
|
|
1631
1628
|
// ( time -- time )
|
|
1632
1629
|
word_AM(interp) {
|
|
1633
1630
|
const time = interp.stack_pop();
|
|
1634
|
-
if (!(time instanceof
|
|
1631
|
+
if (!(time instanceof Temporal.PlainTime))
|
|
1635
1632
|
throw "AM expecting a time";
|
|
1636
1633
|
let result = time;
|
|
1637
1634
|
if (time.hour >= 12) {
|
|
1638
|
-
result =
|
|
1635
|
+
result = Temporal.PlainTime.from({
|
|
1639
1636
|
hour: time.hour - 12,
|
|
1640
1637
|
minute: time.minute,
|
|
1641
1638
|
});
|
|
@@ -1645,11 +1642,11 @@ class GlobalModule extends module_1.Module {
|
|
|
1645
1642
|
// ( time -- time )
|
|
1646
1643
|
word_PM(interp) {
|
|
1647
1644
|
const time = interp.stack_pop();
|
|
1648
|
-
if (!(time instanceof
|
|
1645
|
+
if (!(time instanceof Temporal.PlainTime))
|
|
1649
1646
|
throw "PM expecting a time";
|
|
1650
1647
|
let result = time;
|
|
1651
1648
|
if (time.hour < 12) {
|
|
1652
|
-
result =
|
|
1649
|
+
result = Temporal.PlainTime.from({
|
|
1653
1650
|
hour: time.hour + 12,
|
|
1654
1651
|
minute: time.minute,
|
|
1655
1652
|
});
|
|
@@ -1658,24 +1655,24 @@ class GlobalModule extends module_1.Module {
|
|
|
1658
1655
|
}
|
|
1659
1656
|
// ( -- time )
|
|
1660
1657
|
word_NOW(interp) {
|
|
1661
|
-
const result =
|
|
1658
|
+
const result = Temporal.Now.plainDateTimeISO(interp.get_timezone());
|
|
1662
1659
|
interp.stack_push(result);
|
|
1663
1660
|
}
|
|
1664
1661
|
// ( item -- time )
|
|
1665
1662
|
word_to_TIME(interp) {
|
|
1666
1663
|
const item = interp.stack_pop();
|
|
1667
1664
|
let result;
|
|
1668
|
-
if (item instanceof
|
|
1665
|
+
if (item instanceof Temporal.PlainTime) {
|
|
1669
1666
|
result = item;
|
|
1670
1667
|
}
|
|
1671
|
-
else if (item instanceof
|
|
1672
|
-
result =
|
|
1668
|
+
else if (item instanceof Temporal.PlainDateTime) {
|
|
1669
|
+
result = Temporal.PlainTime.from(item);
|
|
1673
1670
|
}
|
|
1674
1671
|
else {
|
|
1675
1672
|
// NB: We need a date in order for Date.parse to succeed. Also assuming str is a time
|
|
1676
1673
|
const date_string = "Jan 1, 2000 " + item;
|
|
1677
1674
|
const date = new Date(Date.parse(date_string));
|
|
1678
|
-
result =
|
|
1675
|
+
result = Temporal.PlainTime.from({
|
|
1679
1676
|
hour: date.getHours(),
|
|
1680
1677
|
minute: date.getMinutes(),
|
|
1681
1678
|
});
|
|
@@ -1691,12 +1688,12 @@ class GlobalModule extends module_1.Module {
|
|
|
1691
1688
|
// ( str -- date )
|
|
1692
1689
|
word_to_DATE(interp) {
|
|
1693
1690
|
const s = interp.stack_pop();
|
|
1694
|
-
const result =
|
|
1691
|
+
const result = to_date(s);
|
|
1695
1692
|
interp.stack_push(result);
|
|
1696
1693
|
}
|
|
1697
1694
|
// ( -- date )
|
|
1698
1695
|
word_TODAY(interp) {
|
|
1699
|
-
const result =
|
|
1696
|
+
const result = Temporal.Now.plainDateISO(interp.get_timezone());
|
|
1700
1697
|
interp.stack_push(result);
|
|
1701
1698
|
}
|
|
1702
1699
|
// ( -- date )
|
|
@@ -1729,7 +1726,7 @@ class GlobalModule extends module_1.Module {
|
|
|
1729
1726
|
}
|
|
1730
1727
|
static get_day_this_week(day_of_week, timezone) {
|
|
1731
1728
|
// Get plain date for day of week
|
|
1732
|
-
const today =
|
|
1729
|
+
const today = Temporal.Now.plainDateISO(timezone);
|
|
1733
1730
|
const delta_days = (day_of_week - today.dayOfWeek) % 7;
|
|
1734
1731
|
const result = today.add({ days: delta_days });
|
|
1735
1732
|
return result;
|
|
@@ -1738,13 +1735,13 @@ class GlobalModule extends module_1.Module {
|
|
|
1738
1735
|
word_ADD_DAYS(interp) {
|
|
1739
1736
|
const num_days = interp.stack_pop();
|
|
1740
1737
|
const date = interp.stack_pop();
|
|
1741
|
-
const result =
|
|
1738
|
+
const result = Temporal.PlainDate.from(date).add({ days: num_days });
|
|
1742
1739
|
interp.stack_push(result);
|
|
1743
1740
|
}
|
|
1744
1741
|
// ( l_date r_date -- num_days )
|
|
1745
1742
|
word_SUBTRACT_DATES(interp) {
|
|
1746
|
-
const r_date =
|
|
1747
|
-
const l_date =
|
|
1743
|
+
const r_date = Temporal.PlainDate.from(interp.stack_pop());
|
|
1744
|
+
const l_date = Temporal.PlainDate.from(interp.stack_pop());
|
|
1748
1745
|
// Subtract the dates and get the difference in days
|
|
1749
1746
|
const result = r_date.until(l_date).total({ unit: "days" });
|
|
1750
1747
|
interp.stack_push(result);
|
|
@@ -1752,21 +1749,21 @@ class GlobalModule extends module_1.Module {
|
|
|
1752
1749
|
// ( date -- str )
|
|
1753
1750
|
word_DATE_to_STR(interp) {
|
|
1754
1751
|
const date = interp.stack_pop();
|
|
1755
|
-
const result =
|
|
1752
|
+
const result = date_to_string(date);
|
|
1756
1753
|
interp.stack_push(result);
|
|
1757
1754
|
}
|
|
1758
1755
|
// ( date -- int )
|
|
1759
1756
|
// Converts a date like 2023-11-12 to 20231112
|
|
1760
1757
|
word_DATE_to_INT(interp) {
|
|
1761
1758
|
const date = interp.stack_pop();
|
|
1762
|
-
const result =
|
|
1759
|
+
const result = date_to_int(date);
|
|
1763
1760
|
interp.stack_push(result);
|
|
1764
1761
|
}
|
|
1765
1762
|
// ( date time -- datetime )
|
|
1766
1763
|
word_DATE_TIME_to_DATETIME(interp) {
|
|
1767
|
-
const time =
|
|
1768
|
-
const date =
|
|
1769
|
-
const result =
|
|
1764
|
+
const time = Temporal.PlainTime.from(interp.stack_pop());
|
|
1765
|
+
const date = Temporal.PlainDate.from(interp.stack_pop());
|
|
1766
|
+
const result = Temporal.PlainDateTime.from({
|
|
1770
1767
|
year: date.year,
|
|
1771
1768
|
month: date.month,
|
|
1772
1769
|
day: date.day,
|
|
@@ -1786,14 +1783,14 @@ class GlobalModule extends module_1.Module {
|
|
|
1786
1783
|
// ( timestamp -- datetime )
|
|
1787
1784
|
word_TIMESTAMP_to_DATETIME(interp) {
|
|
1788
1785
|
const timestamp = interp.stack_pop();
|
|
1789
|
-
const result =
|
|
1786
|
+
const result = Temporal.Instant.fromEpochSeconds(timestamp).toZonedDateTime({ timeZone: interp.get_timezone(), calendar: "iso8601" });
|
|
1790
1787
|
interp.stack_push(result);
|
|
1791
1788
|
}
|
|
1792
1789
|
// ( str -- datetime )
|
|
1793
1790
|
word_STR_to_DATETIME(interp) {
|
|
1794
1791
|
const s = interp.stack_pop();
|
|
1795
1792
|
const date = new Date(s);
|
|
1796
|
-
const result =
|
|
1793
|
+
const result = Temporal.Instant.fromEpochMilliseconds(date.getTime()).toZonedDateTime({ timeZone: interp.get_timezone(), calendar: "iso8601" });
|
|
1797
1794
|
interp.stack_push(result);
|
|
1798
1795
|
}
|
|
1799
1796
|
// ( str -- timestamp )
|
|
@@ -1894,7 +1891,7 @@ class GlobalModule extends module_1.Module {
|
|
|
1894
1891
|
const non_null_objects = objects.filter((obj) => obj !== null || obj !== undefined);
|
|
1895
1892
|
const res = {};
|
|
1896
1893
|
non_null_objects.forEach((obj) => {
|
|
1897
|
-
const obj_str =
|
|
1894
|
+
const obj_str = is_string(obj) ? obj : JSON.stringify(obj);
|
|
1898
1895
|
if (res[obj_str])
|
|
1899
1896
|
res[obj_str]++;
|
|
1900
1897
|
else
|
|
@@ -1924,14 +1921,14 @@ class GlobalModule extends module_1.Module {
|
|
|
1924
1921
|
return values.every((val) => typeof val == "number");
|
|
1925
1922
|
}
|
|
1926
1923
|
function is_all_records(values) {
|
|
1927
|
-
return values.every((val) =>
|
|
1924
|
+
return values.every((val) => is_record(val));
|
|
1928
1925
|
}
|
|
1929
1926
|
function select_non_null_values(values) {
|
|
1930
1927
|
return values.filter((val) => val !== null && val !== undefined);
|
|
1931
1928
|
}
|
|
1932
1929
|
function compute_mean(values) {
|
|
1933
1930
|
let result;
|
|
1934
|
-
if (
|
|
1931
|
+
if (is_array(values)) {
|
|
1935
1932
|
const non_null_values = select_non_null_values(values);
|
|
1936
1933
|
if (is_all_numbers(non_null_values)) {
|
|
1937
1934
|
result = compute_number_mean(non_null_values);
|
|
@@ -1956,7 +1953,7 @@ class GlobalModule extends module_1.Module {
|
|
|
1956
1953
|
word_MAX(interp) {
|
|
1957
1954
|
const num2 = interp.stack_pop();
|
|
1958
1955
|
let numbers = [];
|
|
1959
|
-
if (
|
|
1956
|
+
if (is_array(num2)) {
|
|
1960
1957
|
numbers = num2;
|
|
1961
1958
|
}
|
|
1962
1959
|
else {
|
|
@@ -1970,7 +1967,7 @@ class GlobalModule extends module_1.Module {
|
|
|
1970
1967
|
word_MIN(interp) {
|
|
1971
1968
|
const num2 = interp.stack_pop();
|
|
1972
1969
|
let numbers = [];
|
|
1973
|
-
if (
|
|
1970
|
+
if (is_array(num2)) {
|
|
1974
1971
|
numbers = num2;
|
|
1975
1972
|
}
|
|
1976
1973
|
else {
|
|
@@ -2424,7 +2421,7 @@ class GlobalModule extends module_1.Module {
|
|
|
2424
2421
|
// ( json -- json )
|
|
2425
2422
|
word_PRETTIFY(interp) {
|
|
2426
2423
|
const json = interp.stack_pop();
|
|
2427
|
-
const result =
|
|
2424
|
+
const result = pretty_print(json);
|
|
2428
2425
|
interp.stack_push(result);
|
|
2429
2426
|
}
|
|
2430
2427
|
// ( json -- object )
|
|
@@ -2439,7 +2436,7 @@ class GlobalModule extends module_1.Module {
|
|
|
2439
2436
|
async word_LOAD_SCREEN(interp) {
|
|
2440
2437
|
const name = interp.stack_pop();
|
|
2441
2438
|
const screen_forthic = interp.get_screen_forthic(name);
|
|
2442
|
-
const location = new
|
|
2439
|
+
const location = new CodeLocation({ screen_name: name });
|
|
2443
2440
|
// await interp.run(screen_forthic, location);
|
|
2444
2441
|
await interp.run(screen_forthic, location);
|
|
2445
2442
|
}
|
|
@@ -2452,13 +2449,13 @@ class GlobalModule extends module_1.Module {
|
|
|
2452
2449
|
else {
|
|
2453
2450
|
console.log("<STACK EMPTY>");
|
|
2454
2451
|
}
|
|
2455
|
-
throw new
|
|
2452
|
+
throw new IntentionalStopError(".s");
|
|
2456
2453
|
}
|
|
2457
2454
|
// ( -- )
|
|
2458
2455
|
word_dot_S(interp) {
|
|
2459
2456
|
const stack = interp.get_stack().get_items().reverse();
|
|
2460
2457
|
console.log(JSON.stringify(stack, null, 2));
|
|
2461
|
-
throw new
|
|
2458
|
+
throw new IntentionalStopError(".S");
|
|
2462
2459
|
}
|
|
2463
2460
|
// ( a b -- a - b )
|
|
2464
2461
|
word_minus(interp) {
|
|
@@ -2467,7 +2464,6 @@ class GlobalModule extends module_1.Module {
|
|
|
2467
2464
|
interp.stack_push(a - b);
|
|
2468
2465
|
}
|
|
2469
2466
|
}
|
|
2470
|
-
exports.GlobalModule = GlobalModule;
|
|
2471
2467
|
// Descends into record using an array of fields, returning final value or null
|
|
2472
2468
|
function drill_for_value(record, fields) {
|
|
2473
2469
|
let result = record;
|