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 CHANGED
@@ -1,4 +1,4 @@
1
- import { read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
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(read_signedLEB128(i.slice(1)).toString());
486
+ vals.push(i[1].toString());
487
487
  break;
488
488
 
489
489
  case Opcodes.f64_const: {
@@ -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 non-capturing group
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 && Porffor.wasm.i32.load8_u(patternPtr, 0, 5) == 58) { // ':'
409
- ncg = true;
410
- patternPtr += 2;
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
- groupDepth += 1;
417
- if (!ncg) {
418
- Porffor.wasm.i32.store8(bcPtr, 0x30, 0, 0); // start capture
419
- Porffor.wasm.i32.store8(bcPtr, captureIndex, 0, 1);
420
- bcPtr += 2;
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
- Porffor.array.fastPushI32(groupStack, captureIndex);
423
- captureIndex += 1;
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
- Porffor.array.fastPushI32(groupStack, -1);
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
- if (capturePop != -1) {
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
- const atomSize: i32 = bcPtr - lastAtomStart;
461
- Porffor.wasm.memory.copy(lastAtomStart + 5, lastAtomStart, atomSize, 0, 0);
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(lastAtomStart, 0x21, 0, 0); // fork
465
- Porffor.wasm.i32.store16(lastAtomStart, 5, 0, 1); // branch1: after fork
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); // target: to be written in later
533
+ Porffor.array.fastPushI32(altStack, bcPtr); // save jump target location
469
534
  bcPtr += 3;
470
535
 
471
- Porffor.wasm.i32.store16(lastAtomStart, bcPtr - lastAtomStart, 0, 3); // fork branch2: after jump
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
- matched = true;
960
- finalSp = sp;
961
- break;
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: bytestring) => {
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: bytestring) => {
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: RegExp) => {
1386
- if (Porffor.type(regexp) !== Porffor.TYPES.regexp) {
1387
- regexp = new RegExp(regexp);
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: RegExp) => {
1394
- if (Porffor.type(regexp) !== Porffor.TYPES.regexp) {
1395
- regexp = new RegExp(regexp);
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
  };