@grain/stdlib 0.5.3 → 0.5.4
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/CHANGELOG.md +38 -0
- package/array.gr +5 -0
- package/array.md +30 -0
- package/char.gr +2 -2
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +33 -5
- package/immutablepriorityqueue.md +44 -1
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/list.gr +2 -2
- package/marshal.gr +4 -4
- package/number.gr +648 -23
- package/number.md +284 -24
- package/package.json +1 -1
- package/priorityqueue.gr +25 -5
- package/priorityqueue.md +30 -0
- package/queue.gr +14 -1
- package/queue.md +16 -1
- package/regex.gr +85 -62
- package/runtime/bigint.gr +4 -4
- package/runtime/compare.gr +2 -1
- package/runtime/equal.gr +2 -1
- package/runtime/exception.gr +9 -5
- package/runtime/exception.md +8 -2
- package/runtime/gc.gr +2 -1
- package/runtime/malloc.gr +1 -3
- package/runtime/numberUtils.gr +11 -11
- package/runtime/numbers.gr +120 -36
- package/runtime/numbers.md +26 -0
- package/runtime/string.gr +4 -2
- package/set.gr +25 -25
- package/stack.gr +12 -0
- package/stack.md +15 -0
- package/string.gr +312 -38
- package/string.md +99 -0
- package/sys/file.gr +1 -1
package/runtime/numbers.gr
CHANGED
|
@@ -79,7 +79,7 @@ export let isFloat = x => {
|
|
|
79
79
|
if (isBoxedNumber(x)) {
|
|
80
80
|
let tag = WasmI32.load(x, 4n)
|
|
81
81
|
WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) ||
|
|
82
|
-
|
|
82
|
+
WasmI32.eq(tag, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
83
83
|
} else {
|
|
84
84
|
false
|
|
85
85
|
}
|
|
@@ -90,8 +90,8 @@ export let isInteger = x => {
|
|
|
90
90
|
if (isBoxedNumber(x)) {
|
|
91
91
|
let tag = WasmI32.load(x, 4n)
|
|
92
92
|
WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG) ||
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG) ||
|
|
94
|
+
WasmI32.eq(tag, Tags._GRAIN_BIGINT_BOXED_NUM_TAG)
|
|
95
95
|
} else {
|
|
96
96
|
true
|
|
97
97
|
}
|
|
@@ -518,13 +518,13 @@ let isIntegerF64 = value => {
|
|
|
518
518
|
@unsafe
|
|
519
519
|
let isSafeIntegerF32 = value => {
|
|
520
520
|
WasmF32.le(WasmF32.abs(value), _F32_MAX_SAFE_INTEGER) &&
|
|
521
|
-
|
|
521
|
+
WasmF32.eq(WasmF32.trunc(value), value)
|
|
522
522
|
}
|
|
523
523
|
|
|
524
524
|
@unsafe
|
|
525
525
|
let isSafeIntegerF64 = value => {
|
|
526
526
|
WasmF64.le(WasmF64.abs(value), _F64_MAX_SAFE_INTEGER) &&
|
|
527
|
-
|
|
527
|
+
WasmF64.eq(WasmF64.trunc(value), value)
|
|
528
528
|
}
|
|
529
529
|
|
|
530
530
|
/** Number-aware equality checking
|
|
@@ -564,12 +564,12 @@ let numberEqualSimpleHelp = (x, y) => {
|
|
|
564
564
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
565
565
|
let yBoxedVal = boxedFloat32Number(y)
|
|
566
566
|
isSafeIntegerF32(yBoxedVal) &&
|
|
567
|
-
|
|
567
|
+
WasmF32.eq(WasmF32.convertI32S(xval), yBoxedVal)
|
|
568
568
|
},
|
|
569
569
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
570
570
|
let yBoxedVal = boxedFloat64Number(y)
|
|
571
571
|
isSafeIntegerF64(yBoxedVal) &&
|
|
572
|
-
|
|
572
|
+
WasmF64.eq(WasmF64.convertI32S(xval), yBoxedVal)
|
|
573
573
|
},
|
|
574
574
|
_ => {
|
|
575
575
|
throw UnknownNumberTag
|
|
@@ -606,12 +606,12 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
606
606
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
607
607
|
let yBoxedVal = boxedFloat32Number(y)
|
|
608
608
|
isSafeIntegerF32(yBoxedVal) &&
|
|
609
|
-
|
|
609
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF32S(yBoxedVal))
|
|
610
610
|
},
|
|
611
611
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
612
612
|
let yBoxedVal = boxedFloat64Number(y)
|
|
613
613
|
isSafeIntegerF64(yBoxedVal) &&
|
|
614
|
-
|
|
614
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF64S(yBoxedVal))
|
|
615
615
|
},
|
|
616
616
|
_ => {
|
|
617
617
|
throw UnknownNumberTag
|
|
@@ -843,14 +843,16 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
843
843
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
844
844
|
let xval = WasmI64.extendI32S(xval)
|
|
845
845
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
846
|
-
let result =
|
|
846
|
+
let result =
|
|
847
|
+
if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
847
848
|
else WasmI64.add(xval, yBoxedVal)
|
|
848
849
|
reducedInteger(result)
|
|
849
850
|
},
|
|
850
851
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
851
852
|
let yBoxedVal = boxedInt64Number(y)
|
|
852
853
|
let xval64 = WasmI64.extendI32S(xval)
|
|
853
|
-
let result =
|
|
854
|
+
let result =
|
|
855
|
+
if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
854
856
|
else WasmI64.add(xval64, yBoxedVal)
|
|
855
857
|
if (
|
|
856
858
|
WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64) ||
|
|
@@ -884,7 +886,8 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
884
886
|
let yDenominator = boxedRationalDenominator(y)
|
|
885
887
|
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
886
888
|
Memory.decRef(xBig)
|
|
887
|
-
let result =
|
|
889
|
+
let result =
|
|
890
|
+
if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
888
891
|
else BI.add(expandedXNumerator, yNumerator)
|
|
889
892
|
let ret = reducedFractionBigInt(result, yDenominator)
|
|
890
893
|
Memory.decRef(expandedXNumerator)
|
|
@@ -894,14 +897,16 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
894
897
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
895
898
|
let yBoxedVal = boxedFloat32Number(y)
|
|
896
899
|
let xval = WasmF32.convertI32S(xval)
|
|
897
|
-
let result =
|
|
900
|
+
let result =
|
|
901
|
+
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
898
902
|
else WasmF32.add(xval, yBoxedVal)
|
|
899
903
|
newFloat32(result)
|
|
900
904
|
},
|
|
901
905
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
902
906
|
let yBoxedVal = boxedFloat64Number(y)
|
|
903
907
|
let xval = WasmF64.convertI32S(xval)
|
|
904
|
-
let result =
|
|
908
|
+
let result =
|
|
909
|
+
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
905
910
|
else WasmF64.add(xval, yBoxedVal)
|
|
906
911
|
newFloat64(result)
|
|
907
912
|
},
|
|
@@ -940,14 +945,16 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
940
945
|
match (yBoxedNumberTag) {
|
|
941
946
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
942
947
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
943
|
-
let result =
|
|
948
|
+
let result =
|
|
949
|
+
if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
944
950
|
else WasmI64.add(xval, yBoxedVal)
|
|
945
951
|
reducedInteger(result)
|
|
946
952
|
},
|
|
947
953
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
948
954
|
let yBoxedVal = boxedInt64Number(y)
|
|
949
955
|
let xval64 = xval
|
|
950
|
-
let result =
|
|
956
|
+
let result =
|
|
957
|
+
if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
951
958
|
else WasmI64.add(xval64, yBoxedVal)
|
|
952
959
|
if (
|
|
953
960
|
WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64) ||
|
|
@@ -981,7 +988,8 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
981
988
|
let yDenominator = boxedRationalDenominator(y)
|
|
982
989
|
let expandedXNumerator = BI.mul(xBig, yDenominator)
|
|
983
990
|
Memory.decRef(xBig)
|
|
984
|
-
let result =
|
|
991
|
+
let result =
|
|
992
|
+
if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
985
993
|
else BI.add(expandedXNumerator, yNumerator)
|
|
986
994
|
let ret = reducedFractionBigInt(result, yDenominator)
|
|
987
995
|
Memory.decRef(expandedXNumerator)
|
|
@@ -991,14 +999,16 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
991
999
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
992
1000
|
let xval = WasmF32.convertI64S(xval)
|
|
993
1001
|
let yBoxedVal = boxedFloat32Number(y)
|
|
994
|
-
let result =
|
|
1002
|
+
let result =
|
|
1003
|
+
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
995
1004
|
else WasmF32.add(xval, yBoxedVal)
|
|
996
1005
|
newFloat32(result)
|
|
997
1006
|
},
|
|
998
1007
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
999
1008
|
let xval = WasmF64.convertI64S(xval)
|
|
1000
1009
|
let yBoxedVal = boxedFloat64Number(y)
|
|
1001
|
-
let result =
|
|
1010
|
+
let result =
|
|
1011
|
+
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
1002
1012
|
else WasmF64.add(xval, yBoxedVal)
|
|
1003
1013
|
newFloat64(result)
|
|
1004
1014
|
},
|
|
@@ -1092,7 +1102,8 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1092
1102
|
let yNumerator = boxedRationalNumerator(y)
|
|
1093
1103
|
let yDenominator = boxedRationalDenominator(y)
|
|
1094
1104
|
let expandedXNumerator = BI.mul(x, yDenominator)
|
|
1095
|
-
let result =
|
|
1105
|
+
let result =
|
|
1106
|
+
if (isSub) BI.sub(expandedXNumerator, yNumerator)
|
|
1096
1107
|
else BI.add(expandedXNumerator, yNumerator)
|
|
1097
1108
|
Memory.decRef(expandedXNumerator)
|
|
1098
1109
|
let ret = reducedFractionBigInt(result, yDenominator)
|
|
@@ -1102,14 +1113,16 @@ let numberAddSubBigIntHelp = (x, y, isSub) => {
|
|
|
1102
1113
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1103
1114
|
let xval = BI.toFloat32(x)
|
|
1104
1115
|
let yBoxedVal = boxedFloat32Number(y)
|
|
1105
|
-
let result =
|
|
1116
|
+
let result =
|
|
1117
|
+
if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
1106
1118
|
else WasmF32.add(xval, yBoxedVal)
|
|
1107
1119
|
newFloat32(result)
|
|
1108
1120
|
},
|
|
1109
1121
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1110
1122
|
let xval = BI.toFloat64(x)
|
|
1111
1123
|
let yBoxedVal = boxedFloat64Number(y)
|
|
1112
|
-
let result =
|
|
1124
|
+
let result =
|
|
1125
|
+
if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
1113
1126
|
else WasmF64.add(xval, yBoxedVal)
|
|
1114
1127
|
newFloat64(result)
|
|
1115
1128
|
},
|
|
@@ -1128,7 +1141,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1128
1141
|
let yval = untagSimple(y)
|
|
1129
1142
|
let yBig = BI.makeWrappedInt32(yval)
|
|
1130
1143
|
let expandedYNumerator = BI.mul(xDenominator, yBig)
|
|
1131
|
-
let result =
|
|
1144
|
+
let result =
|
|
1145
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1132
1146
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1133
1147
|
Memory.decRef(expandedYNumerator)
|
|
1134
1148
|
Memory.decRef(yBig)
|
|
@@ -1145,7 +1159,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1145
1159
|
let yNumerator = boxedRationalNumerator(y)
|
|
1146
1160
|
let yDenominator = boxedRationalDenominator(y)
|
|
1147
1161
|
if (BI.eq(xDenominator, yDenominator)) {
|
|
1148
|
-
let newNumerator =
|
|
1162
|
+
let newNumerator =
|
|
1163
|
+
if (isSub) BI.sub(xNumerator, yNumerator)
|
|
1149
1164
|
else BI.add(xNumerator, yNumerator)
|
|
1150
1165
|
let ret = reducedFractionBigInt(newNumerator, xDenominator)
|
|
1151
1166
|
Memory.decRef(newNumerator)
|
|
@@ -1153,7 +1168,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1153
1168
|
} else {
|
|
1154
1169
|
let numerator1 = BI.mul(xNumerator, yDenominator)
|
|
1155
1170
|
let numerator2 = BI.mul(yNumerator, xDenominator)
|
|
1156
|
-
let numerator =
|
|
1171
|
+
let numerator =
|
|
1172
|
+
if (isSub) BI.sub(numerator1, numerator2)
|
|
1157
1173
|
else BI.add(numerator1, numerator2)
|
|
1158
1174
|
let denominator = BI.mul(xDenominator, yDenominator)
|
|
1159
1175
|
let ret = reducedFractionBigInt(numerator, denominator)
|
|
@@ -1167,7 +1183,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1167
1183
|
let yBig = BI.makeWrappedInt32(boxedInt32Number(y))
|
|
1168
1184
|
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1169
1185
|
Memory.decRef(yBig)
|
|
1170
|
-
let result =
|
|
1186
|
+
let result =
|
|
1187
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1171
1188
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1172
1189
|
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1173
1190
|
Memory.decRef(expandedYNumerator)
|
|
@@ -1178,7 +1195,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1178
1195
|
let yBig = BI.makeWrappedInt64(boxedInt64Number(y))
|
|
1179
1196
|
let expandedYNumerator = BI.mul(yBig, xDenominator)
|
|
1180
1197
|
Memory.decRef(yBig)
|
|
1181
|
-
let result =
|
|
1198
|
+
let result =
|
|
1199
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1182
1200
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1183
1201
|
let ret = reducedFractionBigInt(result, xDenominator)
|
|
1184
1202
|
Memory.decRef(expandedYNumerator)
|
|
@@ -1187,7 +1205,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1187
1205
|
},
|
|
1188
1206
|
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1189
1207
|
let expandedYNumerator = BI.mul(xDenominator, y)
|
|
1190
|
-
let result =
|
|
1208
|
+
let result =
|
|
1209
|
+
if (isSub) BI.sub(xNumerator, expandedYNumerator)
|
|
1191
1210
|
else BI.add(xNumerator, expandedYNumerator)
|
|
1192
1211
|
Memory.decRef(expandedYNumerator)
|
|
1193
1212
|
let ret = reducedFractionBigInt(result, xDenominator)
|
|
@@ -1199,7 +1218,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1199
1218
|
BI.toFloat32(xNumerator),
|
|
1200
1219
|
BI.toFloat32(xDenominator)
|
|
1201
1220
|
)
|
|
1202
|
-
let result =
|
|
1221
|
+
let result =
|
|
1222
|
+
if (isSub) WasmF32.sub(xval, boxedFloat32Number(y))
|
|
1203
1223
|
else WasmF32.add(xval, boxedFloat32Number(y))
|
|
1204
1224
|
newFloat32(result)
|
|
1205
1225
|
},
|
|
@@ -1208,8 +1228,8 @@ let numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
1208
1228
|
let xdenfloat = BI.toFloat64(xDenominator)
|
|
1209
1229
|
let xval = WasmF64.div(xnumfloat, xdenfloat)
|
|
1210
1230
|
let yval = boxedFloat64Number(y)
|
|
1211
|
-
let result =
|
|
1212
|
-
else WasmF64.add(xval, yval)
|
|
1231
|
+
let result =
|
|
1232
|
+
if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
1213
1233
|
let ret = newFloat64(result)
|
|
1214
1234
|
ret
|
|
1215
1235
|
},
|
|
@@ -1404,6 +1424,13 @@ let numberTimesDivideBigIntHelp = (x, y, isDivide) => {
|
|
|
1404
1424
|
Memory.decRef(yBig)
|
|
1405
1425
|
ret
|
|
1406
1426
|
},
|
|
1427
|
+
t when WasmI32.eq(t, Tags._GRAIN_BIGINT_BOXED_NUM_TAG) => {
|
|
1428
|
+
if (isDivide) {
|
|
1429
|
+
reducedBigInteger(BI.div(x, y))
|
|
1430
|
+
} else {
|
|
1431
|
+
reducedBigInteger(BI.mul(x, y))
|
|
1432
|
+
}
|
|
1433
|
+
},
|
|
1407
1434
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
1408
1435
|
let yNumerator = boxedRationalNumerator(y)
|
|
1409
1436
|
let yDenominator = boxedRationalDenominator(y)
|
|
@@ -1548,9 +1575,11 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
1548
1575
|
let yDenominator = boxedRationalDenominator(y)
|
|
1549
1576
|
// (a / b) * (c / d) == (a * c) / (b * d)
|
|
1550
1577
|
// (a / b) / (c / d) == (a * d) / (b * c)
|
|
1551
|
-
let numerator =
|
|
1578
|
+
let numerator =
|
|
1579
|
+
if (isDivide) BI.mul(xNumerator, yDenominator)
|
|
1552
1580
|
else BI.mul(xNumerator, yNumerator)
|
|
1553
|
-
let denominator =
|
|
1581
|
+
let denominator =
|
|
1582
|
+
if (isDivide) BI.mul(xDenominator, yNumerator)
|
|
1554
1583
|
else BI.mul(xDenominator, yDenominator)
|
|
1555
1584
|
reducedFractionBigInt(numerator, denominator)
|
|
1556
1585
|
},
|
|
@@ -1686,7 +1715,8 @@ let numberMod = (x, y) => {
|
|
|
1686
1715
|
WasmI64.gtS(xval, 0N) && WasmI64.ltS(yval, 0N)
|
|
1687
1716
|
) {
|
|
1688
1717
|
let modval = WasmI64.remS(i64abs(xval), i64abs(yval))
|
|
1689
|
-
let result =
|
|
1718
|
+
let result =
|
|
1719
|
+
if (WasmI64.ne(modval, 0N))
|
|
1690
1720
|
WasmI64.mul(
|
|
1691
1721
|
WasmI64.sub(i64abs(yval), modval),
|
|
1692
1722
|
if (WasmI64.ltS(yval, 0N)) -1N else 1N
|
|
@@ -1702,9 +1732,9 @@ let numberMod = (x, y) => {
|
|
|
1702
1732
|
* Int/int and float/float comparisons are always accurate.
|
|
1703
1733
|
* Rational/rational comparisons are approximations with the exception of
|
|
1704
1734
|
* equality, which is always accurate.
|
|
1705
|
-
*
|
|
1735
|
+
*
|
|
1706
1736
|
* Values compared to floats or rationals are first converted to floats.
|
|
1707
|
-
*
|
|
1737
|
+
*
|
|
1708
1738
|
* All comparison operators consider NaN not equal to, less than, or greater
|
|
1709
1739
|
* than NaN, with the exception of `compare`, which considers NaN equal to
|
|
1710
1740
|
* itself and otherwise smaller than any other float value. This provides a
|
|
@@ -2459,3 +2489,57 @@ export let isBigInt = x => {
|
|
|
2459
2489
|
let x = WasmI32.fromGrain(x)
|
|
2460
2490
|
isBigInt(x)
|
|
2461
2491
|
}
|
|
2492
|
+
|
|
2493
|
+
// Scalbn is based on https://git.musl-libc.org/cgit/musl/tree/src/math/scalbn.c
|
|
2494
|
+
/*
|
|
2495
|
+
* ====================================================
|
|
2496
|
+
* Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved.
|
|
2497
|
+
*
|
|
2498
|
+
* Permission to use, copy, modify, and distribute this
|
|
2499
|
+
* software is freely granted, provided that this notice
|
|
2500
|
+
* is preserved.
|
|
2501
|
+
* ====================================================
|
|
2502
|
+
*/
|
|
2503
|
+
/**
|
|
2504
|
+
* Multiplies a floating-point number by an integral power of 2.
|
|
2505
|
+
*
|
|
2506
|
+
* @param x: The floating-point value
|
|
2507
|
+
* @param n: The Integer exponent
|
|
2508
|
+
* @returns The result of x * 2^n
|
|
2509
|
+
*
|
|
2510
|
+
* @since v0.5.4
|
|
2511
|
+
*/
|
|
2512
|
+
@unsafe
|
|
2513
|
+
export let scalbn = (x, n) => {
|
|
2514
|
+
let (>) = WasmI32.gtS
|
|
2515
|
+
let (<) = WasmI32.ltS
|
|
2516
|
+
let (*) = WasmF64.mul
|
|
2517
|
+
let (-) = WasmI32.sub
|
|
2518
|
+
let (+) = WasmI32.add
|
|
2519
|
+
let (<<) = WasmI64.shl
|
|
2520
|
+
// Constants
|
|
2521
|
+
let const_0x1p1023 = 8.98847e+307W
|
|
2522
|
+
let const_0x1p_1022 = 2.22507e-308W
|
|
2523
|
+
let const_0x1p53 = 9.0072e+15W
|
|
2524
|
+
let mut n = n
|
|
2525
|
+
let mut y = x
|
|
2526
|
+
if (n > 1023n) {
|
|
2527
|
+
y *= const_0x1p1023
|
|
2528
|
+
n -= 1023n
|
|
2529
|
+
if (n > 1023n) {
|
|
2530
|
+
y *= const_0x1p1023
|
|
2531
|
+
n -= 1023n
|
|
2532
|
+
if (n > 1023n) n = 1023n
|
|
2533
|
+
} else if (n < -1023n) {
|
|
2534
|
+
/* make sure final n < -53 to avoid double rounding in the subnormal range */
|
|
2535
|
+
y *= const_0x1p_1022 * const_0x1p53
|
|
2536
|
+
n += 1022n - 53n
|
|
2537
|
+
if (n < -1022n) {
|
|
2538
|
+
y *= const_0x1p_1022 * const_0x1p53
|
|
2539
|
+
n += 1022n - 53n
|
|
2540
|
+
if (n < -1022n) n = -1022n
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
}
|
|
2544
|
+
y * WasmF64.reinterpretI64(WasmI64.extendI32S(0x3FFn + n) << 52N)
|
|
2545
|
+
}
|
package/runtime/numbers.md
CHANGED
|
@@ -322,3 +322,29 @@ decr : Number -> Number
|
|
|
322
322
|
isBigInt : a -> Bool
|
|
323
323
|
```
|
|
324
324
|
|
|
325
|
+
### Numbers.**scalbn**
|
|
326
|
+
|
|
327
|
+
<details disabled>
|
|
328
|
+
<summary tabindex="-1">Added in <code>0.5.4</code></summary>
|
|
329
|
+
No other changes yet.
|
|
330
|
+
</details>
|
|
331
|
+
|
|
332
|
+
```grain
|
|
333
|
+
scalbn : (WasmF64, WasmI32) -> WasmF64
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Multiplies a floating-point number by an integral power of 2.
|
|
337
|
+
|
|
338
|
+
Parameters:
|
|
339
|
+
|
|
340
|
+
|param|type|description|
|
|
341
|
+
|-----|----|-----------|
|
|
342
|
+
|`x`|`WasmF64`|The floating-point value|
|
|
343
|
+
|`n`|`WasmI32`|The Integer exponent|
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
|
|
347
|
+
|type|description|
|
|
348
|
+
|----|-----------|
|
|
349
|
+
|`WasmF64`|The result of x * 2^n|
|
|
350
|
+
|
package/runtime/string.gr
CHANGED
|
@@ -547,7 +547,8 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
547
547
|
join(strings)
|
|
548
548
|
},
|
|
549
549
|
}
|
|
550
|
-
},
|
|
550
|
+
},
|
|
551
|
+
toStringHelp = (grainValue, extraIndents, toplevel) => {
|
|
551
552
|
if ((grainValue & 1n) != 0n) {
|
|
552
553
|
// Simple (unboxed) numbers
|
|
553
554
|
NumberUtils.itoa32(grainValue >> 1n, 10n)
|
|
@@ -572,7 +573,8 @@ let rec heapValueToString = (ptr, extraIndents, toplevel) => {
|
|
|
572
573
|
"<unknown value>"
|
|
573
574
|
}
|
|
574
575
|
}
|
|
575
|
-
},
|
|
576
|
+
},
|
|
577
|
+
listToString = (ptr, extraIndents) => {
|
|
576
578
|
let mut cur = ptr
|
|
577
579
|
let mut isFirst = true
|
|
578
580
|
|
package/set.gr
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @module Set: A Set is an unordered collection of unique values. Operations on a Set mutate the internal state, so it never needs to be re-assigned.
|
|
3
3
|
* @example import Set from "set"
|
|
4
4
|
*
|
|
5
|
-
* @since
|
|
5
|
+
* @since v0.3.0
|
|
6
6
|
*/
|
|
7
7
|
import List from "list"
|
|
8
8
|
import Array from "array"
|
|
@@ -33,7 +33,7 @@ record Set<k> {
|
|
|
33
33
|
* @param size: The initial storage size of the set
|
|
34
34
|
* @returns An empty set with the given initial storage size
|
|
35
35
|
*
|
|
36
|
-
* @since
|
|
36
|
+
* @since v0.3.0
|
|
37
37
|
*/
|
|
38
38
|
export let makeSized = size => {
|
|
39
39
|
let buckets = Array.make(size, None)
|
|
@@ -44,7 +44,7 @@ export let makeSized = size => {
|
|
|
44
44
|
*
|
|
45
45
|
* @returns An empty set
|
|
46
46
|
*
|
|
47
|
-
* @since
|
|
47
|
+
* @since v0.3.0
|
|
48
48
|
*/
|
|
49
49
|
export let make = () => {
|
|
50
50
|
makeSized(16)
|
|
@@ -121,7 +121,7 @@ let rec nodeInBucket = (key, node) => {
|
|
|
121
121
|
* @param key: The value to add
|
|
122
122
|
* @param set: The set to update
|
|
123
123
|
*
|
|
124
|
-
* @since
|
|
124
|
+
* @since v0.3.0
|
|
125
125
|
*/
|
|
126
126
|
export let add = (key, set) => {
|
|
127
127
|
let buckets = set.buckets
|
|
@@ -154,7 +154,7 @@ export let add = (key, set) => {
|
|
|
154
154
|
* @param set: The set to search
|
|
155
155
|
* @returns `true` if the set contains the given value or `false` otherwise
|
|
156
156
|
*
|
|
157
|
-
* @since
|
|
157
|
+
* @since v0.3.0
|
|
158
158
|
*/
|
|
159
159
|
export let contains = (key, set) => {
|
|
160
160
|
let buckets = set.buckets
|
|
@@ -186,7 +186,7 @@ let rec removeInBucket = (key, node) => {
|
|
|
186
186
|
* @param key: The value to remove
|
|
187
187
|
* @param set: The set to update
|
|
188
188
|
*
|
|
189
|
-
* @since
|
|
189
|
+
* @since v0.3.0
|
|
190
190
|
*/
|
|
191
191
|
export let remove = (key, set) => {
|
|
192
192
|
let buckets = set.buckets
|
|
@@ -214,7 +214,7 @@ export let remove = (key, set) => {
|
|
|
214
214
|
* @param set: The set to inspect
|
|
215
215
|
* @returns The count of elements in the set
|
|
216
216
|
*
|
|
217
|
-
* @since
|
|
217
|
+
* @since v0.3.0
|
|
218
218
|
*/
|
|
219
219
|
export let size = set => {
|
|
220
220
|
set.size
|
|
@@ -226,7 +226,7 @@ export let size = set => {
|
|
|
226
226
|
* @param set: The set to inspect
|
|
227
227
|
* @returns `true` if the given set is empty or `false` otherwise
|
|
228
228
|
*
|
|
229
|
-
* @since
|
|
229
|
+
* @since v0.3.0
|
|
230
230
|
*/
|
|
231
231
|
export let isEmpty = set => {
|
|
232
232
|
size(set) == 0
|
|
@@ -237,7 +237,7 @@ export let isEmpty = set => {
|
|
|
237
237
|
*
|
|
238
238
|
* @param set: The set to reset
|
|
239
239
|
*
|
|
240
|
-
* @since
|
|
240
|
+
* @since v0.3.0
|
|
241
241
|
*/
|
|
242
242
|
export let clear = set => {
|
|
243
243
|
set.size = 0
|
|
@@ -263,7 +263,7 @@ let rec forEachBucket = (fn, node) => {
|
|
|
263
263
|
* @param fn: The iterator function to call with each element
|
|
264
264
|
* @param set: The set to iterate
|
|
265
265
|
*
|
|
266
|
-
* @since
|
|
266
|
+
* @since v0.3.0
|
|
267
267
|
* @history v0.5.0: Ensured the iterator function return type is always `Void`
|
|
268
268
|
*/
|
|
269
269
|
export let forEach = (fn, set) => {
|
|
@@ -288,7 +288,7 @@ let rec reduceEachBucket = (fn, node, acc) => {
|
|
|
288
288
|
* @param set: The set to iterate
|
|
289
289
|
* @returns The final accumulator returned from `fn`
|
|
290
290
|
*
|
|
291
|
-
* @since
|
|
291
|
+
* @since v0.3.0
|
|
292
292
|
*/
|
|
293
293
|
export let reduce = (fn, init, set) => {
|
|
294
294
|
let buckets = set.buckets
|
|
@@ -305,10 +305,10 @@ export let reduce = (fn, init, set) => {
|
|
|
305
305
|
* @param fn: The predicate function to indicate which elements to remove from the set, where returning `false` indicates the value should be removed
|
|
306
306
|
* @param set: The set to iterate
|
|
307
307
|
*
|
|
308
|
-
* @since
|
|
308
|
+
* @since v0.3.0
|
|
309
309
|
*/
|
|
310
|
-
export let filter = (
|
|
311
|
-
let keysToRemove = reduce((list, key) => if (!
|
|
310
|
+
export let filter = (fn, set) => {
|
|
311
|
+
let keysToRemove = reduce((list, key) => if (!fn(key)) {
|
|
312
312
|
[key, ...list]
|
|
313
313
|
} else {
|
|
314
314
|
list
|
|
@@ -324,10 +324,10 @@ export let filter = (predicate, set) => {
|
|
|
324
324
|
* @param fn: The predicate function to indicate which elements to remove from the set, where returning `true` indicates the value should be removed
|
|
325
325
|
* @param set: The set to iterate
|
|
326
326
|
*
|
|
327
|
-
* @since
|
|
327
|
+
* @since v0.3.0
|
|
328
328
|
*/
|
|
329
|
-
export let reject = (
|
|
330
|
-
filter(key => !
|
|
329
|
+
export let reject = (fn, set) => {
|
|
330
|
+
filter(key => !fn(key), set)
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
/**
|
|
@@ -336,7 +336,7 @@ export let reject = (predicate, set) => {
|
|
|
336
336
|
* @param set: The set to convert
|
|
337
337
|
* @returns A list containing all set values
|
|
338
338
|
*
|
|
339
|
-
* @since
|
|
339
|
+
* @since v0.3.0
|
|
340
340
|
*/
|
|
341
341
|
export let toList = set => {
|
|
342
342
|
reduce((list, key) => [key, ...list], [], set)
|
|
@@ -348,7 +348,7 @@ export let toList = set => {
|
|
|
348
348
|
* @param list: The list to convert
|
|
349
349
|
* @returns A set containing all list values
|
|
350
350
|
*
|
|
351
|
-
* @since
|
|
351
|
+
* @since v0.3.0
|
|
352
352
|
*/
|
|
353
353
|
export let fromList = list => {
|
|
354
354
|
let set = make()
|
|
@@ -364,7 +364,7 @@ export let fromList = list => {
|
|
|
364
364
|
* @param set: The set to convert
|
|
365
365
|
* @returns An array containing all set values
|
|
366
366
|
*
|
|
367
|
-
* @since
|
|
367
|
+
* @since v0.3.0
|
|
368
368
|
*/
|
|
369
369
|
export let toArray = set => {
|
|
370
370
|
Array.fromList(toList(set))
|
|
@@ -376,7 +376,7 @@ export let toArray = set => {
|
|
|
376
376
|
* @param array: The array to convert
|
|
377
377
|
* @returns A set containing all array values
|
|
378
378
|
*
|
|
379
|
-
* @since
|
|
379
|
+
* @since v0.3.0
|
|
380
380
|
*/
|
|
381
381
|
export let fromArray = array => {
|
|
382
382
|
let set = make()
|
|
@@ -393,7 +393,7 @@ export let fromArray = array => {
|
|
|
393
393
|
* @param set2: The second set to combine
|
|
394
394
|
* @returns A set containing all elements of both sets
|
|
395
395
|
*
|
|
396
|
-
* @since
|
|
396
|
+
* @since v0.3.0
|
|
397
397
|
*/
|
|
398
398
|
export let union = (set1, set2) => {
|
|
399
399
|
let set = make()
|
|
@@ -413,7 +413,7 @@ export let union = (set1, set2) => {
|
|
|
413
413
|
* @param set2: The second set to combine
|
|
414
414
|
* @returns A set containing only unshared elements from both sets
|
|
415
415
|
*
|
|
416
|
-
* @since
|
|
416
|
+
* @since v0.3.0
|
|
417
417
|
*/
|
|
418
418
|
export let diff = (set1, set2) => {
|
|
419
419
|
let set = make()
|
|
@@ -437,7 +437,7 @@ export let diff = (set1, set2) => {
|
|
|
437
437
|
* @param set2: The second set to combine
|
|
438
438
|
* @returns A set containing only shared elements from both sets
|
|
439
439
|
*
|
|
440
|
-
* @since
|
|
440
|
+
* @since v0.3.0
|
|
441
441
|
*/
|
|
442
442
|
export let intersect = (set1, set2) => {
|
|
443
443
|
let set = make()
|
|
@@ -461,7 +461,7 @@ export let intersect = (set1, set2) => {
|
|
|
461
461
|
* @param set: The set to inspect
|
|
462
462
|
* @returns The internal state of the set
|
|
463
463
|
*
|
|
464
|
-
* @since
|
|
464
|
+
* @since v0.3.0
|
|
465
465
|
*/
|
|
466
466
|
export let getInternalStats = set => {
|
|
467
467
|
(set.size, Array.length(set.buckets))
|
package/stack.gr
CHANGED
|
@@ -20,10 +20,22 @@ record Stack<a> {
|
|
|
20
20
|
* @section Values: Functions and constants included in the Stack module.
|
|
21
21
|
*/
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* An empty stack.
|
|
25
|
+
*
|
|
26
|
+
* @since v0.5.4
|
|
27
|
+
*/
|
|
28
|
+
export let empty = {
|
|
29
|
+
let empty = { data: [], }
|
|
30
|
+
empty
|
|
31
|
+
}
|
|
32
|
+
|
|
23
33
|
/**
|
|
24
34
|
* Creates a new stack.
|
|
25
35
|
*
|
|
26
36
|
* @returns An empty stack
|
|
37
|
+
*
|
|
38
|
+
* @deprecated This will be removed in the v0.6.0 release of Grain.
|
|
27
39
|
*/
|
|
28
40
|
export let make = () => {
|
|
29
41
|
{ data: [], }
|
package/stack.md
CHANGED
|
@@ -24,8 +24,23 @@ Stacks are immutable data structures that store their data in a List.
|
|
|
24
24
|
|
|
25
25
|
Functions and constants included in the Stack module.
|
|
26
26
|
|
|
27
|
+
### Stack.**empty**
|
|
28
|
+
|
|
29
|
+
<details disabled>
|
|
30
|
+
<summary tabindex="-1">Added in <code>0.5.4</code></summary>
|
|
31
|
+
No other changes yet.
|
|
32
|
+
</details>
|
|
33
|
+
|
|
34
|
+
```grain
|
|
35
|
+
empty : Stack<a>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
An empty stack.
|
|
39
|
+
|
|
27
40
|
### Stack.**make**
|
|
28
41
|
|
|
42
|
+
> **Deprecated:** This will be removed in the v0.6.0 release of Grain.
|
|
43
|
+
|
|
29
44
|
```grain
|
|
30
45
|
make : () -> Stack<a>
|
|
31
46
|
```
|