@mojir/lits 2.2.4 → 2.3.1
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/README.md +2 -1
- package/dist/cli/cli.js +1471 -1126
- package/dist/cli/reference/api.d.ts +5 -5
- package/dist/cli/reference/index.d.ts +8 -2
- package/dist/cli/src/Lits/Lits.d.ts +8 -2
- package/dist/cli/src/builtin/bindingNode.d.ts +2 -1
- package/dist/cli/src/builtin/interface.d.ts +3 -2
- package/dist/cli/src/builtin/modules/number-theory/sequences/index.d.ts +2 -1
- package/dist/cli/src/evaluator/functionExecutors.d.ts +2 -1
- package/dist/cli/src/evaluator/index.d.ts +3 -2
- package/dist/cli/src/evaluator/interface.d.ts +3 -2
- package/dist/cli/src/tokenizer/operators.d.ts +2 -2
- package/dist/cli/src/utils/maybePromise.d.ts +54 -0
- package/dist/full.esm.js +1 -1
- package/dist/full.esm.js.map +1 -1
- package/dist/full.js +1 -1
- package/dist/full.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lits.iife.js +1 -1
- package/dist/lits.iife.js.map +1 -1
- package/dist/modules/assert.esm.js +1 -1
- package/dist/modules/assert.esm.js.map +1 -1
- package/dist/modules/assert.js +1 -1
- package/dist/modules/assert.js.map +1 -1
- package/dist/modules/collection.esm.js +1 -1
- package/dist/modules/collection.esm.js.map +1 -1
- package/dist/modules/collection.js +1 -1
- package/dist/modules/collection.js.map +1 -1
- package/dist/modules/grid.esm.js +1 -1
- package/dist/modules/grid.esm.js.map +1 -1
- package/dist/modules/grid.js +1 -1
- package/dist/modules/grid.js.map +1 -1
- package/dist/modules/number-theory.esm.js +1 -1
- package/dist/modules/number-theory.esm.js.map +1 -1
- package/dist/modules/number-theory.js +1 -1
- package/dist/modules/number-theory.js.map +1 -1
- package/dist/modules/reference/api.d.ts +5 -5
- package/dist/modules/reference/index.d.ts +8 -2
- package/dist/modules/sequence.esm.js +1 -1
- package/dist/modules/sequence.esm.js.map +1 -1
- package/dist/modules/sequence.js +1 -1
- package/dist/modules/sequence.js.map +1 -1
- package/dist/modules/src/Lits/Lits.d.ts +8 -2
- package/dist/modules/src/builtin/bindingNode.d.ts +2 -1
- package/dist/modules/src/builtin/interface.d.ts +3 -2
- package/dist/modules/src/builtin/modules/number-theory/sequences/index.d.ts +2 -1
- package/dist/modules/src/evaluator/functionExecutors.d.ts +2 -1
- package/dist/modules/src/evaluator/index.d.ts +3 -2
- package/dist/modules/src/evaluator/interface.d.ts +3 -2
- package/dist/modules/src/tokenizer/operators.d.ts +2 -2
- package/dist/modules/src/utils/maybePromise.d.ts +54 -0
- package/dist/modules/vector.esm.js +1 -1
- package/dist/modules/vector.esm.js.map +1 -1
- package/dist/modules/vector.js +1 -1
- package/dist/modules/vector.js.map +1 -1
- package/dist/reference/api.d.ts +5 -5
- package/dist/reference/index.d.ts +8 -2
- package/dist/src/Lits/Lits.d.ts +8 -2
- package/dist/src/builtin/bindingNode.d.ts +2 -1
- package/dist/src/builtin/interface.d.ts +3 -2
- package/dist/src/builtin/modules/number-theory/sequences/index.d.ts +2 -1
- package/dist/src/evaluator/functionExecutors.d.ts +2 -1
- package/dist/src/evaluator/index.d.ts +3 -2
- package/dist/src/evaluator/interface.d.ts +3 -2
- package/dist/src/tokenizer/operators.d.ts +2 -2
- package/dist/src/utils/maybePromise.d.ts +54 -0
- package/dist/testFramework.esm.js +1 -1
- package/dist/testFramework.esm.js.map +1 -1
- package/dist/testFramework.js +1 -1
- package/dist/testFramework.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ var readline = require('node:readline');
|
|
|
7
7
|
var os = require('node:os');
|
|
8
8
|
var process$1 = require('node:process');
|
|
9
9
|
|
|
10
|
-
var version = "2.
|
|
10
|
+
var version = "2.3.1";
|
|
11
11
|
|
|
12
12
|
function getCodeMarker(sourceCodeInfo) {
|
|
13
13
|
if (!sourceCodeInfo.position || !sourceCodeInfo.code)
|
|
@@ -858,6 +858,200 @@ function assertCharArray(value, sourceCodeInfo) {
|
|
|
858
858
|
throw getAssertionError('array of strings', value, sourceCodeInfo);
|
|
859
859
|
}
|
|
860
860
|
|
|
861
|
+
/**
|
|
862
|
+
* MaybePromise utilities for transparent async support.
|
|
863
|
+
*
|
|
864
|
+
* The sync path stays zero-overhead — when no async JS functions are involved,
|
|
865
|
+
* everything runs synchronously with only `instanceof Promise` checks as overhead.
|
|
866
|
+
* When an async value is detected, the evaluation chain switches to Promise-based
|
|
867
|
+
* execution for the remainder.
|
|
868
|
+
*/
|
|
869
|
+
/**
|
|
870
|
+
* Chain a value that might be a Promise. If the value is sync, calls fn synchronously.
|
|
871
|
+
* If it's a Promise, chains with .then().
|
|
872
|
+
*/
|
|
873
|
+
function chain(value, fn) {
|
|
874
|
+
if (value instanceof Promise) {
|
|
875
|
+
return value.then(fn);
|
|
876
|
+
}
|
|
877
|
+
return fn(value);
|
|
878
|
+
}
|
|
879
|
+
/**
|
|
880
|
+
* Like Array.map but handles MaybePromise callbacks sequentially.
|
|
881
|
+
* In the sync case, runs as a simple loop. Switches to async only when needed.
|
|
882
|
+
*/
|
|
883
|
+
function mapSequential(arr, fn) {
|
|
884
|
+
const results = [];
|
|
885
|
+
for (let i = 0; i < arr.length; i++) {
|
|
886
|
+
const result = fn(arr[i], i);
|
|
887
|
+
if (result instanceof Promise) {
|
|
888
|
+
return chainRemainingMap(result, results, arr, fn, i);
|
|
889
|
+
}
|
|
890
|
+
results.push(result);
|
|
891
|
+
}
|
|
892
|
+
return results;
|
|
893
|
+
}
|
|
894
|
+
async function chainRemainingMap(currentPromise, results, arr, fn, startIndex) {
|
|
895
|
+
results.push(await currentPromise);
|
|
896
|
+
for (let i = startIndex + 1; i < arr.length; i++) {
|
|
897
|
+
results.push(await fn(arr[i], i));
|
|
898
|
+
}
|
|
899
|
+
return results;
|
|
900
|
+
}
|
|
901
|
+
/**
|
|
902
|
+
* Like Array.reduce but handles MaybePromise callbacks sequentially.
|
|
903
|
+
* In the sync case, runs as a simple loop. Switches to async only when needed.
|
|
904
|
+
*/
|
|
905
|
+
function reduceSequential(arr, fn, initial) {
|
|
906
|
+
let result = initial;
|
|
907
|
+
for (let i = 0; i < arr.length; i++) {
|
|
908
|
+
const next = fn(result, arr[i], i);
|
|
909
|
+
if (next instanceof Promise) {
|
|
910
|
+
return chainRemainingReduce(next, arr, fn, i);
|
|
911
|
+
}
|
|
912
|
+
result = next;
|
|
913
|
+
}
|
|
914
|
+
return result;
|
|
915
|
+
}
|
|
916
|
+
async function chainRemainingReduce(currentPromise, arr, fn, startIndex) {
|
|
917
|
+
let result = await currentPromise;
|
|
918
|
+
for (let i = startIndex + 1; i < arr.length; i++) {
|
|
919
|
+
result = await fn(result, arr[i], i);
|
|
920
|
+
}
|
|
921
|
+
return result;
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* Like Array.forEach but handles MaybePromise callbacks sequentially.
|
|
925
|
+
* In the sync case, runs as a simple loop. Switches to async only when needed.
|
|
926
|
+
*/
|
|
927
|
+
function forEachSequential(arr, fn) {
|
|
928
|
+
for (let i = 0; i < arr.length; i++) {
|
|
929
|
+
const result = fn(arr[i], i);
|
|
930
|
+
if (result instanceof Promise) {
|
|
931
|
+
return chainRemainingForEach(result, arr, fn, i);
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
async function chainRemainingForEach(currentPromise, arr, fn, startIndex) {
|
|
936
|
+
await currentPromise;
|
|
937
|
+
for (let i = startIndex + 1; i < arr.length; i++) {
|
|
938
|
+
await fn(arr[i], i);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
/**
|
|
942
|
+
* Try/catch that handles MaybePromise values correctly.
|
|
943
|
+
* If tryFn returns a Promise, catches both sync throws and Promise rejections.
|
|
944
|
+
*/
|
|
945
|
+
function tryCatch(tryFn, catchFn) {
|
|
946
|
+
try {
|
|
947
|
+
const result = tryFn();
|
|
948
|
+
if (result instanceof Promise) {
|
|
949
|
+
return result.catch(catchFn);
|
|
950
|
+
}
|
|
951
|
+
return result;
|
|
952
|
+
}
|
|
953
|
+
catch (error) {
|
|
954
|
+
return catchFn(error);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
/**
|
|
958
|
+
* Like Array.some but handles MaybePromise callbacks sequentially.
|
|
959
|
+
* Returns the first truthy MaybePromise result, or false.
|
|
960
|
+
*/
|
|
961
|
+
function someSequential(arr, fn) {
|
|
962
|
+
for (let i = 0; i < arr.length; i++) {
|
|
963
|
+
const result = fn(arr[i], i);
|
|
964
|
+
if (result instanceof Promise) {
|
|
965
|
+
return chainRemainingSome(result, arr, fn, i);
|
|
966
|
+
}
|
|
967
|
+
if (result)
|
|
968
|
+
return true;
|
|
969
|
+
}
|
|
970
|
+
return false;
|
|
971
|
+
}
|
|
972
|
+
async function chainRemainingSome(currentPromise, arr, fn, startIndex) {
|
|
973
|
+
if (await currentPromise)
|
|
974
|
+
return true;
|
|
975
|
+
for (let i = startIndex + 1; i < arr.length; i++) {
|
|
976
|
+
if (await fn(arr[i], i))
|
|
977
|
+
return true;
|
|
978
|
+
}
|
|
979
|
+
return false;
|
|
980
|
+
}
|
|
981
|
+
/**
|
|
982
|
+
* Like Array.every but handles MaybePromise callbacks sequentially.
|
|
983
|
+
* Returns false as soon as a falsy result is found.
|
|
984
|
+
*/
|
|
985
|
+
function everySequential(arr, fn) {
|
|
986
|
+
for (let i = 0; i < arr.length; i++) {
|
|
987
|
+
const result = fn(arr[i], i);
|
|
988
|
+
if (result instanceof Promise) {
|
|
989
|
+
return chainRemainingEvery(result, arr, fn, i);
|
|
990
|
+
}
|
|
991
|
+
if (!result)
|
|
992
|
+
return false;
|
|
993
|
+
}
|
|
994
|
+
return true;
|
|
995
|
+
}
|
|
996
|
+
async function chainRemainingEvery(currentPromise, arr, fn, startIndex) {
|
|
997
|
+
if (!await currentPromise)
|
|
998
|
+
return false;
|
|
999
|
+
for (let i = startIndex + 1; i < arr.length; i++) {
|
|
1000
|
+
if (!await fn(arr[i], i))
|
|
1001
|
+
return false;
|
|
1002
|
+
}
|
|
1003
|
+
return true;
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* Like Array.filter but handles MaybePromise callbacks sequentially.
|
|
1007
|
+
* Returns the filtered array.
|
|
1008
|
+
*/
|
|
1009
|
+
function filterSequential(arr, fn) {
|
|
1010
|
+
const results = [];
|
|
1011
|
+
for (let i = 0; i < arr.length; i++) {
|
|
1012
|
+
const result = fn(arr[i], i);
|
|
1013
|
+
if (result instanceof Promise) {
|
|
1014
|
+
return chainRemainingFilter(result, results, arr, fn, i);
|
|
1015
|
+
}
|
|
1016
|
+
if (result)
|
|
1017
|
+
results.push(arr[i]);
|
|
1018
|
+
}
|
|
1019
|
+
return results;
|
|
1020
|
+
}
|
|
1021
|
+
async function chainRemainingFilter(currentPromise, results, arr, fn, startIndex) {
|
|
1022
|
+
if (await currentPromise)
|
|
1023
|
+
results.push(arr[startIndex]);
|
|
1024
|
+
for (let i = startIndex + 1; i < arr.length; i++) {
|
|
1025
|
+
if (await fn(arr[i], i))
|
|
1026
|
+
results.push(arr[i]);
|
|
1027
|
+
}
|
|
1028
|
+
return results;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Like Array.findIndex but handles MaybePromise callbacks sequentially.
|
|
1032
|
+
* Returns -1 if no element matches.
|
|
1033
|
+
*/
|
|
1034
|
+
function findIndexSequential(arr, fn) {
|
|
1035
|
+
for (let i = 0; i < arr.length; i++) {
|
|
1036
|
+
const result = fn(arr[i], i);
|
|
1037
|
+
if (result instanceof Promise) {
|
|
1038
|
+
return chainRemainingFindIndex(result, arr, fn, i);
|
|
1039
|
+
}
|
|
1040
|
+
if (result)
|
|
1041
|
+
return i;
|
|
1042
|
+
}
|
|
1043
|
+
return -1;
|
|
1044
|
+
}
|
|
1045
|
+
async function chainRemainingFindIndex(currentPromise, arr, fn, startIndex) {
|
|
1046
|
+
if (await currentPromise)
|
|
1047
|
+
return startIndex;
|
|
1048
|
+
for (let i = startIndex + 1; i < arr.length; i++) {
|
|
1049
|
+
if (await fn(arr[i], i))
|
|
1050
|
+
return i;
|
|
1051
|
+
}
|
|
1052
|
+
return -1;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
861
1055
|
function mapObjects({ colls, contextStack, executeFunction, fn, sourceCodeInfo, }) {
|
|
862
1056
|
assertObj(colls[0], sourceCodeInfo);
|
|
863
1057
|
const keys = Object.keys(colls[0]);
|
|
@@ -877,10 +1071,13 @@ function mapObjects({ colls, contextStack, executeFunction, fn, sourceCodeInfo,
|
|
|
877
1071
|
params[key].push(value);
|
|
878
1072
|
});
|
|
879
1073
|
});
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
return
|
|
883
|
-
|
|
1074
|
+
const initialObj = {};
|
|
1075
|
+
return reduceSequential(keys, (result, key) => {
|
|
1076
|
+
return chain(executeFunction(fn, params[key], contextStack, sourceCodeInfo), (value) => {
|
|
1077
|
+
result[key] = value;
|
|
1078
|
+
return result;
|
|
1079
|
+
});
|
|
1080
|
+
}, initialObj);
|
|
884
1081
|
}
|
|
885
1082
|
function get$1(coll, key) {
|
|
886
1083
|
if (isObj(coll)) {
|
|
@@ -919,21 +1116,33 @@ const collectionNormalExpression = {
|
|
|
919
1116
|
assertColl(coll, sourceCodeInfo);
|
|
920
1117
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
921
1118
|
if (Array.isArray(coll)) {
|
|
922
|
-
|
|
923
|
-
|
|
1119
|
+
return reduceSequential(coll, (result, elem) => {
|
|
1120
|
+
return chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), (keep) => {
|
|
1121
|
+
if (keep)
|
|
1122
|
+
result.push(elem);
|
|
1123
|
+
return result;
|
|
1124
|
+
});
|
|
1125
|
+
}, []);
|
|
924
1126
|
}
|
|
925
1127
|
if (isString(coll)) {
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
1128
|
+
const chars = coll.split('');
|
|
1129
|
+
return chain(reduceSequential(chars, (result, elem) => {
|
|
1130
|
+
return chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), (keep) => {
|
|
1131
|
+
if (keep)
|
|
1132
|
+
result.push(elem);
|
|
1133
|
+
return result;
|
|
1134
|
+
});
|
|
1135
|
+
}, []), filtered => filtered.join(''));
|
|
1136
|
+
}
|
|
1137
|
+
const entries = Object.entries(coll);
|
|
1138
|
+
const initialObj = {};
|
|
1139
|
+
return reduceSequential(entries, (result, [key, value]) => {
|
|
1140
|
+
return chain(executeFunction(fn, [value], contextStack, sourceCodeInfo), (keep) => {
|
|
1141
|
+
if (keep)
|
|
1142
|
+
result[key] = value;
|
|
1143
|
+
return result;
|
|
1144
|
+
});
|
|
1145
|
+
}, initialObj);
|
|
937
1146
|
},
|
|
938
1147
|
arity: toFixedArity(2),
|
|
939
1148
|
docs: {
|
|
@@ -996,12 +1205,14 @@ filter(
|
|
|
996
1205
|
for (let i = 0; i < len; i++) {
|
|
997
1206
|
paramArray.push(seqs.map(seq => seq[i]));
|
|
998
1207
|
}
|
|
999
|
-
const mapped = paramArray
|
|
1208
|
+
const mapped = mapSequential(paramArray, p => executeFunction(fn, p, contextStack, sourceCodeInfo));
|
|
1000
1209
|
if (!isStr) {
|
|
1001
1210
|
return mapped;
|
|
1002
1211
|
}
|
|
1003
|
-
mapped
|
|
1004
|
-
|
|
1212
|
+
return chain(mapped, (resolvedMapped) => {
|
|
1213
|
+
resolvedMapped.forEach(char => assertString(char, sourceCodeInfo));
|
|
1214
|
+
return resolvedMapped.join('');
|
|
1215
|
+
});
|
|
1005
1216
|
},
|
|
1006
1217
|
arity: { min: 2 },
|
|
1007
1218
|
docs: {
|
|
@@ -1036,21 +1247,21 @@ filter(
|
|
|
1036
1247
|
assertString(initial, sourceCodeInfo);
|
|
1037
1248
|
if (coll.length === 0)
|
|
1038
1249
|
return initial;
|
|
1039
|
-
return coll.split('')
|
|
1250
|
+
return reduceSequential(coll.split(''), (result, elem) => {
|
|
1040
1251
|
return executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
1041
1252
|
}, initial);
|
|
1042
1253
|
}
|
|
1043
1254
|
else if (Array.isArray(coll)) {
|
|
1044
1255
|
if (coll.length === 0)
|
|
1045
1256
|
return initial;
|
|
1046
|
-
return coll
|
|
1257
|
+
return reduceSequential(coll, (result, elem) => {
|
|
1047
1258
|
return executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
1048
1259
|
}, initial);
|
|
1049
1260
|
}
|
|
1050
1261
|
else {
|
|
1051
1262
|
if (Object.keys(coll).length === 0)
|
|
1052
1263
|
return initial;
|
|
1053
|
-
return Object.entries(coll)
|
|
1264
|
+
return reduceSequential(Object.entries(coll), (result, [, elem]) => {
|
|
1054
1265
|
return executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
1055
1266
|
}, initial);
|
|
1056
1267
|
}
|
|
@@ -1490,7 +1701,7 @@ flatten([
|
|
|
1490
1701
|
evaluate: ([arr, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
1491
1702
|
assertArray(arr, sourceCodeInfo);
|
|
1492
1703
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
1493
|
-
return arr
|
|
1704
|
+
return chain(mapSequential(arr, elem => executeFunction(fn, [elem], contextStack, sourceCodeInfo)), mapped => mapped.flat(1));
|
|
1494
1705
|
},
|
|
1495
1706
|
arity: toFixedArity(2),
|
|
1496
1707
|
docs: {
|
|
@@ -1527,13 +1738,11 @@ mapcat(
|
|
|
1527
1738
|
assertArray(arr, sourceCodeInfo);
|
|
1528
1739
|
assertNumber(windowSize, sourceCodeInfo, { integer: true, lte: arr.length });
|
|
1529
1740
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
1530
|
-
const
|
|
1741
|
+
const windows = [];
|
|
1531
1742
|
for (let i = 0; i <= arr.length - windowSize; i++) {
|
|
1532
|
-
|
|
1533
|
-
const value = executeFunction(fn, [window], contextStack, sourceCodeInfo);
|
|
1534
|
-
result.push(value);
|
|
1743
|
+
windows.push(arr.slice(i, i + windowSize));
|
|
1535
1744
|
}
|
|
1536
|
-
return
|
|
1745
|
+
return mapSequential(windows, window => executeFunction(fn, [window], contextStack, sourceCodeInfo));
|
|
1537
1746
|
},
|
|
1538
1747
|
arity: toFixedArity(3),
|
|
1539
1748
|
docs: {
|
|
@@ -1558,12 +1767,11 @@ mapcat(
|
|
|
1558
1767
|
evaluate: ([arr, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
1559
1768
|
assertArray(arr, sourceCodeInfo);
|
|
1560
1769
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
1561
|
-
const
|
|
1770
|
+
const subArrays = [];
|
|
1562
1771
|
for (let i = 0; i < arr.length; i += 1) {
|
|
1563
|
-
|
|
1564
|
-
result.push(executeFunction(fn, [subArr], contextStack, sourceCodeInfo));
|
|
1772
|
+
subArrays.push(arr.slice(0, i + 1));
|
|
1565
1773
|
}
|
|
1566
|
-
return
|
|
1774
|
+
return mapSequential(subArrays, subArr => executeFunction(fn, [subArr], contextStack, sourceCodeInfo));
|
|
1567
1775
|
},
|
|
1568
1776
|
arity: toFixedArity(2),
|
|
1569
1777
|
docs: {
|
|
@@ -1922,7 +2130,7 @@ For string $seq returns all but the first characters in $seq.`,
|
|
|
1922
2130
|
{ argumentNames: ['seq', 'start', 'stop'] },
|
|
1923
2131
|
],
|
|
1924
2132
|
description: 'Returns a copy of a portion of $seq from index $start (inclusive) to $stop (exclusive).',
|
|
1925
|
-
seeAlso: ['
|
|
2133
|
+
seeAlso: ['take', 'drop', 'sequence.splice', 'nth'],
|
|
1926
2134
|
examples: [
|
|
1927
2135
|
'[1, 2, 3, 4, 5] slice 2',
|
|
1928
2136
|
'slice([1, 2, 3, 4, 5], 2, 4)',
|
|
@@ -1938,9 +2146,14 @@ For string $seq returns all but the first characters in $seq.`,
|
|
|
1938
2146
|
assertSeq(seq, sourceCodeInfo);
|
|
1939
2147
|
if (seq.length === 0)
|
|
1940
2148
|
return null;
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
2149
|
+
const items = typeof seq === 'string' ? seq.split('') : seq;
|
|
2150
|
+
return reduceSequential(items, (found, elem) => {
|
|
2151
|
+
if (found !== null)
|
|
2152
|
+
return found;
|
|
2153
|
+
return chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), (result) => {
|
|
2154
|
+
return result ? toAny(elem) : null;
|
|
2155
|
+
});
|
|
2156
|
+
}, null);
|
|
1944
2157
|
},
|
|
1945
2158
|
arity: toFixedArity(2),
|
|
1946
2159
|
docs: {
|
|
@@ -1985,7 +2198,7 @@ some(
|
|
|
1985
2198
|
},
|
|
1986
2199
|
},
|
|
1987
2200
|
'sort': {
|
|
1988
|
-
evaluate: (params, sourceCodeInfo,
|
|
2201
|
+
evaluate: (params, sourceCodeInfo, _contextStack, { executeFunction: _executeFunction }) => {
|
|
1989
2202
|
const [seq] = params;
|
|
1990
2203
|
const defaultComparer = params.length === 1;
|
|
1991
2204
|
const comparer = defaultComparer ? null : params[1];
|
|
@@ -1997,8 +2210,12 @@ some(
|
|
|
1997
2210
|
}
|
|
1998
2211
|
else {
|
|
1999
2212
|
assertFunctionLike(comparer, sourceCodeInfo);
|
|
2213
|
+
// Note: sort comparator must be synchronous — async comparators would need a different approach
|
|
2000
2214
|
result.sort((a, b) => {
|
|
2001
|
-
const compareValue =
|
|
2215
|
+
const compareValue = _executeFunction(comparer, [a, b], _contextStack, sourceCodeInfo);
|
|
2216
|
+
if (compareValue instanceof Promise) {
|
|
2217
|
+
throw new TypeError('Async functions cannot be used as sort comparators');
|
|
2218
|
+
}
|
|
2002
2219
|
assertNumber(compareValue, sourceCodeInfo, { finite: true });
|
|
2003
2220
|
return compareValue;
|
|
2004
2221
|
});
|
|
@@ -2016,7 +2233,11 @@ some(
|
|
|
2016
2233
|
else {
|
|
2017
2234
|
result.sort((a, b) => {
|
|
2018
2235
|
assertFunctionLike(comparer, sourceCodeInfo);
|
|
2019
|
-
|
|
2236
|
+
// Note: sort comparator must be synchronous
|
|
2237
|
+
const compareValue = _executeFunction(comparer, [a, b], _contextStack, sourceCodeInfo);
|
|
2238
|
+
if (compareValue instanceof Promise) {
|
|
2239
|
+
throw new TypeError('Async functions cannot be used as sort comparators');
|
|
2240
|
+
}
|
|
2020
2241
|
assertNumber(compareValue, sourceCodeInfo, { finite: true });
|
|
2021
2242
|
return compareValue;
|
|
2022
2243
|
});
|
|
@@ -2051,6 +2272,191 @@ sort(
|
|
|
2051
2272
|
sort(
|
|
2052
2273
|
[3, 1, 2],
|
|
2053
2274
|
(a, b) -> cond case a > b then -1 case a < b then 1 case true then -1 end
|
|
2275
|
+
)`,
|
|
2276
|
+
],
|
|
2277
|
+
},
|
|
2278
|
+
},
|
|
2279
|
+
'take': {
|
|
2280
|
+
evaluate: ([input, n], sourceCodeInfo) => {
|
|
2281
|
+
assertNumber(n, sourceCodeInfo);
|
|
2282
|
+
assertSeq(input, sourceCodeInfo);
|
|
2283
|
+
const num = Math.max(Math.ceil(n), 0);
|
|
2284
|
+
return input.slice(0, num);
|
|
2285
|
+
},
|
|
2286
|
+
arity: toFixedArity(2),
|
|
2287
|
+
docs: {
|
|
2288
|
+
category: 'sequence',
|
|
2289
|
+
returns: { type: 'sequence' },
|
|
2290
|
+
args: {
|
|
2291
|
+
a: { type: 'sequence' },
|
|
2292
|
+
b: { type: 'integer' },
|
|
2293
|
+
n: { type: 'integer' },
|
|
2294
|
+
seq: { type: 'sequence' },
|
|
2295
|
+
},
|
|
2296
|
+
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
2297
|
+
description: 'Constructs a new array/string with the $n first elements from $seq.',
|
|
2298
|
+
seeAlso: ['take-last', 'take-while', 'drop', 'slice', 'sequence.split-at'],
|
|
2299
|
+
examples: [
|
|
2300
|
+
'take([1, 2, 3, 4, 5], 3)',
|
|
2301
|
+
'[1, 2, 3, 4, 5] take 3',
|
|
2302
|
+
'take([1, 2, 3, 4, 5], 0)',
|
|
2303
|
+
'take("Albert", 2)',
|
|
2304
|
+
'take("Albert", 50)',
|
|
2305
|
+
],
|
|
2306
|
+
},
|
|
2307
|
+
},
|
|
2308
|
+
'take-last': {
|
|
2309
|
+
evaluate: ([array, n], sourceCodeInfo) => {
|
|
2310
|
+
assertSeq(array, sourceCodeInfo);
|
|
2311
|
+
assertNumber(n, sourceCodeInfo);
|
|
2312
|
+
const num = Math.max(Math.ceil(n), 0);
|
|
2313
|
+
const from = array.length - num;
|
|
2314
|
+
return array.slice(from);
|
|
2315
|
+
},
|
|
2316
|
+
arity: toFixedArity(2),
|
|
2317
|
+
docs: {
|
|
2318
|
+
category: 'sequence',
|
|
2319
|
+
returns: { type: 'sequence' },
|
|
2320
|
+
args: {
|
|
2321
|
+
a: { type: 'sequence' },
|
|
2322
|
+
b: { type: 'integer' },
|
|
2323
|
+
n: { type: 'integer' },
|
|
2324
|
+
seq: { type: 'sequence' },
|
|
2325
|
+
},
|
|
2326
|
+
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
2327
|
+
description: 'Constructs a new array with the $n last elements from $seq.',
|
|
2328
|
+
seeAlso: ['take', 'drop-last'],
|
|
2329
|
+
examples: [
|
|
2330
|
+
'take-last([1, 2, 3, 4, 5], 3)',
|
|
2331
|
+
'[1, 2, 3, 4, 5] take-last 3',
|
|
2332
|
+
'take-last([1, 2, 3, 4, 5], 0)',
|
|
2333
|
+
],
|
|
2334
|
+
},
|
|
2335
|
+
},
|
|
2336
|
+
'drop': {
|
|
2337
|
+
evaluate: ([input, n], sourceCodeInfo) => {
|
|
2338
|
+
assertNumber(n, sourceCodeInfo);
|
|
2339
|
+
const num = Math.max(Math.ceil(n), 0);
|
|
2340
|
+
assertSeq(input, sourceCodeInfo);
|
|
2341
|
+
return input.slice(num);
|
|
2342
|
+
},
|
|
2343
|
+
arity: toFixedArity(2),
|
|
2344
|
+
docs: {
|
|
2345
|
+
category: 'sequence',
|
|
2346
|
+
returns: { type: 'sequence' },
|
|
2347
|
+
args: {
|
|
2348
|
+
a: { type: 'sequence' },
|
|
2349
|
+
b: { type: 'integer' },
|
|
2350
|
+
seq: { type: 'sequence' },
|
|
2351
|
+
n: { type: 'integer' },
|
|
2352
|
+
},
|
|
2353
|
+
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
2354
|
+
description: 'Constructs a new array/string with the $n first elements dropped from $seq.',
|
|
2355
|
+
seeAlso: ['drop-last', 'drop-while', 'take', 'slice', 'sequence.split-at'],
|
|
2356
|
+
examples: [
|
|
2357
|
+
'drop([1, 2, 3, 4, 5], 3)',
|
|
2358
|
+
'[1, 2, 3, 4, 5] drop 0',
|
|
2359
|
+
'drop("Albert", 2)',
|
|
2360
|
+
'drop("Albert", 50)',
|
|
2361
|
+
],
|
|
2362
|
+
},
|
|
2363
|
+
},
|
|
2364
|
+
'drop-last': {
|
|
2365
|
+
evaluate: ([array, n], sourceCodeInfo) => {
|
|
2366
|
+
assertSeq(array, sourceCodeInfo);
|
|
2367
|
+
assertNumber(n, sourceCodeInfo);
|
|
2368
|
+
const num = Math.max(Math.ceil(n), 0);
|
|
2369
|
+
const from = array.length - num;
|
|
2370
|
+
return array.slice(0, from);
|
|
2371
|
+
},
|
|
2372
|
+
arity: toFixedArity(2),
|
|
2373
|
+
docs: {
|
|
2374
|
+
category: 'sequence',
|
|
2375
|
+
returns: { type: 'sequence' },
|
|
2376
|
+
args: {
|
|
2377
|
+
a: { type: 'sequence' },
|
|
2378
|
+
b: { type: 'integer' },
|
|
2379
|
+
seq: { type: 'sequence' },
|
|
2380
|
+
n: { type: 'integer' },
|
|
2381
|
+
},
|
|
2382
|
+
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
2383
|
+
description: 'Constructs a new array with the $n last elements dropped from $seq.',
|
|
2384
|
+
seeAlso: ['drop', 'take-last'],
|
|
2385
|
+
examples: [
|
|
2386
|
+
'drop-last([1, 2, 3, 4, 5], 3)',
|
|
2387
|
+
'[1, 2, 3, 4, 5] drop-last 3',
|
|
2388
|
+
'drop-last([1, 2, 3, 4, 5], 0)',
|
|
2389
|
+
],
|
|
2390
|
+
},
|
|
2391
|
+
},
|
|
2392
|
+
'take-while': {
|
|
2393
|
+
evaluate: ([seq, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
2394
|
+
assertSeq(seq, sourceCodeInfo);
|
|
2395
|
+
assertFunctionLike(fn, sourceCodeInfo);
|
|
2396
|
+
const arr = typeof seq === 'string' ? seq.split('') : Array.from(seq);
|
|
2397
|
+
// Find the first index where the predicate is false
|
|
2398
|
+
return chain(findIndexSequential(arr, elem => chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), result => !result)), (index) => {
|
|
2399
|
+
const taken = index === -1 ? arr : arr.slice(0, index);
|
|
2400
|
+
return typeof seq === 'string' ? taken.join('') : taken;
|
|
2401
|
+
});
|
|
2402
|
+
},
|
|
2403
|
+
arity: toFixedArity(2),
|
|
2404
|
+
docs: {
|
|
2405
|
+
category: 'sequence',
|
|
2406
|
+
returns: { type: 'sequence' },
|
|
2407
|
+
args: {
|
|
2408
|
+
a: { type: 'sequence' },
|
|
2409
|
+
b: { type: 'function' },
|
|
2410
|
+
seq: { type: 'sequence' },
|
|
2411
|
+
fun: { type: 'function' },
|
|
2412
|
+
},
|
|
2413
|
+
variants: [{ argumentNames: ['seq', 'fun'] }],
|
|
2414
|
+
description: 'Returns the members of $seq in order, stopping before the first one for which `predicate` returns a falsy value.',
|
|
2415
|
+
seeAlso: ['take', 'drop-while', 'sequence.split-with'],
|
|
2416
|
+
examples: [
|
|
2417
|
+
`take-while(
|
|
2418
|
+
[1, 2, 3, 2, 1],
|
|
2419
|
+
-> $ < 3
|
|
2420
|
+
)`,
|
|
2421
|
+
`take-while(
|
|
2422
|
+
[1, 2, 3, 2, 1],
|
|
2423
|
+
-> $ > 3
|
|
2424
|
+
)`,
|
|
2425
|
+
],
|
|
2426
|
+
},
|
|
2427
|
+
},
|
|
2428
|
+
'drop-while': {
|
|
2429
|
+
evaluate: ([seq, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
2430
|
+
assertSeq(seq, sourceCodeInfo);
|
|
2431
|
+
assertFunctionLike(fn, sourceCodeInfo);
|
|
2432
|
+
const arr = Array.isArray(seq) ? seq : seq.split('');
|
|
2433
|
+
return chain(findIndexSequential(arr, elem => chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), result => !result)), (from) => {
|
|
2434
|
+
if (from === -1)
|
|
2435
|
+
return typeof seq === 'string' ? '' : [];
|
|
2436
|
+
return typeof seq === 'string' ? arr.slice(from).join('') : seq.slice(from);
|
|
2437
|
+
});
|
|
2438
|
+
},
|
|
2439
|
+
arity: toFixedArity(2),
|
|
2440
|
+
docs: {
|
|
2441
|
+
category: 'sequence',
|
|
2442
|
+
returns: { type: 'sequence' },
|
|
2443
|
+
args: {
|
|
2444
|
+
a: { type: 'sequence' },
|
|
2445
|
+
b: { type: 'function' },
|
|
2446
|
+
seq: { type: 'sequence' },
|
|
2447
|
+
fun: { type: 'function' },
|
|
2448
|
+
},
|
|
2449
|
+
variants: [{ argumentNames: ['seq', 'fun'] }],
|
|
2450
|
+
description: 'Returns the members of $seq in order, skipping the fist elements for witch the `predicate` returns a truethy value.',
|
|
2451
|
+
seeAlso: ['drop', 'take-while', 'sequence.split-with'],
|
|
2452
|
+
examples: [
|
|
2453
|
+
`drop-while(
|
|
2454
|
+
[1, 2, 3, 2, 1],
|
|
2455
|
+
-> $ < 3
|
|
2456
|
+
)`,
|
|
2457
|
+
`drop-while(
|
|
2458
|
+
[1, 2, 3, 2, 1],
|
|
2459
|
+
-> $ > 3
|
|
2054
2460
|
)`,
|
|
2055
2461
|
],
|
|
2056
2462
|
},
|
|
@@ -2987,7 +3393,7 @@ const miscNormalExpression = {
|
|
|
2987
3393
|
{ argumentNames: ['x', 'ys'] },
|
|
2988
3394
|
],
|
|
2989
3395
|
description: 'Returns `true` if all `values` are structaul equal to each other, otherwise result is `false`.',
|
|
2990
|
-
seeAlso: ['
|
|
3396
|
+
seeAlso: ['!=', 'identical?'],
|
|
2991
3397
|
examples: [
|
|
2992
3398
|
'1 == 1',
|
|
2993
3399
|
'[1, 2] == [1, 2]',
|
|
@@ -3009,7 +3415,7 @@ const miscNormalExpression = {
|
|
|
3009
3415
|
],
|
|
3010
3416
|
},
|
|
3011
3417
|
},
|
|
3012
|
-
'
|
|
3418
|
+
'!=': {
|
|
3013
3419
|
evaluate: (params, sourceCodeInfo) => {
|
|
3014
3420
|
return !isEqual(params, sourceCodeInfo);
|
|
3015
3421
|
},
|
|
@@ -3027,15 +3433,15 @@ const miscNormalExpression = {
|
|
|
3027
3433
|
{ argumentNames: ['x'] },
|
|
3028
3434
|
{ argumentNames: ['x', 'ys'] },
|
|
3029
3435
|
],
|
|
3030
|
-
description: 'Returns `true` if all `values` are not equal to each other, otherwise result is `false`. `(
|
|
3436
|
+
description: 'Returns `true` if all `values` are not equal to each other, otherwise result is `false`. `(!= a b c)` is same as `(not (== a b c))`.',
|
|
3031
3437
|
seeAlso: ['==', 'identical?'],
|
|
3032
3438
|
examples: [
|
|
3033
|
-
'1
|
|
3034
|
-
'3
|
|
3035
|
-
'
|
|
3036
|
-
'
|
|
3037
|
-
'
|
|
3038
|
-
'
|
|
3439
|
+
'1 != 2',
|
|
3440
|
+
'3 != 3',
|
|
3441
|
+
'!=(3)',
|
|
3442
|
+
'!=(3, 3, 2)',
|
|
3443
|
+
'!=("3", "2", "1", "0",)',
|
|
3444
|
+
'!=(0, -0)',
|
|
3039
3445
|
],
|
|
3040
3446
|
},
|
|
3041
3447
|
},
|
|
@@ -3053,7 +3459,7 @@ const miscNormalExpression = {
|
|
|
3053
3459
|
},
|
|
3054
3460
|
variants: [{ argumentNames: ['a', 'b'] }],
|
|
3055
3461
|
description: 'Returns true if $a and $b are referential equal.',
|
|
3056
|
-
seeAlso: ['==', '
|
|
3462
|
+
seeAlso: ['==', '!='],
|
|
3057
3463
|
examples: [
|
|
3058
3464
|
'identical?({ a: 10, b: 20 }, { b: 20, a: 10 })',
|
|
3059
3465
|
'identical?([1, true, null], [1, true, null])',
|
|
@@ -3204,7 +3610,7 @@ const miscNormalExpression = {
|
|
|
3204
3610
|
],
|
|
3205
3611
|
},
|
|
3206
3612
|
},
|
|
3207
|
-
'
|
|
3613
|
+
'not': {
|
|
3208
3614
|
evaluate: ([first]) => !first,
|
|
3209
3615
|
arity: toFixedArity(1),
|
|
3210
3616
|
docs: {
|
|
@@ -3215,13 +3621,13 @@ const miscNormalExpression = {
|
|
|
3215
3621
|
description: 'Computes logical negation. Note that any other $x than `false`, `0`, `null` and `\'\'` is truthy.',
|
|
3216
3622
|
seeAlso: ['boolean'],
|
|
3217
3623
|
examples: [
|
|
3218
|
-
'
|
|
3219
|
-
'
|
|
3220
|
-
'
|
|
3221
|
-
'
|
|
3222
|
-
'
|
|
3223
|
-
'
|
|
3224
|
-
'
|
|
3624
|
+
'not(3)',
|
|
3625
|
+
'not(true)',
|
|
3626
|
+
'not("A string")',
|
|
3627
|
+
'not(0)',
|
|
3628
|
+
'not(false)',
|
|
3629
|
+
'not(null)',
|
|
3630
|
+
'not("")',
|
|
3225
3631
|
],
|
|
3226
3632
|
},
|
|
3227
3633
|
},
|
|
@@ -3302,7 +3708,7 @@ const miscNormalExpression = {
|
|
|
3302
3708
|
args: { x: { type: 'any' } },
|
|
3303
3709
|
variants: [{ argumentNames: ['x'] }],
|
|
3304
3710
|
description: 'Coerces $x to boolean.',
|
|
3305
|
-
seeAlso: ['
|
|
3711
|
+
seeAlso: ['not', 'boolean?', 'true?', 'false?'],
|
|
3306
3712
|
examples: [
|
|
3307
3713
|
'boolean(0)',
|
|
3308
3714
|
'boolean(1)',
|
|
@@ -3611,17 +4017,23 @@ If no arguments are provided \`null\` is returned.`,
|
|
|
3611
4017
|
const rest = params.slice(1, -1);
|
|
3612
4018
|
assertObj(first, sourceCodeInfo);
|
|
3613
4019
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
3614
|
-
return rest
|
|
4020
|
+
return reduceSequential(rest, (result, obj) => {
|
|
3615
4021
|
assertObj(obj, sourceCodeInfo);
|
|
3616
|
-
Object.entries(obj)
|
|
4022
|
+
const entries = Object.entries(obj);
|
|
4023
|
+
return chain(reduceSequential(entries, (res, entry) => {
|
|
3617
4024
|
const key = asString(entry[0], sourceCodeInfo);
|
|
3618
4025
|
const val = toAny(entry[1]);
|
|
3619
|
-
if (collHasKey(
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
4026
|
+
if (collHasKey(res, key)) {
|
|
4027
|
+
return chain(executeFunction(fn, [res[key], val], contextStack, sourceCodeInfo), (merged) => {
|
|
4028
|
+
res[key] = merged;
|
|
4029
|
+
return res;
|
|
4030
|
+
});
|
|
4031
|
+
}
|
|
4032
|
+
else {
|
|
4033
|
+
res[key] = val;
|
|
4034
|
+
return res;
|
|
4035
|
+
}
|
|
4036
|
+
}, result), r => r);
|
|
3625
4037
|
}, { ...first });
|
|
3626
4038
|
},
|
|
3627
4039
|
arity: { min: 2 },
|
|
@@ -5043,13 +5455,11 @@ const andSpecialExpression = {
|
|
|
5043
5455
|
arity: {},
|
|
5044
5456
|
docs: docs$f,
|
|
5045
5457
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
}
|
|
5052
|
-
return value;
|
|
5458
|
+
return reduceSequential(node[1][1], (acc, param) => {
|
|
5459
|
+
if (!acc)
|
|
5460
|
+
return acc;
|
|
5461
|
+
return evaluateNode(param, contextStack);
|
|
5462
|
+
}, true);
|
|
5053
5463
|
},
|
|
5054
5464
|
evaluateAsNormalExpression: (params, sourceCodeInfo) => {
|
|
5055
5465
|
let value = true;
|
|
@@ -5095,13 +5505,17 @@ const condSpecialExpression = {
|
|
|
5095
5505
|
docs: docs$e,
|
|
5096
5506
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5097
5507
|
const params = node[1][1];
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
return evaluateNode(
|
|
5508
|
+
function processCase(index) {
|
|
5509
|
+
if (index >= params.length)
|
|
5510
|
+
return null;
|
|
5511
|
+
const [test, form] = params[index];
|
|
5512
|
+
return chain(evaluateNode(test, contextStack), (value) => {
|
|
5513
|
+
if (!value)
|
|
5514
|
+
return processCase(index + 1);
|
|
5515
|
+
return evaluateNode(form, contextStack);
|
|
5516
|
+
});
|
|
5103
5517
|
}
|
|
5104
|
-
return
|
|
5518
|
+
return processCase(0);
|
|
5105
5519
|
},
|
|
5106
5520
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1].flat(), contextStack, builtin, evaluateNode),
|
|
5107
5521
|
};
|
|
@@ -5139,14 +5553,20 @@ const switchSpecialExpression = {
|
|
|
5139
5553
|
docs: docs$d,
|
|
5140
5554
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5141
5555
|
const [, switchValueNode, cases] = node[1];
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5556
|
+
return chain(evaluateNode(switchValueNode, contextStack), (switchValue) => {
|
|
5557
|
+
function processCase(index) {
|
|
5558
|
+
if (index >= cases.length)
|
|
5559
|
+
return null;
|
|
5560
|
+
const [test, form] = cases[index];
|
|
5561
|
+
return chain(evaluateNode(test, contextStack), (value) => {
|
|
5562
|
+
if (value === switchValue) {
|
|
5563
|
+
return evaluateNode(form, contextStack);
|
|
5564
|
+
}
|
|
5565
|
+
return processCase(index + 1);
|
|
5566
|
+
});
|
|
5147
5567
|
}
|
|
5148
|
-
|
|
5149
|
-
|
|
5568
|
+
return processCase(0);
|
|
5569
|
+
});
|
|
5150
5570
|
},
|
|
5151
5571
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols([node[1][1], ...node[1][2].flat()], contextStack, builtin, evaluateNode),
|
|
5152
5572
|
};
|
|
@@ -5226,37 +5646,47 @@ function walkDefaults(bindingTarget, onDefault) {
|
|
|
5226
5646
|
function evaluateBindingNodeValues(target, value, evaluate) {
|
|
5227
5647
|
const sourceCodeInfo = target[2];
|
|
5228
5648
|
const record = {};
|
|
5229
|
-
createRecord(target, value, evaluate, sourceCodeInfo, record);
|
|
5230
|
-
return record;
|
|
5649
|
+
return chain(createRecord(target, value, evaluate, sourceCodeInfo, record), () => record);
|
|
5231
5650
|
}
|
|
5232
5651
|
function createRecord(bindingTarget, value, evaluate, sourceCodeInfo, record) {
|
|
5233
5652
|
if (bindingTarget[0] === bindingTargetTypes.object) {
|
|
5234
5653
|
assertUnknownRecord(value, sourceCodeInfo);
|
|
5235
5654
|
const capturedKeys = new Set();
|
|
5236
5655
|
let restElement;
|
|
5237
|
-
Object.entries(bindingTarget[1][0])
|
|
5656
|
+
const entries = Object.entries(bindingTarget[1][0]);
|
|
5657
|
+
return chain(forEachSequential(entries, ([key, element]) => {
|
|
5238
5658
|
if (element[0] === bindingTargetTypes.rest) {
|
|
5239
5659
|
restElement = element;
|
|
5240
5660
|
return;
|
|
5241
5661
|
}
|
|
5242
5662
|
capturedKeys.add(key);
|
|
5243
|
-
const
|
|
5244
|
-
|
|
5245
|
-
|
|
5663
|
+
const existingVal = value[key];
|
|
5664
|
+
const maybeVal = existingVal !== undefined
|
|
5665
|
+
? existingVal
|
|
5666
|
+
: element[1][1]
|
|
5667
|
+
? evaluate(element[1][1])
|
|
5668
|
+
: null;
|
|
5669
|
+
return chain(maybeVal, (resolvedVal) => {
|
|
5670
|
+
const val = resolvedVal ?? null;
|
|
5671
|
+
assertAny(val, sourceCodeInfo);
|
|
5672
|
+
return createRecord(element, val, evaluate, sourceCodeInfo, record);
|
|
5673
|
+
});
|
|
5674
|
+
}), () => {
|
|
5675
|
+
if (restElement) {
|
|
5676
|
+
const restValues = Object.entries(value)
|
|
5677
|
+
.filter(([key]) => !capturedKeys.has(key))
|
|
5678
|
+
.reduce((acc, [key, val]) => {
|
|
5679
|
+
acc[key] = asAny(val);
|
|
5680
|
+
return acc;
|
|
5681
|
+
}, {});
|
|
5682
|
+
record[restElement[1][0]] = restValues;
|
|
5683
|
+
}
|
|
5246
5684
|
});
|
|
5247
|
-
if (restElement) {
|
|
5248
|
-
const restValues = Object.entries(value)
|
|
5249
|
-
.filter(([key]) => !capturedKeys.has(key))
|
|
5250
|
-
.reduce((acc, [key, val]) => {
|
|
5251
|
-
acc[key] = asAny(val);
|
|
5252
|
-
return acc;
|
|
5253
|
-
}, {});
|
|
5254
|
-
record[restElement[1][0]] = restValues;
|
|
5255
|
-
}
|
|
5256
5685
|
}
|
|
5257
5686
|
else if (bindingTarget[0] === bindingTargetTypes.array) {
|
|
5258
5687
|
let restIndex = null;
|
|
5259
5688
|
assertArray(value, sourceCodeInfo);
|
|
5689
|
+
const elements = [];
|
|
5260
5690
|
for (let index = 0; index < bindingTarget[1][0].length; index += 1) {
|
|
5261
5691
|
const element = bindingTarget[1][0][index] ?? null;
|
|
5262
5692
|
if (element === null) {
|
|
@@ -5266,15 +5696,27 @@ function createRecord(bindingTarget, value, evaluate, sourceCodeInfo, record) {
|
|
|
5266
5696
|
restIndex = index;
|
|
5267
5697
|
break;
|
|
5268
5698
|
}
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5272
|
-
|
|
5273
|
-
|
|
5274
|
-
|
|
5275
|
-
|
|
5276
|
-
|
|
5277
|
-
|
|
5699
|
+
elements.push({ element, index });
|
|
5700
|
+
}
|
|
5701
|
+
return chain(forEachSequential(elements, ({ element, index }) => {
|
|
5702
|
+
const existingVal = value[index];
|
|
5703
|
+
const maybeVal = existingVal !== undefined
|
|
5704
|
+
? existingVal
|
|
5705
|
+
: element[1][1]
|
|
5706
|
+
? evaluate(element[1][1])
|
|
5707
|
+
: null;
|
|
5708
|
+
return chain(maybeVal, (resolvedVal) => {
|
|
5709
|
+
const val = resolvedVal ?? null;
|
|
5710
|
+
assertAny(val, sourceCodeInfo);
|
|
5711
|
+
return createRecord(element, val, evaluate, sourceCodeInfo, record);
|
|
5712
|
+
});
|
|
5713
|
+
}), () => {
|
|
5714
|
+
if (restIndex !== null) {
|
|
5715
|
+
const restValues = value.slice(restIndex);
|
|
5716
|
+
const restElement = bindingTarget[1][0][restIndex];
|
|
5717
|
+
record[restElement[1][0]] = restValues;
|
|
5718
|
+
}
|
|
5719
|
+
});
|
|
5278
5720
|
}
|
|
5279
5721
|
else if (bindingTarget[0] === bindingTargetTypes.rest) {
|
|
5280
5722
|
record[bindingTarget[1][0]] = asAny(value);
|
|
@@ -5322,10 +5764,12 @@ const defSpecialExpression = {
|
|
|
5322
5764
|
const bindingNode = node[1][1];
|
|
5323
5765
|
const target = bindingNode[1][0];
|
|
5324
5766
|
const value = bindingNode[1][1];
|
|
5325
|
-
|
|
5326
|
-
|
|
5327
|
-
|
|
5328
|
-
|
|
5767
|
+
return chain(evaluateNode(value, contextStack), (bindingValue) => {
|
|
5768
|
+
return chain(evaluateBindingNodeValues(target, bindingValue, Node => evaluateNode(Node, contextStack)), (values) => {
|
|
5769
|
+
contextStack.exportValues(values, target[2]);
|
|
5770
|
+
return bindingValue;
|
|
5771
|
+
});
|
|
5772
|
+
});
|
|
5329
5773
|
},
|
|
5330
5774
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
|
|
5331
5775
|
const bindingNode = node[1][1];
|
|
@@ -5362,10 +5806,7 @@ const doSpecialExpression = {
|
|
|
5362
5806
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5363
5807
|
const newContext = {};
|
|
5364
5808
|
const newContextStack = contextStack.create(newContext);
|
|
5365
|
-
|
|
5366
|
-
for (const form of node[1][1])
|
|
5367
|
-
result = evaluateNode(form, newContextStack);
|
|
5368
|
-
return result;
|
|
5809
|
+
return reduceSequential(node[1][1], (_acc, form) => evaluateNode(form, newContextStack), null);
|
|
5369
5810
|
},
|
|
5370
5811
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
|
|
5371
5812
|
return getUndefinedSymbols(node[1][1], contextStack.create({}), builtin, evaluateNode);
|
|
@@ -5460,13 +5901,15 @@ const ifSpecialExpression = {
|
|
|
5460
5901
|
docs: docs$a,
|
|
5461
5902
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5462
5903
|
const [conditionNode, trueNode, falseNode] = node[1][1];
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5904
|
+
return chain(evaluateNode(conditionNode, contextStack), (condition) => {
|
|
5905
|
+
if (condition) {
|
|
5906
|
+
return evaluateNode(trueNode, contextStack);
|
|
5907
|
+
}
|
|
5908
|
+
else if (falseNode) {
|
|
5909
|
+
return evaluateNode(falseNode, contextStack);
|
|
5910
|
+
}
|
|
5911
|
+
return null;
|
|
5912
|
+
});
|
|
5470
5913
|
},
|
|
5471
5914
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1].filter(n => !!n), contextStack, builtin, evaluateNode),
|
|
5472
5915
|
};
|
|
@@ -5497,13 +5940,15 @@ const unlessSpecialExpression = {
|
|
|
5497
5940
|
docs: docs$9,
|
|
5498
5941
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5499
5942
|
const [conditionNode, trueNode, falseNode] = node[1][1];
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5943
|
+
return chain(evaluateNode(conditionNode, contextStack), (condition) => {
|
|
5944
|
+
if (!condition) {
|
|
5945
|
+
return evaluateNode(trueNode, contextStack);
|
|
5946
|
+
}
|
|
5947
|
+
else if (falseNode) {
|
|
5948
|
+
return evaluateNode(falseNode, contextStack);
|
|
5949
|
+
}
|
|
5950
|
+
return null;
|
|
5951
|
+
});
|
|
5507
5952
|
},
|
|
5508
5953
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => getUndefinedSymbols(node[1][1].filter(n => !!n), contextStack, builtin, evaluateNode),
|
|
5509
5954
|
};
|
|
@@ -5529,10 +5974,12 @@ const letSpecialExpression = {
|
|
|
5529
5974
|
const bindingNode = node[1][1];
|
|
5530
5975
|
const target = bindingNode[1][0];
|
|
5531
5976
|
const value = bindingNode[1][1];
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5977
|
+
return chain(evaluateNode(value, contextStack), (bindingValue) => {
|
|
5978
|
+
return chain(evaluateBindingNodeValues(target, bindingValue, Node => evaluateNode(Node, contextStack)), (values) => {
|
|
5979
|
+
contextStack.addValues(values, target[2]);
|
|
5980
|
+
return bindingValue;
|
|
5981
|
+
});
|
|
5982
|
+
});
|
|
5536
5983
|
},
|
|
5537
5984
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
|
|
5538
5985
|
const bindingNode = node[1][1];
|
|
@@ -5579,39 +6026,93 @@ const loopSpecialExpression = {
|
|
|
5579
6026
|
docs: docs$7,
|
|
5580
6027
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5581
6028
|
const bindingNodes = node[1][1];
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
6029
|
+
// Set up initial binding context sequentially (bindings may depend on each other)
|
|
6030
|
+
const initialContext = {};
|
|
6031
|
+
const setupBindings = reduceSequential(bindingNodes, (result, bindingNode) => {
|
|
6032
|
+
return chain(evaluateNode(bindingNode[1][1], contextStack.create(result)), (val) => {
|
|
6033
|
+
return chain(evaluateBindingNodeValues(bindingNode[1][0], val, Node => evaluateNode(Node, contextStack)), (valueRecord) => {
|
|
6034
|
+
Object.entries(valueRecord).forEach(([name, value]) => {
|
|
6035
|
+
result[name] = { value };
|
|
6036
|
+
});
|
|
6037
|
+
return result;
|
|
6038
|
+
});
|
|
5587
6039
|
});
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
if (error instanceof RecurSignal) {
|
|
5599
|
-
const params = error.params;
|
|
5600
|
-
if (params.length !== bindingNodes.length) {
|
|
5601
|
-
throw new LitsError(`recur expected ${bindingNodes.length} parameters, got ${valueToString(params.length)}`, node[2]);
|
|
5602
|
-
}
|
|
5603
|
-
bindingNodes.forEach((bindingNode, index) => {
|
|
5604
|
-
const valueRecord = evaluateBindingNodeValues(bindingNode[1][0], asAny(params[index]), Node => evaluateNode(Node, contextStack));
|
|
6040
|
+
}, initialContext);
|
|
6041
|
+
return chain(setupBindings, (bindingContext) => {
|
|
6042
|
+
const newContextStack = contextStack.create(bindingContext);
|
|
6043
|
+
const body = node[1][2];
|
|
6044
|
+
function rebindAndIterate(params) {
|
|
6045
|
+
if (params.length !== bindingNodes.length) {
|
|
6046
|
+
throw new LitsError(`recur expected ${bindingNodes.length} parameters, got ${valueToString(params.length)}`, node[2]);
|
|
6047
|
+
}
|
|
6048
|
+
return chain(forEachSequential(bindingNodes, (bindingNode, index) => {
|
|
6049
|
+
return chain(evaluateBindingNodeValues(bindingNode[1][0], asAny(params[index]), Node => evaluateNode(Node, contextStack)), (valueRecord) => {
|
|
5605
6050
|
for (const [name, value] of Object.entries(valueRecord)) {
|
|
5606
6051
|
bindingContext[name].value = value;
|
|
5607
6052
|
}
|
|
5608
6053
|
});
|
|
5609
|
-
|
|
6054
|
+
}), () => iterate());
|
|
6055
|
+
}
|
|
6056
|
+
function iterate() {
|
|
6057
|
+
return tryCatch(() => evaluateNode(body, newContextStack), (error) => {
|
|
6058
|
+
if (error instanceof RecurSignal) {
|
|
6059
|
+
return rebindAndIterate(error.params);
|
|
6060
|
+
}
|
|
6061
|
+
throw error;
|
|
6062
|
+
});
|
|
6063
|
+
}
|
|
6064
|
+
// Use sync for(;;) loop for the sync case to avoid stack overflow
|
|
6065
|
+
for (;;) {
|
|
6066
|
+
try {
|
|
6067
|
+
const result = evaluateNode(body, newContextStack);
|
|
6068
|
+
if (result instanceof Promise) {
|
|
6069
|
+
// Async path: handle recur via promise chain
|
|
6070
|
+
return result.catch((error) => {
|
|
6071
|
+
if (error instanceof RecurSignal) {
|
|
6072
|
+
return rebindAndIterate(error.params);
|
|
6073
|
+
}
|
|
6074
|
+
throw error;
|
|
6075
|
+
});
|
|
6076
|
+
}
|
|
6077
|
+
return result;
|
|
6078
|
+
}
|
|
6079
|
+
catch (error) {
|
|
6080
|
+
if (error instanceof RecurSignal) {
|
|
6081
|
+
const params = error.params;
|
|
6082
|
+
if (params.length !== bindingNodes.length) {
|
|
6083
|
+
throw new LitsError(`recur expected ${bindingNodes.length} parameters, got ${valueToString(params.length)}`, node[2]);
|
|
6084
|
+
}
|
|
6085
|
+
// rebindAndIterate returns MaybePromise — if any binding default is async,
|
|
6086
|
+
// we must switch to the async iterate path
|
|
6087
|
+
for (let index = 0; index < bindingNodes.length; index += 1) {
|
|
6088
|
+
const bindingNode = bindingNodes[index];
|
|
6089
|
+
const valueRecord = evaluateBindingNodeValues(bindingNode[1][0], asAny(params[index]), Node => evaluateNode(Node, contextStack));
|
|
6090
|
+
if (valueRecord instanceof Promise) {
|
|
6091
|
+
// Switch to fully async path
|
|
6092
|
+
return valueRecord.then((resolved) => {
|
|
6093
|
+
for (const [name, value] of Object.entries(resolved)) {
|
|
6094
|
+
bindingContext[name].value = value;
|
|
6095
|
+
}
|
|
6096
|
+
// Handle remaining bindings then iterate
|
|
6097
|
+
return chain(forEachSequential(bindingNodes.slice(index + 1), (bn, subIndex) => {
|
|
6098
|
+
return chain(evaluateBindingNodeValues(bn[1][0], asAny(params[index + 1 + subIndex]), Node => evaluateNode(Node, contextStack)), (vr) => {
|
|
6099
|
+
for (const [name, value] of Object.entries(vr)) {
|
|
6100
|
+
bindingContext[name].value = value;
|
|
6101
|
+
}
|
|
6102
|
+
});
|
|
6103
|
+
}), () => iterate());
|
|
6104
|
+
});
|
|
6105
|
+
}
|
|
6106
|
+
for (const [name, value] of Object.entries(valueRecord)) {
|
|
6107
|
+
bindingContext[name].value = value;
|
|
6108
|
+
}
|
|
6109
|
+
}
|
|
6110
|
+
continue;
|
|
6111
|
+
}
|
|
6112
|
+
throw error;
|
|
5610
6113
|
}
|
|
5611
|
-
throw error;
|
|
5612
6114
|
}
|
|
5613
|
-
|
|
5614
|
-
}
|
|
6115
|
+
});
|
|
5615
6116
|
},
|
|
5616
6117
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
|
|
5617
6118
|
const bindingNodes = node[1][1];
|
|
@@ -5631,74 +6132,107 @@ const loopSpecialExpression = {
|
|
|
5631
6132
|
};
|
|
5632
6133
|
|
|
5633
6134
|
function addToContext(bindings, context, contextStack, evaluateNode) {
|
|
6135
|
+
let bindingChain = undefined;
|
|
5634
6136
|
for (const bindingNode of bindings) {
|
|
5635
|
-
|
|
5636
|
-
|
|
5637
|
-
|
|
5638
|
-
|
|
5639
|
-
|
|
6137
|
+
bindingChain = chain(bindingChain, () => {
|
|
6138
|
+
const [target, bindingValue] = bindingNode[1];
|
|
6139
|
+
return chain(evaluateNode(bindingValue, contextStack), (val) => {
|
|
6140
|
+
return chain(evaluateBindingNodeValues(target, val, Node => evaluateNode(Node, contextStack)), (valueRecord) => {
|
|
6141
|
+
Object.entries(valueRecord).forEach(([name, value]) => {
|
|
6142
|
+
context[name] = { value };
|
|
6143
|
+
});
|
|
6144
|
+
});
|
|
6145
|
+
});
|
|
5640
6146
|
});
|
|
5641
6147
|
}
|
|
6148
|
+
return bindingChain;
|
|
5642
6149
|
}
|
|
5643
6150
|
function evaluateLoop(returnResult, loopNode, contextStack, evaluateNode) {
|
|
5644
6151
|
const sourceCodeInfo = loopNode[2];
|
|
5645
6152
|
const [, loopBindings, body] = loopNode[1];
|
|
5646
6153
|
const result = [];
|
|
5647
6154
|
const bindingIndices = loopBindings.map(() => 0);
|
|
5648
|
-
|
|
5649
|
-
while (!abort) {
|
|
6155
|
+
function processIteration() {
|
|
5650
6156
|
const context = {};
|
|
5651
6157
|
const newContextStack = contextStack.create(context);
|
|
5652
|
-
|
|
5653
|
-
|
|
6158
|
+
function processBinding(bindingIndex) {
|
|
6159
|
+
if (bindingIndex >= loopBindings.length)
|
|
6160
|
+
return 'continue';
|
|
5654
6161
|
const [bindingNode, letBindings, whenNode, whileNode] = loopBindings[bindingIndex];
|
|
5655
6162
|
const [targetNode, valueNode] = bindingNode[1];
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
|
|
5660
|
-
|
|
5661
|
-
break;
|
|
5662
|
-
}
|
|
5663
|
-
const index = asNonUndefined(bindingIndices[bindingIndex], sourceCodeInfo);
|
|
5664
|
-
if (index >= seq.length) {
|
|
5665
|
-
skip = true;
|
|
5666
|
-
if (bindingIndex === 0) {
|
|
5667
|
-
abort = true;
|
|
5668
|
-
break;
|
|
6163
|
+
return chain(evaluateNode(valueNode, newContextStack), (rawColl) => {
|
|
6164
|
+
const coll = asColl(rawColl, sourceCodeInfo);
|
|
6165
|
+
const seq = isSeq(coll) ? coll : Object.entries(coll);
|
|
6166
|
+
if (seq.length === 0) {
|
|
6167
|
+
return 'abort';
|
|
5669
6168
|
}
|
|
5670
|
-
bindingIndices[bindingIndex]
|
|
5671
|
-
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
6169
|
+
const index = asNonUndefined(bindingIndices[bindingIndex], sourceCodeInfo);
|
|
6170
|
+
if (index >= seq.length) {
|
|
6171
|
+
if (bindingIndex === 0) {
|
|
6172
|
+
return 'abort';
|
|
6173
|
+
}
|
|
6174
|
+
bindingIndices[bindingIndex] = 0;
|
|
6175
|
+
bindingIndices[bindingIndex - 1] = asNonUndefined(bindingIndices[bindingIndex - 1], sourceCodeInfo) + 1;
|
|
6176
|
+
return 'skip';
|
|
6177
|
+
}
|
|
6178
|
+
const val = asAny(seq[index], sourceCodeInfo);
|
|
6179
|
+
return chain(evaluateBindingNodeValues(targetNode, val, Node => evaluateNode(Node, newContextStack)), (valueRecord) => {
|
|
6180
|
+
Object.entries(valueRecord).forEach(([name, value]) => {
|
|
6181
|
+
context[name] = { value };
|
|
6182
|
+
});
|
|
6183
|
+
return chain(letBindings.length > 0
|
|
6184
|
+
? addToContext(letBindings, context, newContextStack, evaluateNode)
|
|
6185
|
+
: undefined, () => {
|
|
6186
|
+
if (whenNode) {
|
|
6187
|
+
return chain(evaluateNode(whenNode, newContextStack), (whenResult) => {
|
|
6188
|
+
if (!whenResult) {
|
|
6189
|
+
bindingIndices[bindingIndex] = asNonUndefined(bindingIndices[bindingIndex], sourceCodeInfo) + 1;
|
|
6190
|
+
return 'skip';
|
|
6191
|
+
}
|
|
6192
|
+
if (whileNode) {
|
|
6193
|
+
return chain(evaluateNode(whileNode, newContextStack), (whileResult) => {
|
|
6194
|
+
if (!whileResult) {
|
|
6195
|
+
bindingIndices[bindingIndex] = Number.POSITIVE_INFINITY;
|
|
6196
|
+
return 'skip';
|
|
6197
|
+
}
|
|
6198
|
+
return processBinding(bindingIndex + 1);
|
|
6199
|
+
});
|
|
6200
|
+
}
|
|
6201
|
+
return processBinding(bindingIndex + 1);
|
|
6202
|
+
});
|
|
6203
|
+
}
|
|
6204
|
+
if (whileNode) {
|
|
6205
|
+
return chain(evaluateNode(whileNode, newContextStack), (whileResult) => {
|
|
6206
|
+
if (!whileResult) {
|
|
6207
|
+
bindingIndices[bindingIndex] = Number.POSITIVE_INFINITY;
|
|
6208
|
+
return 'skip';
|
|
6209
|
+
}
|
|
6210
|
+
return processBinding(bindingIndex + 1);
|
|
6211
|
+
});
|
|
6212
|
+
}
|
|
6213
|
+
return processBinding(bindingIndex + 1);
|
|
6214
|
+
});
|
|
6215
|
+
});
|
|
5678
6216
|
});
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
bindingIndices[bindingIndex] = asNonUndefined(bindingIndices[bindingIndex], sourceCodeInfo) + 1;
|
|
5684
|
-
skip = true;
|
|
5685
|
-
break bindingsLoop;
|
|
6217
|
+
}
|
|
6218
|
+
return chain(processBinding(0), (status) => {
|
|
6219
|
+
if (status === 'abort') {
|
|
6220
|
+
return returnResult ? result : null;
|
|
5686
6221
|
}
|
|
5687
|
-
if (
|
|
5688
|
-
|
|
5689
|
-
skip = true;
|
|
5690
|
-
break bindingsLoop;
|
|
6222
|
+
if (status === 'skip') {
|
|
6223
|
+
return processIteration();
|
|
5691
6224
|
}
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
6225
|
+
// status === 'continue'
|
|
6226
|
+
return chain(evaluateNode(body, newContextStack), (value) => {
|
|
6227
|
+
if (returnResult)
|
|
6228
|
+
result.push(value);
|
|
6229
|
+
if (bindingIndices.length > 0)
|
|
6230
|
+
bindingIndices[bindingIndices.length - 1] += 1;
|
|
6231
|
+
return processIteration();
|
|
6232
|
+
});
|
|
6233
|
+
});
|
|
5700
6234
|
}
|
|
5701
|
-
return
|
|
6235
|
+
return processIteration();
|
|
5702
6236
|
}
|
|
5703
6237
|
function analyze(loopNode, contextStack, getUndefinedSymbols, builtin, evaluateNode) {
|
|
5704
6238
|
const result = new Set();
|
|
@@ -5787,8 +6321,7 @@ const doseqSpecialExpression = {
|
|
|
5787
6321
|
arity: toFixedArity(1),
|
|
5788
6322
|
docs: doseqDocs,
|
|
5789
6323
|
evaluate: (node, contextStack, helpers) => {
|
|
5790
|
-
evaluateLoop(false, node, contextStack, helpers.evaluateNode);
|
|
5791
|
-
return null;
|
|
6324
|
+
return chain(evaluateLoop(false, node, contextStack, helpers.evaluateNode), () => null);
|
|
5792
6325
|
},
|
|
5793
6326
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => analyze(node, contextStack, getUndefinedSymbols, builtin, evaluateNode),
|
|
5794
6327
|
};
|
|
@@ -5828,13 +6361,11 @@ const orSpecialExpression = {
|
|
|
5828
6361
|
arity: {},
|
|
5829
6362
|
docs: docs$6,
|
|
5830
6363
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5831
|
-
|
|
5832
|
-
|
|
5833
|
-
|
|
5834
|
-
|
|
5835
|
-
|
|
5836
|
-
}
|
|
5837
|
-
return value;
|
|
6364
|
+
return reduceSequential(node[1][1], (acc, param) => {
|
|
6365
|
+
if (acc)
|
|
6366
|
+
return acc;
|
|
6367
|
+
return evaluateNode(param, contextStack);
|
|
6368
|
+
}, false);
|
|
5838
6369
|
},
|
|
5839
6370
|
evaluateAsNormalExpression: (params, sourceCodeInfo) => {
|
|
5840
6371
|
let value = false;
|
|
@@ -5887,16 +6418,21 @@ const qqSpecialExpression = {
|
|
|
5887
6418
|
arity: { min: 1 },
|
|
5888
6419
|
docs: docs$5,
|
|
5889
6420
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5890
|
-
|
|
6421
|
+
// Use a sentinel to know we haven't found a non-null value yet
|
|
6422
|
+
const SENTINEL = Symbol('qq-sentinel');
|
|
6423
|
+
return chain(reduceSequential(node[1][1], (acc, param) => {
|
|
6424
|
+
if (acc !== SENTINEL)
|
|
6425
|
+
return acc;
|
|
5891
6426
|
if (isUserDefinedSymbolNode(param) && contextStack.lookUp(param) === null) {
|
|
5892
|
-
|
|
5893
|
-
}
|
|
5894
|
-
const result = evaluateNode(param, contextStack);
|
|
5895
|
-
if (result !== null) {
|
|
5896
|
-
return result;
|
|
6427
|
+
return SENTINEL;
|
|
5897
6428
|
}
|
|
5898
|
-
|
|
5899
|
-
|
|
6429
|
+
return chain(evaluateNode(param, contextStack), (result) => {
|
|
6430
|
+
if (result !== null) {
|
|
6431
|
+
return result;
|
|
6432
|
+
}
|
|
6433
|
+
return SENTINEL;
|
|
6434
|
+
});
|
|
6435
|
+
}, SENTINEL), result => result === SENTINEL ? null : result);
|
|
5900
6436
|
},
|
|
5901
6437
|
evaluateAsNormalExpression: (params, sourceCodeInfo) => {
|
|
5902
6438
|
for (const param of params) {
|
|
@@ -5918,7 +6454,7 @@ const docs$4 = {
|
|
|
5918
6454
|
`
|
|
5919
6455
|
let foo = (n) -> do
|
|
5920
6456
|
write!(n);
|
|
5921
|
-
if
|
|
6457
|
+
if not(zero?(n)) then
|
|
5922
6458
|
recur(n - 1)
|
|
5923
6459
|
end
|
|
5924
6460
|
end;
|
|
@@ -5926,14 +6462,14 @@ foo(3)`,
|
|
|
5926
6462
|
`
|
|
5927
6463
|
(n -> do
|
|
5928
6464
|
write!(n);
|
|
5929
|
-
if
|
|
6465
|
+
if not(zero?(n)) then
|
|
5930
6466
|
recur(n - 1)
|
|
5931
6467
|
end
|
|
5932
6468
|
end)(3)`,
|
|
5933
6469
|
`
|
|
5934
6470
|
loop (n = 3) -> do
|
|
5935
6471
|
write!(n);
|
|
5936
|
-
if
|
|
6472
|
+
if not(zero?(n)) then
|
|
5937
6473
|
recur(n - 1)
|
|
5938
6474
|
end
|
|
5939
6475
|
end`,
|
|
@@ -5944,8 +6480,9 @@ const recurSpecialExpression = {
|
|
|
5944
6480
|
docs: docs$4,
|
|
5945
6481
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5946
6482
|
const params = node[1][1];
|
|
5947
|
-
|
|
5948
|
-
|
|
6483
|
+
return chain(mapSequential(params, paramNode => evaluateNode(paramNode, contextStack)), (evaluatedParams) => {
|
|
6484
|
+
throw new RecurSignal(evaluatedParams);
|
|
6485
|
+
});
|
|
5949
6486
|
},
|
|
5950
6487
|
evaluateAsNormalExpression: (params) => {
|
|
5951
6488
|
throw new RecurSignal(params);
|
|
@@ -5976,10 +6513,12 @@ const throwSpecialExpression = {
|
|
|
5976
6513
|
arity: toFixedArity(1),
|
|
5977
6514
|
docs: docs$3,
|
|
5978
6515
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
5979
|
-
|
|
5980
|
-
|
|
6516
|
+
return chain(evaluateNode(node[1][1], contextStack), (result) => {
|
|
6517
|
+
const message = asString(result, node[2], {
|
|
6518
|
+
nonEmpty: true,
|
|
6519
|
+
});
|
|
6520
|
+
throw new UserDefinedError(message, node[2]);
|
|
5981
6521
|
});
|
|
5982
|
-
throw new UserDefinedError(message, node[2]);
|
|
5983
6522
|
},
|
|
5984
6523
|
evaluateAsNormalExpression: (params, sourceCodeInfo) => {
|
|
5985
6524
|
const message = asString(params[0], sourceCodeInfo, {
|
|
@@ -6025,17 +6564,14 @@ const trySpecialExpression = {
|
|
|
6025
6564
|
docs: docs$2,
|
|
6026
6565
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
6027
6566
|
const [, tryExpression, errorSymbol, catchExpression] = node[1];
|
|
6028
|
-
|
|
6029
|
-
return evaluateNode(tryExpression, contextStack);
|
|
6030
|
-
}
|
|
6031
|
-
catch (error) {
|
|
6567
|
+
return tryCatch(() => evaluateNode(tryExpression, contextStack), (error) => {
|
|
6032
6568
|
const newContext = errorSymbol
|
|
6033
6569
|
? {
|
|
6034
6570
|
[errorSymbol[1]]: { value: error },
|
|
6035
6571
|
}
|
|
6036
6572
|
: {};
|
|
6037
6573
|
return evaluateNode(catchExpression, contextStack.create(newContext));
|
|
6038
|
-
}
|
|
6574
|
+
});
|
|
6039
6575
|
},
|
|
6040
6576
|
getUndefinedSymbols: (node, contextStack, { getUndefinedSymbols, builtin, evaluateNode }) => {
|
|
6041
6577
|
const [, tryExpression, errorSymbol, catchExpression] = node[1];
|
|
@@ -6082,19 +6618,21 @@ const arraySpecialExpression = {
|
|
|
6082
6618
|
docs: docs$1,
|
|
6083
6619
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
6084
6620
|
const result = [];
|
|
6085
|
-
|
|
6621
|
+
return chain(forEachSequential(node[1][1], (param) => {
|
|
6086
6622
|
if (isSpreadNode(param)) {
|
|
6087
|
-
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6623
|
+
return chain(evaluateNode(param[1], contextStack), (spreadValue) => {
|
|
6624
|
+
if (!Array.isArray(spreadValue)) {
|
|
6625
|
+
throw new LitsError('Spread value is not an array', param[2]);
|
|
6626
|
+
}
|
|
6627
|
+
result.push(...spreadValue);
|
|
6628
|
+
});
|
|
6092
6629
|
}
|
|
6093
6630
|
else {
|
|
6094
|
-
|
|
6631
|
+
return chain(evaluateNode(param, contextStack), (value) => {
|
|
6632
|
+
result.push(value);
|
|
6633
|
+
});
|
|
6095
6634
|
}
|
|
6096
|
-
}
|
|
6097
|
-
return result;
|
|
6635
|
+
}), () => result);
|
|
6098
6636
|
},
|
|
6099
6637
|
evaluateAsNormalExpression: (params, sourceCodeInfo) => {
|
|
6100
6638
|
const result = [];
|
|
@@ -6147,28 +6685,34 @@ const objectSpecialExpression = {
|
|
|
6147
6685
|
evaluate: (node, contextStack, { evaluateNode }) => {
|
|
6148
6686
|
const result = {};
|
|
6149
6687
|
const params = node[1][1];
|
|
6150
|
-
|
|
6688
|
+
function processEntry(i) {
|
|
6689
|
+
if (i >= params.length)
|
|
6690
|
+
return result;
|
|
6151
6691
|
const keyNode = params[i];
|
|
6152
6692
|
if (isSpreadNode(keyNode)) {
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6693
|
+
return chain(evaluateNode(keyNode[1], contextStack), (spreadObject) => {
|
|
6694
|
+
if (!isUnknownRecord(spreadObject)) {
|
|
6695
|
+
throw new LitsError('Spread value is not an object', keyNode[2]);
|
|
6696
|
+
}
|
|
6697
|
+
Object.assign(result, spreadObject);
|
|
6698
|
+
return processEntry(i + 1);
|
|
6699
|
+
});
|
|
6159
6700
|
}
|
|
6160
6701
|
else {
|
|
6161
|
-
const key = evaluateNode(keyNode, contextStack);
|
|
6162
6702
|
const valueNode = params[i + 1];
|
|
6163
6703
|
if (valueNode === undefined) {
|
|
6164
6704
|
throw new LitsError('Missing value for key', keyNode[2]);
|
|
6165
6705
|
}
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6706
|
+
return chain(evaluateNode(keyNode, contextStack), (key) => {
|
|
6707
|
+
return chain(evaluateNode(valueNode, contextStack), (value) => {
|
|
6708
|
+
assertString(key, keyNode[2]);
|
|
6709
|
+
result[key] = value;
|
|
6710
|
+
return processEntry(i + 2);
|
|
6711
|
+
});
|
|
6712
|
+
});
|
|
6169
6713
|
}
|
|
6170
6714
|
}
|
|
6171
|
-
return
|
|
6715
|
+
return processEntry(0);
|
|
6172
6716
|
},
|
|
6173
6717
|
evaluateAsNormalExpression: (params, sourceCodeInfo) => {
|
|
6174
6718
|
const result = {};
|
|
@@ -6267,7 +6811,19 @@ function isNumberReservedSymbol(symbol) {
|
|
|
6267
6811
|
const functionExecutors = {
|
|
6268
6812
|
NativeJsFunction: (fn, params, sourceCodeInfo) => {
|
|
6269
6813
|
try {
|
|
6270
|
-
|
|
6814
|
+
const result = fn.nativeFn.fn(...params);
|
|
6815
|
+
// If the native function returns a Promise, await it transparently
|
|
6816
|
+
if (result instanceof Promise) {
|
|
6817
|
+
return result.then(resolved => toAny(resolved), (error) => {
|
|
6818
|
+
const message = typeof error === 'string'
|
|
6819
|
+
? error
|
|
6820
|
+
: isUnknownRecord(error) && typeof error.message === 'string'
|
|
6821
|
+
? error.message
|
|
6822
|
+
: '<no message>';
|
|
6823
|
+
throw new LitsError(`Native function threw: "${message}"`, sourceCodeInfo);
|
|
6824
|
+
});
|
|
6825
|
+
}
|
|
6826
|
+
return toAny(result);
|
|
6271
6827
|
}
|
|
6272
6828
|
catch (error) {
|
|
6273
6829
|
const message = typeof error === 'string'
|
|
@@ -6279,9 +6835,9 @@ const functionExecutors = {
|
|
|
6279
6835
|
}
|
|
6280
6836
|
},
|
|
6281
6837
|
UserDefined: (fn, params, sourceCodeInfo, contextStack, { evaluateNode }) => {
|
|
6282
|
-
|
|
6283
|
-
if (!arityAcceptsMin(fn.arity,
|
|
6284
|
-
throw new LitsError(`Expected ${fn.arity} arguments, got ${
|
|
6838
|
+
function setupAndExecute(currentParams) {
|
|
6839
|
+
if (!arityAcceptsMin(fn.arity, currentParams.length)) {
|
|
6840
|
+
throw new LitsError(`Expected ${fn.arity} arguments, got ${currentParams.length}.`, sourceCodeInfo);
|
|
6285
6841
|
}
|
|
6286
6842
|
const evaluatedFunction = fn.evaluatedfunction;
|
|
6287
6843
|
const args = evaluatedFunction[0];
|
|
@@ -6289,39 +6845,70 @@ const functionExecutors = {
|
|
|
6289
6845
|
const newContextStack = contextStack.create(fn.evaluatedfunction[2]);
|
|
6290
6846
|
const newContext = { self: { value: fn } };
|
|
6291
6847
|
const rest = [];
|
|
6292
|
-
|
|
6848
|
+
// Process non-rest params sequentially since binding evaluation may be async
|
|
6849
|
+
let paramSetup = undefined;
|
|
6850
|
+
for (let i = 0; i < currentParams.length; i += 1) {
|
|
6293
6851
|
if (i < nbrOfNonRestArgs) {
|
|
6294
|
-
const
|
|
6295
|
-
|
|
6296
|
-
|
|
6297
|
-
|
|
6852
|
+
const paramIndex = i;
|
|
6853
|
+
paramSetup = chain(paramSetup, () => {
|
|
6854
|
+
const param = toAny(currentParams[paramIndex]);
|
|
6855
|
+
return chain(evaluateBindingNodeValues(args[paramIndex], param, node => evaluateNode(node, newContextStack.create(newContext))), (valueRecord) => {
|
|
6856
|
+
Object.entries(valueRecord).forEach(([key, value]) => {
|
|
6857
|
+
newContext[key] = { value };
|
|
6858
|
+
});
|
|
6859
|
+
});
|
|
6298
6860
|
});
|
|
6299
6861
|
}
|
|
6300
6862
|
else {
|
|
6301
|
-
rest.push(toAny(
|
|
6863
|
+
rest.push(toAny(currentParams[i]));
|
|
6302
6864
|
}
|
|
6303
6865
|
}
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
const
|
|
6308
|
-
|
|
6309
|
-
|
|
6866
|
+
// Handle default values for optional params — chain sequentially since they may be async
|
|
6867
|
+
let defaultSetup = undefined;
|
|
6868
|
+
for (let i = currentParams.length; i < nbrOfNonRestArgs; i++) {
|
|
6869
|
+
const argIndex = i;
|
|
6870
|
+
defaultSetup = chain(defaultSetup, () => {
|
|
6871
|
+
const arg = args[argIndex];
|
|
6872
|
+
return chain(evaluateNode(arg[1][1], contextStack.create(newContext)), (defaultValue) => {
|
|
6873
|
+
return chain(evaluateBindingNodeValues(arg, defaultValue, node => evaluateNode(node, contextStack.create(newContext))), (valueRecord) => {
|
|
6874
|
+
Object.entries(valueRecord).forEach(([key, value]) => {
|
|
6875
|
+
newContext[key] = { value };
|
|
6876
|
+
});
|
|
6877
|
+
});
|
|
6878
|
+
});
|
|
6310
6879
|
});
|
|
6311
6880
|
}
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
const
|
|
6315
|
-
|
|
6316
|
-
|
|
6881
|
+
return chain(paramSetup, () => chain(defaultSetup, () => {
|
|
6882
|
+
const restArgument = args.find(arg => arg[0] === bindingTargetTypes.rest);
|
|
6883
|
+
const restSetup = restArgument !== undefined
|
|
6884
|
+
? chain(evaluateBindingNodeValues(restArgument, rest, node => evaluateNode(node, contextStack.create(newContext))), (valueRecord) => {
|
|
6885
|
+
Object.entries(valueRecord).forEach(([key, value]) => {
|
|
6886
|
+
newContext[key] = { value };
|
|
6887
|
+
});
|
|
6888
|
+
})
|
|
6889
|
+
: undefined;
|
|
6890
|
+
return chain(restSetup, () => {
|
|
6891
|
+
// Evaluate body nodes sequentially
|
|
6892
|
+
const newContextStack2 = newContextStack.create(newContext);
|
|
6893
|
+
const bodyResult = reduceSequential(evaluatedFunction[1], (_acc, node) => evaluateNode(node, newContextStack2), null);
|
|
6894
|
+
// Handle RecurSignal for async body results
|
|
6895
|
+
if (bodyResult instanceof Promise) {
|
|
6896
|
+
return bodyResult.catch((error) => {
|
|
6897
|
+
if (error instanceof RecurSignal) {
|
|
6898
|
+
return setupAndExecute(error.params);
|
|
6899
|
+
}
|
|
6900
|
+
throw error;
|
|
6901
|
+
});
|
|
6902
|
+
}
|
|
6903
|
+
return bodyResult;
|
|
6317
6904
|
});
|
|
6318
|
-
}
|
|
6905
|
+
}));
|
|
6906
|
+
}
|
|
6907
|
+
// Sync recur loop: use for(;;) to avoid stack overflow for sync tail recursion
|
|
6908
|
+
for (;;) {
|
|
6319
6909
|
try {
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
for (const node of evaluatedFunction[1]) {
|
|
6323
|
-
result = evaluateNode(node, newContextStack2);
|
|
6324
|
-
}
|
|
6910
|
+
const result = setupAndExecute(params);
|
|
6911
|
+
// If result is async, the RecurSignal handling is inside the Promise chain
|
|
6325
6912
|
return result;
|
|
6326
6913
|
}
|
|
6327
6914
|
catch (error) {
|
|
@@ -6351,38 +6938,51 @@ const functionExecutors = {
|
|
|
6351
6938
|
throw new LitsError(`(comp) expects one argument, got ${valueToString(params.length)}.`, sourceCodeInfo);
|
|
6352
6939
|
return asAny(params[0], sourceCodeInfo);
|
|
6353
6940
|
}
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6941
|
+
// reduceRight with MaybePromise: each step wraps result in array, passes to next function
|
|
6942
|
+
let result = params;
|
|
6943
|
+
for (let i = f.length - 1; i >= 0; i--) {
|
|
6944
|
+
const fun = f[i];
|
|
6945
|
+
result = chain(result, (currentParams) => {
|
|
6946
|
+
return chain(executeFunction(asFunctionLike(fun, sourceCodeInfo), currentParams, contextStack, sourceCodeInfo), r => [r]);
|
|
6947
|
+
});
|
|
6948
|
+
}
|
|
6949
|
+
return chain(result, finalArr => asAny(finalArr[0], sourceCodeInfo));
|
|
6357
6950
|
},
|
|
6358
6951
|
Constantly: (fn) => {
|
|
6359
6952
|
return fn.value;
|
|
6360
6953
|
},
|
|
6361
6954
|
Juxt: (fn, params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
6362
|
-
return fn.params
|
|
6955
|
+
return mapSequential(fn.params, fun => executeFunction(asFunctionLike(fun, sourceCodeInfo), params, contextStack, sourceCodeInfo));
|
|
6363
6956
|
},
|
|
6364
6957
|
Complement: (fn, params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
6365
|
-
return
|
|
6958
|
+
return chain(executeFunction(fn.function, params, contextStack, sourceCodeInfo), result => !result);
|
|
6366
6959
|
},
|
|
6367
6960
|
EveryPred: (fn, params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
6961
|
+
// Flatten to sequential checks: for each predicate, for each param
|
|
6962
|
+
const checks = [];
|
|
6368
6963
|
for (const f of fn.params) {
|
|
6369
6964
|
for (const param of params) {
|
|
6370
|
-
|
|
6371
|
-
if (!result)
|
|
6372
|
-
return false;
|
|
6965
|
+
checks.push(() => executeFunction(asFunctionLike(f, sourceCodeInfo), [param], contextStack, sourceCodeInfo));
|
|
6373
6966
|
}
|
|
6374
6967
|
}
|
|
6375
|
-
return
|
|
6968
|
+
return reduceSequential(checks, (acc, check) => {
|
|
6969
|
+
if (!acc)
|
|
6970
|
+
return false;
|
|
6971
|
+
return chain(check(), result => !!result);
|
|
6972
|
+
}, true);
|
|
6376
6973
|
},
|
|
6377
6974
|
SomePred: (fn, params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
6975
|
+
const checks = [];
|
|
6378
6976
|
for (const f of fn.params) {
|
|
6379
6977
|
for (const param of params) {
|
|
6380
|
-
|
|
6381
|
-
if (result)
|
|
6382
|
-
return true;
|
|
6978
|
+
checks.push(() => executeFunction(asFunctionLike(f, sourceCodeInfo), [param], contextStack, sourceCodeInfo));
|
|
6383
6979
|
}
|
|
6384
6980
|
}
|
|
6385
|
-
return
|
|
6981
|
+
return reduceSequential(checks, (acc, check) => {
|
|
6982
|
+
if (acc)
|
|
6983
|
+
return true;
|
|
6984
|
+
return chain(check(), result => !!result);
|
|
6985
|
+
}, false);
|
|
6386
6986
|
},
|
|
6387
6987
|
Fnull: (fn, params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
6388
6988
|
const fnulledParams = params.map((param, index) => (param === null ? toAny(fn.params[index]) : param));
|
|
@@ -6416,11 +7016,7 @@ const functionExecutors = {
|
|
|
6416
7016
|
};
|
|
6417
7017
|
|
|
6418
7018
|
function evaluate(ast, contextStack) {
|
|
6419
|
-
|
|
6420
|
-
for (const node of ast.body) {
|
|
6421
|
-
result = evaluateNode(node, contextStack);
|
|
6422
|
-
}
|
|
6423
|
-
return result;
|
|
7019
|
+
return reduceSequential(ast.body, (_acc, node) => evaluateNode(node, contextStack), null);
|
|
6424
7020
|
}
|
|
6425
7021
|
function evaluateNode(node, contextStack) {
|
|
6426
7022
|
switch (node[0]) {
|
|
@@ -6436,13 +7032,15 @@ function evaluateNode(node, contextStack) {
|
|
|
6436
7032
|
return evaluateReservedSymbol(node);
|
|
6437
7033
|
case NodeTypes.NormalExpression: {
|
|
6438
7034
|
const result = evaluateNormalExpression(node, contextStack);
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
7035
|
+
return chain(result, (resolved) => {
|
|
7036
|
+
if (typeof resolved === 'number' && Number.isNaN(resolved)) {
|
|
7037
|
+
throw new LitsError('Number is NaN', node[2]);
|
|
7038
|
+
}
|
|
7039
|
+
return annotate(resolved);
|
|
7040
|
+
});
|
|
6443
7041
|
}
|
|
6444
7042
|
case NodeTypes.SpecialExpression:
|
|
6445
|
-
return
|
|
7043
|
+
return chain(evaluateSpecialExpression(node, contextStack), resolved => annotate(resolved));
|
|
6446
7044
|
/* v8 ignore next 2 */
|
|
6447
7045
|
default:
|
|
6448
7046
|
throw new LitsError(`${getNodeTypeName(node[0])}-node cannot be evaluated`, node[2]);
|
|
@@ -6462,73 +7060,84 @@ function evaluateReservedSymbol(node) {
|
|
|
6462
7060
|
const value = reservedSymbolRecord[reservedName];
|
|
6463
7061
|
return asNonUndefined(value, node[2]);
|
|
6464
7062
|
}
|
|
6465
|
-
function
|
|
6466
|
-
const sourceCodeInfo = node[2];
|
|
6467
|
-
const paramNodes = node[1][1];
|
|
7063
|
+
function evaluateParams(paramNodes, contextStack) {
|
|
6468
7064
|
const params = [];
|
|
6469
7065
|
const placeholders = [];
|
|
6470
|
-
paramNodes
|
|
7066
|
+
const result = forEachSequential(paramNodes, (paramNode, index) => {
|
|
6471
7067
|
if (isSpreadNode(paramNode)) {
|
|
6472
|
-
|
|
6473
|
-
|
|
6474
|
-
|
|
6475
|
-
|
|
6476
|
-
|
|
6477
|
-
|
|
6478
|
-
|
|
7068
|
+
return chain(evaluateNode(paramNode[1], contextStack), (spreadValue) => {
|
|
7069
|
+
if (Array.isArray(spreadValue)) {
|
|
7070
|
+
params.push(...spreadValue);
|
|
7071
|
+
}
|
|
7072
|
+
else {
|
|
7073
|
+
throw new LitsError(`Spread operator requires an array, got ${valueToString(paramNode)}`, paramNode[2]);
|
|
7074
|
+
}
|
|
7075
|
+
});
|
|
6479
7076
|
}
|
|
6480
7077
|
else if (paramNode[0] === NodeTypes.ReservedSymbol && paramNode[1] === '_') {
|
|
6481
7078
|
placeholders.push(index);
|
|
6482
7079
|
}
|
|
6483
7080
|
else {
|
|
6484
|
-
|
|
7081
|
+
return chain(evaluateNode(paramNode, contextStack), (value) => {
|
|
7082
|
+
params.push(value);
|
|
7083
|
+
});
|
|
6485
7084
|
}
|
|
6486
7085
|
});
|
|
6487
|
-
|
|
6488
|
-
|
|
6489
|
-
|
|
6490
|
-
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6496
|
-
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
if (
|
|
6510
|
-
|
|
7086
|
+
return chain(result, () => ({ params, placeholders }));
|
|
7087
|
+
}
|
|
7088
|
+
function evaluateNormalExpression(node, contextStack) {
|
|
7089
|
+
const sourceCodeInfo = node[2];
|
|
7090
|
+
return chain(evaluateParams(node[1][1], contextStack), ({ params, placeholders }) => {
|
|
7091
|
+
if (isNormalExpressionNodeWithName(node)) {
|
|
7092
|
+
const nameSymbol = node[1][0];
|
|
7093
|
+
if (placeholders.length > 0) {
|
|
7094
|
+
const fn = evaluateNode(nameSymbol, contextStack);
|
|
7095
|
+
return chain(fn, (resolvedFn) => {
|
|
7096
|
+
const partialFunction = {
|
|
7097
|
+
[FUNCTION_SYMBOL]: true,
|
|
7098
|
+
function: asFunctionLike(resolvedFn, sourceCodeInfo),
|
|
7099
|
+
functionType: 'Partial',
|
|
7100
|
+
params,
|
|
7101
|
+
placeholders,
|
|
7102
|
+
sourceCodeInfo,
|
|
7103
|
+
arity: toFixedArity(placeholders.length),
|
|
7104
|
+
};
|
|
7105
|
+
return partialFunction;
|
|
7106
|
+
});
|
|
7107
|
+
}
|
|
7108
|
+
if (isNormalBuiltinSymbolNode(nameSymbol)) {
|
|
7109
|
+
const type = nameSymbol[1];
|
|
7110
|
+
const normalExpression = builtin.allNormalExpressions[type];
|
|
7111
|
+
return normalExpression.evaluate(params, node[2], contextStack, { executeFunction });
|
|
7112
|
+
}
|
|
7113
|
+
else {
|
|
7114
|
+
const fn = contextStack.getValue(nameSymbol[1]);
|
|
7115
|
+
if (fn !== undefined) {
|
|
7116
|
+
return executeFunction(asFunctionLike(fn, sourceCodeInfo), params, contextStack, sourceCodeInfo);
|
|
7117
|
+
}
|
|
7118
|
+
throw new UndefinedSymbolError(nameSymbol[1], node[2]);
|
|
6511
7119
|
}
|
|
6512
|
-
throw new UndefinedSymbolError(nameSymbol[1], node[2]);
|
|
6513
7120
|
}
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
7121
|
+
else {
|
|
7122
|
+
const fnNode = node[1][0];
|
|
7123
|
+
return chain(evaluateNode(fnNode, contextStack), (resolvedFn) => {
|
|
7124
|
+
const fn = asFunctionLike(resolvedFn, sourceCodeInfo);
|
|
7125
|
+
if (placeholders.length > 0) {
|
|
7126
|
+
const partialFunction = {
|
|
7127
|
+
[FUNCTION_SYMBOL]: true,
|
|
7128
|
+
function: fn,
|
|
7129
|
+
functionType: 'Partial',
|
|
7130
|
+
params,
|
|
7131
|
+
placeholders,
|
|
7132
|
+
sourceCodeInfo,
|
|
7133
|
+
arity: toFixedArity(placeholders.length),
|
|
7134
|
+
};
|
|
7135
|
+
return partialFunction;
|
|
7136
|
+
}
|
|
7137
|
+
return executeFunction(fn, params, contextStack, sourceCodeInfo);
|
|
7138
|
+
});
|
|
6529
7139
|
}
|
|
6530
|
-
|
|
6531
|
-
}
|
|
7140
|
+
});
|
|
6532
7141
|
}
|
|
6533
7142
|
function executeFunction(fn, params, contextStack, sourceCodeInfo) {
|
|
6534
7143
|
if (isLitsFunction(fn))
|
|
@@ -6804,7 +7413,7 @@ const binaryOperators = [
|
|
|
6804
7413
|
'≥', // greater than or equal
|
|
6805
7414
|
'==', // equal
|
|
6806
7415
|
'!=', // not equal
|
|
6807
|
-
'
|
|
7416
|
+
'!=', // not equal
|
|
6808
7417
|
'&', // bitwise AND
|
|
6809
7418
|
'xor', // bitwise XOR
|
|
6810
7419
|
'|', // bitwise OR
|
|
@@ -7587,6 +8196,7 @@ class ParserContext {
|
|
|
7587
8196
|
const token = this.tokens[this.position];
|
|
7588
8197
|
if (!token) {
|
|
7589
8198
|
const lastToken = this.tokens.at(-1);
|
|
8199
|
+
/* v8 ignore next */
|
|
7590
8200
|
const sourceCodeInfo = lastToken ? lastToken[2] : undefined;
|
|
7591
8201
|
throw new LitsError('Unexpected end of input', sourceCodeInfo);
|
|
7592
8202
|
}
|
|
@@ -7713,7 +8323,6 @@ function fromBinaryOperatorToNode(operator, symbolNode, left, right, sourceCodeI
|
|
|
7713
8323
|
case '≥':
|
|
7714
8324
|
case '==':
|
|
7715
8325
|
case '!=':
|
|
7716
|
-
case '≠':
|
|
7717
8326
|
case '&':
|
|
7718
8327
|
case 'xor':
|
|
7719
8328
|
case '|':
|
|
@@ -8637,7 +9246,6 @@ function getPrecedence(operatorSign, sourceCodeInfo) {
|
|
|
8637
9246
|
return 7;
|
|
8638
9247
|
case '==': // equal
|
|
8639
9248
|
case '!=': // not equal
|
|
8640
|
-
case '≠': // not equal
|
|
8641
9249
|
return 6;
|
|
8642
9250
|
case '&': // bitwise AND
|
|
8643
9251
|
case 'xor': // bitwise XOR
|
|
@@ -8863,15 +9471,36 @@ class Lits {
|
|
|
8863
9471
|
debug: this.debug,
|
|
8864
9472
|
};
|
|
8865
9473
|
}
|
|
9474
|
+
async = {
|
|
9475
|
+
run: async (program, params = {}) => {
|
|
9476
|
+
const ast = this.generateAst(program, params);
|
|
9477
|
+
return this.evaluate(ast, params);
|
|
9478
|
+
},
|
|
9479
|
+
context: async (programOrAst, params = {}) => {
|
|
9480
|
+
const ast = typeof programOrAst === 'string' ? this.generateAst(programOrAst, params) : programOrAst;
|
|
9481
|
+
const contextStack = createContextStack(params, this.modules);
|
|
9482
|
+
await evaluate(ast, contextStack);
|
|
9483
|
+
return contextStack.globalContext;
|
|
9484
|
+
},
|
|
9485
|
+
apply: async (fn, fnParams, params = {}) => {
|
|
9486
|
+
return this.apply(fn, fnParams, params);
|
|
9487
|
+
},
|
|
9488
|
+
};
|
|
8866
9489
|
run(program, params = {}) {
|
|
8867
9490
|
const ast = this.generateAst(program, params);
|
|
8868
9491
|
const result = this.evaluate(ast, params);
|
|
9492
|
+
if (result instanceof Promise) {
|
|
9493
|
+
throw new TypeError('Unexpected async result in synchronous run(). Use lits.async.run() for async operations.');
|
|
9494
|
+
}
|
|
8869
9495
|
return result;
|
|
8870
9496
|
}
|
|
8871
9497
|
context(programOrAst, params = {}) {
|
|
8872
9498
|
const ast = typeof programOrAst === 'string' ? this.generateAst(programOrAst, params) : programOrAst;
|
|
8873
9499
|
const contextStack = createContextStack(params, this.modules);
|
|
8874
|
-
evaluate(ast, contextStack);
|
|
9500
|
+
const result = evaluate(ast, contextStack);
|
|
9501
|
+
if (result instanceof Promise) {
|
|
9502
|
+
throw new TypeError('Unexpected async result in synchronous context(). Use lits.async.context() for async operations.');
|
|
9503
|
+
}
|
|
8875
9504
|
return contextStack.globalContext;
|
|
8876
9505
|
}
|
|
8877
9506
|
getUndefinedSymbols(programOrAst, params = {}) {
|
|
@@ -10137,13 +10766,9 @@ const assertNormalExpression = {
|
|
|
10137
10766
|
}
|
|
10138
10767
|
message ??= '';
|
|
10139
10768
|
assertFunctionLike(func, sourceCodeInfo);
|
|
10140
|
-
|
|
10141
|
-
|
|
10142
|
-
}
|
|
10143
|
-
catch {
|
|
10144
|
-
return null;
|
|
10145
|
-
}
|
|
10146
|
-
throw new AssertionError(`Expected function to throw.${message}`, sourceCodeInfo);
|
|
10769
|
+
return tryCatch(() => chain(executeFunction(func, [], contextStack, sourceCodeInfo), () => {
|
|
10770
|
+
throw new AssertionError(`Expected function to throw.${message}`, sourceCodeInfo);
|
|
10771
|
+
}), () => null);
|
|
10147
10772
|
},
|
|
10148
10773
|
arity: { min: 1, max: 2 },
|
|
10149
10774
|
},
|
|
@@ -10156,17 +10781,15 @@ const assertNormalExpression = {
|
|
|
10156
10781
|
message ??= '';
|
|
10157
10782
|
assertString(throwMessage, sourceCodeInfo);
|
|
10158
10783
|
assertFunctionLike(func, sourceCodeInfo);
|
|
10159
|
-
|
|
10160
|
-
|
|
10161
|
-
}
|
|
10162
|
-
catch (error) {
|
|
10784
|
+
return tryCatch(() => chain(executeFunction(func, [], contextStack, sourceCodeInfo), () => {
|
|
10785
|
+
throw new AssertionError(`Expected function to throw "${throwMessage}".${message}`, sourceCodeInfo);
|
|
10786
|
+
}), (error) => {
|
|
10163
10787
|
const errorMessage = error.shortMessage;
|
|
10164
10788
|
if (errorMessage !== throwMessage) {
|
|
10165
10789
|
throw new AssertionError(`Expected function to throw "${throwMessage}", but thrown "${errorMessage}".${message}`, sourceCodeInfo);
|
|
10166
10790
|
}
|
|
10167
10791
|
return null;
|
|
10168
|
-
}
|
|
10169
|
-
throw new AssertionError(`Expected function to throw "${throwMessage}".${message}`, sourceCodeInfo);
|
|
10792
|
+
});
|
|
10170
10793
|
},
|
|
10171
10794
|
arity: { min: 2, max: 3 },
|
|
10172
10795
|
},
|
|
@@ -10178,13 +10801,9 @@ const assertNormalExpression = {
|
|
|
10178
10801
|
}
|
|
10179
10802
|
message ??= '';
|
|
10180
10803
|
assertFunctionLike(func, sourceCodeInfo);
|
|
10181
|
-
|
|
10182
|
-
executeFunction(func, [], contextStack, sourceCodeInfo);
|
|
10183
|
-
}
|
|
10184
|
-
catch {
|
|
10804
|
+
return tryCatch(() => chain(executeFunction(func, [], contextStack, sourceCodeInfo), () => null), () => {
|
|
10185
10805
|
throw new AssertionError(`Expected function not to throw.${message}`, sourceCodeInfo);
|
|
10186
|
-
}
|
|
10187
|
-
return null;
|
|
10806
|
+
});
|
|
10188
10807
|
},
|
|
10189
10808
|
arity: { min: 1, max: 2 },
|
|
10190
10809
|
},
|
|
@@ -11572,14 +12191,13 @@ const gridFunctions = {
|
|
|
11572
12191
|
evaluate: ([grid, predicate], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
11573
12192
|
assertGrid(grid, sourceCodeInfo);
|
|
11574
12193
|
assertFunctionLike(predicate, sourceCodeInfo);
|
|
12194
|
+
const cells = [];
|
|
11575
12195
|
for (const row of grid) {
|
|
11576
12196
|
for (const cell of row) {
|
|
11577
|
-
|
|
11578
|
-
return false;
|
|
11579
|
-
}
|
|
12197
|
+
cells.push(cell);
|
|
11580
12198
|
}
|
|
11581
12199
|
}
|
|
11582
|
-
return
|
|
12200
|
+
return everySequential(cells, cell => executeFunction(predicate, [cell], contextStack, sourceCodeInfo));
|
|
11583
12201
|
},
|
|
11584
12202
|
arity: toFixedArity(2),
|
|
11585
12203
|
},
|
|
@@ -11587,14 +12205,13 @@ const gridFunctions = {
|
|
|
11587
12205
|
evaluate: ([grid, predicate], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
11588
12206
|
assertGrid(grid, sourceCodeInfo);
|
|
11589
12207
|
assertFunctionLike(predicate, sourceCodeInfo);
|
|
12208
|
+
const cells = [];
|
|
11590
12209
|
for (const row of grid) {
|
|
11591
12210
|
for (const cell of row) {
|
|
11592
|
-
|
|
11593
|
-
return true;
|
|
11594
|
-
}
|
|
12211
|
+
cells.push(cell);
|
|
11595
12212
|
}
|
|
11596
12213
|
}
|
|
11597
|
-
return
|
|
12214
|
+
return someSequential(cells, cell => executeFunction(predicate, [cell], contextStack, sourceCodeInfo));
|
|
11598
12215
|
},
|
|
11599
12216
|
arity: toFixedArity(2),
|
|
11600
12217
|
},
|
|
@@ -11602,12 +12219,7 @@ const gridFunctions = {
|
|
|
11602
12219
|
evaluate: ([grid, predicate], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
11603
12220
|
assertGrid(grid, sourceCodeInfo);
|
|
11604
12221
|
assertFunctionLike(predicate, sourceCodeInfo);
|
|
11605
|
-
|
|
11606
|
-
if (!executeFunction(predicate, [row], contextStack, sourceCodeInfo)) {
|
|
11607
|
-
return false;
|
|
11608
|
-
}
|
|
11609
|
-
}
|
|
11610
|
-
return true;
|
|
12222
|
+
return everySequential(Array.from(grid), row => executeFunction(predicate, [row], contextStack, sourceCodeInfo));
|
|
11611
12223
|
},
|
|
11612
12224
|
arity: toFixedArity(2),
|
|
11613
12225
|
},
|
|
@@ -11615,12 +12227,7 @@ const gridFunctions = {
|
|
|
11615
12227
|
evaluate: ([grid, predicate], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
11616
12228
|
assertGrid(grid, sourceCodeInfo);
|
|
11617
12229
|
assertFunctionLike(predicate, sourceCodeInfo);
|
|
11618
|
-
|
|
11619
|
-
if (executeFunction(predicate, [row], contextStack, sourceCodeInfo)) {
|
|
11620
|
-
return true;
|
|
11621
|
-
}
|
|
11622
|
-
}
|
|
11623
|
-
return false;
|
|
12230
|
+
return someSequential(Array.from(grid), row => executeFunction(predicate, [row], contextStack, sourceCodeInfo));
|
|
11624
12231
|
},
|
|
11625
12232
|
arity: toFixedArity(2),
|
|
11626
12233
|
},
|
|
@@ -11629,12 +12236,7 @@ const gridFunctions = {
|
|
|
11629
12236
|
assertGrid(grid, sourceCodeInfo);
|
|
11630
12237
|
assertFunctionLike(predicate, sourceCodeInfo);
|
|
11631
12238
|
const transposed = transpose(grid);
|
|
11632
|
-
|
|
11633
|
-
if (!executeFunction(predicate, [row], contextStack, sourceCodeInfo)) {
|
|
11634
|
-
return false;
|
|
11635
|
-
}
|
|
11636
|
-
}
|
|
11637
|
-
return true;
|
|
12239
|
+
return everySequential(Array.from(transposed), row => executeFunction(predicate, [row], contextStack, sourceCodeInfo));
|
|
11638
12240
|
},
|
|
11639
12241
|
arity: toFixedArity(2),
|
|
11640
12242
|
},
|
|
@@ -11643,12 +12245,7 @@ const gridFunctions = {
|
|
|
11643
12245
|
assertGrid(grid, sourceCodeInfo);
|
|
11644
12246
|
assertFunctionLike(predicate, sourceCodeInfo);
|
|
11645
12247
|
const transposed = transpose(grid);
|
|
11646
|
-
|
|
11647
|
-
if (executeFunction(predicate, [row], contextStack, sourceCodeInfo)) {
|
|
11648
|
-
return true;
|
|
11649
|
-
}
|
|
11650
|
-
}
|
|
11651
|
-
return false;
|
|
12248
|
+
return someSequential(Array.from(transposed), row => executeFunction(predicate, [row], contextStack, sourceCodeInfo));
|
|
11652
12249
|
},
|
|
11653
12250
|
arity: toFixedArity(2),
|
|
11654
12251
|
},
|
|
@@ -11697,17 +12294,14 @@ const gridFunctions = {
|
|
|
11697
12294
|
assertNumber(rows, sourceCodeInfo, { integer: true, positive: true });
|
|
11698
12295
|
assertNumber(cols, sourceCodeInfo, { integer: true, positive: true });
|
|
11699
12296
|
assertFunctionLike(generator, sourceCodeInfo);
|
|
11700
|
-
|
|
11701
|
-
|
|
11702
|
-
|
|
11703
|
-
|
|
11704
|
-
|
|
11705
|
-
|
|
11706
|
-
|
|
11707
|
-
|
|
11708
|
-
result.push(row);
|
|
11709
|
-
}
|
|
11710
|
-
return result;
|
|
12297
|
+
return mapSequential(Array.from({ length: rows }), (_, i) => {
|
|
12298
|
+
return mapSequential(Array.from({ length: cols }), (__, j) => {
|
|
12299
|
+
return chain(executeFunction(generator, [i, j], contextStack, sourceCodeInfo), (value) => {
|
|
12300
|
+
assertAny(value, sourceCodeInfo);
|
|
12301
|
+
return value;
|
|
12302
|
+
});
|
|
12303
|
+
});
|
|
12304
|
+
});
|
|
11711
12305
|
},
|
|
11712
12306
|
arity: toFixedArity(3),
|
|
11713
12307
|
},
|
|
@@ -11994,16 +12588,12 @@ const gridFunctions = {
|
|
|
11994
12588
|
throw new LitsError(`All grids must have the same number of columns, but got ${cols} and ${grid[0].length}`, sourceCodeInfo);
|
|
11995
12589
|
}
|
|
11996
12590
|
});
|
|
11997
|
-
|
|
11998
|
-
|
|
11999
|
-
const row = [];
|
|
12000
|
-
for (let j = 0; j < cols; j += 1) {
|
|
12591
|
+
return mapSequential(Array.from({ length: rows }), (_, i) => {
|
|
12592
|
+
return mapSequential(Array.from({ length: cols }), (__, j) => {
|
|
12001
12593
|
const args = grids.map(grid => grid[i][j]);
|
|
12002
|
-
|
|
12003
|
-
}
|
|
12004
|
-
|
|
12005
|
-
}
|
|
12006
|
-
return result;
|
|
12594
|
+
return chain(executeFunction(fn, args, contextStack, sourceCodeInfo), val => asAny(val));
|
|
12595
|
+
});
|
|
12596
|
+
});
|
|
12007
12597
|
},
|
|
12008
12598
|
arity: { min: 2 },
|
|
12009
12599
|
},
|
|
@@ -12013,15 +12603,11 @@ const gridFunctions = {
|
|
|
12013
12603
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
12014
12604
|
const rows = grid.length;
|
|
12015
12605
|
const cols = grid[0].length;
|
|
12016
|
-
|
|
12017
|
-
|
|
12018
|
-
|
|
12019
|
-
|
|
12020
|
-
|
|
12021
|
-
}
|
|
12022
|
-
result.push(row);
|
|
12023
|
-
}
|
|
12024
|
-
return result;
|
|
12606
|
+
return mapSequential(Array.from({ length: rows }), (_, i) => {
|
|
12607
|
+
return mapSequential(Array.from({ length: cols }), (__, j) => {
|
|
12608
|
+
return chain(executeFunction(fn, [grid[i][j], i, j], contextStack, sourceCodeInfo), val => asAny(val));
|
|
12609
|
+
});
|
|
12610
|
+
});
|
|
12025
12611
|
},
|
|
12026
12612
|
arity: toFixedArity(2),
|
|
12027
12613
|
},
|
|
@@ -12029,13 +12615,13 @@ const gridFunctions = {
|
|
|
12029
12615
|
evaluate: ([grid, fn, initialValue], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
12030
12616
|
assertGrid(grid, sourceCodeInfo);
|
|
12031
12617
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
12032
|
-
|
|
12618
|
+
const cells = [];
|
|
12033
12619
|
for (const row of grid) {
|
|
12034
12620
|
for (const cell of row) {
|
|
12035
|
-
|
|
12621
|
+
cells.push(cell);
|
|
12036
12622
|
}
|
|
12037
12623
|
}
|
|
12038
|
-
return accumulator;
|
|
12624
|
+
return reduceSequential(cells, (accumulator, cell) => executeFunction(fn, [accumulator, cell], contextStack, sourceCodeInfo), asAny(initialValue));
|
|
12039
12625
|
},
|
|
12040
12626
|
arity: toFixedArity(3),
|
|
12041
12627
|
},
|
|
@@ -12043,13 +12629,13 @@ const gridFunctions = {
|
|
|
12043
12629
|
evaluate: ([grid, fn, initialValue], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
12044
12630
|
assertGrid(grid, sourceCodeInfo);
|
|
12045
12631
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
12046
|
-
|
|
12632
|
+
const cells = [];
|
|
12047
12633
|
for (let i = 0; i < grid.length; i += 1) {
|
|
12048
12634
|
for (let j = 0; j < grid[i].length; j += 1) {
|
|
12049
|
-
|
|
12635
|
+
cells.push({ cell: grid[i][j], i, j });
|
|
12050
12636
|
}
|
|
12051
12637
|
}
|
|
12052
|
-
return accumulator;
|
|
12638
|
+
return reduceSequential(cells, (accumulator, { cell, i, j }) => executeFunction(fn, [accumulator, cell, i, j], contextStack, sourceCodeInfo), asAny(initialValue));
|
|
12053
12639
|
},
|
|
12054
12640
|
arity: toFixedArity(3),
|
|
12055
12641
|
},
|
|
@@ -18165,10 +18751,11 @@ const vectorFunctions = {
|
|
|
18165
18751
|
evaluate: ([length, generator], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
18166
18752
|
assertNumber(length, sourceCodeInfo, { integer: true, nonNegative: true });
|
|
18167
18753
|
assertFunctionLike(generator, sourceCodeInfo);
|
|
18168
|
-
return Array.from({ length }, (_, i) => {
|
|
18169
|
-
|
|
18170
|
-
|
|
18171
|
-
|
|
18754
|
+
return mapSequential(Array.from({ length }), (_, i) => {
|
|
18755
|
+
return chain(executeFunction(generator, [i], contextStack, sourceCodeInfo), (value) => {
|
|
18756
|
+
assertNumber(value, sourceCodeInfo, { finite: true });
|
|
18757
|
+
return value;
|
|
18758
|
+
});
|
|
18172
18759
|
});
|
|
18173
18760
|
},
|
|
18174
18761
|
arity: toFixedArity(2),
|
|
@@ -26799,16 +27386,17 @@ const abundantSequence = {
|
|
|
26799
27386
|
'abundant?': n => isAbundant(n),
|
|
26800
27387
|
'abundant-take-while': (takeWhile) => {
|
|
26801
27388
|
const abundants = [];
|
|
26802
|
-
|
|
26803
|
-
if (!isAbundant(i))
|
|
26804
|
-
|
|
26805
|
-
|
|
26806
|
-
|
|
26807
|
-
|
|
26808
|
-
|
|
26809
|
-
|
|
27389
|
+
function loop(i) {
|
|
27390
|
+
if (!isAbundant(i))
|
|
27391
|
+
return loop(i + 1);
|
|
27392
|
+
return chain(takeWhile(i, abundants.length), (keep) => {
|
|
27393
|
+
if (!keep)
|
|
27394
|
+
return abundants;
|
|
27395
|
+
abundants.push(i);
|
|
27396
|
+
return loop(i + 1);
|
|
27397
|
+
});
|
|
26810
27398
|
}
|
|
26811
|
-
return
|
|
27399
|
+
return loop(2);
|
|
26812
27400
|
},
|
|
26813
27401
|
};
|
|
26814
27402
|
|
|
@@ -26853,15 +27441,20 @@ const arithmeticNormalExpressions = {
|
|
|
26853
27441
|
assertNumber(start, sourceCodeInfo, { finite: true });
|
|
26854
27442
|
assertNumber(step, sourceCodeInfo, { finite: true });
|
|
26855
27443
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
27444
|
+
const s = start;
|
|
27445
|
+
const d = step;
|
|
27446
|
+
const f = fn;
|
|
26856
27447
|
const arithmetic = [];
|
|
26857
|
-
|
|
26858
|
-
const value =
|
|
26859
|
-
|
|
26860
|
-
|
|
26861
|
-
|
|
26862
|
-
|
|
27448
|
+
function loop(i) {
|
|
27449
|
+
const value = s + i * d;
|
|
27450
|
+
return chain(executeFunction(f, [value, i], contextStack, sourceCodeInfo), (keep) => {
|
|
27451
|
+
if (!keep)
|
|
27452
|
+
return arithmetic;
|
|
27453
|
+
arithmetic.push(value);
|
|
27454
|
+
return loop(i + 1);
|
|
27455
|
+
});
|
|
26863
27456
|
}
|
|
26864
|
-
return
|
|
27457
|
+
return loop(0);
|
|
26865
27458
|
},
|
|
26866
27459
|
arity: toFixedArity(3),
|
|
26867
27460
|
},
|
|
@@ -26927,28 +27520,21 @@ function getBernoulliSeq(length) {
|
|
|
26927
27520
|
* @returns Array of Bernoulli numbers generated until predicate returns false
|
|
26928
27521
|
*/
|
|
26929
27522
|
function generateBernoulli(predicate) {
|
|
26930
|
-
const batchSize = 100;
|
|
26931
|
-
// Start with computing the Bernoulli numbers
|
|
26932
27523
|
const bernoulli = [1];
|
|
26933
|
-
|
|
26934
|
-
|
|
26935
|
-
|
|
26936
|
-
|
|
26937
|
-
|
|
26938
|
-
|
|
26939
|
-
|
|
26940
|
-
|
|
26941
|
-
sum += binomialCoefficient(n + 1, k) * bernoulli[k];
|
|
26942
|
-
}
|
|
26943
|
-
const newValue = n > 1 && n % 2 === 1 ? 0 : -sum / (n + 1);
|
|
26944
|
-
// Check if we should continue
|
|
26945
|
-
if (!predicate(newValue, n)) {
|
|
26946
|
-
// We're done, return the generated sequence (including the last value)
|
|
27524
|
+
function loop(n) {
|
|
27525
|
+
let sum = 0;
|
|
27526
|
+
for (let k = 0; k < n; k++) {
|
|
27527
|
+
sum += binomialCoefficient(n + 1, k) * bernoulli[k];
|
|
27528
|
+
}
|
|
27529
|
+
const newValue = n > 1 && n % 2 === 1 ? 0 : -sum / (n + 1);
|
|
27530
|
+
return chain(predicate(newValue, n), (keep) => {
|
|
27531
|
+
if (!keep)
|
|
26947
27532
|
return bernoulli;
|
|
26948
|
-
}
|
|
26949
27533
|
bernoulli.push(newValue);
|
|
26950
|
-
|
|
27534
|
+
return loop(n + 1);
|
|
27535
|
+
});
|
|
26951
27536
|
}
|
|
27537
|
+
return loop(1);
|
|
26952
27538
|
}
|
|
26953
27539
|
const bernoulliNormalExpressions = {
|
|
26954
27540
|
'bernoulli-seq': {
|
|
@@ -26969,8 +27555,8 @@ const bernoulliNormalExpressions = {
|
|
|
26969
27555
|
'bernoulli-take-while': {
|
|
26970
27556
|
evaluate: ([fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
26971
27557
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
26972
|
-
const
|
|
26973
|
-
return
|
|
27558
|
+
const f = fn;
|
|
27559
|
+
return generateBernoulli((value, index) => chain(executeFunction(f, [value, index], contextStack), val => !!val));
|
|
26974
27560
|
},
|
|
26975
27561
|
arity: toFixedArity(1),
|
|
26976
27562
|
},
|
|
@@ -27059,16 +27645,17 @@ const primeSequence = {
|
|
|
27059
27645
|
'prime?': n => isPrime(n),
|
|
27060
27646
|
'prime-take-while': (takeWhile) => {
|
|
27061
27647
|
const primes = [];
|
|
27062
|
-
|
|
27063
|
-
if (!isPrime(i))
|
|
27064
|
-
|
|
27065
|
-
|
|
27066
|
-
|
|
27067
|
-
|
|
27068
|
-
|
|
27069
|
-
|
|
27648
|
+
function loop(i) {
|
|
27649
|
+
if (!isPrime(i))
|
|
27650
|
+
return loop(i + 1);
|
|
27651
|
+
return chain(takeWhile(i, primes.length), (keep) => {
|
|
27652
|
+
if (!keep)
|
|
27653
|
+
return primes;
|
|
27654
|
+
primes.push(i);
|
|
27655
|
+
return loop(i + 1);
|
|
27656
|
+
});
|
|
27070
27657
|
}
|
|
27071
|
-
return
|
|
27658
|
+
return loop(2);
|
|
27072
27659
|
},
|
|
27073
27660
|
};
|
|
27074
27661
|
|
|
@@ -27093,16 +27680,17 @@ const compositeSequence = {
|
|
|
27093
27680
|
'composite?': n => isComposite(n),
|
|
27094
27681
|
'composite-take-while': (takeWhile) => {
|
|
27095
27682
|
const composites = [];
|
|
27096
|
-
|
|
27097
|
-
if (!isComposite(i))
|
|
27098
|
-
|
|
27099
|
-
|
|
27100
|
-
|
|
27101
|
-
|
|
27102
|
-
|
|
27103
|
-
|
|
27683
|
+
function loop(i) {
|
|
27684
|
+
if (!isComposite(i))
|
|
27685
|
+
return loop(i + 1);
|
|
27686
|
+
return chain(takeWhile(i, composites.length), (keep) => {
|
|
27687
|
+
if (!keep)
|
|
27688
|
+
return composites;
|
|
27689
|
+
composites.push(i);
|
|
27690
|
+
return loop(i + 1);
|
|
27691
|
+
});
|
|
27104
27692
|
}
|
|
27105
|
-
return
|
|
27693
|
+
return loop(4);
|
|
27106
27694
|
},
|
|
27107
27695
|
};
|
|
27108
27696
|
|
|
@@ -27126,16 +27714,17 @@ const deficientSequence = {
|
|
|
27126
27714
|
'deficient?': n => isDeficient(n),
|
|
27127
27715
|
'deficient-take-while': (takeWhile) => {
|
|
27128
27716
|
const deficients = [];
|
|
27129
|
-
|
|
27130
|
-
if (!isDeficient(i))
|
|
27131
|
-
|
|
27132
|
-
|
|
27133
|
-
|
|
27134
|
-
|
|
27135
|
-
|
|
27136
|
-
|
|
27717
|
+
function loop(i) {
|
|
27718
|
+
if (!isDeficient(i))
|
|
27719
|
+
return loop(i + 1);
|
|
27720
|
+
return chain(takeWhile(i, deficients.length), (keep) => {
|
|
27721
|
+
if (!keep)
|
|
27722
|
+
return deficients;
|
|
27723
|
+
deficients.push(i);
|
|
27724
|
+
return loop(i + 1);
|
|
27725
|
+
});
|
|
27137
27726
|
}
|
|
27138
|
-
return
|
|
27727
|
+
return loop(1);
|
|
27139
27728
|
},
|
|
27140
27729
|
};
|
|
27141
27730
|
|
|
@@ -27295,15 +27884,20 @@ const geometricNormalExpressions = {
|
|
|
27295
27884
|
assertNumber(start, sourceCodeInfo, { finite: true });
|
|
27296
27885
|
assertNumber(ratio, sourceCodeInfo, { finite: true });
|
|
27297
27886
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
27887
|
+
const s = start;
|
|
27888
|
+
const r = ratio;
|
|
27889
|
+
const f = fn;
|
|
27298
27890
|
const geometric = [];
|
|
27299
|
-
|
|
27300
|
-
const value =
|
|
27301
|
-
|
|
27302
|
-
|
|
27303
|
-
|
|
27304
|
-
|
|
27891
|
+
function loop(i) {
|
|
27892
|
+
const value = s * r ** i;
|
|
27893
|
+
return chain(executeFunction(f, [value, i], contextStack, sourceCodeInfo), (keep) => {
|
|
27894
|
+
if (!keep)
|
|
27895
|
+
return geometric;
|
|
27896
|
+
geometric.push(value);
|
|
27897
|
+
return loop(i + 1);
|
|
27898
|
+
});
|
|
27305
27899
|
}
|
|
27306
|
-
return
|
|
27900
|
+
return loop(0);
|
|
27307
27901
|
},
|
|
27308
27902
|
arity: toFixedArity(3),
|
|
27309
27903
|
},
|
|
@@ -27335,18 +27929,21 @@ function getGolombSeq(n) {
|
|
|
27335
27929
|
return golomb.slice(1);
|
|
27336
27930
|
}
|
|
27337
27931
|
function generateGolombSeq(pred) {
|
|
27338
|
-
if (!pred(1, 0)) {
|
|
27339
|
-
return [];
|
|
27340
|
-
}
|
|
27341
27932
|
const golomb = [0, 1];
|
|
27342
|
-
|
|
27343
|
-
|
|
27344
|
-
|
|
27345
|
-
|
|
27933
|
+
return chain(pred(1, 0), (keepFirst) => {
|
|
27934
|
+
if (!keepFirst)
|
|
27935
|
+
return [];
|
|
27936
|
+
function loop(i) {
|
|
27937
|
+
const golombNumber = 1 + golomb[i - golomb[golomb[i - 1]]];
|
|
27938
|
+
return chain(pred(golombNumber, i - 1), (keep) => {
|
|
27939
|
+
if (!keep)
|
|
27940
|
+
return golomb.slice(1);
|
|
27941
|
+
golomb.push(golombNumber);
|
|
27942
|
+
return loop(i + 1);
|
|
27943
|
+
});
|
|
27346
27944
|
}
|
|
27347
|
-
|
|
27348
|
-
}
|
|
27349
|
-
return golomb.slice(1);
|
|
27945
|
+
return loop(2);
|
|
27946
|
+
});
|
|
27350
27947
|
}
|
|
27351
27948
|
const golombSequence = {
|
|
27352
27949
|
'golomb-seq': length => getGolombSeq(length),
|
|
@@ -27401,23 +27998,17 @@ const happySequence = {
|
|
|
27401
27998
|
'happy?': n => isHappyNumber(n),
|
|
27402
27999
|
'happy-take-while': (takeWhile) => {
|
|
27403
28000
|
const happyNumbers = [];
|
|
27404
|
-
|
|
27405
|
-
|
|
27406
|
-
|
|
27407
|
-
|
|
27408
|
-
|
|
27409
|
-
|
|
27410
|
-
.split('')
|
|
27411
|
-
.reduce((sum, digit) => sum + Number(digit) ** 2, 0);
|
|
27412
|
-
}
|
|
27413
|
-
if (n === 1) {
|
|
27414
|
-
if (!takeWhile(i, happyNumbers.length)) {
|
|
27415
|
-
break;
|
|
27416
|
-
}
|
|
28001
|
+
function loop(i) {
|
|
28002
|
+
if (!isHappyNumber(i))
|
|
28003
|
+
return loop(i + 1);
|
|
28004
|
+
return chain(takeWhile(i, happyNumbers.length), (keep) => {
|
|
28005
|
+
if (!keep)
|
|
28006
|
+
return happyNumbers;
|
|
27417
28007
|
happyNumbers.push(i);
|
|
27418
|
-
|
|
28008
|
+
return loop(i + 1);
|
|
28009
|
+
});
|
|
27419
28010
|
}
|
|
27420
|
-
return
|
|
28011
|
+
return loop(1);
|
|
27421
28012
|
},
|
|
27422
28013
|
};
|
|
27423
28014
|
|
|
@@ -27500,19 +28091,23 @@ const lookAndSaySequence = {
|
|
|
27500
28091
|
return lookAndSay;
|
|
27501
28092
|
},
|
|
27502
28093
|
'look-and-say-take-while': (takeWhile) => {
|
|
27503
|
-
|
|
27504
|
-
|
|
27505
|
-
|
|
27506
|
-
|
|
27507
|
-
|
|
27508
|
-
|
|
27509
|
-
|
|
27510
|
-
|
|
27511
|
-
|
|
28094
|
+
const lookAndSay = [];
|
|
28095
|
+
return chain(takeWhile('1', 0), (keepFirst) => {
|
|
28096
|
+
if (!keepFirst)
|
|
28097
|
+
return lookAndSay;
|
|
28098
|
+
lookAndSay.push('1');
|
|
28099
|
+
function loop(i) {
|
|
28100
|
+
const prev = lookAndSay[i - 1];
|
|
28101
|
+
const next = prev.replace(/(\d)\1*/g, match => `${match.length}${match[0]}`);
|
|
28102
|
+
return chain(takeWhile(next, i), (keep) => {
|
|
28103
|
+
if (!keep)
|
|
28104
|
+
return lookAndSay;
|
|
28105
|
+
lookAndSay.push(next);
|
|
28106
|
+
return loop(i + 1);
|
|
28107
|
+
});
|
|
27512
28108
|
}
|
|
27513
|
-
|
|
27514
|
-
}
|
|
27515
|
-
return lookAndSay;
|
|
28109
|
+
return loop(1);
|
|
28110
|
+
});
|
|
27516
28111
|
},
|
|
27517
28112
|
'look-and-say?': n => isLookAndSay(n),
|
|
27518
28113
|
};
|
|
@@ -27620,42 +28215,45 @@ function generateLuckyNumbers(predicate) {
|
|
|
27620
28215
|
const luckyNumbers = [1]; // 1 is always the first lucky number
|
|
27621
28216
|
let count = 1;
|
|
27622
28217
|
// Check if we should continue after the first number
|
|
27623
|
-
|
|
27624
|
-
|
|
27625
|
-
|
|
27626
|
-
|
|
27627
|
-
|
|
27628
|
-
|
|
27629
|
-
|
|
27630
|
-
|
|
27631
|
-
|
|
27632
|
-
|
|
27633
|
-
|
|
27634
|
-
|
|
27635
|
-
|
|
27636
|
-
|
|
27637
|
-
|
|
27638
|
-
|
|
27639
|
-
|
|
27640
|
-
|
|
27641
|
-
|
|
27642
|
-
|
|
27643
|
-
|
|
27644
|
-
|
|
27645
|
-
|
|
27646
|
-
|
|
27647
|
-
|
|
27648
|
-
|
|
27649
|
-
|
|
27650
|
-
|
|
27651
|
-
|
|
27652
|
-
|
|
27653
|
-
|
|
27654
|
-
|
|
27655
|
-
|
|
28218
|
+
return chain(predicate(1, 0), (keepFirst) => {
|
|
28219
|
+
if (!keepFirst)
|
|
28220
|
+
return [];
|
|
28221
|
+
// Continue the sieve process
|
|
28222
|
+
let index = 1; // Start with the second element (index 1, which is 3)
|
|
28223
|
+
function loop() {
|
|
28224
|
+
// Get the current lucky number
|
|
28225
|
+
const luckyNumber = filteredNumbers[index];
|
|
28226
|
+
// Check if we should continue
|
|
28227
|
+
return chain(predicate(luckyNumber, count), (keep) => {
|
|
28228
|
+
if (!keep)
|
|
28229
|
+
return luckyNumbers;
|
|
28230
|
+
// Add to result
|
|
28231
|
+
luckyNumbers.push(luckyNumber);
|
|
28232
|
+
count++;
|
|
28233
|
+
// Apply the sieve
|
|
28234
|
+
const step = luckyNumber;
|
|
28235
|
+
const newFiltered = [];
|
|
28236
|
+
for (let i = 0; i < filteredNumbers.length; i++) {
|
|
28237
|
+
if ((i + 1) % step !== 0) { // Keep numbers not at positions divisible by step
|
|
28238
|
+
newFiltered.push(filteredNumbers[i]);
|
|
28239
|
+
}
|
|
28240
|
+
}
|
|
28241
|
+
filteredNumbers = newFiltered;
|
|
28242
|
+
index++;
|
|
28243
|
+
// If we're running low on numbers, extend the sequence
|
|
28244
|
+
if (index >= filteredNumbers.length - 5) {
|
|
28245
|
+
const lastNum = filteredNumbers[filteredNumbers.length - 1];
|
|
28246
|
+
let next = lastNum + 2;
|
|
28247
|
+
while (filteredNumbers.length < index + 1000) {
|
|
28248
|
+
filteredNumbers.push(next);
|
|
28249
|
+
next += 2;
|
|
28250
|
+
}
|
|
28251
|
+
}
|
|
28252
|
+
return loop();
|
|
28253
|
+
});
|
|
27656
28254
|
}
|
|
27657
|
-
|
|
27658
|
-
|
|
28255
|
+
return loop();
|
|
28256
|
+
});
|
|
27659
28257
|
}
|
|
27660
28258
|
/**
|
|
27661
28259
|
* Generates lucky numbers up to a specified length or count
|
|
@@ -27818,32 +28416,37 @@ const padovanSequence = {
|
|
|
27818
28416
|
'padovan?': n => isPadovan(n),
|
|
27819
28417
|
'padovan-take-while': (takeWhile) => {
|
|
27820
28418
|
const padovan = [];
|
|
27821
|
-
|
|
27822
|
-
|
|
27823
|
-
|
|
27824
|
-
|
|
27825
|
-
|
|
27826
|
-
|
|
27827
|
-
|
|
27828
|
-
|
|
27829
|
-
|
|
27830
|
-
|
|
27831
|
-
|
|
27832
|
-
|
|
27833
|
-
|
|
27834
|
-
|
|
27835
|
-
|
|
27836
|
-
|
|
27837
|
-
|
|
27838
|
-
|
|
27839
|
-
|
|
27840
|
-
|
|
27841
|
-
|
|
27842
|
-
|
|
27843
|
-
|
|
27844
|
-
|
|
27845
|
-
|
|
27846
|
-
|
|
28419
|
+
return chain(takeWhile(1, 0), (keep0) => {
|
|
28420
|
+
if (!keep0)
|
|
28421
|
+
return padovan;
|
|
28422
|
+
padovan.push(1);
|
|
28423
|
+
return chain(takeWhile(1, 1), (keep1) => {
|
|
28424
|
+
if (!keep1)
|
|
28425
|
+
return padovan;
|
|
28426
|
+
padovan.push(1);
|
|
28427
|
+
return chain(takeWhile(1, 2), (keep2) => {
|
|
28428
|
+
if (!keep2)
|
|
28429
|
+
return padovan;
|
|
28430
|
+
padovan.push(1);
|
|
28431
|
+
let a = 1;
|
|
28432
|
+
let b = 1;
|
|
28433
|
+
let c = 1;
|
|
28434
|
+
function loop(i) {
|
|
28435
|
+
const temp = a + b;
|
|
28436
|
+
a = b;
|
|
28437
|
+
b = c;
|
|
28438
|
+
c = temp;
|
|
28439
|
+
return chain(takeWhile(c, i), (keep) => {
|
|
28440
|
+
if (!keep)
|
|
28441
|
+
return padovan;
|
|
28442
|
+
padovan.push(c);
|
|
28443
|
+
return loop(i + 1);
|
|
28444
|
+
});
|
|
28445
|
+
}
|
|
28446
|
+
return loop(4);
|
|
28447
|
+
});
|
|
28448
|
+
});
|
|
28449
|
+
});
|
|
27847
28450
|
},
|
|
27848
28451
|
};
|
|
27849
28452
|
|
|
@@ -27905,14 +28508,16 @@ const perfectCubeSequence = {
|
|
|
27905
28508
|
'perfect-cube?': n => n > 0 && Number.isInteger(Math.cbrt(n)),
|
|
27906
28509
|
'perfect-cube-take-while': (takeWhile) => {
|
|
27907
28510
|
const perfectcubes = [];
|
|
27908
|
-
|
|
28511
|
+
function loop(i) {
|
|
27909
28512
|
const value = i ** 3;
|
|
27910
|
-
|
|
27911
|
-
|
|
27912
|
-
|
|
27913
|
-
|
|
28513
|
+
return chain(takeWhile(value, i), (keep) => {
|
|
28514
|
+
if (!keep)
|
|
28515
|
+
return perfectcubes;
|
|
28516
|
+
perfectcubes.push(value);
|
|
28517
|
+
return loop(i + 1);
|
|
28518
|
+
});
|
|
27914
28519
|
}
|
|
27915
|
-
return
|
|
28520
|
+
return loop(1);
|
|
27916
28521
|
},
|
|
27917
28522
|
};
|
|
27918
28523
|
|
|
@@ -27957,15 +28562,17 @@ const perfectPowerSequence = {
|
|
|
27957
28562
|
'perfect-power?': n => perfectPower(n) !== null,
|
|
27958
28563
|
'perfect-power-take-while': (takeWhile) => {
|
|
27959
28564
|
const perfectPowers = [];
|
|
27960
|
-
|
|
27961
|
-
if (perfectPower(i))
|
|
27962
|
-
|
|
27963
|
-
|
|
27964
|
-
|
|
28565
|
+
function loop(i) {
|
|
28566
|
+
if (!perfectPower(i))
|
|
28567
|
+
return loop(i + 1);
|
|
28568
|
+
return chain(takeWhile(i, perfectPowers.length), (keep) => {
|
|
28569
|
+
if (!keep)
|
|
28570
|
+
return perfectPowers;
|
|
27965
28571
|
perfectPowers.push(i);
|
|
27966
|
-
|
|
28572
|
+
return loop(i + 1);
|
|
28573
|
+
});
|
|
27967
28574
|
}
|
|
27968
|
-
return
|
|
28575
|
+
return loop(1);
|
|
27969
28576
|
},
|
|
27970
28577
|
};
|
|
27971
28578
|
|
|
@@ -27980,14 +28587,16 @@ const perfectSquareSequence = {
|
|
|
27980
28587
|
'perfect-square?': n => n > 0 && Number.isInteger(Math.sqrt(n)),
|
|
27981
28588
|
'perfect-square-take-while': (takeWhile) => {
|
|
27982
28589
|
const perfectSquares = [];
|
|
27983
|
-
|
|
28590
|
+
function loop(i) {
|
|
27984
28591
|
const value = i ** 2;
|
|
27985
|
-
|
|
27986
|
-
|
|
27987
|
-
|
|
27988
|
-
|
|
28592
|
+
return chain(takeWhile(value, i), (keep) => {
|
|
28593
|
+
if (!keep)
|
|
28594
|
+
return perfectSquares;
|
|
28595
|
+
perfectSquares.push(value);
|
|
28596
|
+
return loop(i + 1);
|
|
28597
|
+
});
|
|
27989
28598
|
}
|
|
27990
|
-
return
|
|
28599
|
+
return loop(1);
|
|
27991
28600
|
},
|
|
27992
28601
|
};
|
|
27993
28602
|
|
|
@@ -28008,15 +28617,19 @@ const poligonalNormalExpressions = {
|
|
|
28008
28617
|
evaluate: ([sides, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
28009
28618
|
assertNumber(sides, sourceCodeInfo, { integer: true, gte: 3 });
|
|
28010
28619
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
28620
|
+
const s = sides;
|
|
28621
|
+
const f = fn;
|
|
28011
28622
|
const polygonal = [];
|
|
28012
|
-
|
|
28013
|
-
const value = (i * i * (
|
|
28014
|
-
|
|
28015
|
-
|
|
28016
|
-
|
|
28017
|
-
|
|
28623
|
+
function loop(i) {
|
|
28624
|
+
const value = (i * i * (s - 2) - i * (s - 4)) / 2;
|
|
28625
|
+
return chain(executeFunction(f, [value, i], contextStack, sourceCodeInfo), (keep) => {
|
|
28626
|
+
if (!keep)
|
|
28627
|
+
return polygonal;
|
|
28628
|
+
polygonal.push(value);
|
|
28629
|
+
return loop(i + 1);
|
|
28630
|
+
});
|
|
28018
28631
|
}
|
|
28019
|
-
return
|
|
28632
|
+
return loop(1);
|
|
28020
28633
|
},
|
|
28021
28634
|
arity: toFixedArity(2),
|
|
28022
28635
|
},
|
|
@@ -28080,23 +28693,29 @@ function generateRecamanSequence(n) {
|
|
|
28080
28693
|
const recamanSequence = {
|
|
28081
28694
|
'recaman-seq': length => generateRecamanSequence(length),
|
|
28082
28695
|
'recaman-take-while': (takeWhile) => {
|
|
28083
|
-
|
|
28084
|
-
return [];
|
|
28085
|
-
const sequence = [0];
|
|
28696
|
+
const sequence = [];
|
|
28086
28697
|
const seen = new Set([0]);
|
|
28087
|
-
|
|
28088
|
-
|
|
28089
|
-
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
28093
|
-
|
|
28094
|
-
|
|
28095
|
-
|
|
28096
|
-
|
|
28097
|
-
|
|
28098
|
-
|
|
28099
|
-
|
|
28698
|
+
return chain(takeWhile(0, 0), (keepFirst) => {
|
|
28699
|
+
if (!keepFirst)
|
|
28700
|
+
return sequence;
|
|
28701
|
+
sequence.push(0);
|
|
28702
|
+
function loop(i) {
|
|
28703
|
+
// Try to go backward
|
|
28704
|
+
let next = sequence[i - 1] - i;
|
|
28705
|
+
// If that's not positive or already seen, go forward
|
|
28706
|
+
if (next <= 0 || seen.has(next)) {
|
|
28707
|
+
next = sequence[i - 1] + i;
|
|
28708
|
+
}
|
|
28709
|
+
return chain(takeWhile(next, i), (keep) => {
|
|
28710
|
+
if (!keep)
|
|
28711
|
+
return sequence;
|
|
28712
|
+
sequence.push(next);
|
|
28713
|
+
seen.add(next);
|
|
28714
|
+
return loop(i + 1);
|
|
28715
|
+
});
|
|
28716
|
+
}
|
|
28717
|
+
return loop(1);
|
|
28718
|
+
});
|
|
28100
28719
|
},
|
|
28101
28720
|
'recaman?': () => true,
|
|
28102
28721
|
};
|
|
@@ -28120,14 +28739,16 @@ const thueMorseSequence = {
|
|
|
28120
28739
|
},
|
|
28121
28740
|
'thue-morse-take-while': (takeWhile) => {
|
|
28122
28741
|
const thueMorse = [];
|
|
28123
|
-
|
|
28742
|
+
function loop(i) {
|
|
28124
28743
|
const value = countSetBits(i) % 2;
|
|
28125
|
-
|
|
28126
|
-
|
|
28127
|
-
|
|
28128
|
-
|
|
28744
|
+
return chain(takeWhile(value, i), (keep) => {
|
|
28745
|
+
if (!keep)
|
|
28746
|
+
return thueMorse;
|
|
28747
|
+
thueMorse.push(value);
|
|
28748
|
+
return loop(i + 1);
|
|
28749
|
+
});
|
|
28129
28750
|
}
|
|
28130
|
-
return
|
|
28751
|
+
return loop(0);
|
|
28131
28752
|
},
|
|
28132
28753
|
'thue-morse?': n => n === 1 || n === 0,
|
|
28133
28754
|
};
|
|
@@ -28251,16 +28872,16 @@ function getFiniteNumberSequence(name, sequence) {
|
|
|
28251
28872
|
return {
|
|
28252
28873
|
[`${name}-seq`]: createSeqNormalExpression(length => sequence.slice(0, length), sequence.length),
|
|
28253
28874
|
[`${name}-take-while`]: createTakeWhileNormalExpression((takeWhile) => {
|
|
28254
|
-
|
|
28255
|
-
|
|
28256
|
-
|
|
28257
|
-
|
|
28258
|
-
|
|
28259
|
-
|
|
28260
|
-
|
|
28261
|
-
}
|
|
28875
|
+
function loop(i) {
|
|
28876
|
+
if (i >= sequence.length)
|
|
28877
|
+
return sequence.slice(0, i);
|
|
28878
|
+
return chain(takeWhile(sequence[i], i), (keep) => {
|
|
28879
|
+
if (!keep)
|
|
28880
|
+
return sequence.slice(0, i);
|
|
28881
|
+
return loop(i + 1);
|
|
28882
|
+
});
|
|
28262
28883
|
}
|
|
28263
|
-
return
|
|
28884
|
+
return loop(0);
|
|
28264
28885
|
}, sequence.length),
|
|
28265
28886
|
[`${name}-nth`]: createNthNormalExpression(() => sequence, sequence.length),
|
|
28266
28887
|
[`${name}?`]: createNumberPredNormalExpression(n => sequence.includes(n)),
|
|
@@ -28313,14 +28934,16 @@ function createTakeWhileNormalExpression(takeWhileFunction, maxLength) {
|
|
|
28313
28934
|
evaluate: (params, sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
28314
28935
|
const fn = params[0];
|
|
28315
28936
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
28316
|
-
const result = takeWhileFunction((value, index) =>
|
|
28317
|
-
|
|
28318
|
-
|
|
28319
|
-
|
|
28320
|
-
|
|
28937
|
+
const result = takeWhileFunction((value, index) => chain(executeFunction(fn, [value, index], contextStack), val => !!val), sourceCodeInfo);
|
|
28938
|
+
return chain(result, (resolved) => {
|
|
28939
|
+
if (typeof resolved[0] === 'number') {
|
|
28940
|
+
/* v8 ignore next 3 */
|
|
28941
|
+
if (resolved.some(n => n > Number.MAX_SAFE_INTEGER)) {
|
|
28942
|
+
throw new LitsError('Result exceeds maximum safe integer', sourceCodeInfo);
|
|
28943
|
+
}
|
|
28321
28944
|
}
|
|
28322
|
-
|
|
28323
|
-
|
|
28945
|
+
return resolved;
|
|
28946
|
+
});
|
|
28324
28947
|
},
|
|
28325
28948
|
arity: typeof maxLength === 'number' ? { max: 1 } : toFixedArity(1),
|
|
28326
28949
|
};
|
|
@@ -29789,38 +30412,30 @@ function update(coll, key, fn, params, contextStack, executeFunction, sourceCode
|
|
|
29789
30412
|
if (isObj(coll)) {
|
|
29790
30413
|
assertString(key, sourceCodeInfo);
|
|
29791
30414
|
const result = { ...coll };
|
|
29792
|
-
|
|
29793
|
-
|
|
30415
|
+
return chain(executeFunction(fn, [result[key], ...params], contextStack, sourceCodeInfo), (val) => {
|
|
30416
|
+
result[key] = val;
|
|
30417
|
+
return result;
|
|
30418
|
+
});
|
|
29794
30419
|
}
|
|
29795
30420
|
else {
|
|
29796
30421
|
assertNumber(key, sourceCodeInfo);
|
|
29797
30422
|
const intKey = toNonNegativeInteger(key);
|
|
29798
30423
|
assertNumber(intKey, sourceCodeInfo, { lte: coll.length });
|
|
29799
30424
|
if (Array.isArray(coll)) {
|
|
29800
|
-
|
|
30425
|
+
return chain(mapSequential(Array.from({ length: coll.length + (intKey === coll.length ? 1 : 0) }), (_, index) => {
|
|
29801
30426
|
if (intKey === index)
|
|
29802
|
-
return executeFunction(fn, [
|
|
29803
|
-
return
|
|
29804
|
-
});
|
|
29805
|
-
if (intKey === coll.length)
|
|
29806
|
-
result[intKey] = executeFunction(fn, [undefined, ...params], contextStack, sourceCodeInfo);
|
|
29807
|
-
return result;
|
|
30427
|
+
return executeFunction(fn, [coll[index], ...params], contextStack, sourceCodeInfo);
|
|
30428
|
+
return coll[index];
|
|
30429
|
+
}), result => result);
|
|
29808
30430
|
}
|
|
29809
30431
|
else {
|
|
29810
|
-
const
|
|
30432
|
+
const chars = coll.split('');
|
|
30433
|
+
return chain(mapSequential(Array.from({ length: chars.length + (intKey === chars.length ? 1 : 0) }), (_, index) => {
|
|
29811
30434
|
if (intKey === index) {
|
|
29812
|
-
return
|
|
29813
|
-
char: true,
|
|
29814
|
-
});
|
|
30435
|
+
return chain(executeFunction(fn, [chars[index], ...params], contextStack, sourceCodeInfo), val => asString(val, sourceCodeInfo, { char: true }));
|
|
29815
30436
|
}
|
|
29816
|
-
return
|
|
29817
|
-
});
|
|
29818
|
-
if (intKey === coll.length) {
|
|
29819
|
-
result[intKey] = asString(executeFunction(fn, [undefined, ...params], contextStack, sourceCodeInfo), sourceCodeInfo, {
|
|
29820
|
-
char: true,
|
|
29821
|
-
});
|
|
29822
|
-
}
|
|
29823
|
-
return result.join('');
|
|
30437
|
+
return chars[index];
|
|
30438
|
+
}), result => result.join(''));
|
|
29824
30439
|
}
|
|
29825
30440
|
}
|
|
29826
30441
|
}
|
|
@@ -30025,13 +30640,18 @@ cu.update(
|
|
|
30025
30640
|
const parentKey = asStringOrNumber(keys[keys.length - 2], sourceCodeInfo);
|
|
30026
30641
|
if (Array.isArray(innerCollMeta.parent)) {
|
|
30027
30642
|
assertNumber(parentKey, sourceCodeInfo);
|
|
30028
|
-
|
|
30643
|
+
return chain(update(innerCollMeta.coll, lastKey, fn, params, contextStack, executeFunction, sourceCodeInfo), (updated) => {
|
|
30644
|
+
innerCollMeta.parent[parentKey] = updated;
|
|
30645
|
+
return coll;
|
|
30646
|
+
});
|
|
30029
30647
|
}
|
|
30030
30648
|
else {
|
|
30031
30649
|
assertString(parentKey, sourceCodeInfo);
|
|
30032
|
-
|
|
30650
|
+
return chain(update(innerCollMeta.coll, lastKey, fn, params, contextStack, executeFunction, sourceCodeInfo), (updated) => {
|
|
30651
|
+
innerCollMeta.parent[parentKey] = updated;
|
|
30652
|
+
return coll;
|
|
30653
|
+
});
|
|
30033
30654
|
}
|
|
30034
|
-
return coll;
|
|
30035
30655
|
},
|
|
30036
30656
|
arity: { min: 3 },
|
|
30037
30657
|
docs: {
|
|
@@ -30092,21 +30712,15 @@ cu.update-in(
|
|
|
30092
30712
|
assertColl(coll, sourceCodeInfo);
|
|
30093
30713
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30094
30714
|
if (Array.isArray(coll)) {
|
|
30095
|
-
|
|
30096
|
-
return result;
|
|
30715
|
+
return filterSequential(coll, (elem, index) => executeFunction(fn, [elem, index], contextStack, sourceCodeInfo));
|
|
30097
30716
|
}
|
|
30098
30717
|
if (typeof coll === 'string') {
|
|
30099
|
-
return coll
|
|
30100
|
-
.split('')
|
|
30101
|
-
.filter((elem, index) => executeFunction(fn, [elem, index], contextStack, sourceCodeInfo))
|
|
30102
|
-
.join('');
|
|
30718
|
+
return chain(filterSequential(coll.split(''), (elem, index) => executeFunction(fn, [elem, index], contextStack, sourceCodeInfo)), filtered => filtered.join(''));
|
|
30103
30719
|
}
|
|
30104
|
-
return Object.entries(coll)
|
|
30105
|
-
.filter(([key, value]) => executeFunction(fn, [value, key], contextStack, sourceCodeInfo))
|
|
30106
|
-
.reduce((result, [key, value]) => {
|
|
30720
|
+
return chain(filterSequential(Object.entries(coll), ([key, value]) => executeFunction(fn, [value, key], contextStack, sourceCodeInfo)), filtered => filtered.reduce((result, [key, value]) => {
|
|
30107
30721
|
result[key] = value;
|
|
30108
30722
|
return result;
|
|
30109
|
-
}, {});
|
|
30723
|
+
}, {}));
|
|
30110
30724
|
},
|
|
30111
30725
|
arity: toFixedArity(2),
|
|
30112
30726
|
docs: {
|
|
@@ -30134,18 +30748,17 @@ cu.update-in(
|
|
|
30134
30748
|
assertColl(coll, sourceCodeInfo);
|
|
30135
30749
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30136
30750
|
if (Array.isArray(coll)) {
|
|
30137
|
-
return coll
|
|
30751
|
+
return mapSequential(coll, (elem, index) => executeFunction(fn, [elem, index], contextStack, sourceCodeInfo));
|
|
30138
30752
|
}
|
|
30139
30753
|
if (typeof coll === 'string') {
|
|
30140
|
-
return coll
|
|
30141
|
-
.split('')
|
|
30142
|
-
.map((elem, index) => executeFunction(fn, [elem, index], contextStack, sourceCodeInfo))
|
|
30143
|
-
.join('');
|
|
30754
|
+
return chain(mapSequential(coll.split(''), (elem, index) => executeFunction(fn, [elem, index], contextStack, sourceCodeInfo)), mapped => mapped.join(''));
|
|
30144
30755
|
}
|
|
30145
|
-
|
|
30146
|
-
|
|
30147
|
-
|
|
30148
|
-
|
|
30756
|
+
const entries = Object.entries(coll);
|
|
30757
|
+
return reduceSequential(entries, (acc, [key, value]) => {
|
|
30758
|
+
return chain(executeFunction(fn, [value, key], contextStack, sourceCodeInfo), (result) => {
|
|
30759
|
+
acc[key] = result;
|
|
30760
|
+
return acc;
|
|
30761
|
+
});
|
|
30149
30762
|
}, {});
|
|
30150
30763
|
},
|
|
30151
30764
|
arity: toFixedArity(2),
|
|
@@ -30180,23 +30793,17 @@ cu.update-in(
|
|
|
30180
30793
|
assertString(initial, sourceCodeInfo);
|
|
30181
30794
|
if (coll.length === 0)
|
|
30182
30795
|
return initial;
|
|
30183
|
-
return coll.split('').
|
|
30184
|
-
return executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo);
|
|
30185
|
-
}, initial);
|
|
30796
|
+
return reduceSequential(coll.split('').map((elem, index) => ({ elem, index })), (result, { elem, index }) => executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo), initial);
|
|
30186
30797
|
}
|
|
30187
30798
|
else if (Array.isArray(coll)) {
|
|
30188
30799
|
if (coll.length === 0)
|
|
30189
30800
|
return initial;
|
|
30190
|
-
return coll.
|
|
30191
|
-
return executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo);
|
|
30192
|
-
}, initial);
|
|
30801
|
+
return reduceSequential(coll.map((elem, index) => ({ elem, index })), (result, { elem, index }) => executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo), initial);
|
|
30193
30802
|
}
|
|
30194
30803
|
else {
|
|
30195
30804
|
if (Object.keys(coll).length === 0)
|
|
30196
30805
|
return initial;
|
|
30197
|
-
return Object.entries(coll)
|
|
30198
|
-
return executeFunction(fn, [result, elem, key], contextStack, sourceCodeInfo);
|
|
30199
|
-
}, initial);
|
|
30806
|
+
return reduceSequential(Object.entries(coll), (result, [key, elem]) => executeFunction(fn, [result, elem, key], contextStack, sourceCodeInfo), initial);
|
|
30200
30807
|
}
|
|
30201
30808
|
},
|
|
30202
30809
|
arity: toFixedArity(3),
|
|
@@ -30232,23 +30839,17 @@ cu.update-in(
|
|
|
30232
30839
|
if (typeof coll === 'string') {
|
|
30233
30840
|
if (coll.length === 0)
|
|
30234
30841
|
return initial;
|
|
30235
|
-
return coll.split('').
|
|
30236
|
-
return executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
30237
|
-
}, initial);
|
|
30842
|
+
return reduceSequential(Array.from(coll.split('')).reverse(), (result, elem) => executeFunction(fn, [result, elem], contextStack, sourceCodeInfo), initial);
|
|
30238
30843
|
}
|
|
30239
30844
|
else if (Array.isArray(coll)) {
|
|
30240
30845
|
if (coll.length === 0)
|
|
30241
30846
|
return initial;
|
|
30242
|
-
return coll.
|
|
30243
|
-
return executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
30244
|
-
}, initial);
|
|
30847
|
+
return reduceSequential(Array.from(coll).reverse(), (result, elem) => executeFunction(fn, [result, elem], contextStack, sourceCodeInfo), initial);
|
|
30245
30848
|
}
|
|
30246
30849
|
else {
|
|
30247
30850
|
if (Object.keys(coll).length === 0)
|
|
30248
30851
|
return initial;
|
|
30249
|
-
return Object.entries(coll).
|
|
30250
|
-
return executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
30251
|
-
}, initial);
|
|
30852
|
+
return reduceSequential(Object.entries(coll).reverse(), (result, [, elem]) => executeFunction(fn, [result, elem], contextStack, sourceCodeInfo), initial);
|
|
30252
30853
|
}
|
|
30253
30854
|
},
|
|
30254
30855
|
arity: toFixedArity(3),
|
|
@@ -30277,23 +30878,17 @@ cu.update-in(
|
|
|
30277
30878
|
if (typeof coll === 'string') {
|
|
30278
30879
|
if (coll.length === 0)
|
|
30279
30880
|
return initial;
|
|
30280
|
-
return coll.split('').
|
|
30281
|
-
return executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo);
|
|
30282
|
-
}, initial);
|
|
30881
|
+
return reduceSequential(Array.from(coll.split('')).reverse().map((elem, _, arr) => ({ elem, index: arr.length - 1 - _ })), (result, { elem, index }) => executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo), initial);
|
|
30283
30882
|
}
|
|
30284
30883
|
else if (Array.isArray(coll)) {
|
|
30285
30884
|
if (coll.length === 0)
|
|
30286
30885
|
return initial;
|
|
30287
|
-
return coll.
|
|
30288
|
-
return executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo);
|
|
30289
|
-
}, initial);
|
|
30886
|
+
return reduceSequential(Array.from(coll).reverse().map((elem, _, arr) => ({ elem, index: arr.length - 1 - _ })), (result, { elem, index }) => executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo), initial);
|
|
30290
30887
|
}
|
|
30291
30888
|
else {
|
|
30292
30889
|
if (Object.keys(coll).length === 0)
|
|
30293
30890
|
return initial;
|
|
30294
|
-
return Object.entries(coll).
|
|
30295
|
-
return executeFunction(fn, [result, elem, key], contextStack, sourceCodeInfo);
|
|
30296
|
-
}, initial);
|
|
30891
|
+
return reduceSequential(Object.entries(coll).reverse(), (result, [key, elem]) => executeFunction(fn, [result, elem, key], contextStack, sourceCodeInfo), initial);
|
|
30297
30892
|
}
|
|
30298
30893
|
},
|
|
30299
30894
|
arity: toFixedArity(3),
|
|
@@ -30327,40 +30922,20 @@ cu.update-in(
|
|
|
30327
30922
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30328
30923
|
assertAny(initial, sourceCodeInfo);
|
|
30329
30924
|
assertAny(initial, sourceCodeInfo);
|
|
30330
|
-
|
|
30331
|
-
assertString(initial, sourceCodeInfo)
|
|
30332
|
-
|
|
30333
|
-
|
|
30334
|
-
|
|
30335
|
-
|
|
30336
|
-
|
|
30925
|
+
const items = typeof coll === 'string'
|
|
30926
|
+
? (assertString(initial, sourceCodeInfo), coll.length === 0 ? [] : coll.split(''))
|
|
30927
|
+
: Array.isArray(coll)
|
|
30928
|
+
? (coll.length === 0 ? [] : Array.from(coll))
|
|
30929
|
+
: (Object.keys(coll).length === 0 ? [] : Object.entries(coll).map(([, v]) => v));
|
|
30930
|
+
if (items.length === 0)
|
|
30931
|
+
return [initial];
|
|
30932
|
+
const resultArray = [initial];
|
|
30933
|
+
return chain(reduceSequential(items, (result, elem) => {
|
|
30934
|
+
return chain(executeFunction(fn, [result, elem], contextStack, sourceCodeInfo), (newVal) => {
|
|
30337
30935
|
resultArray.push(newVal);
|
|
30338
30936
|
return newVal;
|
|
30339
|
-
}
|
|
30340
|
-
|
|
30341
|
-
}
|
|
30342
|
-
else if (Array.isArray(coll)) {
|
|
30343
|
-
if (coll.length === 0)
|
|
30344
|
-
return [initial];
|
|
30345
|
-
const resultArray = [initial];
|
|
30346
|
-
coll.reduce((result, elem) => {
|
|
30347
|
-
const newVal = executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
30348
|
-
resultArray.push(newVal);
|
|
30349
|
-
return newVal;
|
|
30350
|
-
}, initial);
|
|
30351
|
-
return resultArray;
|
|
30352
|
-
}
|
|
30353
|
-
else {
|
|
30354
|
-
if (Object.keys(coll).length === 0)
|
|
30355
|
-
return [initial];
|
|
30356
|
-
const resultArray = [initial];
|
|
30357
|
-
Object.entries(coll).reduce((result, [, elem]) => {
|
|
30358
|
-
const newVal = executeFunction(fn, [result, elem], contextStack, sourceCodeInfo);
|
|
30359
|
-
resultArray.push(newVal);
|
|
30360
|
-
return newVal;
|
|
30361
|
-
}, initial);
|
|
30362
|
-
return resultArray;
|
|
30363
|
-
}
|
|
30937
|
+
});
|
|
30938
|
+
}, initial), () => resultArray);
|
|
30364
30939
|
},
|
|
30365
30940
|
arity: toFixedArity(3),
|
|
30366
30941
|
docs: {
|
|
@@ -30395,40 +30970,21 @@ cu.reductions(
|
|
|
30395
30970
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30396
30971
|
assertAny(initial, sourceCodeInfo);
|
|
30397
30972
|
assertAny(initial, sourceCodeInfo);
|
|
30398
|
-
|
|
30399
|
-
|
|
30400
|
-
|
|
30401
|
-
|
|
30402
|
-
|
|
30403
|
-
|
|
30404
|
-
|
|
30973
|
+
const toIndexedItem = (elem, key) => ({ elem, key });
|
|
30974
|
+
const items = typeof coll === 'string'
|
|
30975
|
+
? (assertString(initial, sourceCodeInfo), coll.length === 0 ? [] : coll.split('').map((elem, index) => toIndexedItem(elem, index)))
|
|
30976
|
+
: Array.isArray(coll)
|
|
30977
|
+
? (coll.length === 0 ? [] : coll.map((elem, index) => toIndexedItem(elem, index)))
|
|
30978
|
+
: (Object.keys(coll).length === 0 ? [] : Object.entries(coll).map(([key, v]) => toIndexedItem(v, key)));
|
|
30979
|
+
if (items.length === 0)
|
|
30980
|
+
return [initial];
|
|
30981
|
+
const resultArray = [initial];
|
|
30982
|
+
return chain(reduceSequential(items, (result, { elem, key }) => {
|
|
30983
|
+
return chain(executeFunction(fn, [result, elem, key], contextStack, sourceCodeInfo), (newVal) => {
|
|
30405
30984
|
resultArray.push(newVal);
|
|
30406
30985
|
return newVal;
|
|
30407
|
-
}
|
|
30408
|
-
|
|
30409
|
-
}
|
|
30410
|
-
else if (Array.isArray(coll)) {
|
|
30411
|
-
if (coll.length === 0)
|
|
30412
|
-
return [initial];
|
|
30413
|
-
const resultArray = [initial];
|
|
30414
|
-
coll.reduce((result, elem, index) => {
|
|
30415
|
-
const newVal = executeFunction(fn, [result, elem, index], contextStack, sourceCodeInfo);
|
|
30416
|
-
resultArray.push(newVal);
|
|
30417
|
-
return newVal;
|
|
30418
|
-
}, initial);
|
|
30419
|
-
return resultArray;
|
|
30420
|
-
}
|
|
30421
|
-
else {
|
|
30422
|
-
if (Object.keys(coll).length === 0)
|
|
30423
|
-
return [initial];
|
|
30424
|
-
const resultArray = [initial];
|
|
30425
|
-
Object.entries(coll).reduce((result, [key, elem]) => {
|
|
30426
|
-
const newVal = executeFunction(fn, [result, elem, key], contextStack, sourceCodeInfo);
|
|
30427
|
-
resultArray.push(newVal);
|
|
30428
|
-
return newVal;
|
|
30429
|
-
}, initial);
|
|
30430
|
-
return resultArray;
|
|
30431
|
-
}
|
|
30986
|
+
});
|
|
30987
|
+
}, initial), () => resultArray);
|
|
30432
30988
|
},
|
|
30433
30989
|
arity: toFixedArity(3),
|
|
30434
30990
|
docs: {
|
|
@@ -30491,11 +31047,12 @@ cu.reductions(
|
|
|
30491
31047
|
evaluate: ([coll, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
30492
31048
|
assertColl(coll, sourceCodeInfo);
|
|
30493
31049
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30494
|
-
|
|
30495
|
-
|
|
30496
|
-
|
|
30497
|
-
|
|
30498
|
-
|
|
31050
|
+
const arr = Array.isArray(coll)
|
|
31051
|
+
? coll
|
|
31052
|
+
: typeof coll === 'string'
|
|
31053
|
+
? coll.split('')
|
|
31054
|
+
: Object.entries(coll);
|
|
31055
|
+
return everySequential(arr, elem => executeFunction(fn, [elem], contextStack, sourceCodeInfo));
|
|
30499
31056
|
},
|
|
30500
31057
|
arity: toFixedArity(2),
|
|
30501
31058
|
docs: {
|
|
@@ -30545,11 +31102,12 @@ cu.every?(
|
|
|
30545
31102
|
evaluate: ([coll, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
30546
31103
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30547
31104
|
assertColl(coll, sourceCodeInfo);
|
|
30548
|
-
|
|
30549
|
-
|
|
30550
|
-
|
|
30551
|
-
|
|
30552
|
-
|
|
31105
|
+
const arr = Array.isArray(coll)
|
|
31106
|
+
? coll
|
|
31107
|
+
: typeof coll === 'string'
|
|
31108
|
+
? coll.split('')
|
|
31109
|
+
: Object.entries(coll);
|
|
31110
|
+
return someSequential(arr, elem => executeFunction(fn, [elem], contextStack, sourceCodeInfo));
|
|
30553
31111
|
},
|
|
30554
31112
|
arity: toFixedArity(2),
|
|
30555
31113
|
docs: {
|
|
@@ -30597,11 +31155,12 @@ cu.any?(
|
|
|
30597
31155
|
evaluate: ([coll, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
30598
31156
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30599
31157
|
assertColl(coll, sourceCodeInfo);
|
|
30600
|
-
|
|
30601
|
-
|
|
30602
|
-
|
|
30603
|
-
|
|
30604
|
-
|
|
31158
|
+
const arr = Array.isArray(coll)
|
|
31159
|
+
? coll
|
|
31160
|
+
: typeof coll === 'string'
|
|
31161
|
+
? coll.split('')
|
|
31162
|
+
: Object.entries(coll);
|
|
31163
|
+
return chain(someSequential(arr, elem => executeFunction(fn, [elem], contextStack, sourceCodeInfo)), result => !result);
|
|
30605
31164
|
},
|
|
30606
31165
|
arity: toFixedArity(2),
|
|
30607
31166
|
docs: {
|
|
@@ -30649,11 +31208,12 @@ cu.not-any?(
|
|
|
30649
31208
|
evaluate: ([coll, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
30650
31209
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
30651
31210
|
assertColl(coll, sourceCodeInfo);
|
|
30652
|
-
|
|
30653
|
-
|
|
30654
|
-
|
|
30655
|
-
|
|
30656
|
-
|
|
31211
|
+
const arr = Array.isArray(coll)
|
|
31212
|
+
? coll
|
|
31213
|
+
: typeof coll === 'string'
|
|
31214
|
+
? coll.split('')
|
|
31215
|
+
: Object.entries(coll);
|
|
31216
|
+
return chain(everySequential(arr, elem => executeFunction(fn, [elem], contextStack, sourceCodeInfo)), result => !result);
|
|
30657
31217
|
},
|
|
30658
31218
|
arity: toFixedArity(2),
|
|
30659
31219
|
docs: {
|
|
@@ -30710,14 +31270,8 @@ const sequenceUtilsFunctions = {
|
|
|
30710
31270
|
if (seq === null)
|
|
30711
31271
|
return null;
|
|
30712
31272
|
assertSeq(seq, sourceCodeInfo);
|
|
30713
|
-
|
|
30714
|
-
|
|
30715
|
-
return index !== -1 ? index : null;
|
|
30716
|
-
}
|
|
30717
|
-
else {
|
|
30718
|
-
const index = seq.findIndex(elem => executeFunction(fn, [elem], contextStack, sourceCodeInfo));
|
|
30719
|
-
return index !== -1 ? index : null;
|
|
30720
|
-
}
|
|
31273
|
+
const arr = typeof seq === 'string' ? seq.split('') : seq;
|
|
31274
|
+
return chain(findIndexSequential(arr, elem => executeFunction(fn, [elem], contextStack, sourceCodeInfo)), index => index !== -1 ? index : null);
|
|
30721
31275
|
},
|
|
30722
31276
|
arity: toFixedArity(2),
|
|
30723
31277
|
docs: {
|
|
@@ -30864,50 +31418,39 @@ su.position(
|
|
|
30864
31418
|
assertSeq(seq, sourceCodeInfo);
|
|
30865
31419
|
assertFunctionLike(keyfn, sourceCodeInfo);
|
|
30866
31420
|
const comparer = defaultComparer ? null : params[2];
|
|
30867
|
-
|
|
30868
|
-
|
|
31421
|
+
const isString = typeof seq === 'string';
|
|
31422
|
+
const arr = isString ? seq.split('') : [...seq];
|
|
31423
|
+
// Pre-compute all keys using mapSequential (async-safe)
|
|
31424
|
+
return chain(mapSequential(arr, elem => executeFunction(keyfn, [elem], contextStack, sourceCodeInfo)), (keys) => {
|
|
30869
31425
|
if (defaultComparer) {
|
|
30870
|
-
|
|
30871
|
-
|
|
30872
|
-
|
|
30873
|
-
|
|
30874
|
-
assertStringOrNumber(
|
|
30875
|
-
return compare(
|
|
31426
|
+
// Create indexed pairs, sort by pre-computed keys
|
|
31427
|
+
const indexed = arr.map((elem, i) => ({ elem, key: keys[i] }));
|
|
31428
|
+
indexed.sort((a, b) => {
|
|
31429
|
+
assertStringOrNumber(a.key, sourceCodeInfo);
|
|
31430
|
+
assertStringOrNumber(b.key, sourceCodeInfo);
|
|
31431
|
+
return compare(a.key, b.key, sourceCodeInfo);
|
|
30876
31432
|
});
|
|
31433
|
+
const sorted = indexed.map(x => x.elem);
|
|
31434
|
+
return isString ? sorted.join('') : sorted;
|
|
30877
31435
|
}
|
|
30878
31436
|
else {
|
|
30879
31437
|
assertFunctionLike(comparer, sourceCodeInfo);
|
|
30880
|
-
|
|
30881
|
-
|
|
30882
|
-
|
|
30883
|
-
|
|
31438
|
+
// Pre-compute keys, then need pairwise comparisons — these may also be async
|
|
31439
|
+
// For sort-by with custom comparer, we must use a non-async sort since
|
|
31440
|
+
// Array.sort requires sync comparators
|
|
31441
|
+
const indexed = arr.map((elem, i) => ({ elem, key: keys[i] }));
|
|
31442
|
+
indexed.sort((a, b) => {
|
|
31443
|
+
const compareValue = executeFunction(comparer, [a.key, b.key], contextStack, sourceCodeInfo);
|
|
31444
|
+
if (compareValue instanceof Promise) {
|
|
31445
|
+
throw new TypeError('Async functions cannot be used as sort-by comparators');
|
|
31446
|
+
}
|
|
30884
31447
|
assertNumber(compareValue, sourceCodeInfo, { finite: true });
|
|
30885
31448
|
return compareValue;
|
|
30886
31449
|
});
|
|
31450
|
+
const sorted = indexed.map(x => x.elem);
|
|
31451
|
+
return isString ? sorted.join('') : sorted;
|
|
30887
31452
|
}
|
|
30888
|
-
|
|
30889
|
-
}
|
|
30890
|
-
const result = [...seq];
|
|
30891
|
-
if (defaultComparer) {
|
|
30892
|
-
result.sort((a, b) => {
|
|
30893
|
-
const aKey = executeFunction(keyfn, [a], contextStack, sourceCodeInfo);
|
|
30894
|
-
assertStringOrNumber(aKey, sourceCodeInfo);
|
|
30895
|
-
const bKey = executeFunction(keyfn, [b], contextStack, sourceCodeInfo);
|
|
30896
|
-
assertStringOrNumber(bKey, sourceCodeInfo);
|
|
30897
|
-
return compare(aKey, bKey, sourceCodeInfo);
|
|
30898
|
-
});
|
|
30899
|
-
}
|
|
30900
|
-
else {
|
|
30901
|
-
assertFunctionLike(comparer, sourceCodeInfo);
|
|
30902
|
-
result.sort((a, b) => {
|
|
30903
|
-
const aKey = executeFunction(keyfn, [a], contextStack, sourceCodeInfo);
|
|
30904
|
-
const bKey = executeFunction(keyfn, [b], contextStack, sourceCodeInfo);
|
|
30905
|
-
const compareValue = executeFunction(comparer, [aKey, bKey], contextStack, sourceCodeInfo);
|
|
30906
|
-
assertNumber(compareValue, sourceCodeInfo, { finite: true });
|
|
30907
|
-
return compareValue;
|
|
30908
|
-
});
|
|
30909
|
-
}
|
|
30910
|
-
return result;
|
|
31453
|
+
});
|
|
30911
31454
|
},
|
|
30912
31455
|
arity: { min: 2, max: 3 },
|
|
30913
31456
|
docs: {
|
|
@@ -30933,202 +31476,6 @@ su.position(
|
|
|
30933
31476
|
],
|
|
30934
31477
|
},
|
|
30935
31478
|
},
|
|
30936
|
-
'take': {
|
|
30937
|
-
evaluate: ([input, n], sourceCodeInfo) => {
|
|
30938
|
-
assertNumber(n, sourceCodeInfo);
|
|
30939
|
-
assertSeq(input, sourceCodeInfo);
|
|
30940
|
-
const num = Math.max(Math.ceil(n), 0);
|
|
30941
|
-
return input.slice(0, num);
|
|
30942
|
-
},
|
|
30943
|
-
arity: toFixedArity(2),
|
|
30944
|
-
docs: {
|
|
30945
|
-
category: 'sequence',
|
|
30946
|
-
returns: { type: 'sequence' },
|
|
30947
|
-
args: {
|
|
30948
|
-
a: { type: 'sequence' },
|
|
30949
|
-
b: { type: 'integer' },
|
|
30950
|
-
n: { type: 'integer' },
|
|
30951
|
-
seq: { type: 'sequence' },
|
|
30952
|
-
},
|
|
30953
|
-
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
30954
|
-
description: 'Constructs a new array/string with the $n first elements from $seq.',
|
|
30955
|
-
seeAlso: ['sequence.take-last', 'sequence.take-while', 'sequence.drop', 'slice', 'sequence.split-at'],
|
|
30956
|
-
examples: [
|
|
30957
|
-
'let su = import("sequence"); su.take([1, 2, 3, 4, 5], 3)',
|
|
30958
|
-
'let su = import("sequence"); su.take([1, 2, 3, 4, 5], 3)',
|
|
30959
|
-
'let su = import("sequence"); su.take([1, 2, 3, 4, 5], 0)',
|
|
30960
|
-
'let su = import("sequence"); su.take("Albert", 2)',
|
|
30961
|
-
'let su = import("sequence"); su.take("Albert", 50)',
|
|
30962
|
-
],
|
|
30963
|
-
},
|
|
30964
|
-
},
|
|
30965
|
-
'take-last': {
|
|
30966
|
-
evaluate: ([array, n], sourceCodeInfo) => {
|
|
30967
|
-
assertSeq(array, sourceCodeInfo);
|
|
30968
|
-
assertNumber(n, sourceCodeInfo);
|
|
30969
|
-
const num = Math.max(Math.ceil(n), 0);
|
|
30970
|
-
const from = array.length - num;
|
|
30971
|
-
return array.slice(from);
|
|
30972
|
-
},
|
|
30973
|
-
arity: toFixedArity(2),
|
|
30974
|
-
docs: {
|
|
30975
|
-
category: 'sequence',
|
|
30976
|
-
returns: { type: 'sequence' },
|
|
30977
|
-
args: {
|
|
30978
|
-
a: { type: 'sequence' },
|
|
30979
|
-
b: { type: 'integer' },
|
|
30980
|
-
n: { type: 'integer' },
|
|
30981
|
-
seq: { type: 'sequence' },
|
|
30982
|
-
},
|
|
30983
|
-
variants: [{ argumentNames: ['n', 'seq'] }],
|
|
30984
|
-
description: 'Constructs a new array with the $n last elements from $seq.',
|
|
30985
|
-
seeAlso: ['sequence.take', 'sequence.drop-last'],
|
|
30986
|
-
examples: [
|
|
30987
|
-
'let su = import("sequence"); su.take-last([1, 2, 3, 4, 5], 3)',
|
|
30988
|
-
'let su = import("sequence"); su.take-last([1, 2, 3, 4, 5], 3)',
|
|
30989
|
-
'let su = import("sequence"); su.take-last([1, 2, 3, 4, 5], 0)',
|
|
30990
|
-
],
|
|
30991
|
-
},
|
|
30992
|
-
},
|
|
30993
|
-
'take-while': {
|
|
30994
|
-
evaluate: ([seq, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
30995
|
-
assertSeq(seq, sourceCodeInfo);
|
|
30996
|
-
assertFunctionLike(fn, sourceCodeInfo);
|
|
30997
|
-
const result = [];
|
|
30998
|
-
for (const item of seq) {
|
|
30999
|
-
if (executeFunction(fn, [item], contextStack, sourceCodeInfo))
|
|
31000
|
-
result.push(item);
|
|
31001
|
-
else
|
|
31002
|
-
break;
|
|
31003
|
-
}
|
|
31004
|
-
return typeof seq === 'string' ? result.join('') : result;
|
|
31005
|
-
},
|
|
31006
|
-
arity: toFixedArity(2),
|
|
31007
|
-
docs: {
|
|
31008
|
-
category: 'sequence',
|
|
31009
|
-
returns: { type: 'sequence' },
|
|
31010
|
-
args: {
|
|
31011
|
-
a: { type: 'sequence' },
|
|
31012
|
-
b: { type: 'function' },
|
|
31013
|
-
seq: { type: 'sequence' },
|
|
31014
|
-
fun: { type: 'function' },
|
|
31015
|
-
},
|
|
31016
|
-
variants: [{ argumentNames: ['seq', 'fun'] }],
|
|
31017
|
-
description: 'Returns the members of $seq in order, stopping before the first one for which `predicate` returns a falsy value.',
|
|
31018
|
-
seeAlso: ['sequence.take', 'sequence.drop-while', 'sequence.split-with'],
|
|
31019
|
-
examples: [
|
|
31020
|
-
`
|
|
31021
|
-
let su = import("sequence");
|
|
31022
|
-
su.take-while(
|
|
31023
|
-
[1, 2, 3, 2, 1],
|
|
31024
|
-
-> $ < 3
|
|
31025
|
-
)`,
|
|
31026
|
-
`
|
|
31027
|
-
let su = import("sequence");
|
|
31028
|
-
su.take-while(
|
|
31029
|
-
[1, 2, 3, 2, 1],
|
|
31030
|
-
-> $ > 3
|
|
31031
|
-
)`,
|
|
31032
|
-
],
|
|
31033
|
-
},
|
|
31034
|
-
},
|
|
31035
|
-
'drop': {
|
|
31036
|
-
evaluate: ([input, n], sourceCodeInfo) => {
|
|
31037
|
-
assertNumber(n, sourceCodeInfo);
|
|
31038
|
-
const num = Math.max(Math.ceil(n), 0);
|
|
31039
|
-
assertSeq(input, sourceCodeInfo);
|
|
31040
|
-
return input.slice(num);
|
|
31041
|
-
},
|
|
31042
|
-
arity: toFixedArity(2),
|
|
31043
|
-
docs: {
|
|
31044
|
-
category: 'sequence',
|
|
31045
|
-
returns: { type: 'sequence' },
|
|
31046
|
-
args: {
|
|
31047
|
-
a: { type: 'sequence' },
|
|
31048
|
-
b: { type: 'integer' },
|
|
31049
|
-
seq: { type: 'sequence' },
|
|
31050
|
-
n: { type: 'integer' },
|
|
31051
|
-
},
|
|
31052
|
-
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
31053
|
-
description: 'Constructs a new array/string with the $n first elements dropped from $seq.',
|
|
31054
|
-
seeAlso: ['sequence.drop-last', 'sequence.drop-while', 'sequence.take', 'slice', 'sequence.split-at'],
|
|
31055
|
-
examples: [
|
|
31056
|
-
'let su = import("sequence"); su.drop([1, 2, 3, 4, 5], 3)',
|
|
31057
|
-
'let su = import("sequence"); su.drop([1, 2, 3, 4, 5], 0)',
|
|
31058
|
-
'let su = import("sequence"); su.drop("Albert", 2)',
|
|
31059
|
-
'let su = import("sequence"); su.drop("Albert", 50)',
|
|
31060
|
-
],
|
|
31061
|
-
},
|
|
31062
|
-
},
|
|
31063
|
-
'drop-last': {
|
|
31064
|
-
evaluate: ([array, n], sourceCodeInfo) => {
|
|
31065
|
-
assertSeq(array, sourceCodeInfo);
|
|
31066
|
-
assertNumber(n, sourceCodeInfo);
|
|
31067
|
-
const num = Math.max(Math.ceil(n), 0);
|
|
31068
|
-
const from = array.length - num;
|
|
31069
|
-
return array.slice(0, from);
|
|
31070
|
-
},
|
|
31071
|
-
arity: toFixedArity(2),
|
|
31072
|
-
docs: {
|
|
31073
|
-
category: 'sequence',
|
|
31074
|
-
returns: { type: 'sequence' },
|
|
31075
|
-
args: {
|
|
31076
|
-
a: { type: 'sequence' },
|
|
31077
|
-
b: { type: 'integer' },
|
|
31078
|
-
seq: { type: 'sequence' },
|
|
31079
|
-
n: { type: 'integer' },
|
|
31080
|
-
},
|
|
31081
|
-
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
31082
|
-
description: 'Constructs a new array with the $n last elements dropped from $seq.',
|
|
31083
|
-
seeAlso: ['sequence.drop', 'sequence.take-last'],
|
|
31084
|
-
examples: [
|
|
31085
|
-
'let su = import("sequence"); su.drop-last([1, 2, 3, 4, 5], 3)',
|
|
31086
|
-
'let su = import("sequence"); su.drop-last([1, 2, 3, 4, 5], 3)',
|
|
31087
|
-
'let su = import("sequence"); su.drop-last([1, 2, 3, 4, 5], 0)',
|
|
31088
|
-
],
|
|
31089
|
-
},
|
|
31090
|
-
},
|
|
31091
|
-
'drop-while': {
|
|
31092
|
-
evaluate: ([seq, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
31093
|
-
assertSeq(seq, sourceCodeInfo);
|
|
31094
|
-
assertFunctionLike(fn, sourceCodeInfo);
|
|
31095
|
-
if (Array.isArray(seq)) {
|
|
31096
|
-
const from = seq.findIndex(elem => !executeFunction(fn, [elem], contextStack, sourceCodeInfo));
|
|
31097
|
-
return seq.slice(from);
|
|
31098
|
-
}
|
|
31099
|
-
const charArray = seq.split('');
|
|
31100
|
-
const from = charArray.findIndex(elem => !executeFunction(fn, [elem], contextStack, sourceCodeInfo));
|
|
31101
|
-
return charArray.slice(from).join('');
|
|
31102
|
-
},
|
|
31103
|
-
arity: toFixedArity(2),
|
|
31104
|
-
docs: {
|
|
31105
|
-
category: 'sequence',
|
|
31106
|
-
returns: { type: 'sequence' },
|
|
31107
|
-
args: {
|
|
31108
|
-
a: { type: 'sequence' },
|
|
31109
|
-
b: { type: 'function' },
|
|
31110
|
-
seq: { type: 'sequence' },
|
|
31111
|
-
fun: { type: 'function' },
|
|
31112
|
-
},
|
|
31113
|
-
variants: [{ argumentNames: ['seq', 'fun'] }],
|
|
31114
|
-
description: 'Returns the members of $seq in order, skipping the fist elements for witch the `predicate` returns a truethy value.',
|
|
31115
|
-
seeAlso: ['sequence.drop', 'sequence.take-while', 'sequence.split-with'],
|
|
31116
|
-
examples: [
|
|
31117
|
-
`
|
|
31118
|
-
let su = import("sequence");
|
|
31119
|
-
su.drop-while(
|
|
31120
|
-
[1, 2, 3, 2, 1],
|
|
31121
|
-
-> $ < 3
|
|
31122
|
-
)`,
|
|
31123
|
-
`
|
|
31124
|
-
let su = import("sequence");
|
|
31125
|
-
su.drop-while(
|
|
31126
|
-
[1, 2, 3, 2, 1],
|
|
31127
|
-
-> $ > 3
|
|
31128
|
-
)`,
|
|
31129
|
-
],
|
|
31130
|
-
},
|
|
31131
|
-
},
|
|
31132
31479
|
'unshift': {
|
|
31133
31480
|
evaluate: ([seq, ...values], sourceCodeInfo) => {
|
|
31134
31481
|
assertSeq(seq, sourceCodeInfo);
|
|
@@ -31201,12 +31548,8 @@ l`,
|
|
|
31201
31548
|
evaluate: ([input, fn], sourceCodeInfo, contextStack, { executeFunction }) => {
|
|
31202
31549
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
31203
31550
|
assertSeq(input, sourceCodeInfo);
|
|
31204
|
-
|
|
31205
|
-
|
|
31206
|
-
return input
|
|
31207
|
-
.split('')
|
|
31208
|
-
.filter(elem => !executeFunction(fn, [elem], contextStack, sourceCodeInfo))
|
|
31209
|
-
.join('');
|
|
31551
|
+
const arr = Array.isArray(input) ? input : input.split('');
|
|
31552
|
+
return chain(filterSequential(arr, elem => chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), result => !result)), filtered => typeof input === 'string' ? filtered.join('') : filtered);
|
|
31210
31553
|
},
|
|
31211
31554
|
arity: toFixedArity(2),
|
|
31212
31555
|
docs: {
|
|
@@ -31281,7 +31624,7 @@ l`,
|
|
|
31281
31624
|
},
|
|
31282
31625
|
variants: [{ argumentNames: ['seq', 'n'] }],
|
|
31283
31626
|
description: 'Returns a pair of sequence `[take(pos input), drop(pos input)]`.',
|
|
31284
|
-
seeAlso: ['sequence.split-with', '
|
|
31627
|
+
seeAlso: ['sequence.split-with', 'take', 'drop'],
|
|
31285
31628
|
examples: [
|
|
31286
31629
|
'let su = import("sequence"); su.split-at([1, 2, 3, 4, 5], 2)',
|
|
31287
31630
|
'let su = import("sequence"); su.split-at("Albert", -2)',
|
|
@@ -31296,10 +31639,11 @@ l`,
|
|
|
31296
31639
|
assertSeq(seq, sourceCodeInfo);
|
|
31297
31640
|
const seqIsArray = Array.isArray(seq);
|
|
31298
31641
|
const arr = seqIsArray ? seq : seq.split('');
|
|
31299
|
-
|
|
31300
|
-
|
|
31301
|
-
|
|
31302
|
-
|
|
31642
|
+
return chain(findIndexSequential(arr, elem => chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), result => !result)), (index) => {
|
|
31643
|
+
if (index === -1)
|
|
31644
|
+
return [seq, seqIsArray ? [] : ''];
|
|
31645
|
+
return [seq.slice(0, index), seq.slice(index)];
|
|
31646
|
+
});
|
|
31303
31647
|
},
|
|
31304
31648
|
arity: toFixedArity(2),
|
|
31305
31649
|
docs: {
|
|
@@ -31313,7 +31657,7 @@ l`,
|
|
|
31313
31657
|
},
|
|
31314
31658
|
variants: [{ argumentNames: ['seq', 'fun'] }],
|
|
31315
31659
|
description: 'Returns a pair of sequences `[take-while(input, fun), drop-while(input, fun)]`.',
|
|
31316
|
-
seeAlso: ['sequence.split-at', '
|
|
31660
|
+
seeAlso: ['sequence.split-at', 'take-while', 'drop-while'],
|
|
31317
31661
|
examples: [
|
|
31318
31662
|
'let su = import("sequence"); su.split-with([1, 2, 3, 4, 5], odd?)',
|
|
31319
31663
|
'let su = import("sequence"); su.split-with([1, 2, 3, 4, 5], -> $ > 3)',
|
|
@@ -31353,13 +31697,14 @@ l`,
|
|
|
31353
31697
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
31354
31698
|
assertSeq(seq, sourceCodeInfo);
|
|
31355
31699
|
const arr = Array.isArray(seq) ? seq : seq.split('');
|
|
31356
|
-
return arr
|
|
31357
|
-
|
|
31358
|
-
|
|
31359
|
-
|
|
31360
|
-
|
|
31361
|
-
|
|
31362
|
-
|
|
31700
|
+
return reduceSequential(arr, (result, val) => {
|
|
31701
|
+
return chain(executeFunction(fn, [val], contextStack, sourceCodeInfo), (key) => {
|
|
31702
|
+
assertString(key, sourceCodeInfo);
|
|
31703
|
+
if (!collHasKey(result, key))
|
|
31704
|
+
result[key] = [];
|
|
31705
|
+
result[key].push(val);
|
|
31706
|
+
return result;
|
|
31707
|
+
});
|
|
31363
31708
|
}, {});
|
|
31364
31709
|
},
|
|
31365
31710
|
arity: toFixedArity(2),
|
|
@@ -31468,17 +31813,17 @@ l`,
|
|
|
31468
31813
|
assertFunctionLike(fn, sourceCodeInfo);
|
|
31469
31814
|
assertSeq(seq, sourceCodeInfo);
|
|
31470
31815
|
const isStringSeq = typeof seq === 'string';
|
|
31471
|
-
|
|
31472
|
-
|
|
31473
|
-
|
|
31474
|
-
|
|
31475
|
-
|
|
31476
|
-
|
|
31477
|
-
|
|
31478
|
-
|
|
31479
|
-
|
|
31480
|
-
|
|
31481
|
-
|
|
31816
|
+
const arr = isStringSeq ? seq.split('') : seq;
|
|
31817
|
+
return chain(reduceSequential(arr, (acc, elem) => {
|
|
31818
|
+
return chain(executeFunction(fn, [elem], contextStack, sourceCodeInfo), (value) => {
|
|
31819
|
+
if (value !== acc.oldValue) {
|
|
31820
|
+
acc.result.push([]);
|
|
31821
|
+
acc.oldValue = value;
|
|
31822
|
+
}
|
|
31823
|
+
acc.result[acc.result.length - 1].push(elem);
|
|
31824
|
+
return acc;
|
|
31825
|
+
});
|
|
31826
|
+
}, { result: [], oldValue: undefined }), ({ result }) => isStringSeq ? result.map(elem => elem.join('')) : result);
|
|
31482
31827
|
},
|
|
31483
31828
|
arity: toFixedArity(2),
|
|
31484
31829
|
docs: {
|
|
@@ -32734,6 +33079,12 @@ const api = {
|
|
|
32734
33079
|
'next',
|
|
32735
33080
|
'sort',
|
|
32736
33081
|
'slice',
|
|
33082
|
+
'take',
|
|
33083
|
+
'take-last',
|
|
33084
|
+
'drop',
|
|
33085
|
+
'drop-last',
|
|
33086
|
+
'take-while',
|
|
33087
|
+
'drop-while',
|
|
32737
33088
|
],
|
|
32738
33089
|
sequenceUtils: [
|
|
32739
33090
|
'sequence.position',
|
|
@@ -32742,12 +33093,6 @@ const api = {
|
|
|
32742
33093
|
'sequence.unshift',
|
|
32743
33094
|
'sequence.splice',
|
|
32744
33095
|
'sequence.sort-by',
|
|
32745
|
-
'sequence.take',
|
|
32746
|
-
'sequence.take-last',
|
|
32747
|
-
'sequence.take-while',
|
|
32748
|
-
'sequence.drop',
|
|
32749
|
-
'sequence.drop-last',
|
|
32750
|
-
'sequence.drop-while',
|
|
32751
33096
|
'sequence.distinct',
|
|
32752
33097
|
'sequence.remove',
|
|
32753
33098
|
'sequence.remove-at',
|
|
@@ -32823,13 +33168,13 @@ const api = {
|
|
|
32823
33168
|
'arity',
|
|
32824
33169
|
],
|
|
32825
33170
|
misc: [
|
|
32826
|
-
'
|
|
33171
|
+
'!=',
|
|
32827
33172
|
'==',
|
|
32828
33173
|
'<',
|
|
32829
33174
|
'>',
|
|
32830
33175
|
'<=',
|
|
32831
33176
|
'>=',
|
|
32832
|
-
'
|
|
33177
|
+
'not',
|
|
32833
33178
|
'write!',
|
|
32834
33179
|
'iso-date->epoch',
|
|
32835
33180
|
'epoch->iso-date',
|