porffor 0.35.0 → 0.35.1

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.
@@ -499,126 +499,19 @@ const performLogicOp = (scope, op, left, right, leftType, rightType) => {
499
499
  ];
500
500
  };
501
501
 
502
- const concatStrings = (scope, left, right, leftType, rightType, allBytestrings = false, skipTypeCheck = false) => {
503
- // todo: this should be rewritten into a built-in/func: String.prototype.concat
504
- // todo: convert left and right to strings if not
505
- // todo: optimize by looking up names in arrays and using that if exists?
506
- // todo: optimize this if using literals/known lengths?
507
-
508
- const rightPointer = localTmp(scope, 'concat_right_pointer', Valtype.i32);
509
- const rightLength = localTmp(scope, 'concat_right_length', Valtype.i32);
510
- const leftLength = localTmp(scope, 'concat_left_length', Valtype.i32);
511
-
512
- const leftPointer = localTmp(scope, 'concat_left_pointer', Valtype.i32);
513
-
514
- // alloc/assign array
515
- const out = localTmp(scope, 'concat_out_pointer', Valtype.i32);
516
-
517
- if (!skipTypeCheck && !allBytestrings) includeBuiltin(scope, '__Porffor_bytestringToString');
502
+ const concatStrings = (scope, left, right, leftType, rightType) => {
518
503
  return [
519
- // setup pointers
520
- ...(left.length === 0 ? [
521
- Opcodes.i32_to_u,
522
- [ Opcodes.local_set, rightPointer ],
523
-
524
- Opcodes.i32_to_u,
525
- [ Opcodes.local_set, leftPointer ],
526
- ] : [
527
- ...left,
528
- Opcodes.i32_to_u,
529
- [ Opcodes.local_set, leftPointer ],
530
-
531
- ...right,
532
- Opcodes.i32_to_u,
533
- [ Opcodes.local_set, rightPointer ],
534
- ]),
535
-
536
- // setup out
537
- [ Opcodes.i32_const, 1 ],
538
- [ Opcodes.memory_grow, 0 ],
539
- [ Opcodes.i32_const, ...signedLEB128(65536) ],
540
- [ Opcodes.i32_mul ],
541
- [ Opcodes.local_tee, out ],
542
-
543
- // calculate length
544
- [ Opcodes.local_get, leftPointer ],
545
- [ Opcodes.i32_load, 0, 0 ],
546
- [ Opcodes.local_tee, leftLength ],
547
-
548
- [ Opcodes.local_get, rightPointer ],
549
- [ Opcodes.i32_load, 0, 0 ],
550
- [ Opcodes.local_tee, rightLength ],
551
-
552
- [ Opcodes.i32_add ],
553
-
554
- // store length
555
- [ Opcodes.i32_store, Math.log2(ValtypeSize.i32) - 1, 0 ],
556
-
557
- ...(skipTypeCheck || allBytestrings ? [] : [
558
- ...leftType,
559
- ...number(TYPES.bytestring, Valtype.i32),
560
- [ Opcodes.i32_eq ],
561
- [ Opcodes.if, Blocktype.void ],
562
- [ Opcodes.local_get, leftPointer ],
563
- [ Opcodes.local_get, leftLength ],
564
- [ Opcodes.call, funcIndex.__Porffor_bytestringToString ],
565
- [ Opcodes.local_set, leftPointer ],
566
- [ Opcodes.end ],
567
-
568
- ...rightType,
569
- ...number(TYPES.bytestring, Valtype.i32),
570
- [ Opcodes.i32_eq ],
571
- [ Opcodes.if, Blocktype.void ],
572
- [ Opcodes.local_get, rightPointer ],
573
- [ Opcodes.local_get, rightLength ],
574
- [ Opcodes.call, funcIndex.__Porffor_bytestringToString ],
575
- [ Opcodes.local_set, rightPointer ],
576
- [ Opcodes.end ]
577
- ]),
578
-
579
- // copy left
580
- // dst = out pointer + length size
581
- [ Opcodes.local_get, out ],
582
- ...number(ValtypeSize.i32, Valtype.i32),
583
- [ Opcodes.i32_add ],
584
-
585
- // src = left pointer + length size
586
- [ Opcodes.local_get, leftPointer ],
587
- ...number(ValtypeSize.i32, Valtype.i32),
588
- [ Opcodes.i32_add ],
589
-
590
- // size = PageSize - length size. we do not need to calculate length as init value
591
- ...number(pageSize - ValtypeSize.i32, Valtype.i32),
592
- [ ...Opcodes.memory_copy, 0x00, 0x00 ],
593
-
594
- // copy right
595
- // dst = out pointer + length size + left length * sizeof valtype
596
- [ Opcodes.local_get, out ],
597
- ...number(ValtypeSize.i32, Valtype.i32),
598
- [ Opcodes.i32_add ],
599
-
600
- [ Opcodes.local_get, leftLength ],
601
- ...number(allBytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
602
- [ Opcodes.i32_mul ],
603
- [ Opcodes.i32_add ],
604
-
605
- // src = right pointer + length size
606
- [ Opcodes.local_get, rightPointer ],
607
- ...number(ValtypeSize.i32, Valtype.i32),
608
- [ Opcodes.i32_add ],
609
-
610
- // size = right length * sizeof valtype
611
- [ Opcodes.local_get, rightLength ],
612
- ...number(allBytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
613
- [ Opcodes.i32_mul ],
614
-
615
- [ ...Opcodes.memory_copy, 0x00, 0x00 ],
504
+ ...left,
505
+ ...(valtypeBinary === Valtype.i32 ? [ [ Opcodes.f64_convert_i32_s ] ] : []),
506
+ ...leftType,
616
507
 
617
- ...setLastType(scope, allBytestrings ? TYPES.bytestring : TYPES.string),
508
+ ...right,
509
+ ...(valtypeBinary === Valtype.i32 ? [ [ Opcodes.f64_convert_i32_s ] ] : []),
510
+ ...rightType,
618
511
 
619
- // return new string (page)
620
- [ Opcodes.local_get, out ],
621
- Opcodes.i32_from_u
512
+ [ Opcodes.call, includeBuiltin(scope, '__Porffor_concatStrings').index ],
513
+ ...setLastType(scope),
514
+ ...(valtypeBinary === Valtype.i32 ? [ Opcodes.i32_trunc_sat_f64_u ] : []),
622
515
  ];
623
516
  };
624
517
 
@@ -860,23 +753,16 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
860
753
  // todo: if equality op and an operand is undefined, return false
861
754
  // todo: niche null hell with 0
862
755
 
863
- if (knownLeft === TYPES.string || knownRight === TYPES.string) {
756
+ if ((knownLeft === TYPES.string || knownRight === TYPES.string) ||
757
+ (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring)) {
864
758
  if (op === '+') {
865
759
  // string concat (a + b)
866
- return [
867
- ...left,
868
- ...right,
869
- ...concatStrings(scope, [], [], leftType, rightType, false, knownLeft === TYPES.string && knownRight === TYPES.string)
870
- ];
760
+ return concatStrings(scope, left, right, leftType, rightType);
871
761
  }
872
762
 
873
763
  // not an equality op, NaN
874
764
  if (!eqOp) return number(NaN);
875
765
 
876
- // else leave bool ops
877
- // todo: convert string to number if string and number/bool
878
- // todo: string (>|>=|<|<=) string
879
-
880
766
  // string comparison
881
767
  if (op === '===' || op === '==' || op === '!==' || op === '!=') {
882
768
  return [
@@ -884,32 +770,8 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
884
770
  ...(op === '!==' || op === '!=' ? [ [ Opcodes.i32_eqz ] ] : [])
885
771
  ];
886
772
  }
887
- }
888
773
 
889
- if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) {
890
- if (op === '+') {
891
- // string concat (a + b)
892
- return [
893
- ...left,
894
- ...right,
895
- ...concatStrings(scope, [], [], leftType, rightType, knownLeft === TYPES.bytestring && knownRight === TYPES.bytestring)
896
- ];
897
- }
898
-
899
- // not an equality op, NaN
900
- if (!eqOp) return number(NaN);
901
-
902
- // else leave bool ops
903
- // todo: convert string to number if string and number/bool
904
- // todo: string (>|>=|<|<=) string
905
-
906
- // string comparison
907
- if (op === '===' || op === '==' || op === '!==' || op === '!=') {
908
- return [
909
- ...compareStrings(scope, left, right, leftType, rightType),
910
- ...(op === '!==' || op === '!=' ? [ [ Opcodes.i32_eqz ] ] : [])
911
- ];
912
- }
774
+ // todo: proper >|>=|<|<=
913
775
  }
914
776
 
915
777
  let ops = operatorOpcode[valtype][op];
@@ -943,39 +805,19 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
943
805
  tmpRight = localTmp(scope, '__tmpop_right');
944
806
 
945
807
  ops.unshift(...stringOnly([
946
- // if left is bytestring
947
- ...leftType,
948
- ...number(TYPES.bytestring, Valtype.i32),
949
- [ Opcodes.i32_eq ],
950
-
951
- // if right is bytestring
952
- ...rightType,
953
- ...number(TYPES.bytestring, Valtype.i32),
954
- [ Opcodes.i32_eq ],
955
-
956
- // if both are true
957
- [ Opcodes.i32_and ],
958
- [ Opcodes.if, Blocktype.void ],
959
- ...concatStrings(scope, [ [ Opcodes.local_get, tmpLeft ] ], [ [ Opcodes.local_get, tmpRight ] ], leftType, rightType, true),
960
- ...(op === '!==' || op === '!=' ? [ [ Opcodes.i32_eqz ] ] : []),
961
- [ Opcodes.br, 1 ],
962
- [ Opcodes.end ],
963
-
964
- // if left is string or bytestring
808
+ // if left or right are string or bytestring
965
809
  ...leftType,
966
810
  ...number(TYPE_FLAGS.parity, Valtype.i32),
967
811
  [ Opcodes.i32_or ],
968
812
  ...number(TYPES.bytestring, Valtype.i32),
969
813
  [ Opcodes.i32_eq ],
970
814
 
971
- // if right is string or bytestring
972
815
  ...rightType,
973
816
  ...number(TYPE_FLAGS.parity, Valtype.i32),
974
817
  [ Opcodes.i32_or ],
975
818
  ...number(TYPES.bytestring, Valtype.i32),
976
819
  [ Opcodes.i32_eq ],
977
820
 
978
- // if either
979
821
  [ Opcodes.i32_or ],
980
822
  [ Opcodes.if, Blocktype.void ],
981
823
  ...concatStrings(scope, [ [ Opcodes.local_get, tmpLeft ] ], [ [ Opcodes.local_get, tmpRight ] ], leftType, rightType),
@@ -1476,6 +1318,7 @@ const getNodeType = (scope, node) => {
1476
1318
  if (node.type === 'AssignmentExpression') {
1477
1319
  const op = node.operator.slice(0, -1) || '=';
1478
1320
  if (op === '=') return getNodeType(scope, node.right);
1321
+ // if (op === '=') return getNodeType(scope, node.left);
1479
1322
 
1480
1323
  return getNodeType(scope, {
1481
1324
  type: ['||', '&&', '??'].includes(op) ? 'LogicalExpression' : 'BinaryExpression',
@@ -1498,11 +1341,14 @@ const getNodeType = (scope, node) => {
1498
1341
  const knownLeft = knownType(scope, leftType);
1499
1342
  const knownRight = knownType(scope, rightType);
1500
1343
 
1501
- if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
1502
- if (knownLeft === TYPES.bytestring && knownRight === TYPES.bytestring) return TYPES.bytestring;
1503
- if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.string;
1344
+ if ((knownLeft != null || knownRight != null) && !(
1345
+ (knownLeft === TYPES.string || knownRight === TYPES.string) ||
1346
+ (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring)
1347
+ )) return TYPES.number;
1504
1348
 
1505
- if (knownLeft != null || knownRight != null) return TYPES.number;
1349
+ // if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
1350
+ // if (knownLeft === TYPES.bytestring && knownRight === TYPES.bytestring) return TYPES.bytestring;
1351
+ // if (knownLeft === TYPES.bytestring || knownRight === TYPES.bytestring) return TYPES.string;
1506
1352
 
1507
1353
  if (scope.locals['#last_type']) return getLastType(scope);
1508
1354
 
@@ -2232,6 +2078,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2232
2078
 
2233
2079
  // value
2234
2080
  i32_const: { imms: 1, args: [], returns: 0 },
2081
+
2082
+ // dst, src, size, _, _
2083
+ memory_copy: { imms: 2, args: [ true, true, true ], returns: 0 }
2235
2084
  };
2236
2085
 
2237
2086
  const opName = name.slice('__Porffor_wasm_'.length);
@@ -2254,9 +2103,12 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2254
2103
  // literals only
2255
2104
  const imms = decl.arguments.slice(op.args.length).map(x => x.value);
2256
2105
 
2106
+ let opcode = Opcodes[opName];
2107
+ if (!Array.isArray(opcode)) opcode = [ opcode ];
2108
+
2257
2109
  return [
2258
2110
  ...argOut,
2259
- [ Opcodes[opName], ...imms ],
2111
+ [ ...opcode, ...imms ],
2260
2112
  ...(new Array(op.returns).fill(Opcodes.i32_from))
2261
2113
  ];
2262
2114
  }
@@ -2975,8 +2827,10 @@ const setLocalWithType = (scope, name, isGlobal, decl, tee = false, overrideType
2975
2827
  // todo: detect last type then i32 conversion op
2976
2828
  const lastOp = out.at(-1);
2977
2829
  if (lastOp[0] === Opcodes.local_set && lastOp[1] === scope.locals['#last_type']?.idx) {
2978
- out.pop();
2830
+ // set last type -> tee last type
2831
+ lastOp[0] = Opcodes.local_tee;
2979
2832
 
2833
+ // still set last type due to side effects or type of decl gotten later
2980
2834
  const setOut = setType(scope, name, []);
2981
2835
  out.push(
2982
2836
  // drop if setType is empty
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
4
- "version": "0.35.0+8b2f7cee3",
4
+ "version": "0.35.1+160a05475",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
package/runner/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs';
3
- globalThis.version = '0.35.0+8b2f7cee3';
3
+ globalThis.version = '0.35.1+160a05475';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {