porffor 0.0.0-8c0bdaa → 0.0.0-bddcdc3
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/README.md +1 -1
- package/compiler/codeGen.js +180 -31
- package/compiler/wrap.js +2 -2
- package/package.json +1 -1
- package/publish.js +3 -1
- package/runner/index.js +1 -0
- package/runner/repl.js +6 -4
- package/runner/transform.js +4 -26
- package/t.js +31 -0
package/README.md
CHANGED
@@ -76,6 +76,7 @@ these include some early (stage 1/0) and/or dead (last commit years ago) proposa
|
|
76
76
|
- string member (char) access via `str[ind]` (eg `str[0]`)
|
77
77
|
- string concat (`+`) (eg `'a' + 'b'`)
|
78
78
|
- truthy/falsy (eg `!'' == true`)
|
79
|
+
- string comparison (eg `'a' == 'a'`, `'a' != 'b'`)
|
79
80
|
|
80
81
|
### built-ins
|
81
82
|
|
@@ -106,7 +107,6 @@ these include some early (stage 1/0) and/or dead (last commit years ago) proposa
|
|
106
107
|
- arrays/strings inside arrays
|
107
108
|
- strings
|
108
109
|
- member setting
|
109
|
-
- equality
|
110
110
|
- more math operators (`**`, etc)
|
111
111
|
- `do { ... } while (...)`
|
112
112
|
- exceptions
|
package/compiler/codeGen.js
CHANGED
@@ -101,6 +101,9 @@ const generate = (scope, decl, global = false, name = undefined) => {
|
|
101
101
|
case 'WhileStatement':
|
102
102
|
return generateWhile(scope, decl);
|
103
103
|
|
104
|
+
/* case 'ForOfStatement':
|
105
|
+
return generateForOf(scope, decl); */
|
106
|
+
|
104
107
|
case 'BreakStatement':
|
105
108
|
return generateBreak(scope, decl);
|
106
109
|
|
@@ -327,13 +330,13 @@ const concatStrings = (scope, left, right, global, name, assign) => {
|
|
327
330
|
|
328
331
|
scope.memory = true;
|
329
332
|
|
330
|
-
const pointer = arrays.get(name ?? '$undeclared');
|
331
|
-
|
332
333
|
const rightPointer = localTmp(scope, 'concat_right_pointer', Valtype.i32);
|
333
334
|
const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
|
334
335
|
const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
|
335
336
|
|
336
337
|
if (assign) {
|
338
|
+
const pointer = arrays.get(name ?? '$undeclared');
|
339
|
+
|
337
340
|
return [
|
338
341
|
// setup right
|
339
342
|
...right,
|
@@ -384,15 +387,12 @@ const concatStrings = (scope, left, right, global, name, assign) => {
|
|
384
387
|
|
385
388
|
const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
|
386
389
|
|
387
|
-
|
390
|
+
// alloc/assign array
|
391
|
+
const [ , pointer ] = makeArray(scope, {
|
388
392
|
rawElements: new Array(0)
|
389
393
|
}, global, name, true, 'i16');
|
390
394
|
|
391
395
|
return [
|
392
|
-
// setup new/out array
|
393
|
-
...newOut,
|
394
|
-
[ Opcodes.drop ],
|
395
|
-
|
396
396
|
// setup left
|
397
397
|
...left,
|
398
398
|
Opcodes.i32_to_u,
|
@@ -458,6 +458,111 @@ const concatStrings = (scope, left, right, global, name, assign) => {
|
|
458
458
|
];
|
459
459
|
};
|
460
460
|
|
461
|
+
const compareStrings = (scope, left, right) => {
|
462
|
+
// todo: this should be rewritten into a built-in/func: String.prototype.concat
|
463
|
+
// todo: convert left and right to strings if not
|
464
|
+
// todo: optimize by looking up names in arrays and using that if exists?
|
465
|
+
// todo: optimize this if using literals/known lengths?
|
466
|
+
|
467
|
+
scope.memory = true;
|
468
|
+
|
469
|
+
const leftPointer = localTmp(scope, 'compare_left_pointer', Valtype.i32);
|
470
|
+
const leftLength = localTmp(scope, 'compare_left_length', Valtype.i32);
|
471
|
+
const rightPointer = localTmp(scope, 'compare_right_pointer', Valtype.i32);
|
472
|
+
const rightLength = localTmp(scope, 'compare_right_length', Valtype.i32);
|
473
|
+
|
474
|
+
const index = localTmp(scope, 'compare_index', Valtype.i32);
|
475
|
+
const indexEnd = localTmp(scope, 'compare_index_end', Valtype.i32);
|
476
|
+
|
477
|
+
return [
|
478
|
+
// setup left
|
479
|
+
...left,
|
480
|
+
Opcodes.i32_to_u,
|
481
|
+
[ Opcodes.local_tee, leftPointer ],
|
482
|
+
|
483
|
+
// setup right
|
484
|
+
...right,
|
485
|
+
Opcodes.i32_to_u,
|
486
|
+
[ Opcodes.local_tee, rightPointer ],
|
487
|
+
|
488
|
+
// fast path: check leftPointer == rightPointer
|
489
|
+
// use if (block) for everything after to "return" a value early
|
490
|
+
[ Opcodes.i32_ne ],
|
491
|
+
[ Opcodes.if, Valtype.i32 ],
|
492
|
+
|
493
|
+
// get lengths
|
494
|
+
[ Opcodes.local_get, leftPointer ],
|
495
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(0) ],
|
496
|
+
[ Opcodes.local_tee, leftLength ],
|
497
|
+
|
498
|
+
[ Opcodes.local_get, rightPointer ],
|
499
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(0) ],
|
500
|
+
[ Opcodes.local_tee, rightLength ],
|
501
|
+
|
502
|
+
// fast path: check leftLength != rightLength
|
503
|
+
[ Opcodes.i32_ne ],
|
504
|
+
[ Opcodes.if, Blocktype.void ],
|
505
|
+
...number(0, Valtype.i32),
|
506
|
+
[ Opcodes.br, 1 ],
|
507
|
+
[ Opcodes.end ],
|
508
|
+
|
509
|
+
// no fast path for length = 0 as it would probably be slower for most of the time?
|
510
|
+
|
511
|
+
// setup index end as length * sizeof i16 (2)
|
512
|
+
// we do this instead of having to do mul/div each iter for perf™
|
513
|
+
[ Opcodes.local_get, leftLength ],
|
514
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
515
|
+
[ Opcodes.i32_mul ],
|
516
|
+
[ Opcodes.local_set, indexEnd ],
|
517
|
+
|
518
|
+
// iterate over each char and check if eq
|
519
|
+
[ Opcodes.loop, Blocktype.void ],
|
520
|
+
|
521
|
+
// fetch left
|
522
|
+
[ Opcodes.local_get, index ],
|
523
|
+
[ Opcodes.local_get, leftPointer ],
|
524
|
+
[ Opcodes.i32_add ],
|
525
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
|
526
|
+
|
527
|
+
// fetch right
|
528
|
+
[ Opcodes.local_get, index ],
|
529
|
+
[ Opcodes.local_get, rightPointer ],
|
530
|
+
[ Opcodes.i32_add ],
|
531
|
+
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ...unsignedLEB128(ValtypeSize.i32) ],
|
532
|
+
|
533
|
+
// not equal, "return" false
|
534
|
+
[ Opcodes.i32_ne ],
|
535
|
+
[ Opcodes.if, Blocktype.void ],
|
536
|
+
...number(0, Valtype.i32),
|
537
|
+
[ Opcodes.br, 2 ],
|
538
|
+
[ Opcodes.end ],
|
539
|
+
|
540
|
+
// index += sizeof i16 (2)
|
541
|
+
[ Opcodes.local_get, index ],
|
542
|
+
...number(ValtypeSize.i16, Valtype.i32),
|
543
|
+
[ Opcodes.i32_add ],
|
544
|
+
[ Opcodes.local_tee, index ],
|
545
|
+
|
546
|
+
// if index != index end (length * sizeof 16), loop
|
547
|
+
[ Opcodes.local_get, indexEnd ],
|
548
|
+
[ Opcodes.i32_ne ],
|
549
|
+
[ Opcodes.br_if, 0 ],
|
550
|
+
[ Opcodes.end ],
|
551
|
+
|
552
|
+
// no failed checks, so true!
|
553
|
+
...number(1, Valtype.i32),
|
554
|
+
|
555
|
+
// pointers match, so true
|
556
|
+
[ Opcodes.else ],
|
557
|
+
...number(1, Valtype.i32),
|
558
|
+
[ Opcodes.end ],
|
559
|
+
|
560
|
+
// convert i32 result to valtype
|
561
|
+
// do not do as automatically added by binary exp gen for equality ops
|
562
|
+
// Opcodes.i32_from_u
|
563
|
+
];
|
564
|
+
};
|
565
|
+
|
461
566
|
const falsy = (scope, wasm, type) => {
|
462
567
|
// arrays are always truthy
|
463
568
|
if (type === TYPES._array) return [
|
@@ -524,11 +629,28 @@ const truthy = (scope, wasm, type) => {
|
|
524
629
|
];
|
525
630
|
};
|
526
631
|
|
527
|
-
const performOp = (scope, op, left, right, leftType, rightType, _global = false, _name = '$
|
632
|
+
const performOp = (scope, op, left, right, leftType, rightType, _global = false, _name = '$undeclared', assign = false) => {
|
528
633
|
if (op === '||' || op === '&&' || op === '??') {
|
529
634
|
return performLogicOp(scope, op, left, right);
|
530
635
|
}
|
531
636
|
|
637
|
+
if (codeLog && (!leftType || !rightType)) log('codegen', 'untracked type in op', op, _name, '\n' + new Error().stack.split('\n').slice(1).join('\n'));
|
638
|
+
|
639
|
+
// if strict (in)equal and known types mismatch, return false (===)/true (!==)
|
640
|
+
if ((op === '===' || op === '!==') && leftType && rightType && leftType !== rightType) {
|
641
|
+
return [
|
642
|
+
...left,
|
643
|
+
...right,
|
644
|
+
|
645
|
+
// drop values
|
646
|
+
[ Opcodes.drop ],
|
647
|
+
[ Opcodes.drop ],
|
648
|
+
|
649
|
+
// return false (===)/true (!==)
|
650
|
+
...number(op === '===' ? 0 : 1, Valtype.i32)
|
651
|
+
];
|
652
|
+
}
|
653
|
+
|
532
654
|
if (leftType === TYPES.string || rightType === TYPES.string) {
|
533
655
|
if (op === '+') {
|
534
656
|
// string concat (a + b)
|
@@ -539,8 +661,20 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
539
661
|
if (!['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(op)) return number(NaN);
|
540
662
|
|
541
663
|
// else leave bool ops
|
542
|
-
// todo: convert string to number if string and number
|
543
|
-
// todo: string
|
664
|
+
// todo: convert string to number if string and number/bool
|
665
|
+
// todo: string (>|>=|<|<=) string
|
666
|
+
|
667
|
+
// string comparison
|
668
|
+
if (op === '===' || op === '==') {
|
669
|
+
return compareStrings(scope, left, right);
|
670
|
+
}
|
671
|
+
|
672
|
+
if (op === '!==' || op === '!=') {
|
673
|
+
return [
|
674
|
+
...compareStrings(scope, left, right),
|
675
|
+
[ Opcodes.i32_eqz ]
|
676
|
+
];
|
677
|
+
}
|
544
678
|
}
|
545
679
|
|
546
680
|
let ops = operatorOpcode[valtype][op];
|
@@ -569,13 +703,17 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
569
703
|
];
|
570
704
|
};
|
571
705
|
|
706
|
+
let binaryExpDepth = 0;
|
572
707
|
const generateBinaryExp = (scope, decl, _global, _name) => {
|
708
|
+
binaryExpDepth++;
|
709
|
+
|
573
710
|
const out = [
|
574
711
|
...performOp(scope, decl.operator, generate(scope, decl.left), generate(scope, decl.right), getNodeType(scope, decl.left), getNodeType(scope, decl.right), _global, _name)
|
575
712
|
];
|
576
713
|
|
577
714
|
if (valtype !== 'i32' && ['==', '===', '!=', '!==', '>', '>=', '<', '<='].includes(decl.operator)) out.push(Opcodes.i32_from_u);
|
578
715
|
|
716
|
+
binaryExpDepth--;
|
579
717
|
return out;
|
580
718
|
};
|
581
719
|
|
@@ -682,6 +820,7 @@ const getType = (scope, _name) => {
|
|
682
820
|
|
683
821
|
const getNodeType = (scope, node) => {
|
684
822
|
if (node.type === 'Literal') {
|
823
|
+
if (['number', 'boolean', 'string', 'undefined', 'object', 'function', 'symbol', 'bigint'].includes(node.value)) return TYPES.number;
|
685
824
|
return TYPES[typeof node.value];
|
686
825
|
}
|
687
826
|
|
@@ -696,7 +835,7 @@ const getNodeType = (scope, node) => {
|
|
696
835
|
if (node.type === 'CallExpression' || node.type === 'NewExpression') {
|
697
836
|
const name = node.callee.name;
|
698
837
|
const func = funcs.find(x => x.name === name);
|
699
|
-
if (func) return func.returnType
|
838
|
+
if (func) return func.returnType;
|
700
839
|
|
701
840
|
if (builtinFuncs[name]) return TYPES[builtinFuncs[name].returnType ?? 'number'];
|
702
841
|
if (internalConstrs[name]) return internalConstrs[name].type;
|
@@ -721,9 +860,7 @@ const getNodeType = (scope, node) => {
|
|
721
860
|
protoFunc = prototypeFuncs[baseType]?.[func];
|
722
861
|
}
|
723
862
|
|
724
|
-
if (protoFunc) return protoFunc.returnType
|
725
|
-
|
726
|
-
return TYPES.number;
|
863
|
+
if (protoFunc) return protoFunc.returnType;
|
727
864
|
}
|
728
865
|
|
729
866
|
if (node.type === 'ExpressionStatement') {
|
@@ -755,9 +892,6 @@ const getNodeType = (scope, node) => {
|
|
755
892
|
|
756
893
|
if (objectType === TYPES.string && node.computed) return TYPES.string;
|
757
894
|
}
|
758
|
-
|
759
|
-
// default to number
|
760
|
-
return TYPES.number;
|
761
895
|
};
|
762
896
|
|
763
897
|
const generateLiteral = (scope, decl, global, name) => {
|
@@ -792,7 +926,7 @@ const generateLiteral = (scope, decl, global, name) => {
|
|
792
926
|
|
793
927
|
return makeArray(scope, {
|
794
928
|
rawElements
|
795
|
-
}, global, name, false, 'i16');
|
929
|
+
}, global, name, false, 'i16')[0];
|
796
930
|
|
797
931
|
default:
|
798
932
|
return todo(`cannot generate literal of type ${typeof decl.value}`);
|
@@ -941,10 +1075,9 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
941
1075
|
if (codeLog) log('codegen', 'cloning unknown dynamic pointer');
|
942
1076
|
|
943
1077
|
// register array
|
944
|
-
makeArray(scope, {
|
1078
|
+
const [ , pointer ] = makeArray(scope, {
|
945
1079
|
rawElements: new Array(0)
|
946
1080
|
}, _global, baseName, true, baseType === TYPES.string ? 'i16' : valtype);
|
947
|
-
pointer = arrays.get(baseName);
|
948
1081
|
|
949
1082
|
const [ local, isGlobal ] = lookupName(scope, baseName);
|
950
1083
|
|
@@ -980,10 +1113,9 @@ const generateCall = (scope, decl, _global, _name) => {
|
|
980
1113
|
set: value => arrayUtil.setLength(pointer, value),
|
981
1114
|
setI32: value => arrayUtil.setLengthI32(pointer, value)
|
982
1115
|
}, generate(scope, decl.arguments[0] ?? DEFAULT_VALUE), protoLocal, (length, itemType) => {
|
983
|
-
|
1116
|
+
return makeArray(scope, {
|
984
1117
|
rawElements: new Array(length)
|
985
1118
|
}, _global, _name, true, itemType);
|
986
|
-
return [ out, arrays.get(_name ?? '$undeclared') ];
|
987
1119
|
}),
|
988
1120
|
[ Opcodes.end ]
|
989
1121
|
];
|
@@ -1289,7 +1421,7 @@ const generateUnary = (scope, decl) => {
|
|
1289
1421
|
return out;
|
1290
1422
|
|
1291
1423
|
case 'typeof':
|
1292
|
-
const type = getNodeType(scope, decl.argument);
|
1424
|
+
const type = getNodeType(scope, decl.argument) ?? TYPES.number;
|
1293
1425
|
|
1294
1426
|
// for custom types, just return object
|
1295
1427
|
if (type > 0xffffffffffff7) return number(TYPES.object);
|
@@ -1422,9 +1554,28 @@ const generateWhile = (scope, decl) => {
|
|
1422
1554
|
return out;
|
1423
1555
|
};
|
1424
1556
|
|
1557
|
+
const generateForOf = (scope, decl) => {
|
1558
|
+
const out = [];
|
1559
|
+
|
1560
|
+
out.push([ Opcodes.loop, Blocktype.void ]);
|
1561
|
+
depth.push('while');
|
1562
|
+
|
1563
|
+
out.push(...generate(scope, decl.test));
|
1564
|
+
out.push(Opcodes.i32_to, [ Opcodes.if, Blocktype.void ]);
|
1565
|
+
depth.push('if');
|
1566
|
+
|
1567
|
+
out.push(...generate(scope, decl.body));
|
1568
|
+
|
1569
|
+
out.push([ Opcodes.br, 1 ]);
|
1570
|
+
out.push([ Opcodes.end ], [ Opcodes.end ]);
|
1571
|
+
depth.pop(); depth.pop();
|
1572
|
+
|
1573
|
+
return out;
|
1574
|
+
};
|
1575
|
+
|
1425
1576
|
const getNearestLoop = () => {
|
1426
1577
|
for (let i = depth.length - 1; i >= 0; i--) {
|
1427
|
-
if (depth[i] === 'while' || depth[i] === 'for') return i;
|
1578
|
+
if (depth[i] === 'while' || depth[i] === 'for' || depth[i] === 'forof') return i;
|
1428
1579
|
}
|
1429
1580
|
|
1430
1581
|
return -1;
|
@@ -1578,12 +1729,12 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
1578
1729
|
|
1579
1730
|
scope.memory = true;
|
1580
1731
|
|
1581
|
-
return out;
|
1732
|
+
return [ out, pointer ];
|
1582
1733
|
};
|
1583
1734
|
|
1584
1735
|
let arrays = new Map();
|
1585
1736
|
const generateArray = (scope, decl, global = false, name = '$undeclared', initEmpty = false) => {
|
1586
|
-
return makeArray(scope, decl, global, name, initEmpty, valtype);
|
1737
|
+
return makeArray(scope, decl, global, name, initEmpty, valtype)[0];
|
1587
1738
|
};
|
1588
1739
|
|
1589
1740
|
export const generateMember = (scope, decl, _global, _name) => {
|
@@ -1644,10 +1795,9 @@ export const generateMember = (scope, decl, _global, _name) => {
|
|
1644
1795
|
|
1645
1796
|
// string
|
1646
1797
|
|
1647
|
-
const newOut = makeArray(scope, {
|
1798
|
+
const [ newOut, newPointer ] = makeArray(scope, {
|
1648
1799
|
rawElements: new Array(1)
|
1649
1800
|
}, _global, _name, true, 'i16');
|
1650
|
-
const newPointer = arrays.get(_name ?? '$undeclared');
|
1651
1801
|
|
1652
1802
|
return [
|
1653
1803
|
// setup new/out array
|
@@ -1753,7 +1903,7 @@ const generateFunc = (scope, decl) => {
|
|
1753
1903
|
name,
|
1754
1904
|
params: Object.values(innerScope.locals).slice(0, params.length).map(x => x.type),
|
1755
1905
|
returns: innerScope.returns,
|
1756
|
-
returnType: innerScope.returnType
|
1906
|
+
returnType: innerScope.returnType,
|
1757
1907
|
locals: innerScope.locals,
|
1758
1908
|
memory: innerScope.memory,
|
1759
1909
|
throws: innerScope.throws,
|
@@ -1912,10 +2062,9 @@ const internalConstrs = {
|
|
1912
2062
|
|
1913
2063
|
// new Array(n)
|
1914
2064
|
|
1915
|
-
makeArray(scope, {
|
2065
|
+
const [ , pointer ] = makeArray(scope, {
|
1916
2066
|
rawElements: new Array(0)
|
1917
2067
|
}, global, name, true);
|
1918
|
-
const pointer = arrays.get(name ?? '$undeclared');
|
1919
2068
|
|
1920
2069
|
const arg = decl.arguments[0] ?? DEFAULT_VALUE;
|
1921
2070
|
|
package/compiler/wrap.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import compile from './index.js';
|
2
2
|
import decompile from './decompile.js';
|
3
|
-
|
3
|
+
import fs from 'node:fs';
|
4
4
|
|
5
5
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
6
6
|
|
@@ -27,7 +27,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
27
27
|
|
28
28
|
if (source.includes('export function')) flags.push('module');
|
29
29
|
|
30
|
-
|
30
|
+
fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
31
31
|
|
32
32
|
times.push(performance.now() - t1);
|
33
33
|
if (flags.includes('info')) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
package/package.json
CHANGED
package/publish.js
CHANGED
@@ -6,6 +6,8 @@ const rev = fs.readFileSync('.git/refs/heads/main', 'utf8').trim().slice(0, 7);
|
|
6
6
|
const packageJson = fs.readFileSync('package.json', 'utf8');
|
7
7
|
fs.writeFileSync('package.json', packageJson.replace('"0.0.0"', `"0.0.0-${rev}"`));
|
8
8
|
|
9
|
+
console.log(rev, packageJson);
|
10
|
+
|
9
11
|
execSync(`npm publish`, { stdio: 'inherit' });
|
10
12
|
|
11
|
-
|
13
|
+
fs.writeFileSync('package.json', packageJson);
|
package/runner/index.js
CHANGED
package/runner/repl.js
CHANGED
@@ -17,7 +17,7 @@ globalThis.valtype = 'f64';
|
|
17
17
|
const valtypeOpt = process.argv.find(x => x.startsWith('-valtype='));
|
18
18
|
if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
|
19
19
|
|
20
|
-
console.log(`welcome to porffor rev ${rev}`);
|
20
|
+
console.log(`welcome to porffor rev ${rev.slice(0, 7)}`);
|
21
21
|
console.log(`info: using opt ${process.argv.find(x => x.startsWith('-O')) ?? '-O1'} and valtype ${valtype}`);
|
22
22
|
console.log();
|
23
23
|
|
@@ -48,15 +48,17 @@ const memoryToString = mem => {
|
|
48
48
|
return out;
|
49
49
|
};
|
50
50
|
|
51
|
+
const alwaysPrev = process.argv.includes('-always-prev');
|
52
|
+
|
51
53
|
let prev = '';
|
52
54
|
const run = async (source, _context, _filename, callback, run = true) => {
|
53
55
|
let toRun = prev + source.trim();
|
54
|
-
prev = toRun + ';\n';
|
56
|
+
if (alwaysPrev) prev = toRun + ';\n';
|
55
57
|
|
56
58
|
const { exports, wasm, pages } = await compile(toRun, []);
|
57
59
|
fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
58
60
|
|
59
|
-
if (exports.$) {
|
61
|
+
if (run && exports.$) {
|
60
62
|
lastMemory = exports.$;
|
61
63
|
lastPages = [...pages.keys()];
|
62
64
|
}
|
@@ -64,7 +66,7 @@ const run = async (source, _context, _filename, callback, run = true) => {
|
|
64
66
|
const ret = run ? exports.main() : undefined;
|
65
67
|
callback(null, ret);
|
66
68
|
|
67
|
-
|
69
|
+
if (!alwaysPrev && (source.includes(' = ') || source.includes('let ') || source.includes('var ') || source.includes('const ') || source.includes('function '))) prev = toRun + ';\n';
|
68
70
|
// prev = toRun + ';\n';
|
69
71
|
};
|
70
72
|
|
package/runner/transform.js
CHANGED
@@ -5,32 +5,10 @@ const file = process.argv.slice(2).find(x => x[0] !== '-');
|
|
5
5
|
|
6
6
|
const source = fs.readFileSync(file, 'utf8');
|
7
7
|
|
8
|
-
const underline = x => `\u001b[4m\u001b[1m${x}\u001b[0m`;
|
9
|
-
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
10
|
-
|
11
|
-
let cache = '';
|
12
|
-
const print = str => {
|
13
|
-
cache += str;
|
14
|
-
|
15
|
-
if (str === '\n') {
|
16
|
-
process.stdout.write(cache);
|
17
|
-
cache = '';
|
18
|
-
}
|
19
|
-
};
|
20
|
-
|
21
8
|
const { wasm } = await compile(source);
|
22
9
|
|
23
|
-
|
24
|
-
|
25
|
-
if (!process.argv.includes('-no-run')) {
|
26
|
-
console.log(`\n\n${underline('output')}`);
|
27
|
-
const t2 = performance.now();
|
28
|
-
|
29
|
-
exports.main();
|
30
|
-
print('\n');
|
31
|
-
|
32
|
-
if (!raw) console.log(bold(`\n\nexecuted in ${(performance.now() - t2).toFixed(2)}ms`));
|
33
|
-
}
|
10
|
+
// const out = `(async () => { const print = str => process.stdout.write(str); (await WebAssembly.instantiate(Uint8Array.from([${wasm.toString()}]), {'': { p: i => print(i.toString()), c: i => print(String.fromCharCode(i))}})).instance.exports.m()})()`;
|
11
|
+
const out = `new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([${wasm.toString()}])),{'':{p:i=>process.stdout.write(i.toString())}}).exports.m()`;
|
34
12
|
|
35
|
-
|
36
|
-
|
13
|
+
console.log(out);
|
14
|
+
eval(out);
|
package/t.js
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
let assert = Object();
|
2
|
+
|
3
|
+
assert._isSameValue = function (a, b) {
|
4
|
+
if (a === b) {
|
5
|
+
// Handle +/-0 vs. -/+0
|
6
|
+
return a !== 0 || 1 / a === 1 / b;
|
7
|
+
}
|
8
|
+
|
9
|
+
// Handle NaN vs. NaN
|
10
|
+
return a !== a && b !== b;
|
11
|
+
|
12
|
+
// return a === b;
|
13
|
+
};
|
14
|
+
|
15
|
+
assert.sameValue = function (actual, expected) {
|
16
|
+
/* try {
|
17
|
+
if (assert._isSameValue(actual, expected)) {
|
18
|
+
return;
|
19
|
+
}
|
20
|
+
} catch (error) {
|
21
|
+
throw new Test262Error('_isSameValue operation threw');
|
22
|
+
} */
|
23
|
+
|
24
|
+
if (assert._isSameValue(actual, expected)) {
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
28
|
+
throw new Test262Error('assert.sameValue failed');
|
29
|
+
};
|
30
|
+
|
31
|
+
assert.sameValue("lego".charAt(), "l");
|