@forthic/interp 0.12.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.
@@ -1,14 +1,11 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.GlobalModule = void 0;
4
- const module_1 = require("./module");
5
- const utils_1 = require("./utils");
6
- const temporal_polyfill_1 = require("temporal-polyfill");
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 module_1.Module {
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 module_1.PushValueWord(string, value);
226
+ return new PushValueWord(string, value);
230
227
  }
231
228
  return null;
232
229
  }
@@ -256,16 +253,61 @@ class GlobalModule extends module_1.Module {
256
253
  return result;
257
254
  }
258
255
  to_literal_date(str_val) {
259
- const match = str_val.match(/(\d{4})-(\d{2})-(\d{2})/);
260
- if (!match)
256
+ // --------------------
257
+ // Handle date format strings like "YYYY-MM-DD" or "YYYY-MM-03" or "YYYY-02-03" or "2025-02-03"
258
+ let year;
259
+ let month;
260
+ let day;
261
+ const date_parts = str_val.split("-");
262
+ const zonedDateTime = Temporal.Now.zonedDateTimeISO(this.interp?.get_timezone() ?? "UTC");
263
+ // Case 1: If time is like "YYYY-MM-DD"
264
+ if (str_val.match(/^YYYY-MM-DD$/)) {
265
+ year = zonedDateTime.year;
266
+ month = zonedDateTime.month;
267
+ day = zonedDateTime.day;
268
+ } // Case 2: If time is like "YYYY-MM-03"
269
+ else if (str_val.match(/^YYYY-MM-\d{2}$/)) {
270
+ year = zonedDateTime.year;
271
+ month = zonedDateTime.month;
272
+ day = parseInt(date_parts[2]);
273
+ } // Case 3: If time is like "YYYY-02-03"
274
+ else if (str_val.match(/^YYYY-\d{2}-\d{2}$/)) {
275
+ year = zonedDateTime.year;
276
+ month = parseInt(date_parts[1]);
277
+ day = parseInt(date_parts[2]);
278
+ } // Case 4: If time is like "2025-02-03"
279
+ else if (str_val.match(/^\d{4}-\d{2}-\d{2}$/)) {
280
+ year = parseInt(date_parts[0]);
281
+ month = parseInt(date_parts[1]);
282
+ day = parseInt(date_parts[2]);
283
+ } // Case 5: If time is like "2025-MM-DD"
284
+ else if (str_val.match(/^\d{4}-MM-DD$/)) {
285
+ year = parseInt(date_parts[0]);
286
+ month = zonedDateTime.month;
287
+ day = zonedDateTime.day;
288
+ } // Case 6: If time is like "2025-02-DD"
289
+ else if (str_val.match(/^\d{4}-\d{2}-DD$/)) {
290
+ year = parseInt(date_parts[0]);
291
+ month = parseInt(date_parts[1]);
292
+ day = zonedDateTime.day;
293
+ } // Case 7: If time is like "2025-MM-03"
294
+ else if (str_val.match(/^\d{4}-MM-\d{2}$/)) {
295
+ year = parseInt(date_parts[0]);
296
+ month = zonedDateTime.month;
297
+ day = parseInt(date_parts[2]);
298
+ } // Case 8: If time is like "YYYY-03-DD"
299
+ else if (str_val.match(/^YYYY-\d{2}-DD$/)) {
300
+ year = zonedDateTime.year;
301
+ month = parseInt(date_parts[1]);
302
+ day = zonedDateTime.day;
303
+ } // Otherwise, return null
304
+ else {
261
305
  return null;
262
- const year = Number(match[1]);
263
- const month = Number(match[2]);
264
- const day = Number(match[3]);
265
- const result = temporal_polyfill_1.Temporal.PlainDate.from({
266
- year,
267
- month,
268
- day,
306
+ }
307
+ const result = Temporal.PlainDate.from({
308
+ year: year,
309
+ month: month,
310
+ day: day,
269
311
  });
270
312
  return result;
271
313
  }
@@ -279,7 +321,7 @@ class GlobalModule extends module_1.Module {
279
321
  return null;
280
322
  if (minutes >= 60)
281
323
  return null;
282
- const result = temporal_polyfill_1.Temporal.PlainTime.from({
324
+ const result = Temporal.PlainTime.from({
283
325
  hour: hours,
284
326
  minute: minutes,
285
327
  });
@@ -304,7 +346,7 @@ class GlobalModule extends module_1.Module {
304
346
  const module = interp.cur_module();
305
347
  varnames.forEach((v) => {
306
348
  if (v.match(/__.*/)) {
307
- throw new errors_1.InvalidVariableNameError(interp.get_top_input_string(), v, "Variable names cannot begin with '__'", interp.get_string_location());
349
+ throw new InvalidVariableNameError(interp.get_top_input_string(), v, "Variable names cannot begin with '__'", interp.get_string_location());
308
350
  }
309
351
  module.add_variable(v);
310
352
  });
@@ -653,7 +695,7 @@ class GlobalModule extends module_1.Module {
653
695
  const string_location = interp.get_string_location();
654
696
  const items = interp.stack_pop();
655
697
  const flags = interp.get_flags(this.module_id);
656
- const map_word = new map_word_1.MapWord(items, forthic, string_location, flags);
698
+ const map_word = new MapWord(items, forthic, string_location, flags);
657
699
  await map_word.execute(interp);
658
700
  }
659
701
  // ( items word -- ? )
@@ -1586,11 +1628,11 @@ class GlobalModule extends module_1.Module {
1586
1628
  // ( time -- time )
1587
1629
  word_AM(interp) {
1588
1630
  const time = interp.stack_pop();
1589
- if (!(time instanceof temporal_polyfill_1.Temporal.PlainTime))
1631
+ if (!(time instanceof Temporal.PlainTime))
1590
1632
  throw "AM expecting a time";
1591
1633
  let result = time;
1592
1634
  if (time.hour >= 12) {
1593
- result = temporal_polyfill_1.Temporal.PlainTime.from({
1635
+ result = Temporal.PlainTime.from({
1594
1636
  hour: time.hour - 12,
1595
1637
  minute: time.minute,
1596
1638
  });
@@ -1600,11 +1642,11 @@ class GlobalModule extends module_1.Module {
1600
1642
  // ( time -- time )
1601
1643
  word_PM(interp) {
1602
1644
  const time = interp.stack_pop();
1603
- if (!(time instanceof temporal_polyfill_1.Temporal.PlainTime))
1645
+ if (!(time instanceof Temporal.PlainTime))
1604
1646
  throw "PM expecting a time";
1605
1647
  let result = time;
1606
1648
  if (time.hour < 12) {
1607
- result = temporal_polyfill_1.Temporal.PlainTime.from({
1649
+ result = Temporal.PlainTime.from({
1608
1650
  hour: time.hour + 12,
1609
1651
  minute: time.minute,
1610
1652
  });
@@ -1613,24 +1655,24 @@ class GlobalModule extends module_1.Module {
1613
1655
  }
1614
1656
  // ( -- time )
1615
1657
  word_NOW(interp) {
1616
- const result = temporal_polyfill_1.Temporal.Now.plainDateTimeISO(interp.get_timezone());
1658
+ const result = Temporal.Now.plainDateTimeISO(interp.get_timezone());
1617
1659
  interp.stack_push(result);
1618
1660
  }
1619
1661
  // ( item -- time )
1620
1662
  word_to_TIME(interp) {
1621
1663
  const item = interp.stack_pop();
1622
1664
  let result;
1623
- if (item instanceof temporal_polyfill_1.Temporal.PlainTime) {
1665
+ if (item instanceof Temporal.PlainTime) {
1624
1666
  result = item;
1625
1667
  }
1626
- else if (item instanceof temporal_polyfill_1.Temporal.PlainDateTime) {
1627
- result = temporal_polyfill_1.Temporal.PlainTime.from(item);
1668
+ else if (item instanceof Temporal.PlainDateTime) {
1669
+ result = Temporal.PlainTime.from(item);
1628
1670
  }
1629
1671
  else {
1630
1672
  // NB: We need a date in order for Date.parse to succeed. Also assuming str is a time
1631
1673
  const date_string = "Jan 1, 2000 " + item;
1632
1674
  const date = new Date(Date.parse(date_string));
1633
- result = temporal_polyfill_1.Temporal.PlainTime.from({
1675
+ result = Temporal.PlainTime.from({
1634
1676
  hour: date.getHours(),
1635
1677
  minute: date.getMinutes(),
1636
1678
  });
@@ -1646,12 +1688,12 @@ class GlobalModule extends module_1.Module {
1646
1688
  // ( str -- date )
1647
1689
  word_to_DATE(interp) {
1648
1690
  const s = interp.stack_pop();
1649
- const result = (0, utils_1.to_date)(s);
1691
+ const result = to_date(s);
1650
1692
  interp.stack_push(result);
1651
1693
  }
1652
1694
  // ( -- date )
1653
1695
  word_TODAY(interp) {
1654
- const result = temporal_polyfill_1.Temporal.Now.plainDateISO(interp.get_timezone());
1696
+ const result = Temporal.Now.plainDateISO(interp.get_timezone());
1655
1697
  interp.stack_push(result);
1656
1698
  }
1657
1699
  // ( -- date )
@@ -1684,7 +1726,7 @@ class GlobalModule extends module_1.Module {
1684
1726
  }
1685
1727
  static get_day_this_week(day_of_week, timezone) {
1686
1728
  // Get plain date for day of week
1687
- const today = temporal_polyfill_1.Temporal.Now.plainDateISO(timezone);
1729
+ const today = Temporal.Now.plainDateISO(timezone);
1688
1730
  const delta_days = (day_of_week - today.dayOfWeek) % 7;
1689
1731
  const result = today.add({ days: delta_days });
1690
1732
  return result;
@@ -1693,13 +1735,13 @@ class GlobalModule extends module_1.Module {
1693
1735
  word_ADD_DAYS(interp) {
1694
1736
  const num_days = interp.stack_pop();
1695
1737
  const date = interp.stack_pop();
1696
- const result = temporal_polyfill_1.Temporal.PlainDate.from(date).add({ days: num_days });
1738
+ const result = Temporal.PlainDate.from(date).add({ days: num_days });
1697
1739
  interp.stack_push(result);
1698
1740
  }
1699
1741
  // ( l_date r_date -- num_days )
1700
1742
  word_SUBTRACT_DATES(interp) {
1701
- const r_date = temporal_polyfill_1.Temporal.PlainDate.from(interp.stack_pop());
1702
- const l_date = temporal_polyfill_1.Temporal.PlainDate.from(interp.stack_pop());
1743
+ const r_date = Temporal.PlainDate.from(interp.stack_pop());
1744
+ const l_date = Temporal.PlainDate.from(interp.stack_pop());
1703
1745
  // Subtract the dates and get the difference in days
1704
1746
  const result = r_date.until(l_date).total({ unit: "days" });
1705
1747
  interp.stack_push(result);
@@ -1707,21 +1749,21 @@ class GlobalModule extends module_1.Module {
1707
1749
  // ( date -- str )
1708
1750
  word_DATE_to_STR(interp) {
1709
1751
  const date = interp.stack_pop();
1710
- const result = (0, utils_1.date_to_string)(date);
1752
+ const result = date_to_string(date);
1711
1753
  interp.stack_push(result);
1712
1754
  }
1713
1755
  // ( date -- int )
1714
1756
  // Converts a date like 2023-11-12 to 20231112
1715
1757
  word_DATE_to_INT(interp) {
1716
1758
  const date = interp.stack_pop();
1717
- const result = (0, utils_1.date_to_int)(date);
1759
+ const result = date_to_int(date);
1718
1760
  interp.stack_push(result);
1719
1761
  }
1720
1762
  // ( date time -- datetime )
1721
1763
  word_DATE_TIME_to_DATETIME(interp) {
1722
- const time = temporal_polyfill_1.Temporal.PlainTime.from(interp.stack_pop());
1723
- const date = temporal_polyfill_1.Temporal.PlainDate.from(interp.stack_pop());
1724
- const result = temporal_polyfill_1.Temporal.PlainDateTime.from({
1764
+ const time = Temporal.PlainTime.from(interp.stack_pop());
1765
+ const date = Temporal.PlainDate.from(interp.stack_pop());
1766
+ const result = Temporal.PlainDateTime.from({
1725
1767
  year: date.year,
1726
1768
  month: date.month,
1727
1769
  day: date.day,
@@ -1741,14 +1783,14 @@ class GlobalModule extends module_1.Module {
1741
1783
  // ( timestamp -- datetime )
1742
1784
  word_TIMESTAMP_to_DATETIME(interp) {
1743
1785
  const timestamp = interp.stack_pop();
1744
- const result = temporal_polyfill_1.Temporal.Instant.fromEpochSeconds(timestamp).toZonedDateTime({ timeZone: interp.get_timezone(), calendar: "iso8601" });
1786
+ const result = Temporal.Instant.fromEpochSeconds(timestamp).toZonedDateTime({ timeZone: interp.get_timezone(), calendar: "iso8601" });
1745
1787
  interp.stack_push(result);
1746
1788
  }
1747
1789
  // ( str -- datetime )
1748
1790
  word_STR_to_DATETIME(interp) {
1749
1791
  const s = interp.stack_pop();
1750
1792
  const date = new Date(s);
1751
- const result = temporal_polyfill_1.Temporal.Instant.fromEpochMilliseconds(date.getTime()).toZonedDateTime({ timeZone: interp.get_timezone(), calendar: "iso8601" });
1793
+ const result = Temporal.Instant.fromEpochMilliseconds(date.getTime()).toZonedDateTime({ timeZone: interp.get_timezone(), calendar: "iso8601" });
1752
1794
  interp.stack_push(result);
1753
1795
  }
1754
1796
  // ( str -- timestamp )
@@ -1849,7 +1891,7 @@ class GlobalModule extends module_1.Module {
1849
1891
  const non_null_objects = objects.filter((obj) => obj !== null || obj !== undefined);
1850
1892
  const res = {};
1851
1893
  non_null_objects.forEach((obj) => {
1852
- const obj_str = (0, utils_1.is_string)(obj) ? obj : JSON.stringify(obj);
1894
+ const obj_str = is_string(obj) ? obj : JSON.stringify(obj);
1853
1895
  if (res[obj_str])
1854
1896
  res[obj_str]++;
1855
1897
  else
@@ -1879,14 +1921,14 @@ class GlobalModule extends module_1.Module {
1879
1921
  return values.every((val) => typeof val == "number");
1880
1922
  }
1881
1923
  function is_all_records(values) {
1882
- return values.every((val) => (0, utils_1.is_record)(val));
1924
+ return values.every((val) => is_record(val));
1883
1925
  }
1884
1926
  function select_non_null_values(values) {
1885
1927
  return values.filter((val) => val !== null && val !== undefined);
1886
1928
  }
1887
1929
  function compute_mean(values) {
1888
1930
  let result;
1889
- if ((0, utils_1.is_array)(values)) {
1931
+ if (is_array(values)) {
1890
1932
  const non_null_values = select_non_null_values(values);
1891
1933
  if (is_all_numbers(non_null_values)) {
1892
1934
  result = compute_number_mean(non_null_values);
@@ -1911,7 +1953,7 @@ class GlobalModule extends module_1.Module {
1911
1953
  word_MAX(interp) {
1912
1954
  const num2 = interp.stack_pop();
1913
1955
  let numbers = [];
1914
- if ((0, utils_1.is_array)(num2)) {
1956
+ if (is_array(num2)) {
1915
1957
  numbers = num2;
1916
1958
  }
1917
1959
  else {
@@ -1925,7 +1967,7 @@ class GlobalModule extends module_1.Module {
1925
1967
  word_MIN(interp) {
1926
1968
  const num2 = interp.stack_pop();
1927
1969
  let numbers = [];
1928
- if ((0, utils_1.is_array)(num2)) {
1970
+ if (is_array(num2)) {
1929
1971
  numbers = num2;
1930
1972
  }
1931
1973
  else {
@@ -2379,7 +2421,7 @@ class GlobalModule extends module_1.Module {
2379
2421
  // ( json -- json )
2380
2422
  word_PRETTIFY(interp) {
2381
2423
  const json = interp.stack_pop();
2382
- const result = (0, utils_1.pretty_print)(json);
2424
+ const result = pretty_print(json);
2383
2425
  interp.stack_push(result);
2384
2426
  }
2385
2427
  // ( json -- object )
@@ -2394,7 +2436,7 @@ class GlobalModule extends module_1.Module {
2394
2436
  async word_LOAD_SCREEN(interp) {
2395
2437
  const name = interp.stack_pop();
2396
2438
  const screen_forthic = interp.get_screen_forthic(name);
2397
- const location = new tokenizer_1.CodeLocation({ screen_name: name });
2439
+ const location = new CodeLocation({ screen_name: name });
2398
2440
  // await interp.run(screen_forthic, location);
2399
2441
  await interp.run(screen_forthic, location);
2400
2442
  }
@@ -2407,13 +2449,13 @@ class GlobalModule extends module_1.Module {
2407
2449
  else {
2408
2450
  console.log("<STACK EMPTY>");
2409
2451
  }
2410
- throw new errors_1.IntentionalStopError(".s");
2452
+ throw new IntentionalStopError(".s");
2411
2453
  }
2412
2454
  // ( -- )
2413
2455
  word_dot_S(interp) {
2414
2456
  const stack = interp.get_stack().get_items().reverse();
2415
2457
  console.log(JSON.stringify(stack, null, 2));
2416
- throw new errors_1.IntentionalStopError(".S");
2458
+ throw new IntentionalStopError(".S");
2417
2459
  }
2418
2460
  // ( a b -- a - b )
2419
2461
  word_minus(interp) {
@@ -2422,7 +2464,6 @@ class GlobalModule extends module_1.Module {
2422
2464
  interp.stack_push(a - b);
2423
2465
  }
2424
2466
  }
2425
- exports.GlobalModule = GlobalModule;
2426
2467
  // Descends into record using an array of fields, returning final value or null
2427
2468
  function drill_for_value(record, fields) {
2428
2469
  let result = record;