@grain/stdlib 0.5.3 → 0.5.5
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 +61 -0
- package/array.gr +65 -57
- package/array.md +54 -6
- package/buffer.gr +71 -1
- package/buffer.md +142 -0
- package/bytes.gr +52 -3
- package/bytes.md +117 -0
- package/char.gr +23 -20
- package/char.md +18 -3
- package/immutablemap.gr +493 -0
- package/immutablemap.md +479 -0
- package/immutablepriorityqueue.gr +44 -16
- package/immutablepriorityqueue.md +44 -1
- package/immutableset.gr +498 -0
- package/immutableset.md +449 -0
- package/int32.gr +39 -37
- package/int32.md +6 -0
- package/int64.gr +39 -37
- package/int64.md +6 -0
- package/list.gr +33 -24
- package/list.md +39 -10
- package/map.gr +19 -28
- package/marshal.gr +4 -4
- package/number.gr +727 -26
- package/number.md +345 -23
- package/option.gr +30 -26
- package/option.md +12 -0
- package/package.json +1 -1
- package/path.gr +787 -0
- package/path.md +727 -0
- package/pervasives.gr +3 -4
- package/pervasives.md +6 -1
- package/priorityqueue.gr +25 -5
- package/priorityqueue.md +30 -0
- package/queue.gr +22 -7
- package/queue.md +18 -1
- package/regex.gr +161 -65
- package/regex.md +70 -0
- package/result.gr +24 -20
- package/result.md +12 -0
- package/runtime/atof/common.gr +198 -0
- package/runtime/atof/common.md +243 -0
- package/runtime/atof/decimal.gr +663 -0
- package/runtime/atof/decimal.md +59 -0
- package/runtime/atof/lemire.gr +264 -0
- package/runtime/atof/lemire.md +6 -0
- package/runtime/atof/parse.gr +615 -0
- package/runtime/atof/parse.md +12 -0
- package/runtime/atof/slow.gr +238 -0
- package/runtime/atof/slow.md +6 -0
- package/runtime/atof/table.gr +2016 -0
- package/runtime/atof/table.md +12 -0
- package/runtime/{stringUtils.gr → atoi/parse.gr} +1 -1
- package/runtime/{stringUtils.md → atoi/parse.md} +1 -1
- package/runtime/bigint.gr +7 -7
- package/runtime/compare.gr +2 -1
- package/runtime/equal.gr +3 -2
- 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 +13 -13
- package/runtime/numberUtils.md +6 -0
- package/runtime/numbers.gr +123 -39
- package/runtime/numbers.md +26 -0
- package/runtime/string.gr +4 -2
- package/runtime/unsafe/conv.gr +21 -41
- package/runtime/unsafe/conv.md +0 -3
- package/runtime/unsafe/printWasm.gr +4 -40
- package/runtime/utils/printing.gr +3 -3
- package/set.gr +25 -25
- package/stack.gr +14 -0
- package/stack.md +17 -0
- package/string.gr +313 -39
- package/string.md +99 -0
- package/sys/file.gr +1 -1
- package/sys/time.gr +4 -4
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
|
+
reducedFractionBigInt(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
|
|
@@ -2190,7 +2220,7 @@ export let (>>) = (x: Number, y: Number) => {
|
|
|
2190
2220
|
// we will fail if attempting to coerce to an int!
|
|
2191
2221
|
|
|
2192
2222
|
@unsafe
|
|
2193
|
-
export let
|
|
2223
|
+
export let coerceNumberToInt32 = (x: Number) => {
|
|
2194
2224
|
let x = WasmI32.fromGrain(x)
|
|
2195
2225
|
let result = if (
|
|
2196
2226
|
!isSimpleNumber(x) &&
|
|
@@ -2209,7 +2239,7 @@ export let rec coerceNumberToInt32 = (x: Number) => {
|
|
|
2209
2239
|
}
|
|
2210
2240
|
|
|
2211
2241
|
@unsafe
|
|
2212
|
-
export let
|
|
2242
|
+
export let coerceNumberToInt64 = (x: Number) => {
|
|
2213
2243
|
let x = WasmI32.fromGrain(x)
|
|
2214
2244
|
let result = if (
|
|
2215
2245
|
!isSimpleNumber(x) &&
|
|
@@ -2227,7 +2257,7 @@ export let rec coerceNumberToInt64 = (x: Number) => {
|
|
|
2227
2257
|
}
|
|
2228
2258
|
|
|
2229
2259
|
@unsafe
|
|
2230
|
-
export let
|
|
2260
|
+
export let coerceNumberToBigInt = (x: Number) => {
|
|
2231
2261
|
let x = WasmI32.fromGrain(x)
|
|
2232
2262
|
let result = if (isBigInt(x)) {
|
|
2233
2263
|
// avoid extra malloc and prevent x from being freed
|
|
@@ -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/runtime/unsafe/conv.gr
CHANGED
|
@@ -1,69 +1,53 @@
|
|
|
1
|
-
import Memory from "runtime/unsafe/memory"
|
|
2
1
|
import WasmI32 from "runtime/unsafe/wasmi32"
|
|
3
2
|
import WasmI64 from "runtime/unsafe/wasmi64"
|
|
4
3
|
import WasmF32 from "runtime/unsafe/wasmf32"
|
|
5
4
|
import WasmF64 from "runtime/unsafe/wasmf64"
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
import {
|
|
6
|
+
newInt32,
|
|
7
|
+
newInt64,
|
|
8
|
+
newFloat32,
|
|
9
|
+
newFloat64,
|
|
10
|
+
} from "runtime/dataStructures"
|
|
11
|
+
|
|
12
|
+
@unsafe
|
|
9
13
|
export let toInt32 = n => {
|
|
10
|
-
|
|
11
|
-
WasmI32.store(ptr, Tags._GRAIN_BOXED_NUM_HEAP_TAG, 0n)
|
|
12
|
-
WasmI32.store(ptr, Tags._GRAIN_INT32_BOXED_NUM_TAG, 4n)
|
|
13
|
-
WasmI32.store(ptr, n, 8n)
|
|
14
|
-
|
|
15
|
-
WasmI32.toGrain(ptr): Int32
|
|
14
|
+
WasmI32.toGrain(newInt32(n)): Int32
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
@
|
|
17
|
+
@unsafe
|
|
19
18
|
export let fromInt32 = (n: Int32) => {
|
|
20
19
|
let ptr = WasmI32.fromGrain(n)
|
|
21
20
|
WasmI32.load(ptr, 8n)
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
@
|
|
23
|
+
@unsafe
|
|
25
24
|
export let toInt64 = n => {
|
|
26
|
-
|
|
27
|
-
WasmI32.store(ptr, Tags._GRAIN_BOXED_NUM_HEAP_TAG, 0n)
|
|
28
|
-
WasmI32.store(ptr, Tags._GRAIN_INT64_BOXED_NUM_TAG, 4n)
|
|
29
|
-
WasmI64.store(ptr, n, 8n)
|
|
30
|
-
|
|
31
|
-
WasmI32.toGrain(ptr): Int64
|
|
25
|
+
WasmI32.toGrain(newInt64(n)): Int64
|
|
32
26
|
}
|
|
33
27
|
|
|
34
|
-
@
|
|
28
|
+
@unsafe
|
|
35
29
|
export let fromInt64 = (n: Int64) => {
|
|
36
30
|
let ptr = WasmI32.fromGrain(n)
|
|
37
31
|
WasmI64.load(ptr, 8n)
|
|
38
32
|
}
|
|
39
33
|
|
|
40
|
-
@
|
|
34
|
+
@unsafe
|
|
41
35
|
export let toFloat32 = n => {
|
|
42
|
-
|
|
43
|
-
WasmI32.store(ptr, Tags._GRAIN_BOXED_NUM_HEAP_TAG, 0n)
|
|
44
|
-
WasmI32.store(ptr, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG, 4n)
|
|
45
|
-
WasmF32.store(ptr, n, 8n)
|
|
46
|
-
|
|
47
|
-
WasmI32.toGrain(ptr): Float32
|
|
36
|
+
WasmI32.toGrain(newFloat32(n)): Float32
|
|
48
37
|
}
|
|
49
38
|
|
|
50
|
-
@
|
|
39
|
+
@unsafe
|
|
51
40
|
export let fromFloat32 = (n: Float32) => {
|
|
52
41
|
let ptr = WasmI32.fromGrain(n)
|
|
53
42
|
WasmF32.load(ptr, 8n)
|
|
54
43
|
}
|
|
55
44
|
|
|
56
|
-
@
|
|
45
|
+
@unsafe
|
|
57
46
|
export let toFloat64 = n => {
|
|
58
|
-
|
|
59
|
-
WasmI32.store(ptr, Tags._GRAIN_BOXED_NUM_HEAP_TAG, 0n)
|
|
60
|
-
WasmI32.store(ptr, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG, 4n)
|
|
61
|
-
WasmF64.store(ptr, n, 8n)
|
|
62
|
-
|
|
63
|
-
WasmI32.toGrain(ptr): Float64
|
|
47
|
+
WasmI32.toGrain(newFloat64(n)): Float64
|
|
64
48
|
}
|
|
65
49
|
|
|
66
|
-
@
|
|
50
|
+
@unsafe
|
|
67
51
|
export let fromFloat64 = (n: Float64) => {
|
|
68
52
|
let ptr = WasmI32.fromGrain(n)
|
|
69
53
|
WasmF64.load(ptr, 8n)
|
|
@@ -72,13 +56,10 @@ export let fromFloat64 = (n: Float64) => {
|
|
|
72
56
|
/**
|
|
73
57
|
* Converts a WasmI32 value to Number.
|
|
74
58
|
*
|
|
75
|
-
* This function is meant to be called from a `@disableGC` context without
|
|
76
|
-
* need to call incRef on the function.
|
|
77
|
-
*
|
|
78
59
|
* @param n: The WasmI32 to convert
|
|
79
60
|
* @returns The value converted to either a simple or a 32 bit heap allocated number.
|
|
80
61
|
*/
|
|
81
|
-
@
|
|
62
|
+
@unsafe
|
|
82
63
|
export let wasmI32ToNumber = (n: WasmI32) => {
|
|
83
64
|
// Follows a little optimization. Instead of testing if n is range of allowed
|
|
84
65
|
// non heap allocated simple numbers (-1073741824n..1073741823n), actually
|
|
@@ -106,8 +87,7 @@ export let wasmI32ToNumber = (n: WasmI32) => {
|
|
|
106
87
|
// If it did overflow, then the value differs and we need to discard it and
|
|
107
88
|
// allocate the number on the heap. A boxed 32 bit number actually is the
|
|
108
89
|
// same thing as an Int32. It only needs to be cast into Number.
|
|
109
|
-
|
|
110
|
-
WasmI32.toGrain(WasmI32.fromGrain(asInt32)): Number
|
|
90
|
+
WasmI32.toGrain(newInt32(n)): Number
|
|
111
91
|
}
|
|
112
92
|
result
|
|
113
93
|
}
|
package/runtime/unsafe/conv.md
CHANGED
|
@@ -4,74 +4,38 @@ import Memory from "runtime/unsafe/memory"
|
|
|
4
4
|
|
|
5
5
|
// [FIXME] These all leak ATM (grain-lang/grain#791)
|
|
6
6
|
|
|
7
|
-
@
|
|
7
|
+
@unsafe
|
|
8
8
|
export let printI32 = val => {
|
|
9
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
10
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
11
9
|
let conv = Conv.toInt32(val)
|
|
12
|
-
Memory.incRef(WasmI32.fromGrain(conv))
|
|
13
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
14
10
|
let s1 = toString(conv)
|
|
15
11
|
let s2 = "n"
|
|
16
|
-
Memory.incRef(WasmI32.fromGrain(s1))
|
|
17
|
-
Memory.incRef(WasmI32.fromGrain(s2))
|
|
18
|
-
Memory.incRef(WasmI32.fromGrain((++)))
|
|
19
12
|
let s = s1 ++ s2
|
|
20
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
21
|
-
Memory.incRef(WasmI32.fromGrain(s))
|
|
22
13
|
print(s)
|
|
23
14
|
}
|
|
24
15
|
|
|
25
|
-
@
|
|
16
|
+
@unsafe
|
|
26
17
|
export let printI64 = val => {
|
|
27
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
28
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
29
18
|
let conv = Conv.toInt64(val)
|
|
30
|
-
Memory.incRef(WasmI32.fromGrain(conv))
|
|
31
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
32
19
|
let s1 = toString(conv)
|
|
33
20
|
let s2 = "N"
|
|
34
|
-
Memory.incRef(WasmI32.fromGrain(s1))
|
|
35
|
-
Memory.incRef(WasmI32.fromGrain(s2))
|
|
36
|
-
Memory.incRef(WasmI32.fromGrain((++)))
|
|
37
21
|
let s = s1 ++ s2
|
|
38
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
39
|
-
Memory.incRef(WasmI32.fromGrain(s))
|
|
40
22
|
print(s)
|
|
41
23
|
}
|
|
42
24
|
|
|
43
|
-
@
|
|
25
|
+
@unsafe
|
|
44
26
|
export let printF32 = val => {
|
|
45
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
46
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
47
27
|
let conv = Conv.toFloat32(val)
|
|
48
|
-
Memory.incRef(WasmI32.fromGrain(conv))
|
|
49
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
50
28
|
let s1 = toString(conv)
|
|
51
29
|
let s2 = "w"
|
|
52
|
-
Memory.incRef(WasmI32.fromGrain(s1))
|
|
53
|
-
Memory.incRef(WasmI32.fromGrain(s2))
|
|
54
|
-
Memory.incRef(WasmI32.fromGrain((++)))
|
|
55
30
|
let s = s1 ++ s2
|
|
56
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
57
|
-
Memory.incRef(WasmI32.fromGrain(s))
|
|
58
31
|
print(s)
|
|
59
32
|
}
|
|
60
33
|
|
|
61
|
-
@
|
|
34
|
+
@unsafe
|
|
62
35
|
export let printF64 = val => {
|
|
63
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
64
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
65
36
|
let conv = Conv.toFloat64(val)
|
|
66
|
-
Memory.incRef(WasmI32.fromGrain(conv))
|
|
67
|
-
Memory.incRef(WasmI32.fromGrain(toString))
|
|
68
37
|
let s1 = toString(conv)
|
|
69
38
|
let s2 = "W"
|
|
70
|
-
Memory.incRef(WasmI32.fromGrain(s1))
|
|
71
|
-
Memory.incRef(WasmI32.fromGrain(s2))
|
|
72
|
-
Memory.incRef(WasmI32.fromGrain((++)))
|
|
73
39
|
let s = s1 ++ s2
|
|
74
|
-
Memory.incRef(WasmI32.fromGrain(print))
|
|
75
|
-
Memory.incRef(WasmI32.fromGrain(s))
|
|
76
40
|
print(s)
|
|
77
41
|
}
|
|
@@ -12,12 +12,12 @@ import foreign wasm fd_write: (
|
|
|
12
12
|
) -> WasmI32 from "wasi_snapshot_preview1"
|
|
13
13
|
|
|
14
14
|
@unsafe
|
|
15
|
-
export let
|
|
15
|
+
export let numberToString = (n: WasmI64) => {
|
|
16
16
|
NumberUtils.itoa64(n, 10n)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
@unsafe
|
|
20
|
-
export let
|
|
20
|
+
export let printNumber = (n: WasmI64) => {
|
|
21
21
|
// like print(), but `s` should be a Grain string
|
|
22
22
|
let (+) = WasmI32.add
|
|
23
23
|
let s = numberToString(n)
|
|
@@ -40,7 +40,7 @@ export let rec printNumber = (n: WasmI64) => {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
@unsafe
|
|
43
|
-
export let
|
|
43
|
+
export let printString = (s: String) => {
|
|
44
44
|
// like print(), but `s` should be a Grain string
|
|
45
45
|
let (+) = WasmI32.add
|
|
46
46
|
let ptr = WasmI32.fromGrain(s)
|