porffor 0.55.15 → 0.55.16
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/compiler/builtins/bigint.ts +233 -0
- package/compiler/builtins_precompiled.js +485 -398
- package/compiler/precompile.js +1 -1
- package/compiler/wrap.js +14 -0
- package/package.json +1 -1
- package/r.cjs +0 -4
- package/runner/index.js +1 -1
@@ -0,0 +1,233 @@
|
|
1
|
+
import type {} from './porffor.d.ts';
|
2
|
+
|
3
|
+
// digits is an array of u32s as digits in base 2^32
|
4
|
+
export const __Porffor_bigint_fromDigits = (negative: boolean, digits: i32[]): bigint => {
|
5
|
+
const len: i32 = digits.length;
|
6
|
+
if (len > 16383) throw new RangeError('Maximum BigInt size exceeded'); // (65536 - 4) / 4
|
7
|
+
|
8
|
+
// const ptr: i32 = Porffor.allocate();
|
9
|
+
const ptr: i32 = Porffor.wasm`local.get ${digits}`;
|
10
|
+
|
11
|
+
Porffor.wasm.i32.store8(ptr, negative ? 1 : 0, 0, 0);
|
12
|
+
Porffor.wasm.i32.store16(ptr, len, 0, 2);
|
13
|
+
|
14
|
+
for (let i: i32 = 0; i < len; i++) {
|
15
|
+
Porffor.wasm.i32.store(ptr + i * 4, digits[i], 0, 4);
|
16
|
+
}
|
17
|
+
|
18
|
+
const out: bigint = ptr;
|
19
|
+
return out;
|
20
|
+
};
|
21
|
+
|
22
|
+
export const __Porffor_bigint_fromNumber = (n: number): bigint => {
|
23
|
+
if (!Number.isInteger(n) || !Number.isFinite(n)) throw new RangeError('Cannot convert non-integer to BigInt');
|
24
|
+
|
25
|
+
const negative: boolean = n < 0;
|
26
|
+
n = Math.abs(n);
|
27
|
+
|
28
|
+
const digits: i32[] = Porffor.allocate();
|
29
|
+
while (n > 0) {
|
30
|
+
digits.unshift(n % 0x100000000);
|
31
|
+
n = Math.trunc(n / 0x100000000);
|
32
|
+
}
|
33
|
+
|
34
|
+
return __Porffor_bigint_fromDigits(negative, digits);
|
35
|
+
};
|
36
|
+
|
37
|
+
export const __Porffor_bigint_toNumber = (ptr: i32): number => {
|
38
|
+
const negative: boolean = Porffor.wasm.i32.load8_u(ptr, 0, 0) != 0;
|
39
|
+
const len: i32 = Porffor.wasm.i32.load16_u(ptr, 0, 2);
|
40
|
+
|
41
|
+
let out: number = 0;
|
42
|
+
for (let i: i32 = 0; i < len; i++) {
|
43
|
+
const d: i32 = Porffor.wasm.i32.load(ptr + i * 4, 0, 4);
|
44
|
+
out = out * 0x100000000 + d;
|
45
|
+
}
|
46
|
+
|
47
|
+
if (negative) out = -out;
|
48
|
+
return out;
|
49
|
+
};
|
50
|
+
|
51
|
+
export const __Porffor_bigint_fromString = (n: string|bytestring): bigint => {
|
52
|
+
const len: i32 = n.length;
|
53
|
+
|
54
|
+
let negative: boolean = false;
|
55
|
+
let end: i32 = 0;
|
56
|
+
if (n[0] === '-') {
|
57
|
+
negative = true;
|
58
|
+
end = 1;
|
59
|
+
} else if (n[0] === '+') {
|
60
|
+
end = 1;
|
61
|
+
}
|
62
|
+
|
63
|
+
// n -> digits (base 2^32) (most to least significant)
|
64
|
+
// 4294967294 -> [ 4294967294 ]
|
65
|
+
// 4294967295 -> [ 4294967295 ]
|
66
|
+
// 4294967296 -> [ 1, 0 ]
|
67
|
+
// 4294967297 -> [ 1, 1 ]
|
68
|
+
// 4294967298 -> [ 1, 2 ]
|
69
|
+
// 9007199254740992 -> [ 2097152 ]
|
70
|
+
// 9007199254740993 -> [ 2097152, 1 ]
|
71
|
+
// 9007199254740994 -> [ 2097152, 2 ]
|
72
|
+
// 9007199254740995 -> [ 2097152, 3 ]
|
73
|
+
|
74
|
+
const digits: i32[] = Porffor.allocate();
|
75
|
+
|
76
|
+
const base = 0x100000000; // 2^32
|
77
|
+
|
78
|
+
for (let i: i32 = end; i < len; i++) {
|
79
|
+
const char: i32 = n.charCodeAt(i);
|
80
|
+
const digit: i32 = char - 48;
|
81
|
+
if (digit < 0 || digit > 9) throw new SyntaxError('Invalid characters in BigInt string');
|
82
|
+
|
83
|
+
// Multiply current digits by 10 and add the new digit
|
84
|
+
let carry: i32 = digit;
|
85
|
+
for (let j: i32 = 0; j < digits.length; j++) {
|
86
|
+
const value: i32 = digits[j] * 10 + carry;
|
87
|
+
digits[j] = value % base;
|
88
|
+
carry = Math.trunc(value / base);
|
89
|
+
}
|
90
|
+
|
91
|
+
// If there's a carry left, push it as a new digit
|
92
|
+
if (carry > 0) {
|
93
|
+
digits.push(carry);
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
return __Porffor_bigint_fromDigits(negative, digits);
|
98
|
+
};
|
99
|
+
|
100
|
+
export const __Porffor_bigint_toString = (ptr: i32, radix: number): string => {
|
101
|
+
// todo
|
102
|
+
// return '';
|
103
|
+
};
|
104
|
+
|
105
|
+
export const __Porffor_bigint_add = (a: i32, b: i32, sub: boolean): bigint => {
|
106
|
+
const aNegative: boolean = Porffor.wasm.i32.load8_u(a, 0, 0) != 0;
|
107
|
+
const aLen: i32 = Porffor.wasm.i32.load16_u(a, 0, 2);
|
108
|
+
|
109
|
+
let bNegative: boolean = Porffor.wasm.i32.load8_u(b, 0, 0) != 0;
|
110
|
+
if (sub) bNegative = !bNegative;
|
111
|
+
const bLen: i32 = Porffor.wasm.i32.load16_u(b, 0, 2);
|
112
|
+
|
113
|
+
const maxLen: i32 = Math.max(aLen, bLen);
|
114
|
+
const digits: i32[] = Porffor.allocate();
|
115
|
+
|
116
|
+
// fast path: same sign
|
117
|
+
let negative: boolean = false;
|
118
|
+
let carry: i32 = 0;
|
119
|
+
if (aNegative == bNegative) {
|
120
|
+
negative = aNegative;
|
121
|
+
|
122
|
+
for (let i: i32 = 0; i < maxLen; i++) {
|
123
|
+
let aDigit: i32 = 0;
|
124
|
+
const aOffset: i32 = aLen - i;
|
125
|
+
if (aOffset > 0) aDigit = Porffor.wasm.i32.load(a + aOffset * 4, 0, 0);
|
126
|
+
|
127
|
+
let bDigit: i32 = 0;
|
128
|
+
const bOffset: i32 = bLen - i;
|
129
|
+
if (bOffset > 0) bDigit = Porffor.wasm.i32.load(b + bOffset * 4, 0, 0);
|
130
|
+
|
131
|
+
let sum: i32 = aDigit + bDigit + carry;
|
132
|
+
if (sum >= 0x100000000) {
|
133
|
+
sum -= 0x100000000;
|
134
|
+
carry = 1;
|
135
|
+
} else if (sum < 0) {
|
136
|
+
sum += 0x100000000;
|
137
|
+
carry = 1;
|
138
|
+
} else {
|
139
|
+
carry = 0;
|
140
|
+
}
|
141
|
+
|
142
|
+
digits.unshift(sum);
|
143
|
+
}
|
144
|
+
} else {
|
145
|
+
let aLarger: i32 = 0;
|
146
|
+
for (let i: i32 = 0; i < maxLen; i++) {
|
147
|
+
let aDigit: i32 = 0;
|
148
|
+
const aOffset: i32 = aLen - i;
|
149
|
+
if (aOffset > 0) aDigit = Porffor.wasm.i32.load(a + aOffset * 4, 0, 0);
|
150
|
+
|
151
|
+
let bDigit: i32 = 0;
|
152
|
+
const bOffset: i32 = bLen - i;
|
153
|
+
if (bOffset > 0) bDigit = Porffor.wasm.i32.load(b + bOffset * 4, 0, 0);
|
154
|
+
|
155
|
+
let sum: i32 = carry;
|
156
|
+
if (aNegative) sum -= aDigit;
|
157
|
+
else sum += aDigit;
|
158
|
+
if (bNegative) sum -= bDigit;
|
159
|
+
else sum += bDigit;
|
160
|
+
|
161
|
+
if (aDigit != bDigit) aLarger = aDigit > bDigit ? 1 : -1;
|
162
|
+
|
163
|
+
if (sum >= 0x100000000) {
|
164
|
+
sum -= 0x100000000;
|
165
|
+
carry = 1;
|
166
|
+
} else if (sum < 0) {
|
167
|
+
sum += 0x100000000;
|
168
|
+
carry = -1;
|
169
|
+
} else {
|
170
|
+
carry = 0;
|
171
|
+
}
|
172
|
+
|
173
|
+
digits.unshift(sum);
|
174
|
+
}
|
175
|
+
|
176
|
+
if (aLarger == 1) negative = aNegative;
|
177
|
+
else if (aLarger == -1) negative = bNegative;
|
178
|
+
}
|
179
|
+
|
180
|
+
if (carry != 0) {
|
181
|
+
digits.unshift(Math.abs(carry));
|
182
|
+
if (carry < 0) negative = !negative;
|
183
|
+
}
|
184
|
+
|
185
|
+
return __Porffor_bigint_fromDigits(negative, digits);
|
186
|
+
};
|
187
|
+
|
188
|
+
export const __Porffor_bigint_sub = (a: i32, b: i32): bigint => {
|
189
|
+
return __Porffor_bigint_add(a, b, true);
|
190
|
+
};
|
191
|
+
|
192
|
+
export const __Porffor_bigint_mul = (a: i32, b: i32): bigint => {
|
193
|
+
// todo
|
194
|
+
// return 0n;
|
195
|
+
};
|
196
|
+
|
197
|
+
export const __Porffor_bigint_div = (a: i32, b: i32): bigint => {
|
198
|
+
// todo
|
199
|
+
// return 0n;
|
200
|
+
};
|
201
|
+
|
202
|
+
export const __Porffor_bigint_rem = (a: i32, b: i32): bigint => {
|
203
|
+
// todo
|
204
|
+
// return 0n;
|
205
|
+
};
|
206
|
+
|
207
|
+
export const __Porffor_bigint_eq = (a: i32, b: i32): boolean => {
|
208
|
+
// todo
|
209
|
+
// return false;
|
210
|
+
};
|
211
|
+
|
212
|
+
export const __Porffor_bigint_ne = (a: i32, b: i32): boolean => {
|
213
|
+
return !__Porffor_bigint_eq(a, b);
|
214
|
+
};
|
215
|
+
|
216
|
+
export const __Porffor_bigint_gt = (a: i32, b: i32): boolean => {
|
217
|
+
// todo
|
218
|
+
// return false;
|
219
|
+
};
|
220
|
+
|
221
|
+
export const __Porffor_bigint_ge = (a: i32, b: i32): boolean => {
|
222
|
+
// todo
|
223
|
+
// return false;
|
224
|
+
};
|
225
|
+
|
226
|
+
export const __Porffor_bigint_lt = (a: i32, b: i32): boolean => {
|
227
|
+
return !__Porffor_bigint_ge(a, b);
|
228
|
+
};
|
229
|
+
|
230
|
+
export const __Porffor_bigint_le = (a: i32, b: i32): boolean => {
|
231
|
+
return !__Porffor_bigint_gt(a, b);
|
232
|
+
};
|
233
|
+
|