porffor 0.59.8 → 0.59.9
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/2c.js +7 -5
- package/compiler/builtins/console.ts +0 -56
- package/compiler/builtins/json.ts +206 -14
- package/compiler/builtins_precompiled.js +497 -493
- package/compiler/codegen.js +79 -22
- package/package.json +1 -1
- package/runtime/index.js +1 -1
package/compiler/2c.js
CHANGED
@@ -534,8 +534,9 @@ export default ({ funcs, globals, data, pages }) => {
|
|
534
534
|
case Opcodes.if: {
|
535
535
|
let cond = removeBrackets(vals.pop());
|
536
536
|
if (!lastCond) {
|
537
|
-
if (cond.startsWith(`(i32)`)) cond = `${cond.slice(5)} != 0e+0`;
|
538
|
-
|
537
|
+
// if (cond.startsWith(`(i32)`)) cond = `${cond.slice(5)} != 0e+0`;
|
538
|
+
// else cond = `(${cond}) != 0`;
|
539
|
+
cond = `(${cond}) != 0`;
|
539
540
|
}
|
540
541
|
|
541
542
|
line(`// if ${invValtype[i[1]] ?? ''}`, false);
|
@@ -600,7 +601,7 @@ export default ({ funcs, globals, data, pages }) => {
|
|
600
601
|
const importFunc = importFuncs[i[1]];
|
601
602
|
switch (importFunc.name) {
|
602
603
|
case 'print':
|
603
|
-
line(`printf("${valtype === 'f64' ? '
|
604
|
+
line(`printf("${valtype === 'f64' ? '%.15g' : '%i'}", ${vals.pop()})`);
|
604
605
|
includes.set('stdio.h', true);
|
605
606
|
break;
|
606
607
|
case 'printChar':
|
@@ -772,8 +773,9 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
772
773
|
|
773
774
|
let cond = removeBrackets(vals.pop());
|
774
775
|
if (!lastCond) {
|
775
|
-
if (cond.startsWith(`(i32)`)) cond = `${cond.slice(5)} != 0e+0`;
|
776
|
-
|
776
|
+
// if (cond.startsWith(`(i32)`)) cond = `${cond.slice(5)} != 0e+0`;
|
777
|
+
// else cond = `(${cond}) != 0`;
|
778
|
+
cond = `(${cond}) != 0`;
|
777
779
|
}
|
778
780
|
|
779
781
|
line(`if (${cond}) {`, false);
|
@@ -29,62 +29,6 @@ export const __Porffor_printHexDigit = (arg: number) => {
|
|
29
29
|
}
|
30
30
|
};
|
31
31
|
|
32
|
-
export const __Porffor_numberLog = (arg: number) => {
|
33
|
-
print(arg);
|
34
|
-
Porffor.printStatic('\n');
|
35
|
-
};
|
36
|
-
|
37
|
-
export const __Porffor_miniLog = (arg: any) => {
|
38
|
-
switch (Porffor.type(arg)) {
|
39
|
-
case Porffor.TYPES.number:
|
40
|
-
print(arg);
|
41
|
-
break;
|
42
|
-
|
43
|
-
case Porffor.TYPES.boolean:
|
44
|
-
if (arg) {
|
45
|
-
Porffor.printStatic('true');
|
46
|
-
} else {
|
47
|
-
Porffor.printStatic('false');
|
48
|
-
}
|
49
|
-
break;
|
50
|
-
|
51
|
-
case Porffor.TYPES.bytestring:
|
52
|
-
case Porffor.TYPES.string:
|
53
|
-
Porffor.printStatic("'");
|
54
|
-
__Porffor_printString(arg);
|
55
|
-
Porffor.printStatic("'");
|
56
|
-
break;
|
57
|
-
|
58
|
-
case Porffor.TYPES.array:
|
59
|
-
const arrLen: i32 = arg.length - 1;
|
60
|
-
if (arrLen == -1) {
|
61
|
-
Porffor.printStatic('[]');
|
62
|
-
} else {
|
63
|
-
Porffor.printStatic('[ ');
|
64
|
-
for (let i: i32 = 0; i <= arrLen; i++) {
|
65
|
-
__Porffor_miniLog(arg[i]);
|
66
|
-
if (i != arrLen) Porffor.printStatic(', ');
|
67
|
-
}
|
68
|
-
Porffor.printStatic(' ]');
|
69
|
-
}
|
70
|
-
break;
|
71
|
-
|
72
|
-
case Porffor.TYPES.undefined:
|
73
|
-
Porffor.printStatic('undefined');
|
74
|
-
break;
|
75
|
-
|
76
|
-
case Porffor.TYPES.object:
|
77
|
-
if (arg) {
|
78
|
-
Porffor.printStatic('[Object]');
|
79
|
-
} else {
|
80
|
-
Porffor.printStatic('null');
|
81
|
-
}
|
82
|
-
break;
|
83
|
-
}
|
84
|
-
|
85
|
-
Porffor.printStatic('\n');
|
86
|
-
};
|
87
|
-
|
88
32
|
export const __Porffor_print = (arg: any, colors: boolean = true, depth: number = 0) => {
|
89
33
|
const __Porffor_printArray = (arg: any[]|Uint8Array|Int8Array|Uint8ClampedArray|Uint16Array|Int16Array|Uint32Array|Int32Array|Float32Array|Float64Array, colors: boolean, length: boolean = false) => {
|
90
34
|
const arrLen: i32 = arg.length;
|
@@ -46,8 +46,10 @@ export const __Porffor_json_serialize = (value: any, depth: i32, space: bytestri
|
|
46
46
|
Porffor.bytestring.append2Char(out, 92, 117); // \u
|
47
47
|
Porffor.bytestring.append2Char(out, 48, 48); // 00
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
const h1: i32 = (c & 0xf0) / 0x10;
|
50
|
+
const h2: i32 = c & 0x0f;
|
51
|
+
Porffor.bytestring.appendChar(out, h1 < 10 ? h1 + 48 : h1 + 55); // 0-9 or A-F
|
52
|
+
Porffor.bytestring.appendChar(out, h2 < 10 ? h2 + 48 : h2 + 55); // 0-9 or A-F
|
51
53
|
continue;
|
52
54
|
}
|
53
55
|
|
@@ -73,7 +75,7 @@ export const __Porffor_json_serialize = (value: any, depth: i32, space: bytestri
|
|
73
75
|
Porffor.type(value) == Porffor.TYPES.number,
|
74
76
|
Porffor.type(value) == Porffor.TYPES.numberobject
|
75
77
|
)) { // number
|
76
|
-
if (Number.isFinite(value)) return
|
78
|
+
if (Number.isFinite(value)) return value + '';
|
77
79
|
return 'null';
|
78
80
|
}
|
79
81
|
|
@@ -87,7 +89,7 @@ export const __Porffor_json_serialize = (value: any, depth: i32, space: bytestri
|
|
87
89
|
for (const x of (value as any[])) {
|
88
90
|
if (hasSpace) {
|
89
91
|
Porffor.bytestring.appendChar(out, 10); // \n
|
90
|
-
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space);
|
92
|
+
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space as bytestring);
|
91
93
|
}
|
92
94
|
|
93
95
|
Porffor.bytestring.appendStr(out, __Porffor_json_serialize(x, depth, space) ?? 'null');
|
@@ -100,10 +102,9 @@ export const __Porffor_json_serialize = (value: any, depth: i32, space: bytestri
|
|
100
102
|
// swap trailing , with ] (or append if empty)
|
101
103
|
if (out.length > 1) {
|
102
104
|
if (hasSpace) {
|
103
|
-
Porffor.
|
104
|
-
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space);
|
105
|
-
Porffor.
|
106
|
-
out.length += 1;
|
105
|
+
Porffor.bytestring.appendChar(out, 10); // \n
|
106
|
+
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space as bytestring);
|
107
|
+
Porffor.bytestring.appendChar(out, 93); // ]
|
107
108
|
} else {
|
108
109
|
Porffor.wasm.i32.store8(Porffor.wasm`local.get ${out}` + out.length, 93, 0, 3); // ]
|
109
110
|
}
|
@@ -132,7 +133,7 @@ export const __Porffor_json_serialize = (value: any, depth: i32, space: bytestri
|
|
132
133
|
|
133
134
|
if (hasSpace) {
|
134
135
|
Porffor.bytestring.appendChar(out, 10); // \n
|
135
|
-
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space);
|
136
|
+
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space as bytestring);
|
136
137
|
}
|
137
138
|
|
138
139
|
Porffor.bytestring.appendChar(out, 34); // "
|
@@ -152,10 +153,9 @@ export const __Porffor_json_serialize = (value: any, depth: i32, space: bytestri
|
|
152
153
|
// swap trailing , with } (or append if empty)
|
153
154
|
if (out.length > 1) {
|
154
155
|
if (hasSpace) {
|
155
|
-
Porffor.
|
156
|
-
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space);
|
157
|
-
Porffor.
|
158
|
-
out.length += 1;
|
156
|
+
Porffor.bytestring.appendChar(out, 10); // \n
|
157
|
+
for (let i: i32 = 0; i < depth; i++) Porffor.bytestring.appendStr(out, space as bytestring);
|
158
|
+
Porffor.bytestring.appendChar(out, 125); // }
|
159
159
|
} else {
|
160
160
|
Porffor.wasm.i32.store8(Porffor.wasm`local.get ${out}` + out.length, 125, 0, 3); // }
|
161
161
|
}
|
@@ -183,7 +183,6 @@ export const __JSON_stringify = (value: any, replacer: any, space: any) => {
|
|
183
183
|
Porffor.type(space) == Porffor.TYPES.numberobject
|
184
184
|
)) {
|
185
185
|
space = Math.min(Math.trunc(space), 10);
|
186
|
-
Porffor.print(space); Porffor.printStatic('\n');
|
187
186
|
|
188
187
|
if (space < 1) {
|
189
188
|
space = undefined;
|
@@ -211,4 +210,197 @@ export const __JSON_stringify = (value: any, replacer: any, space: any) => {
|
|
211
210
|
}
|
212
211
|
|
213
212
|
return __Porffor_json_serialize(value, 0, space);
|
213
|
+
};
|
214
|
+
|
215
|
+
|
216
|
+
// todo: not globals when closures work well
|
217
|
+
let text: bytestring, pos: i32, len: i32;
|
218
|
+
export const __JSON_parse = (_: bytestring) => {
|
219
|
+
text = _;
|
220
|
+
pos = 0;
|
221
|
+
len = text.length;
|
222
|
+
|
223
|
+
const skipWhitespace = () => {
|
224
|
+
while (pos < len) {
|
225
|
+
const c: i32 = text.charCodeAt(pos);
|
226
|
+
if (c > 32) break; // fast path
|
227
|
+
|
228
|
+
if (c == 32 || c == 9 || c == 10 || c == 13) pos++;
|
229
|
+
else break;
|
230
|
+
}
|
231
|
+
};
|
232
|
+
|
233
|
+
const parseValue = (): any => {
|
234
|
+
skipWhitespace();
|
235
|
+
if (pos >= len) throw new SyntaxError('Unexpected end of JSON input');
|
236
|
+
|
237
|
+
const c: i32 = text.charCodeAt(pos);
|
238
|
+
if (c == 110) { // 'n' - null
|
239
|
+
if (pos + 4 <= len &&
|
240
|
+
text.charCodeAt(pos + 1) == 117 && // 'u'
|
241
|
+
text.charCodeAt(pos + 2) == 108 && // 'l'
|
242
|
+
text.charCodeAt(pos + 3) == 108) { // 'l'
|
243
|
+
pos += 4;
|
244
|
+
return null;
|
245
|
+
}
|
246
|
+
throw new SyntaxError('Unexpected token');
|
247
|
+
}
|
248
|
+
|
249
|
+
if (c == 116) { // 't' - true
|
250
|
+
if (pos + 4 <= len &&
|
251
|
+
text.charCodeAt(pos + 1) == 114 && // 'r'
|
252
|
+
text.charCodeAt(pos + 2) == 117 && // 'u'
|
253
|
+
text.charCodeAt(pos + 3) == 101) { // 'e'
|
254
|
+
pos += 4;
|
255
|
+
return true;
|
256
|
+
}
|
257
|
+
throw new SyntaxError('Unexpected token');
|
258
|
+
}
|
259
|
+
|
260
|
+
if (c == 102) { // 'f' - false
|
261
|
+
if (pos + 5 <= len &&
|
262
|
+
text.charCodeAt(pos + 1) == 97 && // 'a'
|
263
|
+
text.charCodeAt(pos + 2) == 108 && // 'l'
|
264
|
+
text.charCodeAt(pos + 3) == 115 && // 's'
|
265
|
+
text.charCodeAt(pos + 4) == 101) { // 'e'
|
266
|
+
pos += 5;
|
267
|
+
return false;
|
268
|
+
}
|
269
|
+
throw new SyntaxError('Unexpected token');
|
270
|
+
}
|
271
|
+
|
272
|
+
if (c == 34) { // '"' - string
|
273
|
+
pos++;
|
274
|
+
const out: bytestring = Porffor.allocate();
|
275
|
+
|
276
|
+
while (pos < len) {
|
277
|
+
const ch: i32 = text.charCodeAt(pos);
|
278
|
+
if (ch == 34) { // closing "
|
279
|
+
pos++;
|
280
|
+
return out;
|
281
|
+
}
|
282
|
+
if (ch == 92) { // backslash
|
283
|
+
pos++;
|
284
|
+
if (pos >= len) throw new SyntaxError('Unterminated string');
|
285
|
+
|
286
|
+
const esc: i32 = text.charCodeAt(pos++);
|
287
|
+
if (esc == 34) Porffor.bytestring.appendChar(out, 34); // \"
|
288
|
+
else if (esc == 92) Porffor.bytestring.appendChar(out, 92); // \\
|
289
|
+
else if (esc == 47) Porffor.bytestring.appendChar(out, 47); // \/
|
290
|
+
else if (esc == 98) Porffor.bytestring.appendChar(out, 8); // \b
|
291
|
+
else if (esc == 102) Porffor.bytestring.appendChar(out, 12); // \f
|
292
|
+
else if (esc == 110) Porffor.bytestring.appendChar(out, 10); // \n
|
293
|
+
else if (esc == 114) Porffor.bytestring.appendChar(out, 13); // \r
|
294
|
+
else if (esc == 116) Porffor.bytestring.appendChar(out, 9); // \t
|
295
|
+
else if (esc == 117) { // \u
|
296
|
+
if (pos + 4 >= len) throw new SyntaxError('Invalid unicode escape');
|
297
|
+
let unicode: i32 = 0;
|
298
|
+
for (let i: i32 = 0; i < 4; i++) {
|
299
|
+
const hex: i32 = text.charCodeAt(pos + i);
|
300
|
+
unicode <<= 4;
|
301
|
+
if (hex >= 48 && hex <= 57) unicode |= hex - 48; // 0-9
|
302
|
+
else if (hex >= 65 && hex <= 70) unicode |= hex - 55; // A-F
|
303
|
+
else if (hex >= 97 && hex <= 102) unicode |= hex - 87; // a-f
|
304
|
+
else throw new SyntaxError('Invalid unicode escape');
|
305
|
+
}
|
306
|
+
pos += 4;
|
307
|
+
Porffor.bytestring.appendChar(out, unicode);
|
308
|
+
} else throw new SyntaxError('Invalid escape sequence');
|
309
|
+
} else {
|
310
|
+
if (ch >= 0x00 && ch <= 0x1f) throw new SyntaxError('Unescaped control character');
|
311
|
+
Porffor.bytestring.appendChar(out, ch);
|
312
|
+
pos++;
|
313
|
+
}
|
314
|
+
}3
|
315
|
+
throw new SyntaxError('Unterminated string');
|
316
|
+
}
|
317
|
+
|
318
|
+
if (c == 91) { // '[' - array
|
319
|
+
pos++;
|
320
|
+
const arr: any[] = Porffor.allocate();
|
321
|
+
skipWhitespace();
|
322
|
+
|
323
|
+
if (pos < len && text.charCodeAt(pos) == 93) { // empty array
|
324
|
+
pos++;
|
325
|
+
return arr;
|
326
|
+
}
|
327
|
+
|
328
|
+
while (true) {
|
329
|
+
arr.push(parseValue());
|
330
|
+
skipWhitespace();
|
331
|
+
if (pos >= len) throw new SyntaxError('Unterminated array');
|
332
|
+
|
333
|
+
const next: i32 = text.charCodeAt(pos);
|
334
|
+
if (next == 93) { // ]
|
335
|
+
pos++;
|
336
|
+
break;
|
337
|
+
}
|
338
|
+
if (next == 44) { // ,
|
339
|
+
pos++;
|
340
|
+
continue;
|
341
|
+
}
|
342
|
+
throw new SyntaxError('Expected , or ]');
|
343
|
+
}
|
344
|
+
return arr;
|
345
|
+
}
|
346
|
+
|
347
|
+
if (c == 123) { // '{' - object
|
348
|
+
pos++;
|
349
|
+
const obj: any = {};
|
350
|
+
skipWhitespace();
|
351
|
+
|
352
|
+
if (pos < len && text.charCodeAt(pos) == 125) { // empty object
|
353
|
+
pos++;
|
354
|
+
return obj;
|
355
|
+
}
|
356
|
+
|
357
|
+
while (true) {
|
358
|
+
skipWhitespace();
|
359
|
+
if (pos >= len || text.charCodeAt(pos) != 34) throw new SyntaxError('Expected string key');
|
360
|
+
|
361
|
+
const key: any = parseValue();
|
362
|
+
skipWhitespace();
|
363
|
+
if (pos >= len || text.charCodeAt(pos) != 58) throw new SyntaxError('Expected :');
|
364
|
+
pos++;
|
365
|
+
|
366
|
+
const value: any = parseValue();
|
367
|
+
obj[key] = value;
|
368
|
+
|
369
|
+
skipWhitespace();
|
370
|
+
if (pos >= len) throw new SyntaxError('Unterminated object');
|
371
|
+
|
372
|
+
const next: i32 = text.charCodeAt(pos);
|
373
|
+
if (next == 125) { // }
|
374
|
+
pos++;
|
375
|
+
break;
|
376
|
+
}
|
377
|
+
if (next == 44) { // ,
|
378
|
+
pos++;
|
379
|
+
continue;
|
380
|
+
}
|
381
|
+
throw new SyntaxError('Expected , or }');
|
382
|
+
}
|
383
|
+
return obj;
|
384
|
+
}
|
385
|
+
|
386
|
+
// number
|
387
|
+
if ((c >= 48 && c <= 57) || c == 45) { // 0-9 or -
|
388
|
+
const start: i32 = pos;
|
389
|
+
if (c == 45) pos++; // skip -
|
390
|
+
|
391
|
+
while (pos < len) {
|
392
|
+
const ch: i32 = text.charCodeAt(pos);
|
393
|
+
if (ch >= 48 && ch <= 57) pos++; // 0-9
|
394
|
+
else if (ch == 46 || ch == 101 || ch == 69) pos++; // . e E
|
395
|
+
else if ((ch == 43 || ch == 45) && pos > start + 1) pos++; // + - (not at start)
|
396
|
+
else break;
|
397
|
+
}
|
398
|
+
|
399
|
+
return +ecma262.StringToNumber(__ByteString_prototype_slice(text, start, pos));
|
400
|
+
}
|
401
|
+
|
402
|
+
throw new SyntaxError('Unexpected token');
|
403
|
+
};
|
404
|
+
|
405
|
+
return parseValue();
|
214
406
|
};
|