@grain/stdlib 0.4.2 → 0.4.6
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 +52 -0
- package/LICENSE +1 -1
- package/array.gr +200 -89
- package/array.md +81 -5
- package/buffer.gr +93 -36
- package/bytes.gr +10 -10
- package/char.gr +112 -56
- package/char.md +200 -0
- package/float32.gr +120 -4
- package/float32.md +315 -0
- package/float64.gr +120 -4
- package/float64.md +315 -0
- package/hash.gr +42 -15
- package/hash.md +44 -0
- package/int32.gr +370 -75
- package/int32.md +833 -0
- package/int64.gr +370 -75
- package/int64.md +833 -0
- package/list.gr +121 -50
- package/map.gr +106 -110
- package/number.gr +37 -1
- package/number.md +66 -0
- package/option.gr +260 -53
- package/option.md +579 -0
- package/package.json +1 -1
- package/pervasives.gr +32 -20
- package/queue.gr +102 -30
- package/queue.md +191 -0
- package/range.gr +26 -26
- package/range.md +1 -1
- package/regex.md +9 -9
- package/result.gr +216 -70
- package/result.md +446 -0
- package/runtime/dataStructures.gr +28 -29
- package/runtime/debug.gr +0 -1
- package/runtime/equal.gr +37 -16
- package/runtime/exception.gr +28 -15
- package/runtime/gc.gr +33 -20
- package/runtime/malloc.gr +19 -11
- package/runtime/numberUtils.gr +208 -103
- package/runtime/numbers.gr +217 -118
- package/runtime/string.gr +98 -39
- package/runtime/stringUtils.gr +176 -0
- package/runtime/unsafe/conv.gr +10 -10
- package/runtime/unsafe/memory.gr +14 -3
- package/runtime/unsafe/printWasm.gr +4 -4
- package/runtime/unsafe/tags.gr +2 -2
- package/runtime/unsafe/wasmf32.gr +9 -2
- package/runtime/unsafe/wasmf64.gr +9 -2
- package/runtime/unsafe/wasmi32.gr +65 -47
- package/runtime/unsafe/wasmi64.gr +78 -50
- package/runtime/wasi.gr +199 -45
- package/set.gr +281 -119
- package/set.md +502 -0
- package/stack.gr +26 -26
- package/string.gr +657 -341
- package/string.md +815 -0
- package/sys/file.gr +356 -177
- package/sys/process.gr +10 -6
- package/sys/random.gr +3 -6
- package/sys/time.gr +3 -3
package/runtime/numbers.gr
CHANGED
|
@@ -9,10 +9,10 @@ import WasmI64 from "runtime/unsafe/wasmi64"
|
|
|
9
9
|
import WasmF32 from "runtime/unsafe/wasmf32"
|
|
10
10
|
import WasmF64 from "runtime/unsafe/wasmf64"
|
|
11
11
|
|
|
12
|
-
primitive (!)
|
|
13
|
-
primitive (&&)
|
|
14
|
-
primitive (||)
|
|
15
|
-
primitive throw
|
|
12
|
+
primitive (!): Bool -> Bool = "@not"
|
|
13
|
+
primitive (&&): (Bool, Bool) -> Bool = "@and"
|
|
14
|
+
primitive (||): (Bool, Bool) -> Bool = "@or"
|
|
15
|
+
primitive throw: Exception -> a = "@throw"
|
|
16
16
|
|
|
17
17
|
exception UnknownNumberTag
|
|
18
18
|
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
newInt32,
|
|
22
22
|
newInt64,
|
|
23
23
|
newFloat32,
|
|
24
|
-
newFloat64
|
|
24
|
+
newFloat64,
|
|
25
25
|
} from "runtime/dataStructures"
|
|
26
26
|
|
|
27
27
|
export newRational
|
|
@@ -40,41 +40,50 @@ let _F64_MAX_SAFE_INTEGER = 9007199254740991.W
|
|
|
40
40
|
let (==) = WasmI32.eq
|
|
41
41
|
let (!=) = WasmI32.ne
|
|
42
42
|
|
|
43
|
-
let tagSimple =
|
|
43
|
+
let tagSimple = x => {
|
|
44
44
|
WasmI32.xor(WasmI32.shl(x, 1n), 1n)
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
let untagSimple =
|
|
47
|
+
let untagSimple = x => {
|
|
48
48
|
WasmI32.shrS(x, 1n)
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
let isSimpleNumber =
|
|
52
|
-
WasmI32.eq(
|
|
51
|
+
let isSimpleNumber = x => {
|
|
52
|
+
WasmI32.eq(
|
|
53
|
+
WasmI32.and(x, Tags._GRAIN_NUMBER_TAG_MASK),
|
|
54
|
+
Tags._GRAIN_NUMBER_TAG_TYPE
|
|
55
|
+
)
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
export let isBoxedNumber =
|
|
56
|
-
if (
|
|
58
|
+
export let isBoxedNumber = x => {
|
|
59
|
+
if (
|
|
60
|
+
WasmI32.eq(
|
|
61
|
+
WasmI32.and(x, Tags._GRAIN_GENERIC_TAG_MASK),
|
|
62
|
+
Tags._GRAIN_GENERIC_HEAP_TAG_TYPE
|
|
63
|
+
)
|
|
64
|
+
) {
|
|
57
65
|
WasmI32.eq(WasmI32.load(x, 0n), Tags._GRAIN_BOXED_NUM_HEAP_TAG)
|
|
58
66
|
} else {
|
|
59
67
|
false
|
|
60
68
|
}
|
|
61
69
|
}
|
|
62
70
|
|
|
63
|
-
export let isFloat =
|
|
71
|
+
export let isFloat = x => {
|
|
64
72
|
if (isBoxedNumber(x)) {
|
|
65
73
|
let tag = WasmI32.load(x, 4n)
|
|
66
|
-
WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) ||
|
|
74
|
+
WasmI32.eq(tag, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) ||
|
|
75
|
+
WasmI32.eq(tag, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
67
76
|
} else {
|
|
68
77
|
false
|
|
69
78
|
}
|
|
70
79
|
}
|
|
71
80
|
|
|
72
|
-
export let isNumber =
|
|
81
|
+
export let isNumber = x => {
|
|
73
82
|
// x is a number if it is a literal number or a boxed_num heap value
|
|
74
83
|
isSimpleNumber(x) || isBoxedNumber(x)
|
|
75
84
|
}
|
|
76
85
|
|
|
77
|
-
let safeI64toI32 =
|
|
86
|
+
let safeI64toI32 = x => {
|
|
78
87
|
if (WasmI64.gtS(x, _I32_MAX) || WasmI64.ltS(x, _I32_MIN)) {
|
|
79
88
|
throw Exception.Overflow
|
|
80
89
|
} else {
|
|
@@ -82,10 +91,10 @@ let safeI64toI32 = (x) => {
|
|
|
82
91
|
}
|
|
83
92
|
}
|
|
84
93
|
|
|
85
|
-
let i32neg =
|
|
94
|
+
let i32neg = x => WasmI32.sub(0n, x)
|
|
86
95
|
|
|
87
|
-
let i64not =
|
|
88
|
-
let i64neg =
|
|
96
|
+
let i64not = x => WasmI64.xor(x, 0xffffffffffffffffN)
|
|
97
|
+
let i64neg = x => WasmI64.sub(0N, x)
|
|
89
98
|
|
|
90
99
|
// https://en.wikipedia.org/wiki/Binary_GCD_algorithm
|
|
91
100
|
let rec gcdHelp = (x, y) => {
|
|
@@ -131,10 +140,13 @@ let gcd32 = (x, y) => {
|
|
|
131
140
|
WasmI32.wrapI64(gcd(WasmI64.extendI32S(x), WasmI64.extendI32S(y)))
|
|
132
141
|
}
|
|
133
142
|
|
|
134
|
-
export let reducedInteger =
|
|
143
|
+
export let reducedInteger = x => {
|
|
135
144
|
if (WasmI64.gtS(x, _I32_MAX) || WasmI64.ltS(x, _I32_MIN)) {
|
|
136
145
|
newInt64(x)
|
|
137
|
-
} else if (
|
|
146
|
+
} else if (
|
|
147
|
+
WasmI64.gtS(x, WasmI64.shrS(_I32_MAX, 1N)) ||
|
|
148
|
+
WasmI64.ltS(x, WasmI64.shrS(_I32_MIN, 1N))
|
|
149
|
+
) {
|
|
138
150
|
newInt32(WasmI32.wrapI64(x))
|
|
139
151
|
} else {
|
|
140
152
|
tagSimple(WasmI32.wrapI64(x))
|
|
@@ -228,36 +240,34 @@ let safeI64Multiply = (x, y) => {
|
|
|
228
240
|
* [numerator, denominator]
|
|
229
241
|
*/
|
|
230
242
|
|
|
231
|
-
export let boxedNumberTag =
|
|
243
|
+
export let boxedNumberTag = xptr => {
|
|
232
244
|
WasmI32.load(xptr, 4n)
|
|
233
245
|
}
|
|
234
246
|
|
|
235
|
-
export let boxedInt32Number =
|
|
247
|
+
export let boxedInt32Number = xptr => {
|
|
236
248
|
WasmI32.load(xptr, 8n)
|
|
237
249
|
}
|
|
238
250
|
|
|
239
|
-
export let boxedInt64Number =
|
|
251
|
+
export let boxedInt64Number = xptr => {
|
|
240
252
|
WasmI64.load(xptr, 8n)
|
|
241
253
|
}
|
|
242
254
|
|
|
243
|
-
export let boxedFloat32Number =
|
|
255
|
+
export let boxedFloat32Number = xptr => {
|
|
244
256
|
WasmF32.load(xptr, 8n)
|
|
245
257
|
}
|
|
246
258
|
|
|
247
|
-
export let boxedFloat64Number =
|
|
259
|
+
export let boxedFloat64Number = xptr => {
|
|
248
260
|
WasmF64.load(xptr, 8n)
|
|
249
261
|
}
|
|
250
262
|
|
|
251
|
-
export let boxedRationalNumerator =
|
|
263
|
+
export let boxedRationalNumerator = xptr => {
|
|
252
264
|
WasmI32.load(xptr, 8n)
|
|
253
265
|
}
|
|
254
266
|
|
|
255
|
-
export let boxedRationalDenominator =
|
|
267
|
+
export let boxedRationalDenominator = xptr => {
|
|
256
268
|
WasmI32.load(xptr, 12n)
|
|
257
269
|
}
|
|
258
270
|
|
|
259
|
-
|
|
260
|
-
|
|
261
271
|
export let coerceNumberToWasmF32 = (x: Number) => {
|
|
262
272
|
let x = WasmI32.fromGrain(x)
|
|
263
273
|
if (isSimpleNumber(x)) {
|
|
@@ -272,7 +282,10 @@ export let coerceNumberToWasmF32 = (x: Number) => {
|
|
|
272
282
|
WasmF32.convertI64S(boxedInt64Number(x))
|
|
273
283
|
},
|
|
274
284
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
275
|
-
WasmF32.div(
|
|
285
|
+
WasmF32.div(
|
|
286
|
+
WasmF32.convertI32S(boxedRationalNumerator(x)),
|
|
287
|
+
WasmF32.convertI32S(boxedRationalDenominator(x))
|
|
288
|
+
)
|
|
276
289
|
},
|
|
277
290
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
278
291
|
boxedFloat32Number(x)
|
|
@@ -288,7 +301,7 @@ export let coerceNumberToWasmF32 = (x: Number) => {
|
|
|
288
301
|
},
|
|
289
302
|
_ => {
|
|
290
303
|
throw UnknownNumberTag
|
|
291
|
-
}
|
|
304
|
+
},
|
|
292
305
|
}
|
|
293
306
|
}
|
|
294
307
|
}
|
|
@@ -307,7 +320,10 @@ export let coerceNumberToWasmF64 = (x: Number) => {
|
|
|
307
320
|
WasmF64.convertI64S(boxedInt64Number(x))
|
|
308
321
|
},
|
|
309
322
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
310
|
-
WasmF64.div(
|
|
323
|
+
WasmF64.div(
|
|
324
|
+
WasmF64.convertI32S(boxedRationalNumerator(x)),
|
|
325
|
+
WasmF64.convertI32S(boxedRationalDenominator(x))
|
|
326
|
+
)
|
|
311
327
|
},
|
|
312
328
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
313
329
|
WasmF64.promoteF32(boxedFloat32Number(x))
|
|
@@ -317,7 +333,7 @@ export let coerceNumberToWasmF64 = (x: Number) => {
|
|
|
317
333
|
},
|
|
318
334
|
_ => {
|
|
319
335
|
throw UnknownNumberTag
|
|
320
|
-
}
|
|
336
|
+
},
|
|
321
337
|
}
|
|
322
338
|
}
|
|
323
339
|
}
|
|
@@ -338,7 +354,7 @@ export let coerceNumberToWasmI64 = (x: Number) => {
|
|
|
338
354
|
_ => {
|
|
339
355
|
// rationals are never integral, and we refuse to coerce floats to ints
|
|
340
356
|
throw Exception.NumberNotIntlike
|
|
341
|
-
}
|
|
357
|
+
},
|
|
342
358
|
}
|
|
343
359
|
}
|
|
344
360
|
}
|
|
@@ -363,26 +379,27 @@ export let coerceNumberToWasmI32 = (x: Number) => {
|
|
|
363
379
|
_ => {
|
|
364
380
|
// rationals are never integral, and we refuse to coerce floats to ints
|
|
365
381
|
throw Exception.NumberNotIntlike
|
|
366
|
-
}
|
|
382
|
+
},
|
|
367
383
|
}
|
|
368
384
|
}
|
|
369
385
|
}
|
|
370
386
|
|
|
371
|
-
|
|
372
|
-
let isIntegerF32 = (value) => {
|
|
387
|
+
let isIntegerF32 = value => {
|
|
373
388
|
WasmF32.eq(value, WasmF32.trunc(value))
|
|
374
389
|
}
|
|
375
390
|
|
|
376
|
-
let isIntegerF64 =
|
|
391
|
+
let isIntegerF64 = value => {
|
|
377
392
|
WasmF64.eq(value, WasmF64.trunc(value))
|
|
378
393
|
}
|
|
379
394
|
|
|
380
|
-
let isSafeIntegerF32 =
|
|
381
|
-
WasmF32.le(WasmF32.abs(value), _F32_MAX_SAFE_INTEGER) &&
|
|
395
|
+
let isSafeIntegerF32 = value => {
|
|
396
|
+
WasmF32.le(WasmF32.abs(value), _F32_MAX_SAFE_INTEGER) &&
|
|
397
|
+
WasmF32.eq(WasmF32.trunc(value), value)
|
|
382
398
|
}
|
|
383
399
|
|
|
384
|
-
let isSafeIntegerF64 =
|
|
385
|
-
WasmF64.le(WasmF64.abs(value), _F64_MAX_SAFE_INTEGER) &&
|
|
400
|
+
let isSafeIntegerF64 = value => {
|
|
401
|
+
WasmF64.le(WasmF64.abs(value), _F64_MAX_SAFE_INTEGER) &&
|
|
402
|
+
WasmF64.eq(WasmF64.trunc(value), value)
|
|
386
403
|
}
|
|
387
404
|
|
|
388
405
|
/** Number-aware equality checking
|
|
@@ -417,20 +434,21 @@ let numberEqualSimpleHelp = (x, y) => {
|
|
|
417
434
|
},
|
|
418
435
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
419
436
|
let yBoxedVal = boxedFloat32Number(y)
|
|
420
|
-
isSafeIntegerF32(yBoxedVal) &&
|
|
437
|
+
isSafeIntegerF32(yBoxedVal) &&
|
|
438
|
+
WasmF32.eq(WasmF32.convertI32S(xval), yBoxedVal)
|
|
421
439
|
},
|
|
422
440
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
423
441
|
let yBoxedVal = boxedFloat64Number(y)
|
|
424
|
-
isSafeIntegerF64(yBoxedVal) &&
|
|
442
|
+
isSafeIntegerF64(yBoxedVal) &&
|
|
443
|
+
WasmF64.eq(WasmF64.convertI32S(xval), yBoxedVal)
|
|
425
444
|
},
|
|
426
445
|
_ => {
|
|
427
446
|
throw UnknownNumberTag
|
|
428
|
-
}
|
|
447
|
+
},
|
|
429
448
|
}
|
|
430
449
|
}
|
|
431
450
|
}
|
|
432
451
|
|
|
433
|
-
|
|
434
452
|
let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
435
453
|
// PRECONDITION: x !== y and isNumber(y)
|
|
436
454
|
// Basic number:
|
|
@@ -454,15 +472,17 @@ let numberEqualInt64Help = (xBoxedVal, y) => {
|
|
|
454
472
|
},
|
|
455
473
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
456
474
|
let yBoxedVal = boxedFloat32Number(y)
|
|
457
|
-
isSafeIntegerF32(yBoxedVal) &&
|
|
475
|
+
isSafeIntegerF32(yBoxedVal) &&
|
|
476
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF32S(yBoxedVal))
|
|
458
477
|
},
|
|
459
478
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
460
479
|
let yBoxedVal = boxedFloat64Number(y)
|
|
461
|
-
isSafeIntegerF64(yBoxedVal) &&
|
|
480
|
+
isSafeIntegerF64(yBoxedVal) &&
|
|
481
|
+
WasmI64.eq(xBoxedVal, WasmI64.truncF64S(yBoxedVal))
|
|
462
482
|
},
|
|
463
483
|
_ => {
|
|
464
484
|
throw UnknownNumberTag
|
|
465
|
-
}
|
|
485
|
+
},
|
|
466
486
|
}
|
|
467
487
|
}
|
|
468
488
|
}
|
|
@@ -492,23 +512,30 @@ let numberEqualRationalHelp = (xptr, y) => {
|
|
|
492
512
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
493
513
|
let yNumerator = boxedRationalNumerator(y)
|
|
494
514
|
let yDenominator = boxedRationalDenominator(y)
|
|
495
|
-
WasmI32.eq(xNumerator, yNumerator) &&
|
|
515
|
+
WasmI32.eq(xNumerator, yNumerator) &&
|
|
516
|
+
WasmI32.eq(xDenominator, yDenominator)
|
|
496
517
|
},
|
|
497
518
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
498
519
|
let yBoxedVal = boxedFloat32Number(y)
|
|
499
|
-
let xAsFloat = WasmF32.div(
|
|
520
|
+
let xAsFloat = WasmF32.div(
|
|
521
|
+
WasmF32.convertI32S(xNumerator),
|
|
522
|
+
WasmF32.convertI32S(xDenominator)
|
|
523
|
+
)
|
|
500
524
|
// TODO: (#303) maybe we should have some sort of tolerance?
|
|
501
525
|
WasmF32.eq(xAsFloat, yBoxedVal)
|
|
502
526
|
},
|
|
503
527
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
504
528
|
let yBoxedVal = boxedFloat64Number(y)
|
|
505
|
-
let xAsFloat = WasmF64.div(
|
|
529
|
+
let xAsFloat = WasmF64.div(
|
|
530
|
+
WasmF64.convertI32S(xNumerator),
|
|
531
|
+
WasmF64.convertI32S(xDenominator)
|
|
532
|
+
)
|
|
506
533
|
// TODO: (#303) maybe we should have some sort of tolerance?
|
|
507
534
|
WasmF64.eq(xAsFloat, yBoxedVal)
|
|
508
535
|
},
|
|
509
536
|
_ => {
|
|
510
537
|
throw UnknownNumberTag
|
|
511
|
-
}
|
|
538
|
+
},
|
|
512
539
|
}
|
|
513
540
|
}
|
|
514
541
|
}
|
|
@@ -533,7 +560,10 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
533
560
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
534
561
|
let yNumerator = boxedRationalNumerator(y)
|
|
535
562
|
let yDenominator = boxedRationalDenominator(y)
|
|
536
|
-
let yAsFloat = WasmF64.div(
|
|
563
|
+
let yAsFloat = WasmF64.div(
|
|
564
|
+
WasmF64.convertI32S(yNumerator),
|
|
565
|
+
WasmF64.convertI32S(yDenominator)
|
|
566
|
+
)
|
|
537
567
|
WasmF64.eq(x, yAsFloat)
|
|
538
568
|
},
|
|
539
569
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
@@ -548,7 +578,7 @@ let numberEqualFloat64Help = (x, y) => {
|
|
|
548
578
|
},
|
|
549
579
|
_ => {
|
|
550
580
|
throw UnknownNumberTag
|
|
551
|
-
}
|
|
581
|
+
},
|
|
552
582
|
}
|
|
553
583
|
}
|
|
554
584
|
}
|
|
@@ -568,7 +598,7 @@ let numberEqualFloat32Help = (x, y) => {
|
|
|
568
598
|
},
|
|
569
599
|
_ => {
|
|
570
600
|
numberEqualFloat64Help(WasmF64.promoteF32(x), y)
|
|
571
|
-
}
|
|
601
|
+
},
|
|
572
602
|
}
|
|
573
603
|
}
|
|
574
604
|
}
|
|
@@ -600,7 +630,7 @@ export let numberEqual = (x, y) => {
|
|
|
600
630
|
},
|
|
601
631
|
_ => {
|
|
602
632
|
throw UnknownNumberTag
|
|
603
|
-
}
|
|
633
|
+
},
|
|
604
634
|
}
|
|
605
635
|
}
|
|
606
636
|
}
|
|
@@ -628,13 +658,15 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
628
658
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
629
659
|
let xval = WasmI64.extendI32S(xval)
|
|
630
660
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
631
|
-
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
661
|
+
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
662
|
+
else WasmI64.add(xval, yBoxedVal)
|
|
632
663
|
reducedInteger(result)
|
|
633
664
|
},
|
|
634
665
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
635
666
|
let yBoxedVal = boxedInt64Number(y)
|
|
636
667
|
let xval64 = WasmI64.extendI32S(xval)
|
|
637
|
-
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
668
|
+
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
669
|
+
else WasmI64.add(xval64, yBoxedVal)
|
|
638
670
|
if (WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64)) {
|
|
639
671
|
throw Exception.Overflow
|
|
640
672
|
} else if (WasmI64.ltS(yBoxedVal, 0N) && WasmI64.gtS(result, xval64)) {
|
|
@@ -646,8 +678,12 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
646
678
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => {
|
|
647
679
|
let yNumerator = WasmI64.extendI32S(boxedRationalNumerator(y))
|
|
648
680
|
let yDenominator = WasmI64.extendI32S(boxedRationalDenominator(y))
|
|
649
|
-
let expandedXNumerator = safeI64Multiply(
|
|
650
|
-
|
|
681
|
+
let expandedXNumerator = safeI64Multiply(
|
|
682
|
+
WasmI64.extendI32S(xval),
|
|
683
|
+
yDenominator
|
|
684
|
+
)
|
|
685
|
+
let result = if (isSub) WasmI64.sub(expandedXNumerator, yNumerator)
|
|
686
|
+
else WasmI64.add(expandedXNumerator, yNumerator)
|
|
651
687
|
if (WasmI64.ltS(result, _I32_MIN) || WasmI64.gtS(result, _I32_MAX)) {
|
|
652
688
|
throw Exception.Overflow
|
|
653
689
|
}
|
|
@@ -656,19 +692,21 @@ let numberAddSubSimpleHelp = (x, y, isSub) => {
|
|
|
656
692
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
657
693
|
let yBoxedVal = boxedFloat32Number(y)
|
|
658
694
|
let xval = WasmF32.convertI32S(xval)
|
|
659
|
-
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
695
|
+
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
696
|
+
else WasmF32.add(xval, yBoxedVal)
|
|
660
697
|
// TODO: (#304) is this safe?
|
|
661
698
|
newFloat32(result)
|
|
662
699
|
},
|
|
663
700
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
664
701
|
let yBoxedVal = boxedFloat64Number(y)
|
|
665
702
|
let xval = WasmF64.convertI32S(xval)
|
|
666
|
-
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
703
|
+
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
704
|
+
else WasmF64.add(xval, yBoxedVal)
|
|
667
705
|
newFloat64(result)
|
|
668
706
|
},
|
|
669
707
|
_ => {
|
|
670
708
|
throw UnknownNumberTag
|
|
671
|
-
}
|
|
709
|
+
},
|
|
672
710
|
}
|
|
673
711
|
}
|
|
674
712
|
}
|
|
@@ -688,13 +726,15 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
688
726
|
match (yBoxedNumberTag) {
|
|
689
727
|
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
690
728
|
let yBoxedVal = WasmI64.extendI32S(boxedInt32Number(y))
|
|
691
|
-
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
729
|
+
let result = if (isSub) WasmI64.sub(xval, yBoxedVal)
|
|
730
|
+
else WasmI64.add(xval, yBoxedVal)
|
|
692
731
|
reducedInteger(result)
|
|
693
732
|
},
|
|
694
733
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
695
734
|
let yBoxedVal = boxedInt64Number(y)
|
|
696
735
|
let xval64 = xval
|
|
697
|
-
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
736
|
+
let result = if (isSub) WasmI64.sub(xval64, yBoxedVal)
|
|
737
|
+
else WasmI64.add(xval64, yBoxedVal)
|
|
698
738
|
if (WasmI64.geS(yBoxedVal, 0N) && WasmI64.ltS(result, xval64)) {
|
|
699
739
|
throw Exception.Overflow
|
|
700
740
|
} else if (WasmI64.ltS(yBoxedVal, 0N) && WasmI64.gtS(result, xval64)) {
|
|
@@ -707,7 +747,8 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
707
747
|
let yNumerator = WasmI64.extendI32S(boxedRationalNumerator(y))
|
|
708
748
|
let yDenominator = WasmI64.extendI32S(boxedRationalDenominator(y))
|
|
709
749
|
let expandedXNumerator = safeI64Multiply(xval, yDenominator)
|
|
710
|
-
let result = if (isSub) WasmI64.sub(expandedXNumerator, yNumerator)
|
|
750
|
+
let result = if (isSub) WasmI64.sub(expandedXNumerator, yNumerator)
|
|
751
|
+
else WasmI64.add(expandedXNumerator, yNumerator)
|
|
711
752
|
if (WasmI64.ltS(result, _I32_MIN) || WasmI64.gtS(result, _I32_MAX)) {
|
|
712
753
|
throw Exception.Overflow
|
|
713
754
|
}
|
|
@@ -716,44 +757,48 @@ let numberAddSubInt64Help = (xval, y, isSub) => {
|
|
|
716
757
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
717
758
|
let xval = WasmF32.convertI64S(xval)
|
|
718
759
|
let yBoxedVal = boxedFloat32Number(y)
|
|
719
|
-
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
760
|
+
let result = if (isSub) WasmF32.sub(xval, yBoxedVal)
|
|
761
|
+
else WasmF32.add(xval, yBoxedVal)
|
|
720
762
|
// TODO: (#304) this isn't safe enough
|
|
721
763
|
newFloat32(result)
|
|
722
764
|
},
|
|
723
765
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
724
766
|
let xval = WasmF64.convertI64S(xval)
|
|
725
767
|
let yBoxedVal = boxedFloat64Number(y)
|
|
726
|
-
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
768
|
+
let result = if (isSub) WasmF64.sub(xval, yBoxedVal)
|
|
769
|
+
else WasmF64.add(xval, yBoxedVal)
|
|
727
770
|
newFloat64(result)
|
|
728
771
|
},
|
|
729
772
|
_ => {
|
|
730
773
|
throw UnknownNumberTag
|
|
731
|
-
}
|
|
774
|
+
},
|
|
732
775
|
}
|
|
733
776
|
}
|
|
734
777
|
}
|
|
735
778
|
|
|
736
779
|
let numberAddSubFloat32Help = (xval, y, isSub) => {
|
|
737
|
-
if (
|
|
780
|
+
if (
|
|
781
|
+
!isSimpleNumber(y) &&
|
|
782
|
+
WasmI32.eq(boxedNumberTag(y), Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
783
|
+
) {
|
|
738
784
|
// Special case: promote to f64 if RHS is f64
|
|
739
785
|
let xval = WasmF64.promoteF32(xval)
|
|
740
786
|
let yval = boxedFloat64Number(y)
|
|
741
787
|
let result = if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
742
788
|
newFloat64(result)
|
|
743
789
|
} else {
|
|
744
|
-
let yval = coerceNumberToWasmF32(WasmI32.toGrain(y)
|
|
790
|
+
let yval = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
745
791
|
let result = if (isSub) WasmF32.sub(xval, yval) else WasmF32.add(xval, yval)
|
|
746
792
|
newFloat32(result)
|
|
747
793
|
}
|
|
748
794
|
}
|
|
749
795
|
|
|
750
796
|
let numberAddSubFloat64Help = (xval, y, isSub) => {
|
|
751
|
-
let yval = coerceNumberToWasmF64(WasmI32.toGrain(y)
|
|
797
|
+
let yval = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
752
798
|
let result = if (isSub) WasmF64.sub(xval, yval) else WasmF64.add(xval, yval)
|
|
753
799
|
newFloat64(result)
|
|
754
800
|
}
|
|
755
801
|
|
|
756
|
-
|
|
757
802
|
let numberAddSubInt32Help = (xval, y, isSub) => {
|
|
758
803
|
numberAddSubInt64Help(WasmI64.extendI32S(xval), y, isSub)
|
|
759
804
|
}
|
|
@@ -781,11 +826,10 @@ let rec numberAddSubHelp = (x, y, isSub) => {
|
|
|
781
826
|
},
|
|
782
827
|
_ => {
|
|
783
828
|
throw UnknownNumberTag
|
|
784
|
-
}
|
|
829
|
+
},
|
|
785
830
|
}
|
|
786
831
|
}
|
|
787
|
-
},
|
|
788
|
-
numberAddSubRationalHelp = (x, y, isSub) => {
|
|
832
|
+
}, numberAddSubRationalHelp = (x, y, isSub) => {
|
|
789
833
|
if (isSimpleNumber(y)) {
|
|
790
834
|
numberAddSubSimpleHelp(y, x, isSub)
|
|
791
835
|
} else {
|
|
@@ -799,16 +843,19 @@ numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
799
843
|
let yDenominator = WasmI64.extendI32S(boxedRationalDenominator(y))
|
|
800
844
|
// TODO: {#304) this could be written in a more overflow-proof way
|
|
801
845
|
if (WasmI64.eq(xDenominator, yDenominator)) {
|
|
802
|
-
let result = if (isSub) WasmI64.sub(xNumerator, yNumerator)
|
|
846
|
+
let result = if (isSub) WasmI64.sub(xNumerator, yNumerator)
|
|
847
|
+
else WasmI64.add(xNumerator, yNumerator)
|
|
803
848
|
reducedFraction64(result, xDenominator)
|
|
804
849
|
} else {
|
|
805
850
|
let numerator1 = safeI64Multiply(xNumerator, yDenominator)
|
|
806
851
|
let numerator2 = safeI64Multiply(yNumerator, xDenominator)
|
|
807
|
-
let numerator = if (isSub) WasmI64.sub(numerator1, numerator2)
|
|
852
|
+
let numerator = if (isSub) WasmI64.sub(numerator1, numerator2)
|
|
853
|
+
else WasmI64.add(numerator1, numerator2)
|
|
808
854
|
let denominator = safeI64Multiply(xDenominator, yDenominator)
|
|
809
855
|
reducedFraction64(numerator, denominator)
|
|
810
856
|
}
|
|
811
|
-
},
|
|
857
|
+
},
|
|
858
|
+
t when WasmI32.eq(t, Tags._GRAIN_INT32_BOXED_NUM_TAG) => {
|
|
812
859
|
numberAddSubHelp(y, x, isSub)
|
|
813
860
|
},
|
|
814
861
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => {
|
|
@@ -822,7 +869,7 @@ numberAddSubRationalHelp = (x, y, isSub) => {
|
|
|
822
869
|
},
|
|
823
870
|
_ => {
|
|
824
871
|
throw UnknownNumberTag
|
|
825
|
-
}
|
|
872
|
+
},
|
|
826
873
|
}
|
|
827
874
|
}
|
|
828
875
|
}
|
|
@@ -900,7 +947,7 @@ let numberTimesDivideInt64Help = (xval, y, isDivide) => {
|
|
|
900
947
|
},
|
|
901
948
|
_ => {
|
|
902
949
|
throw UnknownNumberTag
|
|
903
|
-
}
|
|
950
|
+
},
|
|
904
951
|
}
|
|
905
952
|
}
|
|
906
953
|
}
|
|
@@ -922,11 +969,17 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
922
969
|
if (isSimpleNumber(y)) {
|
|
923
970
|
if (isDivide) {
|
|
924
971
|
// (a / b) / y == a / (b * y)
|
|
925
|
-
let denominator = safeI64Multiply(
|
|
972
|
+
let denominator = safeI64Multiply(
|
|
973
|
+
xDenominator,
|
|
974
|
+
WasmI64.extendI32S(untagSimple(y))
|
|
975
|
+
)
|
|
926
976
|
reducedFraction64(xNumerator, denominator)
|
|
927
977
|
} else {
|
|
928
978
|
// (a / b) * y == (a * y) / b
|
|
929
|
-
let numerator = safeI64Multiply(
|
|
979
|
+
let numerator = safeI64Multiply(
|
|
980
|
+
xNumerator,
|
|
981
|
+
WasmI64.extendI32S(untagSimple(y))
|
|
982
|
+
)
|
|
930
983
|
reducedFraction64(numerator, xDenominator)
|
|
931
984
|
}
|
|
932
985
|
} else {
|
|
@@ -936,11 +989,17 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
936
989
|
// Same idea as above
|
|
937
990
|
if (isDivide) {
|
|
938
991
|
// (a / b) / y == a / (b * y)
|
|
939
|
-
let denominator = safeI64Multiply(
|
|
992
|
+
let denominator = safeI64Multiply(
|
|
993
|
+
xDenominator,
|
|
994
|
+
WasmI64.extendI32S(boxedInt32Number(y))
|
|
995
|
+
)
|
|
940
996
|
reducedFraction64(xNumerator, denominator)
|
|
941
997
|
} else {
|
|
942
998
|
// (a / b) * y == (a * y) / b
|
|
943
|
-
let numerator = safeI64Multiply(
|
|
999
|
+
let numerator = safeI64Multiply(
|
|
1000
|
+
xNumerator,
|
|
1001
|
+
WasmI64.extendI32S(boxedInt32Number(y))
|
|
1002
|
+
)
|
|
944
1003
|
reducedFraction64(numerator, xDenominator)
|
|
945
1004
|
}
|
|
946
1005
|
},
|
|
@@ -964,12 +1023,18 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
964
1023
|
// (a / b) * (c / d) == (a * c) / (b * d)
|
|
965
1024
|
// (a / b) / (c / d) == (a * d) / (b * c)
|
|
966
1025
|
// TODO: (#304) this could maybe be written in a more overflow-proof way
|
|
967
|
-
let numerator = if (isDivide) safeI64Multiply(xNumerator, yDenominator)
|
|
968
|
-
|
|
1026
|
+
let numerator = if (isDivide) safeI64Multiply(xNumerator, yDenominator)
|
|
1027
|
+
else safeI64Multiply(xNumerator, yNumerator)
|
|
1028
|
+
let denominator = if (isDivide)
|
|
1029
|
+
safeI64Multiply(xDenominator, yNumerator)
|
|
1030
|
+
else safeI64Multiply(xDenominator, yDenominator)
|
|
969
1031
|
reducedFraction64(numerator, denominator)
|
|
970
1032
|
},
|
|
971
1033
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
972
|
-
let asFloat = WasmF32.div(
|
|
1034
|
+
let asFloat = WasmF32.div(
|
|
1035
|
+
WasmF32.convertI64S(xNumerator),
|
|
1036
|
+
WasmF32.convertI64S(xDenominator)
|
|
1037
|
+
)
|
|
973
1038
|
if (isDivide) {
|
|
974
1039
|
newFloat32(WasmF32.div(asFloat, boxedFloat32Number(y)))
|
|
975
1040
|
} else {
|
|
@@ -977,7 +1042,10 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
977
1042
|
}
|
|
978
1043
|
},
|
|
979
1044
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
980
|
-
let asFloat = WasmF64.div(
|
|
1045
|
+
let asFloat = WasmF64.div(
|
|
1046
|
+
WasmF64.convertI64S(xNumerator),
|
|
1047
|
+
WasmF64.convertI64S(xDenominator)
|
|
1048
|
+
)
|
|
981
1049
|
if (isDivide) {
|
|
982
1050
|
newFloat64(WasmF64.div(asFloat, boxedFloat64Number(y)))
|
|
983
1051
|
} else {
|
|
@@ -986,13 +1054,13 @@ let numberTimesDivideRationalHelp = (x, y, isDivide) => {
|
|
|
986
1054
|
},
|
|
987
1055
|
_ => {
|
|
988
1056
|
throw UnknownNumberTag
|
|
989
|
-
}
|
|
1057
|
+
},
|
|
990
1058
|
}
|
|
991
1059
|
}
|
|
992
1060
|
}
|
|
993
1061
|
|
|
994
1062
|
let numberTimesDivideFloat64Help = (x, y, isDivide) => {
|
|
995
|
-
let yAsFloat = coerceNumberToWasmF64(WasmI32.toGrain(y)
|
|
1063
|
+
let yAsFloat = coerceNumberToWasmF64(WasmI32.toGrain(y): Number)
|
|
996
1064
|
if (isDivide) {
|
|
997
1065
|
newFloat64(WasmF64.div(x, yAsFloat))
|
|
998
1066
|
} else {
|
|
@@ -1001,7 +1069,10 @@ let numberTimesDivideFloat64Help = (x, y, isDivide) => {
|
|
|
1001
1069
|
}
|
|
1002
1070
|
|
|
1003
1071
|
let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
1004
|
-
if (
|
|
1072
|
+
if (
|
|
1073
|
+
isBoxedNumber(y) &&
|
|
1074
|
+
WasmI32.eq(boxedNumberTag(y), Tags._GRAIN_INT64_BOXED_NUM_TAG)
|
|
1075
|
+
) {
|
|
1005
1076
|
// Special case: f32->f64 promotion
|
|
1006
1077
|
if (isDivide) {
|
|
1007
1078
|
newFloat64(WasmF64.div(WasmF64.promoteF32(x), boxedFloat64Number(y)))
|
|
@@ -1009,7 +1080,7 @@ let numberTimesDivideFloat32Help = (x, y, isDivide) => {
|
|
|
1009
1080
|
newFloat64(WasmF64.mul(WasmF64.promoteF32(x), boxedFloat64Number(y)))
|
|
1010
1081
|
}
|
|
1011
1082
|
} else {
|
|
1012
|
-
let yAsFloat = coerceNumberToWasmF32(WasmI32.toGrain(y)
|
|
1083
|
+
let yAsFloat = coerceNumberToWasmF32(WasmI32.toGrain(y): Number)
|
|
1013
1084
|
if (isDivide) {
|
|
1014
1085
|
newFloat32(WasmF32.div(x, yAsFloat))
|
|
1015
1086
|
} else {
|
|
@@ -1041,7 +1112,7 @@ let numberTimesDivideHelp = (x, y, isDivide) => {
|
|
|
1041
1112
|
},
|
|
1042
1113
|
_ => {
|
|
1043
1114
|
throw UnknownNumberTag
|
|
1044
|
-
}
|
|
1115
|
+
},
|
|
1045
1116
|
}
|
|
1046
1117
|
}
|
|
1047
1118
|
}
|
|
@@ -1059,18 +1130,25 @@ let numberDivide = (x, y) => {
|
|
|
1059
1130
|
* (same schema as equal())
|
|
1060
1131
|
*/
|
|
1061
1132
|
|
|
1062
|
-
let i64abs =
|
|
1133
|
+
let i64abs = x => if (WasmI64.geS(x, 0N)) x else WasmI64.sub(0N, x)
|
|
1063
1134
|
|
|
1064
1135
|
let numberMod = (x, y) => {
|
|
1065
|
-
let xval = coerceNumberToWasmI64(WasmI32.toGrain(x)
|
|
1066
|
-
let yval = coerceNumberToWasmI64(WasmI32.toGrain(y)
|
|
1136
|
+
let xval = coerceNumberToWasmI64(WasmI32.toGrain(x): Number)
|
|
1137
|
+
let yval = coerceNumberToWasmI64(WasmI32.toGrain(y): Number)
|
|
1067
1138
|
if (WasmI64.eqz(yval)) {
|
|
1068
1139
|
throw Exception.ModuloByZero
|
|
1069
1140
|
}
|
|
1070
1141
|
// We implement true modulo
|
|
1071
|
-
if (
|
|
1142
|
+
if (
|
|
1143
|
+
WasmI64.ltS(xval, 0N) && WasmI64.gtS(yval, 0N) ||
|
|
1144
|
+
WasmI64.gtS(xval, 0N) && WasmI64.ltS(yval, 0N)
|
|
1145
|
+
) {
|
|
1072
1146
|
let modval = WasmI64.remS(i64abs(xval), i64abs(yval))
|
|
1073
|
-
let result = if (WasmI64.ne(modval, 0N))
|
|
1147
|
+
let result = if (WasmI64.ne(modval, 0N))
|
|
1148
|
+
WasmI64.mul(
|
|
1149
|
+
WasmI64.sub(i64abs(yval), modval),
|
|
1150
|
+
if (WasmI64.ltS(yval, 0N)) -1N else 1N
|
|
1151
|
+
) else modval
|
|
1074
1152
|
reducedInteger(result)
|
|
1075
1153
|
} else {
|
|
1076
1154
|
reducedInteger(WasmI64.remS(xval, yval))
|
|
@@ -1225,7 +1303,6 @@ export let rec (>>) = (x: Number, y: Number) => {
|
|
|
1225
1303
|
ret
|
|
1226
1304
|
}
|
|
1227
1305
|
|
|
1228
|
-
|
|
1229
1306
|
/// USER-EXPOSED COERCION FUNCTIONS
|
|
1230
1307
|
//
|
|
1231
1308
|
// [NOTE]: Coercion is a *conservative* process! For example, even if a float is 1.0,
|
|
@@ -1233,12 +1310,15 @@ export let rec (>>) = (x: Number, y: Number) => {
|
|
|
1233
1310
|
|
|
1234
1311
|
export let rec coerceNumberToInt32 = (x: Number) => {
|
|
1235
1312
|
let x = WasmI32.fromGrain(x)
|
|
1236
|
-
let result = if (
|
|
1313
|
+
let result = if (
|
|
1314
|
+
!isSimpleNumber(x) &&
|
|
1315
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_INT32_BOXED_NUM_TAG)
|
|
1316
|
+
) {
|
|
1237
1317
|
// avoid extra malloc
|
|
1238
1318
|
x
|
|
1239
1319
|
} else {
|
|
1240
1320
|
// can possibly fail
|
|
1241
|
-
newInt32(coerceNumberToWasmI32(WasmI32.toGrain(x)
|
|
1321
|
+
newInt32(coerceNumberToWasmI32(WasmI32.toGrain(x): Number))
|
|
1242
1322
|
}
|
|
1243
1323
|
let ret = WasmI32.toGrain(result): Int32
|
|
1244
1324
|
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
@@ -1251,11 +1331,14 @@ export let rec coerceNumberToInt32 = (x: Number) => {
|
|
|
1251
1331
|
|
|
1252
1332
|
export let rec coerceNumberToInt64 = (x: Number) => {
|
|
1253
1333
|
let x = WasmI32.fromGrain(x)
|
|
1254
|
-
let result = if (
|
|
1334
|
+
let result = if (
|
|
1335
|
+
!isSimpleNumber(x) &&
|
|
1336
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_INT64_BOXED_NUM_TAG)
|
|
1337
|
+
) {
|
|
1255
1338
|
// avoid extra malloc
|
|
1256
1339
|
x
|
|
1257
1340
|
} else {
|
|
1258
|
-
newInt64(coerceNumberToWasmI64(WasmI32.toGrain(x)
|
|
1341
|
+
newInt64(coerceNumberToWasmI64(WasmI32.toGrain(x): Number))
|
|
1259
1342
|
}
|
|
1260
1343
|
let ret = WasmI32.toGrain(result): Int64
|
|
1261
1344
|
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
@@ -1277,7 +1360,7 @@ export let rec coerceNumberToRational = (x: Number) => {
|
|
|
1277
1360
|
} else if (WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG)) {
|
|
1278
1361
|
newRational(boxedInt32Number(x), 1n)
|
|
1279
1362
|
} else if (WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG)) {
|
|
1280
|
-
newRational(coerceNumberToWasmI32(WasmI32.toGrain(x)
|
|
1363
|
+
newRational(coerceNumberToWasmI32(WasmI32.toGrain(x): Number), 1n)
|
|
1281
1364
|
} else {
|
|
1282
1365
|
throw Exception.NumberNotRational
|
|
1283
1366
|
}
|
|
@@ -1293,11 +1376,14 @@ export let rec coerceNumberToRational = (x: Number) => {
|
|
|
1293
1376
|
|
|
1294
1377
|
export let rec coerceNumberToFloat32 = (x: Number) => {
|
|
1295
1378
|
let x = WasmI32.fromGrain(x)
|
|
1296
|
-
let result = if (
|
|
1379
|
+
let result = if (
|
|
1380
|
+
!isSimpleNumber(x) &&
|
|
1381
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_FLOAT32_BOXED_NUM_TAG)
|
|
1382
|
+
) {
|
|
1297
1383
|
// avoid extra malloc
|
|
1298
1384
|
x
|
|
1299
1385
|
} else {
|
|
1300
|
-
newFloat32(coerceNumberToWasmF32(WasmI32.toGrain(x)
|
|
1386
|
+
newFloat32(coerceNumberToWasmF32(WasmI32.toGrain(x): Number))
|
|
1301
1387
|
}
|
|
1302
1388
|
let ret = WasmI32.toGrain(result): Float32
|
|
1303
1389
|
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
@@ -1310,11 +1396,14 @@ export let rec coerceNumberToFloat32 = (x: Number) => {
|
|
|
1310
1396
|
|
|
1311
1397
|
export let rec coerceNumberToFloat64 = (x: Number) => {
|
|
1312
1398
|
let x = WasmI32.fromGrain(x)
|
|
1313
|
-
let result = if (
|
|
1399
|
+
let result = if (
|
|
1400
|
+
!isSimpleNumber(x) &&
|
|
1401
|
+
WasmI32.eq(boxedNumberTag(x), Tags._GRAIN_FLOAT64_BOXED_NUM_TAG)
|
|
1402
|
+
) {
|
|
1314
1403
|
// avoid extra malloc
|
|
1315
1404
|
x
|
|
1316
1405
|
} else {
|
|
1317
|
-
newFloat64(coerceNumberToWasmF64(WasmI32.toGrain(x)
|
|
1406
|
+
newFloat64(coerceNumberToWasmF64(WasmI32.toGrain(x): Number))
|
|
1318
1407
|
}
|
|
1319
1408
|
let ret = WasmI32.toGrain(result): Float64
|
|
1320
1409
|
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
@@ -1364,12 +1453,16 @@ export let rec convertExactToInexact = (x: Number) => {
|
|
|
1364
1453
|
ret
|
|
1365
1454
|
}
|
|
1366
1455
|
|
|
1367
|
-
let convertInexactToExactHelp =
|
|
1456
|
+
let convertInexactToExactHelp = x => {
|
|
1368
1457
|
if (isSimpleNumber(x)) {
|
|
1369
1458
|
x
|
|
1370
1459
|
} else {
|
|
1371
1460
|
let tag = boxedNumberTag(x)
|
|
1372
|
-
if (
|
|
1461
|
+
if (
|
|
1462
|
+
WasmI32.eq(tag, Tags._GRAIN_INT32_BOXED_NUM_TAG) ||
|
|
1463
|
+
WasmI32.eq(tag, Tags._GRAIN_INT64_BOXED_NUM_TAG) ||
|
|
1464
|
+
WasmI32.eq(tag, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG)
|
|
1465
|
+
) {
|
|
1373
1466
|
x
|
|
1374
1467
|
} else {
|
|
1375
1468
|
match (tag) {
|
|
@@ -1377,21 +1470,27 @@ let convertInexactToExactHelp = (x) => {
|
|
|
1377
1470
|
t when WasmI32.eq(t, Tags._GRAIN_INT64_BOXED_NUM_TAG) => x,
|
|
1378
1471
|
t when WasmI32.eq(t, Tags._GRAIN_RATIONAL_BOXED_NUM_TAG) => x,
|
|
1379
1472
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT32_BOXED_NUM_TAG) => {
|
|
1380
|
-
reducedInteger(
|
|
1473
|
+
reducedInteger(
|
|
1474
|
+
WasmI64.truncF32S(WasmF32.nearest(boxedFloat32Number(x)))
|
|
1475
|
+
)
|
|
1381
1476
|
},
|
|
1382
1477
|
t when WasmI32.eq(t, Tags._GRAIN_FLOAT64_BOXED_NUM_TAG) => {
|
|
1383
|
-
reducedInteger(
|
|
1478
|
+
reducedInteger(
|
|
1479
|
+
WasmI64.truncF64S(WasmF64.nearest(boxedFloat64Number(x)))
|
|
1480
|
+
)
|
|
1384
1481
|
},
|
|
1385
1482
|
_ => {
|
|
1386
1483
|
throw UnknownNumberTag
|
|
1387
|
-
}
|
|
1484
|
+
},
|
|
1388
1485
|
}
|
|
1389
1486
|
}
|
|
1390
1487
|
}
|
|
1391
1488
|
}
|
|
1392
1489
|
|
|
1393
1490
|
export let rec convertInexactToExact = (x: Number) => {
|
|
1394
|
-
let ret = WasmI32.toGrain(
|
|
1491
|
+
let ret = WasmI32.toGrain(
|
|
1492
|
+
convertInexactToExactHelp(WasmI32.fromGrain(x))
|
|
1493
|
+
): Number
|
|
1395
1494
|
if (WasmI32.fromGrain(ret) != WasmI32.fromGrain(x)) {
|
|
1396
1495
|
Memory.decRef(WasmI32.fromGrain(x))
|
|
1397
1496
|
void
|
|
@@ -1452,13 +1551,13 @@ export let rec (%) = (x: Number, y: Number) => {
|
|
|
1452
1551
|
|
|
1453
1552
|
// inc/dec
|
|
1454
1553
|
|
|
1455
|
-
export let incr =
|
|
1554
|
+
export let incr = x => {
|
|
1456
1555
|
Memory.incRef(WasmI32.fromGrain((+)))
|
|
1457
1556
|
// skip incRef on x (to pass through)
|
|
1458
1557
|
x + 1
|
|
1459
1558
|
}
|
|
1460
1559
|
|
|
1461
|
-
export let decr =
|
|
1560
|
+
export let decr = x => {
|
|
1462
1561
|
Memory.incRef(WasmI32.fromGrain((-)))
|
|
1463
1562
|
// skip incRef on x (to pass through)
|
|
1464
1563
|
x - 1
|