porffor 0.60.8 → 0.60.10
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 +2 -2
- package/compiler/assemble.js +13 -0
- package/compiler/builtins/regexp.ts +180 -36
- package/compiler/builtins.js +79 -69
- package/compiler/builtins_precompiled.js +2160 -2160
- package/compiler/codegen.js +73 -63
- package/compiler/cyclone.js +2 -2
- package/compiler/disassemble.js +2 -2
- package/compiler/encoding.js +22 -4
- package/compiler/expression.js +0 -25
- package/compiler/opt.js +15 -15
- package/compiler/precompile.js +4 -4
- package/compiler/wrap.js +4 -1
- package/foo.js +34 -0
- package/package.json +2 -2
- package/runtime/index.js +1 -1
package/compiler/2c.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { read_unsignedLEB128 } from './encoding.js';
|
2
2
|
import { Blocktype, Opcodes, Valtype, PageSize } from './wasmSpec.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { log } from './log.js';
|
@@ -483,7 +483,7 @@ export default ({ funcs, globals, data, pages }) => {
|
|
483
483
|
switch (i[0]) {
|
484
484
|
case Opcodes.i32_const:
|
485
485
|
case Opcodes.i64_const:
|
486
|
-
vals.push(
|
486
|
+
vals.push(i[1].toString());
|
487
487
|
break;
|
488
488
|
|
489
489
|
case Opcodes.f64_const: {
|
package/compiler/assemble.js
CHANGED
@@ -69,6 +69,9 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
69
69
|
};
|
70
70
|
|
71
71
|
const unsigned = n => {
|
72
|
+
if (n === Infinity) return unsigned(4294967295);
|
73
|
+
if (n === -Infinity) return unsigned(0);
|
74
|
+
|
72
75
|
n |= 0;
|
73
76
|
if (n >= 0 && n <= 127) return byte(n);
|
74
77
|
|
@@ -84,6 +87,9 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
84
87
|
};
|
85
88
|
|
86
89
|
const signed = n => {
|
90
|
+
if (n === Infinity) return signed(2147483647);
|
91
|
+
if (n === -Infinity) return signed(-2147483648);
|
92
|
+
|
87
93
|
n |= 0;
|
88
94
|
if (n >= 0 && n <= 63) return byte(n);
|
89
95
|
|
@@ -400,6 +406,13 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
400
406
|
continue;
|
401
407
|
}
|
402
408
|
|
409
|
+
// encode i32.const/i64.const ops as signed leb128 from raw number
|
410
|
+
if (op === Opcodes.i32_const || op === Opcodes.i64_const) {
|
411
|
+
byte(op);
|
412
|
+
signed(o[1]);
|
413
|
+
continue;
|
414
|
+
}
|
415
|
+
|
403
416
|
// encode f64.const ops as ieee754 from raw number
|
404
417
|
if (op === Opcodes.f64_const) {
|
405
418
|
byte(op);
|
@@ -35,6 +35,10 @@ import type {} from './porffor.d.ts';
|
|
35
35
|
// dot - 0x09
|
36
36
|
// back reference - 0x0a:
|
37
37
|
// index (u8)
|
38
|
+
// lookahead positive - 0x0b:
|
39
|
+
// target (u16) - where to jump if lookahead succeeds
|
40
|
+
// lookahead negative - 0x0c:
|
41
|
+
// target (u16) - where to jump if lookahead fails
|
38
42
|
// ----------------------------
|
39
43
|
// accept - 0x10
|
40
44
|
// reject - 0x11
|
@@ -402,27 +406,63 @@ export const __Porffor_regex_compile = (patternStr: bytestring, flagsStr: bytest
|
|
402
406
|
if (char == 40) { // '('
|
403
407
|
lastAtomStart = bcPtr;
|
404
408
|
|
405
|
-
// Check for
|
409
|
+
// Check for special group types
|
406
410
|
let ncg: boolean = false;
|
411
|
+
let isLookahead: boolean = false;
|
412
|
+
let isNegativeLookahead: boolean = false;
|
413
|
+
|
407
414
|
if (patternPtr < patternEndPtr && Porffor.wasm.i32.load8_u(patternPtr, 0, 4) == 63) { // '?'
|
408
|
-
if ((patternPtr + 1) < patternEndPtr
|
409
|
-
|
410
|
-
|
415
|
+
if ((patternPtr + 1) < patternEndPtr) {
|
416
|
+
const nextChar = Porffor.wasm.i32.load8_u(patternPtr, 0, 5);
|
417
|
+
if (nextChar == 58) { // ':' - non-capturing group
|
418
|
+
ncg = true;
|
419
|
+
patternPtr += 2;
|
420
|
+
} else if (nextChar == 61) { // '=' - positive lookahead
|
421
|
+
isLookahead = true;
|
422
|
+
patternPtr += 2;
|
423
|
+
} else if (nextChar == 33) { // '!' - negative lookahead
|
424
|
+
isLookahead = true;
|
425
|
+
isNegativeLookahead = true;
|
426
|
+
patternPtr += 2;
|
427
|
+
}
|
411
428
|
}
|
412
429
|
}
|
413
430
|
|
414
431
|
Porffor.array.fastPushI32(groupStack, lastAtomStart);
|
415
432
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
433
|
+
if (isLookahead) {
|
434
|
+
// Generate lookahead opcodes
|
435
|
+
if (isNegativeLookahead) {
|
436
|
+
Porffor.wasm.i32.store8(bcPtr, 0x0c, 0, 0); // lookahead negative
|
437
|
+
} else {
|
438
|
+
Porffor.wasm.i32.store8(bcPtr, 0x0b, 0, 0); // lookahead positive
|
439
|
+
}
|
440
|
+
|
441
|
+
// Store placeholder for target address (will be filled when we see closing paren)
|
442
|
+
const lookaheadJumpPtr = bcPtr + 1;
|
443
|
+
Porffor.wasm.i32.store16(bcPtr, 0, 0, 1);
|
444
|
+
bcPtr += 3;
|
421
445
|
|
422
|
-
|
423
|
-
|
446
|
+
// Store jump address on stack to fill in later, and special marker
|
447
|
+
Porffor.array.fastPushI32(groupStack, lookaheadJumpPtr);
|
448
|
+
Porffor.array.fastPushI32(groupStack, isNegativeLookahead ? -2 : -3);
|
449
|
+
groupDepth += 1;
|
424
450
|
} else {
|
425
|
-
|
451
|
+
groupDepth += 1;
|
452
|
+
// Store the alternation scope start for this group depth in altStack
|
453
|
+
// We'll use even indices for jump targets and odd indices for scope starts
|
454
|
+
const scopeStackIdx = groupDepth * 2 + 1;
|
455
|
+
if (scopeStackIdx < 6144) altStack[scopeStackIdx] = bcPtr;
|
456
|
+
if (!ncg) {
|
457
|
+
Porffor.wasm.i32.store8(bcPtr, 0x30, 0, 0); // start capture
|
458
|
+
Porffor.wasm.i32.store8(bcPtr, captureIndex, 0, 1);
|
459
|
+
bcPtr += 2;
|
460
|
+
|
461
|
+
Porffor.array.fastPushI32(groupStack, captureIndex);
|
462
|
+
captureIndex += 1;
|
463
|
+
} else {
|
464
|
+
Porffor.array.fastPushI32(groupStack, -1);
|
465
|
+
}
|
426
466
|
}
|
427
467
|
|
428
468
|
lastWasAtom = false;
|
@@ -442,7 +482,18 @@ export const __Porffor_regex_compile = (patternStr: bytestring, flagsStr: bytest
|
|
442
482
|
groupDepth -= 1;
|
443
483
|
|
444
484
|
const capturePop: i32 = Porffor.array.fastPopI32(groupStack);
|
445
|
-
|
485
|
+
|
486
|
+
// Handle lookaheads
|
487
|
+
if (capturePop == -2 || capturePop == -3) {
|
488
|
+
const jumpPtr: i32 = Porffor.array.fastPopI32(groupStack);
|
489
|
+
|
490
|
+
// Emit accept to properly end the lookahead
|
491
|
+
Porffor.wasm.i32.store8(bcPtr, 0x10, 0, 0); // accept
|
492
|
+
bcPtr += 1;
|
493
|
+
|
494
|
+
// Update the jump target to point past this closing paren
|
495
|
+
Porffor.wasm.i32.store16(jumpPtr, bcPtr - jumpPtr - 2, 0, 0);
|
496
|
+
} else if (capturePop != -1) {
|
446
497
|
Porffor.wasm.i32.store8(bcPtr, 0x31, 0, 0); // end capture
|
447
498
|
Porffor.wasm.i32.store8(bcPtr, capturePop, 0, 1);
|
448
499
|
bcPtr += 2;
|
@@ -457,18 +508,32 @@ export const __Porffor_regex_compile = (patternStr: bytestring, flagsStr: bytest
|
|
457
508
|
if (char == 124) { // '|'
|
458
509
|
altDepth[groupDepth] += 1;
|
459
510
|
|
460
|
-
|
461
|
-
|
511
|
+
let forkPos: i32 = lastAtomStart;
|
512
|
+
if (altDepth[groupDepth] == 1) {
|
513
|
+
// First alternation - go back to start of alternation scope
|
514
|
+
if (groupDepth == 0) {
|
515
|
+
// Top level alternation
|
516
|
+
forkPos = bcStart;
|
517
|
+
} else {
|
518
|
+
// Group alternation - get stored scope start
|
519
|
+
const scopeStackIdx = groupDepth * 2 + 1;
|
520
|
+
if (scopeStackIdx < 6144 && altStack[scopeStackIdx] > 0) {
|
521
|
+
forkPos = altStack[scopeStackIdx];
|
522
|
+
}
|
523
|
+
}
|
524
|
+
}
|
525
|
+
|
526
|
+
Porffor.wasm.memory.copy(forkPos + 5, forkPos, bcPtr - forkPos, 0, 0);
|
462
527
|
bcPtr += 5;
|
463
528
|
|
464
|
-
Porffor.wasm.i32.store8(
|
465
|
-
Porffor.wasm.i32.store16(
|
529
|
+
Porffor.wasm.i32.store8(forkPos, 0x21, 0, 0); // fork
|
530
|
+
Porffor.wasm.i32.store16(forkPos, 5, 0, 1); // branch1: try this alternative
|
466
531
|
|
467
532
|
Porffor.wasm.i32.store8(bcPtr, 0x20, 0, 0); // jump
|
468
|
-
Porffor.array.fastPushI32(altStack, bcPtr); //
|
533
|
+
Porffor.array.fastPushI32(altStack, bcPtr); // save jump target location
|
469
534
|
bcPtr += 3;
|
470
535
|
|
471
|
-
Porffor.wasm.i32.store16(
|
536
|
+
Porffor.wasm.i32.store16(forkPos, bcPtr - forkPos, 0, 3); // fork branch2: next alternative
|
472
537
|
|
473
538
|
lastAtomStart = bcPtr;
|
474
539
|
lastWasAtom = false;
|
@@ -955,10 +1020,45 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
|
|
955
1020
|
|
956
1021
|
while (true) {
|
957
1022
|
const op: i32 = Porffor.wasm.i32.load8_u(pc, 0, 0);
|
1023
|
+
|
958
1024
|
if (op == 0x10) { // accept
|
959
|
-
|
960
|
-
|
961
|
-
|
1025
|
+
// Check if this is a lookahead accept
|
1026
|
+
if (backtrackStack.length >= 4) {
|
1027
|
+
const marker = backtrackStack[backtrackStack.length - 1];
|
1028
|
+
if (marker == -2000 || marker == -3000) { // lookahead markers
|
1029
|
+
// This is a lookahead accept
|
1030
|
+
const isNegative = marker == -2000;
|
1031
|
+
|
1032
|
+
const savedMarker = Porffor.array.fastPopI32(backtrackStack);
|
1033
|
+
const savedCapturesLen = Porffor.array.fastPopI32(backtrackStack);
|
1034
|
+
const savedSp = Porffor.array.fastPopI32(backtrackStack);
|
1035
|
+
const lookaheadEndPc = Porffor.array.fastPopI32(backtrackStack);
|
1036
|
+
|
1037
|
+
// Restore string position (lookaheads don't consume)
|
1038
|
+
sp = savedSp;
|
1039
|
+
captures.length = savedCapturesLen;
|
1040
|
+
|
1041
|
+
if (isNegative) {
|
1042
|
+
// Negative lookahead: pattern matched, so fail completely
|
1043
|
+
matched = false;
|
1044
|
+
break;
|
1045
|
+
} else {
|
1046
|
+
// Positive lookahead: pattern matched, so continue after lookahead
|
1047
|
+
pc = lookaheadEndPc;
|
1048
|
+
continue;
|
1049
|
+
}
|
1050
|
+
} else {
|
1051
|
+
// Normal accept
|
1052
|
+
matched = true;
|
1053
|
+
finalSp = sp;
|
1054
|
+
break;
|
1055
|
+
}
|
1056
|
+
} else {
|
1057
|
+
// Normal accept
|
1058
|
+
matched = true;
|
1059
|
+
finalSp = sp;
|
1060
|
+
break;
|
1061
|
+
}
|
962
1062
|
}
|
963
1063
|
|
964
1064
|
let backtrack: boolean = false;
|
@@ -1186,6 +1286,25 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
|
|
1186
1286
|
}
|
1187
1287
|
}
|
1188
1288
|
}
|
1289
|
+
} else if (op == 0x0b || op == 0x0c) { // positive or negative lookahead
|
1290
|
+
const jumpOffset = Porffor.wasm.i32.load16_s(pc, 0, 1);
|
1291
|
+
const lookaheadEndPc = pc + jumpOffset + 3;
|
1292
|
+
const savedSp = sp; // Save current string position
|
1293
|
+
|
1294
|
+
|
1295
|
+
// Use fork to test the lookahead pattern
|
1296
|
+
Porffor.array.fastPushI32(backtrackStack, lookaheadEndPc); // Continue point after lookahead
|
1297
|
+
Porffor.array.fastPushI32(backtrackStack, savedSp); // Restore original sp
|
1298
|
+
Porffor.array.fastPushI32(backtrackStack, captures.length);
|
1299
|
+
|
1300
|
+
// Mark this as a lookahead with special values
|
1301
|
+
if (op == 0x0c) { // negative lookahead
|
1302
|
+
Porffor.array.fastPushI32(backtrackStack, -2000); // Special marker for negative
|
1303
|
+
} else { // positive lookahead
|
1304
|
+
Porffor.array.fastPushI32(backtrackStack, -3000); // Special marker for positive
|
1305
|
+
}
|
1306
|
+
|
1307
|
+
pc = pc + 3; // Jump to lookahead content
|
1189
1308
|
} else if (op == 0x20) { // jump
|
1190
1309
|
pc += Porffor.wasm.i32.load16_s(pc, 0, 1);
|
1191
1310
|
} else if (op == 0x21) { // fork
|
@@ -1217,6 +1336,35 @@ export const __Porffor_regex_interpret = (regexp: RegExp, input: i32, isTest: bo
|
|
1217
1336
|
|
1218
1337
|
if (backtrack) {
|
1219
1338
|
if (backtrackStack.length == 0) break;
|
1339
|
+
|
1340
|
+
|
1341
|
+
// Check if we're backtracking from a lookahead
|
1342
|
+
if (backtrackStack.length >= 4) {
|
1343
|
+
const marker = backtrackStack[backtrackStack.length - 1];
|
1344
|
+
if (marker == -2000 || marker == -3000) { // lookahead markers
|
1345
|
+
const isNegative = marker == -2000;
|
1346
|
+
const savedMarker = Porffor.array.fastPopI32(backtrackStack);
|
1347
|
+
const savedCapturesLen = Porffor.array.fastPopI32(backtrackStack);
|
1348
|
+
const savedSp = Porffor.array.fastPopI32(backtrackStack);
|
1349
|
+
const lookaheadEndPc = Porffor.array.fastPopI32(backtrackStack);
|
1350
|
+
|
1351
|
+
// Restore state
|
1352
|
+
sp = savedSp;
|
1353
|
+
captures.length = savedCapturesLen;
|
1354
|
+
|
1355
|
+
if (isNegative) {
|
1356
|
+
// Negative lookahead: pattern failed to match, so succeed and continue
|
1357
|
+
pc = lookaheadEndPc;
|
1358
|
+
backtrack = false;
|
1359
|
+
} else {
|
1360
|
+
// Positive lookahead: pattern failed to match, so fail
|
1361
|
+
backtrack = true;
|
1362
|
+
}
|
1363
|
+
continue;
|
1364
|
+
}
|
1365
|
+
}
|
1366
|
+
|
1367
|
+
// Normal backtracking
|
1220
1368
|
// Porffor.log(`backtrack! before: captures.length = ${captures.length}, sp = ${sp}, pc = ${pc}`);
|
1221
1369
|
captures.length = Porffor.array.fastPopI32(backtrackStack);
|
1222
1370
|
sp = Porffor.array.fastPopI32(backtrackStack);
|
@@ -1374,26 +1522,22 @@ export const RegExp = function (pattern: any, flags: any): RegExp {
|
|
1374
1522
|
};
|
1375
1523
|
|
1376
1524
|
|
1377
|
-
export const __RegExp_prototype_exec = (_this: RegExp, input:
|
1525
|
+
export const __RegExp_prototype_exec = (_this: RegExp, input: any) => {
|
1526
|
+
if (Porffor.type(input) !== Porffor.TYPES.bytestring) input = ecma262.ToString(input);
|
1378
1527
|
return __Porffor_regex_interpret(_this, input, false);
|
1379
1528
|
};
|
1380
1529
|
|
1381
|
-
export const __RegExp_prototype_test = (_this: RegExp, input:
|
1530
|
+
export const __RegExp_prototype_test = (_this: RegExp, input: any) => {
|
1531
|
+
if (Porffor.type(input) !== Porffor.TYPES.bytestring) input = ecma262.ToString(input);
|
1382
1532
|
return __Porffor_regex_interpret(_this, input, true);
|
1383
1533
|
};
|
1384
1534
|
|
1385
|
-
export const __String_prototype_match = (_this: string, regexp:
|
1386
|
-
if (Porffor.type(regexp) !== Porffor.TYPES.regexp)
|
1387
|
-
|
1388
|
-
}
|
1389
|
-
|
1390
|
-
return regexp.exec(_this);
|
1535
|
+
export const __String_prototype_match = (_this: string, regexp: any) => {
|
1536
|
+
if (Porffor.type(regexp) !== Porffor.TYPES.regexp) regexp = new RegExp(regexp);
|
1537
|
+
return __RegExp_prototype_exec(regexp, _this);
|
1391
1538
|
};
|
1392
1539
|
|
1393
|
-
export const __ByteString_prototype_match = (_this: bytestring, regexp:
|
1394
|
-
if (Porffor.type(regexp) !== Porffor.TYPES.regexp)
|
1395
|
-
|
1396
|
-
}
|
1397
|
-
|
1398
|
-
return regexp.exec(_this);
|
1540
|
+
export const __ByteString_prototype_match = (_this: bytestring, regexp: any) => {
|
1541
|
+
if (Porffor.type(regexp) !== Porffor.TYPES.regexp) regexp = new RegExp(regexp);
|
1542
|
+
return __RegExp_prototype_exec(regexp, _this);
|
1399
1543
|
};
|