@forthix/forthic 0.11.0 → 0.13.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/interpreter.js +2 -0
- package/dist/cjs/forthic/interpreter.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/array_module.d.ts +17 -7
- package/dist/cjs/forthic/modules/standard/array_module.js +326 -78
- package/dist/cjs/forthic/modules/standard/array_module.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/boolean_module.d.ts +5 -6
- package/dist/cjs/forthic/modules/standard/boolean_module.js +43 -60
- package/dist/cjs/forthic/modules/standard/boolean_module.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/core_module.d.ts +13 -14
- package/dist/cjs/forthic/modules/standard/core_module.js +101 -97
- package/dist/cjs/forthic/modules/standard/core_module.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/datetime_module.d.ts +4 -2
- package/dist/cjs/forthic/modules/standard/datetime_module.js +39 -20
- package/dist/cjs/forthic/modules/standard/datetime_module.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/json_module.d.ts +0 -1
- package/dist/cjs/forthic/modules/standard/json_module.js +0 -15
- package/dist/cjs/forthic/modules/standard/json_module.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/math_module.d.ts +7 -12
- package/dist/cjs/forthic/modules/standard/math_module.js +76 -137
- package/dist/cjs/forthic/modules/standard/math_module.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/record_module.d.ts +23 -4
- package/dist/cjs/forthic/modules/standard/record_module.js +319 -58
- package/dist/cjs/forthic/modules/standard/record_module.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/string_module.d.ts +14 -6
- package/dist/cjs/forthic/modules/standard/string_module.js +183 -60
- package/dist/cjs/forthic/modules/standard/string_module.js.map +1 -1
- package/dist/cjs/forthic/tokenizer.js +29 -1
- package/dist/cjs/forthic/tokenizer.js.map +1 -1
- package/dist/esm/forthic/interpreter.js +2 -0
- package/dist/esm/forthic/interpreter.js.map +1 -1
- package/dist/esm/forthic/modules/standard/array_module.d.ts +17 -7
- package/dist/esm/forthic/modules/standard/array_module.js +293 -72
- package/dist/esm/forthic/modules/standard/array_module.js.map +1 -1
- package/dist/esm/forthic/modules/standard/boolean_module.d.ts +5 -6
- package/dist/esm/forthic/modules/standard/boolean_module.js +38 -54
- package/dist/esm/forthic/modules/standard/boolean_module.js.map +1 -1
- package/dist/esm/forthic/modules/standard/core_module.d.ts +13 -14
- package/dist/esm/forthic/modules/standard/core_module.js +83 -83
- package/dist/esm/forthic/modules/standard/core_module.js.map +1 -1
- package/dist/esm/forthic/modules/standard/datetime_module.d.ts +4 -2
- package/dist/esm/forthic/modules/standard/datetime_module.js +30 -17
- package/dist/esm/forthic/modules/standard/datetime_module.js.map +1 -1
- package/dist/esm/forthic/modules/standard/json_module.d.ts +0 -1
- package/dist/esm/forthic/modules/standard/json_module.js +0 -12
- package/dist/esm/forthic/modules/standard/json_module.js.map +1 -1
- package/dist/esm/forthic/modules/standard/math_module.d.ts +7 -12
- package/dist/esm/forthic/modules/standard/math_module.js +69 -117
- package/dist/esm/forthic/modules/standard/math_module.js.map +1 -1
- package/dist/esm/forthic/modules/standard/record_module.d.ts +23 -4
- package/dist/esm/forthic/modules/standard/record_module.js +300 -57
- package/dist/esm/forthic/modules/standard/record_module.js.map +1 -1
- package/dist/esm/forthic/modules/standard/string_module.d.ts +14 -6
- package/dist/esm/forthic/modules/standard/string_module.js +151 -54
- package/dist/esm/forthic/modules/standard/string_module.js.map +1 -1
- package/dist/esm/forthic/tokenizer.js +29 -1
- package/dist/esm/forthic/tokenizer.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,20 +5,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { dup_interpreter } from "../../interpreter.js";
|
|
8
|
-
import { DecoratedModule, ForthicWord,
|
|
8
|
+
import { DecoratedModule, ForthicWord, registerModuleDoc } from "../../decorators/word.js";
|
|
9
9
|
export class ArrayModule extends DecoratedModule {
|
|
10
10
|
static {
|
|
11
11
|
registerModuleDoc(ArrayModule, `
|
|
12
12
|
Array and collection operations for manipulating arrays and records.
|
|
13
13
|
|
|
14
14
|
## Categories
|
|
15
|
-
- Access: NTH, LAST, SLICE, TAKE,
|
|
16
|
-
- Transform: MAP, REVERSE
|
|
17
|
-
- Combine: APPEND, ZIP,
|
|
18
|
-
- Filter:
|
|
19
|
-
- Sort: SORT,
|
|
20
|
-
-
|
|
21
|
-
-
|
|
15
|
+
- Access: NTH, FIRST, LAST, SLICE, TAKE, TAKE-LAST, SKIP, LENGTH, INDEX, KEY-OF
|
|
16
|
+
- Transform: MAP, MAP-AT, REVERSE
|
|
17
|
+
- Combine: APPEND, ZIP, ZIP-WITH
|
|
18
|
+
- Filter: FILTER, UNIQUE, UNIQUE-BY, DIFFERENCE, INTERSECTION, UNION
|
|
19
|
+
- Sort: SORT, SORT-BY, SORT-U
|
|
20
|
+
- Search: FIND, COUNT
|
|
21
|
+
- Extrema: MIN-BY, MAX-BY
|
|
22
|
+
- Indexing: NUMBERED
|
|
23
|
+
- Group: BY-FIELD, GROUP-BY, GROUP-BY-FIELD, GROUPS-OF
|
|
24
|
+
- Iteration: FOREACH, REDUCE, UNPACK, FLATTEN, TIMES-RUN
|
|
22
25
|
|
|
23
26
|
## Options
|
|
24
27
|
Several words support options via the ~> operator using syntax: [.option_name value ...] ~> WORD
|
|
@@ -39,17 +42,14 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
39
42
|
constructor() {
|
|
40
43
|
super("array");
|
|
41
44
|
}
|
|
42
|
-
async APPEND(
|
|
43
|
-
let result =
|
|
44
|
-
if (
|
|
45
|
+
async APPEND(array, item) {
|
|
46
|
+
let result = array;
|
|
47
|
+
if (result === null || result === undefined)
|
|
45
48
|
result = [];
|
|
46
|
-
if (result instanceof Array) {
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
// If not a list, treat as record - item should be [key, value]
|
|
51
|
-
result[item[0]] = item[1];
|
|
49
|
+
if (!(result instanceof Array)) {
|
|
50
|
+
throw new Error("APPEND requires an array. For records, use JQ! to set a key.");
|
|
52
51
|
}
|
|
52
|
+
result.push(item);
|
|
53
53
|
return result;
|
|
54
54
|
}
|
|
55
55
|
async REVERSE(container) {
|
|
@@ -71,14 +71,16 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
71
71
|
return result;
|
|
72
72
|
}
|
|
73
73
|
async LENGTH(container) {
|
|
74
|
-
if (
|
|
74
|
+
if (container === null || container === undefined)
|
|
75
75
|
return 0;
|
|
76
|
-
if (container instanceof Array)
|
|
76
|
+
if (container instanceof Array)
|
|
77
77
|
return container.length;
|
|
78
|
+
if (typeof container === "string") {
|
|
79
|
+
throw new Error("LENGTH operates on arrays and records. For strings, use STR-LENGTH.");
|
|
78
80
|
}
|
|
79
|
-
|
|
81
|
+
if (typeof container === "object")
|
|
80
82
|
return Object.keys(container).length;
|
|
81
|
-
|
|
83
|
+
throw new Error("LENGTH operates on arrays and records.");
|
|
82
84
|
}
|
|
83
85
|
async NTH(container, n) {
|
|
84
86
|
if (n === null || !container)
|
|
@@ -96,6 +98,21 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
96
98
|
return container[key];
|
|
97
99
|
}
|
|
98
100
|
}
|
|
101
|
+
async FIRST(container) {
|
|
102
|
+
if (!container)
|
|
103
|
+
return null;
|
|
104
|
+
if (container instanceof Array) {
|
|
105
|
+
if (container.length === 0)
|
|
106
|
+
return null;
|
|
107
|
+
return container[0];
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const keys = Object.keys(container).sort();
|
|
111
|
+
if (keys.length === 0)
|
|
112
|
+
return null;
|
|
113
|
+
return container[keys[0]];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
99
116
|
async LAST(container) {
|
|
100
117
|
if (!container)
|
|
101
118
|
return null;
|
|
@@ -194,7 +211,7 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
194
211
|
}
|
|
195
212
|
return taken;
|
|
196
213
|
}
|
|
197
|
-
async
|
|
214
|
+
async SKIP(container, n) {
|
|
198
215
|
if (!container)
|
|
199
216
|
return [];
|
|
200
217
|
if (n <= 0)
|
|
@@ -208,6 +225,23 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
208
225
|
return rest_keys.map((k) => container[k]);
|
|
209
226
|
}
|
|
210
227
|
}
|
|
228
|
+
async TAKE_LAST(container, n) {
|
|
229
|
+
if (!container)
|
|
230
|
+
return [];
|
|
231
|
+
if (n <= 0)
|
|
232
|
+
return container instanceof Array ? [] : {};
|
|
233
|
+
if (container instanceof Array) {
|
|
234
|
+
return container.slice(Math.max(0, container.length - n));
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
const keys = Object.keys(container).sort();
|
|
238
|
+
const tail = keys.slice(Math.max(0, keys.length - n));
|
|
239
|
+
const result = {};
|
|
240
|
+
for (const k of tail)
|
|
241
|
+
result[k] = container[k];
|
|
242
|
+
return result;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
211
245
|
async DIFFERENCE(lcontainer, rcontainer) {
|
|
212
246
|
let _lcontainer = lcontainer || [];
|
|
213
247
|
let _rcontainer = rcontainer || [];
|
|
@@ -364,29 +398,6 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
364
398
|
}
|
|
365
399
|
return result;
|
|
366
400
|
}
|
|
367
|
-
async SHUFFLE(array) {
|
|
368
|
-
if (!array)
|
|
369
|
-
return array;
|
|
370
|
-
const result = [...array];
|
|
371
|
-
for (let i = result.length - 1; i > 0; i--) {
|
|
372
|
-
const j = Math.floor(Math.random() * (i + 1));
|
|
373
|
-
[result[i], result[j]] = [result[j], result[i]];
|
|
374
|
-
}
|
|
375
|
-
return result;
|
|
376
|
-
}
|
|
377
|
-
async ROTATE(container) {
|
|
378
|
-
if (!container)
|
|
379
|
-
return container;
|
|
380
|
-
let result = container;
|
|
381
|
-
if (container instanceof Array) {
|
|
382
|
-
if (container.length > 0) {
|
|
383
|
-
result = [...container];
|
|
384
|
-
const val = result.pop();
|
|
385
|
-
result.unshift(val);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
return result;
|
|
389
|
-
}
|
|
390
401
|
async UNPACK(container) {
|
|
391
402
|
let _container = container;
|
|
392
403
|
if (!_container)
|
|
@@ -599,7 +610,7 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
599
610
|
return null;
|
|
600
611
|
}
|
|
601
612
|
}
|
|
602
|
-
async
|
|
613
|
+
async FILTER(container, forthic, options) {
|
|
603
614
|
const interp = this.interp;
|
|
604
615
|
const string_location = interp.get_string_location();
|
|
605
616
|
const flags = {
|
|
@@ -814,24 +825,207 @@ Several words support options via the ~> operator using syntax: [.option_name va
|
|
|
814
825
|
await map_word.execute(this.interp);
|
|
815
826
|
return undefined; // MapWord pushes result directly
|
|
816
827
|
}
|
|
817
|
-
async
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
const string_location = interp.get_string_location();
|
|
828
|
+
async MAP_AT(container, key, forthic) {
|
|
829
|
+
if (container === null || container === undefined)
|
|
830
|
+
return container;
|
|
831
|
+
const string_location = this.interp.get_string_location();
|
|
832
|
+
// Path-array form: walk the path, transforming the value at the leaf
|
|
833
|
+
if (Array.isArray(key)) {
|
|
834
|
+
if (key.length === 0) {
|
|
835
|
+
// Apply forthic to the entire container
|
|
836
|
+
this.interp.stack_push(container);
|
|
837
|
+
await this.interp.run(forthic, string_location);
|
|
838
|
+
return this.interp.stack_pop();
|
|
839
|
+
}
|
|
840
|
+
const [head, ...rest] = key;
|
|
841
|
+
return this._mapAtRecursive(container, head, rest, forthic, string_location);
|
|
842
|
+
}
|
|
843
|
+
// Single-key form
|
|
844
|
+
return this._mapAtSingle(container, key, forthic, string_location);
|
|
845
|
+
}
|
|
846
|
+
async _mapAtRecursive(container, head, rest, forthic, string_location) {
|
|
847
|
+
if (rest.length === 0) {
|
|
848
|
+
return this._mapAtSingle(container, head, forthic, string_location);
|
|
849
|
+
}
|
|
850
|
+
if (container instanceof Array) {
|
|
851
|
+
const idx = typeof head === "number" ? head : Number(head);
|
|
852
|
+
if (!Number.isInteger(idx) || idx < 0 || idx >= container.length)
|
|
853
|
+
return container;
|
|
854
|
+
const result = [...container];
|
|
855
|
+
result[idx] = await this._mapAtRecursive(result[idx], rest[0], rest.slice(1), forthic, string_location);
|
|
856
|
+
return result;
|
|
857
|
+
}
|
|
858
|
+
if (typeof container === "object" && container !== null) {
|
|
859
|
+
if (!Object.prototype.hasOwnProperty.call(container, head))
|
|
860
|
+
return container;
|
|
861
|
+
const result = { ...container };
|
|
862
|
+
result[head] = await this._mapAtRecursive(result[head], rest[0], rest.slice(1), forthic, string_location);
|
|
863
|
+
return result;
|
|
864
|
+
}
|
|
865
|
+
return container;
|
|
866
|
+
}
|
|
867
|
+
async _mapAtSingle(container, key, forthic, string_location) {
|
|
868
|
+
if (container instanceof Array) {
|
|
869
|
+
const idx = typeof key === "number" ? key : Number(key);
|
|
870
|
+
if (!Number.isInteger(idx) || idx < 0 || idx >= container.length)
|
|
871
|
+
return container;
|
|
872
|
+
const result = [...container];
|
|
873
|
+
this.interp.stack_push(result[idx]);
|
|
874
|
+
await this.interp.run(forthic, string_location);
|
|
875
|
+
result[idx] = this.interp.stack_pop();
|
|
876
|
+
return result;
|
|
877
|
+
}
|
|
878
|
+
if (typeof container === "object" && container !== null) {
|
|
879
|
+
if (!Object.prototype.hasOwnProperty.call(container, key))
|
|
880
|
+
return container;
|
|
881
|
+
const result = { ...container };
|
|
882
|
+
this.interp.stack_push(result[key]);
|
|
883
|
+
await this.interp.run(forthic, string_location);
|
|
884
|
+
result[key] = this.interp.stack_pop();
|
|
885
|
+
return result;
|
|
886
|
+
}
|
|
887
|
+
return container;
|
|
888
|
+
}
|
|
889
|
+
async TIMES_RUN(num_times, forthic) {
|
|
890
|
+
if (num_times === null || num_times === undefined || !forthic)
|
|
891
|
+
return;
|
|
892
|
+
const string_location = this.interp.get_string_location();
|
|
821
893
|
for (let i = 0; i < num_times; i++) {
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
894
|
+
await this.interp.run(forthic, string_location);
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
// ========================================
|
|
898
|
+
// Functional / jq-style additions
|
|
899
|
+
// ========================================
|
|
900
|
+
async FIND(items, forthic) {
|
|
901
|
+
if (!items)
|
|
902
|
+
return null;
|
|
903
|
+
const string_location = this.interp.get_string_location();
|
|
904
|
+
const seq = items instanceof Array ? items : Object.keys(items).map((k) => items[k]);
|
|
905
|
+
for (const item of seq) {
|
|
906
|
+
this.interp.stack_push(item);
|
|
907
|
+
await this.interp.run(forthic, string_location);
|
|
908
|
+
const matched = this.interp.stack_pop();
|
|
909
|
+
if (matched)
|
|
910
|
+
return item;
|
|
911
|
+
}
|
|
912
|
+
return null;
|
|
913
|
+
}
|
|
914
|
+
async COUNT(items, forthic) {
|
|
915
|
+
if (!items)
|
|
916
|
+
return 0;
|
|
917
|
+
const string_location = this.interp.get_string_location();
|
|
918
|
+
const seq = items instanceof Array ? items : Object.keys(items).map((k) => items[k]);
|
|
919
|
+
let n = 0;
|
|
920
|
+
for (const item of seq) {
|
|
921
|
+
this.interp.stack_push(item);
|
|
922
|
+
await this.interp.run(forthic, string_location);
|
|
923
|
+
if (this.interp.stack_pop())
|
|
924
|
+
n++;
|
|
925
|
+
}
|
|
926
|
+
return n;
|
|
927
|
+
}
|
|
928
|
+
async SORT_BY(items, forthic) {
|
|
929
|
+
if (!Array.isArray(items))
|
|
930
|
+
return items;
|
|
931
|
+
const string_location = this.interp.get_string_location();
|
|
932
|
+
const decorated = [];
|
|
933
|
+
for (const item of items) {
|
|
934
|
+
this.interp.stack_push(item);
|
|
935
|
+
await this.interp.run(forthic, string_location);
|
|
936
|
+
decorated.push({ item, key: this.interp.stack_pop() });
|
|
937
|
+
}
|
|
938
|
+
decorated.sort((a, b) => {
|
|
939
|
+
if (a.key < b.key)
|
|
940
|
+
return -1;
|
|
941
|
+
if (a.key > b.key)
|
|
942
|
+
return 1;
|
|
943
|
+
return 0;
|
|
944
|
+
});
|
|
945
|
+
return decorated.map((d) => d.item);
|
|
946
|
+
}
|
|
947
|
+
async MIN_BY(items, forthic) {
|
|
948
|
+
if (!Array.isArray(items) || items.length === 0)
|
|
949
|
+
return null;
|
|
950
|
+
const string_location = this.interp.get_string_location();
|
|
951
|
+
let best_item = null;
|
|
952
|
+
let best_key = null;
|
|
953
|
+
let first = true;
|
|
954
|
+
for (const item of items) {
|
|
955
|
+
this.interp.stack_push(item);
|
|
956
|
+
await this.interp.run(forthic, string_location);
|
|
957
|
+
const key = this.interp.stack_pop();
|
|
958
|
+
if (first || key < best_key) {
|
|
959
|
+
best_item = item;
|
|
960
|
+
best_key = key;
|
|
961
|
+
first = false;
|
|
962
|
+
}
|
|
830
963
|
}
|
|
964
|
+
return best_item;
|
|
965
|
+
}
|
|
966
|
+
async MAX_BY(items, forthic) {
|
|
967
|
+
if (!Array.isArray(items) || items.length === 0)
|
|
968
|
+
return null;
|
|
969
|
+
const string_location = this.interp.get_string_location();
|
|
970
|
+
let best_item = null;
|
|
971
|
+
let best_key = null;
|
|
972
|
+
let first = true;
|
|
973
|
+
for (const item of items) {
|
|
974
|
+
this.interp.stack_push(item);
|
|
975
|
+
await this.interp.run(forthic, string_location);
|
|
976
|
+
const key = this.interp.stack_pop();
|
|
977
|
+
if (first || key > best_key) {
|
|
978
|
+
best_item = item;
|
|
979
|
+
best_key = key;
|
|
980
|
+
first = false;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
return best_item;
|
|
984
|
+
}
|
|
985
|
+
async UNIQUE_BY(items, forthic) {
|
|
986
|
+
if (!Array.isArray(items))
|
|
987
|
+
return items;
|
|
988
|
+
const string_location = this.interp.get_string_location();
|
|
989
|
+
const seen = new Set();
|
|
990
|
+
const result = [];
|
|
991
|
+
for (const item of items) {
|
|
992
|
+
this.interp.stack_push(item);
|
|
993
|
+
await this.interp.run(forthic, string_location);
|
|
994
|
+
const key = this.interp.stack_pop();
|
|
995
|
+
const skey = JSON.stringify(key);
|
|
996
|
+
if (!seen.has(skey)) {
|
|
997
|
+
seen.add(skey);
|
|
998
|
+
result.push(item);
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
return result;
|
|
1002
|
+
}
|
|
1003
|
+
async NUMBERED(items) {
|
|
1004
|
+
if (!Array.isArray(items))
|
|
1005
|
+
return [];
|
|
1006
|
+
return items.map((item, i) => [i, item]);
|
|
1007
|
+
}
|
|
1008
|
+
// ========================================
|
|
1009
|
+
// Bash/shell-flavored array additions (PR 7)
|
|
1010
|
+
// ========================================
|
|
1011
|
+
async SORT_U(strings) {
|
|
1012
|
+
if (!Array.isArray(strings))
|
|
1013
|
+
return strings;
|
|
1014
|
+
const sorted = [...strings].sort();
|
|
1015
|
+
const seen = new Set();
|
|
1016
|
+
const result = [];
|
|
1017
|
+
for (const s of sorted) {
|
|
1018
|
+
const key = JSON.stringify(s);
|
|
1019
|
+
if (!seen.has(key)) {
|
|
1020
|
+
seen.add(key);
|
|
1021
|
+
result.push(s);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
return result;
|
|
831
1025
|
}
|
|
832
1026
|
}
|
|
833
1027
|
__decorate([
|
|
834
|
-
ForthicWord("(
|
|
1028
|
+
ForthicWord("( array:any[] item:any -- array:any[] )", "Append item to array. For records, use JQ! to set a key.", "APPEND")
|
|
835
1029
|
], ArrayModule.prototype, "APPEND", null);
|
|
836
1030
|
__decorate([
|
|
837
1031
|
ForthicWord("( container:any -- container:any )", "Reverse array")
|
|
@@ -840,11 +1034,14 @@ __decorate([
|
|
|
840
1034
|
ForthicWord("( array:any[] -- array:any[] )", "Remove duplicates from array")
|
|
841
1035
|
], ArrayModule.prototype, "UNIQUE", null);
|
|
842
1036
|
__decorate([
|
|
843
|
-
ForthicWord("( container:any -- length:number )", "
|
|
1037
|
+
ForthicWord("( container:any -- length:number )", "Length of an array or record. For strings, use STR-LENGTH.")
|
|
844
1038
|
], ArrayModule.prototype, "LENGTH", null);
|
|
845
1039
|
__decorate([
|
|
846
1040
|
ForthicWord("( container:any n:number -- item:any )", "Get nth element from array or record")
|
|
847
1041
|
], ArrayModule.prototype, "NTH", null);
|
|
1042
|
+
__decorate([
|
|
1043
|
+
ForthicWord("( container:any -- item:any )", "Get first element from array or record (sorted-key order for records)")
|
|
1044
|
+
], ArrayModule.prototype, "FIRST", null);
|
|
848
1045
|
__decorate([
|
|
849
1046
|
ForthicWord("( container:any -- item:any )", "Get last element from array or record")
|
|
850
1047
|
], ArrayModule.prototype, "LAST", null);
|
|
@@ -855,8 +1052,11 @@ __decorate([
|
|
|
855
1052
|
ForthicWord("( container:any[] n:number [options:WordOptions] -- result:any[] )", "Take first n elements")
|
|
856
1053
|
], ArrayModule.prototype, "TAKE", null);
|
|
857
1054
|
__decorate([
|
|
858
|
-
ForthicWord("( container:any n:number -- result:any )", "
|
|
859
|
-
], ArrayModule.prototype, "
|
|
1055
|
+
ForthicWord("( container:any n:number -- result:any )", "Skip first n elements from array or record")
|
|
1056
|
+
], ArrayModule.prototype, "SKIP", null);
|
|
1057
|
+
__decorate([
|
|
1058
|
+
ForthicWord("( container:any n:number -- result:any )", "Take last n elements from array or record (sorted-key order for records).", "TAKE-LAST")
|
|
1059
|
+
], ArrayModule.prototype, "TAKE_LAST", null);
|
|
860
1060
|
__decorate([
|
|
861
1061
|
ForthicWord("( lcontainer:any rcontainer:any -- result:any )", "Set difference between two containers")
|
|
862
1062
|
], ArrayModule.prototype, "DIFFERENCE", null);
|
|
@@ -869,12 +1069,6 @@ __decorate([
|
|
|
869
1069
|
__decorate([
|
|
870
1070
|
ForthicWord("( container:any[] [options:WordOptions] -- array:any[] )", "Sort container. Options: comparator (string or function). Example: [3 1 4] [.comparator \"-1 *\"] ~> SORT")
|
|
871
1071
|
], ArrayModule.prototype, "SORT", null);
|
|
872
|
-
__decorate([
|
|
873
|
-
ForthicWord("( array:any[] -- array:any[] )", "Shuffle array randomly")
|
|
874
|
-
], ArrayModule.prototype, "SHUFFLE", null);
|
|
875
|
-
__decorate([
|
|
876
|
-
ForthicWord("( container:any -- container:any )", "Rotate container by moving last element to front")
|
|
877
|
-
], ArrayModule.prototype, "ROTATE", null);
|
|
878
1072
|
__decorate([
|
|
879
1073
|
ForthicWord("( container:any -- elements:any )", "Unpack array or record elements onto stack")
|
|
880
1074
|
], ArrayModule.prototype, "UNPACK", null);
|
|
@@ -897,8 +1091,8 @@ __decorate([
|
|
|
897
1091
|
ForthicWord("( container:any value:any -- key:any )", "Find key of value in container", "KEY-OF")
|
|
898
1092
|
], ArrayModule.prototype, "KEY_OF", null);
|
|
899
1093
|
__decorate([
|
|
900
|
-
ForthicWord("( container:any forthic:string [options:WordOptions] -- filtered:any )", "Filter items with predicate. Options: with_key (bool)")
|
|
901
|
-
], ArrayModule.prototype, "
|
|
1094
|
+
ForthicWord("( container:any forthic:string [options:WordOptions] -- filtered:any )", "Filter items with predicate. Options: with_key (bool)", "FILTER")
|
|
1095
|
+
], ArrayModule.prototype, "FILTER", null);
|
|
902
1096
|
__decorate([
|
|
903
1097
|
ForthicWord("( container:any[] field:string -- indexed:any )", "Index records by field value", "BY-FIELD")
|
|
904
1098
|
], ArrayModule.prototype, "BY_FIELD", null);
|
|
@@ -918,8 +1112,35 @@ __decorate([
|
|
|
918
1112
|
ForthicWord("( items:any forthic:string [options:WordOptions] -- mapped:any )", "Map function over items. Options: with_key (bool), push_error (bool), depth (num), push_rest (bool). Example: [1 2 3] '2 *' [.with_key TRUE] ~> MAP")
|
|
919
1113
|
], ArrayModule.prototype, "MAP", null);
|
|
920
1114
|
__decorate([
|
|
921
|
-
|
|
922
|
-
], ArrayModule.prototype, "
|
|
1115
|
+
ForthicWord("( container:any key:any|any[] forthic:string -- container:any )", "Apply forthic to the value at key/index, returning a new container with that slot transformed. The key arg may be a single key (one-level update) or a path-array for deep updates. Polymorphic over arrays and records. Equivalent of jq's |= operator.", "MAP-AT")
|
|
1116
|
+
], ArrayModule.prototype, "MAP_AT", null);
|
|
1117
|
+
__decorate([
|
|
1118
|
+
ForthicWord("( num_times:number forthic:string -- )", "Run forthic num_times. Each invocation runs in the current stack — no automatic per-iteration value passing.", "TIMES-RUN")
|
|
1119
|
+
], ArrayModule.prototype, "TIMES_RUN", null);
|
|
1120
|
+
__decorate([
|
|
1121
|
+
ForthicWord("( items:any forthic:string -- item:any )", "Return the first item where forthic returns truthy, or null if none.", "FIND")
|
|
1122
|
+
], ArrayModule.prototype, "FIND", null);
|
|
1123
|
+
__decorate([
|
|
1124
|
+
ForthicWord("( items:any forthic:string -- n:number )", "Count items where forthic returns truthy.", "COUNT")
|
|
1125
|
+
], ArrayModule.prototype, "COUNT", null);
|
|
1126
|
+
__decorate([
|
|
1127
|
+
ForthicWord("( items:any[] forthic:string -- sorted:any[] )", "Sort items by the value forthic produces (ascending).", "SORT-BY")
|
|
1128
|
+
], ArrayModule.prototype, "SORT_BY", null);
|
|
1129
|
+
__decorate([
|
|
1130
|
+
ForthicWord("( items:any[] forthic:string -- item:any )", "Return the item with the smallest value produced by forthic. Null on empty input.", "MIN-BY")
|
|
1131
|
+
], ArrayModule.prototype, "MIN_BY", null);
|
|
1132
|
+
__decorate([
|
|
1133
|
+
ForthicWord("( items:any[] forthic:string -- item:any )", "Return the item with the largest value produced by forthic. Null on empty input.", "MAX-BY")
|
|
1134
|
+
], ArrayModule.prototype, "MAX_BY", null);
|
|
1135
|
+
__decorate([
|
|
1136
|
+
ForthicWord("( items:any[] forthic:string -- items:any[] )", "Dedupe items by the key forthic produces (keeps first occurrence).", "UNIQUE-BY")
|
|
1137
|
+
], ArrayModule.prototype, "UNIQUE_BY", null);
|
|
1138
|
+
__decorate([
|
|
1139
|
+
ForthicWord("( items:any[] -- pairs:any[] )", "Pair each item with its index: [v0 v1 v2] -> [[0 v0] [1 v1] [2 v2]]. (Python's enumerate.)", "NUMBERED")
|
|
1140
|
+
], ArrayModule.prototype, "NUMBERED", null);
|
|
1141
|
+
__decorate([
|
|
1142
|
+
ForthicWord("( strings:any[] -- strings:any[] )", "Sort an array and remove duplicates (bash sort -u).", "SORT-U")
|
|
1143
|
+
], ArrayModule.prototype, "SORT_U", null);
|
|
923
1144
|
// ( items forthic -- [ ? ] )
|
|
924
1145
|
class MapWord {
|
|
925
1146
|
forthic;
|