porffor 0.34.21 → 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
-
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
773
 
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),
@@ -1066,9 +908,6 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
1066
908
  }
1067
909
 
1068
910
  if (decl.operator === 'in') {
1069
- // hack: a in b -> Object.hasOwn(b, a)
1070
- // todo: not spec compliant, in should check prototype chain too (once we have it)
1071
-
1072
911
  return generate(scope, {
1073
912
  type: 'CallExpression',
1074
913
  callee: {
@@ -1112,6 +951,7 @@ const asmFuncToAsm = (scope, func) => {
1112
951
  builtin: (n, offset = false) => {
1113
952
  let idx = funcIndex[n] ?? importedFuncs[n];
1114
953
  if (idx == null && builtinFuncs[n]) {
954
+ // console.log(scope.name, '->', n);
1115
955
  includeBuiltin(scope, n);
1116
956
  idx = funcIndex[n];
1117
957
  }
@@ -1478,6 +1318,7 @@ const getNodeType = (scope, node) => {
1478
1318
  if (node.type === 'AssignmentExpression') {
1479
1319
  const op = node.operator.slice(0, -1) || '=';
1480
1320
  if (op === '=') return getNodeType(scope, node.right);
1321
+ // if (op === '=') return getNodeType(scope, node.left);
1481
1322
 
1482
1323
  return getNodeType(scope, {
1483
1324
  type: ['||', '&&', '??'].includes(op) ? 'LogicalExpression' : 'BinaryExpression',
@@ -1500,11 +1341,14 @@ const getNodeType = (scope, node) => {
1500
1341
  const knownLeft = knownType(scope, leftType);
1501
1342
  const knownRight = knownType(scope, rightType);
1502
1343
 
1503
- if (knownLeft === TYPES.string || knownRight === TYPES.string) return TYPES.string;
1504
- if (knownLeft === TYPES.bytestring && knownRight === TYPES.bytestring) return TYPES.bytestring;
1505
- 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;
1506
1348
 
1507
- 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;
1508
1352
 
1509
1353
  if (scope.locals['#last_type']) return getLastType(scope);
1510
1354
 
@@ -2234,6 +2078,9 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2234
2078
 
2235
2079
  // value
2236
2080
  i32_const: { imms: 1, args: [], returns: 0 },
2081
+
2082
+ // dst, src, size, _, _
2083
+ memory_copy: { imms: 2, args: [ true, true, true ], returns: 0 }
2237
2084
  };
2238
2085
 
2239
2086
  const opName = name.slice('__Porffor_wasm_'.length);
@@ -2256,9 +2103,12 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
2256
2103
  // literals only
2257
2104
  const imms = decl.arguments.slice(op.args.length).map(x => x.value);
2258
2105
 
2106
+ let opcode = Opcodes[opName];
2107
+ if (!Array.isArray(opcode)) opcode = [ opcode ];
2108
+
2259
2109
  return [
2260
2110
  ...argOut,
2261
- [ Opcodes[opName], ...imms ],
2111
+ [ ...opcode, ...imms ],
2262
2112
  ...(new Array(op.returns).fill(Opcodes.i32_from))
2263
2113
  ];
2264
2114
  }
@@ -2977,8 +2827,10 @@ const setLocalWithType = (scope, name, isGlobal, decl, tee = false, overrideType
2977
2827
  // todo: detect last type then i32 conversion op
2978
2828
  const lastOp = out.at(-1);
2979
2829
  if (lastOp[0] === Opcodes.local_set && lastOp[1] === scope.locals['#last_type']?.idx) {
2980
- out.pop();
2830
+ // set last type -> tee last type
2831
+ lastOp[0] = Opcodes.local_tee;
2981
2832
 
2833
+ // still set last type due to side effects or type of decl gotten later
2982
2834
  const setOut = setType(scope, name, []);
2983
2835
  out.push(
2984
2836
  // drop if setType is empty
@@ -3173,7 +3025,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
3173
3025
  const usedProps = [];
3174
3026
  for (const prop of properties) {
3175
3027
  if (prop.type == 'Property') { // let { foo } = {}
3176
- usedProps.push(!prop.computed && prop.key.type !== 'Literal' ? { type: 'Literal', value: prop.key.name } : prop.key);
3028
+ usedProps.push(getProperty(prop));
3177
3029
 
3178
3030
  if (prop.value.type === 'AssignmentPattern') { // let { foo = defaultValue } = {}
3179
3031
  decls.push(
@@ -3257,13 +3109,22 @@ const generateVar = (scope, decl) => {
3257
3109
  return out;
3258
3110
  };
3259
3111
 
3260
- const getMemberProperty = decl => {
3261
- if (decl.computed) return decl.property;
3112
+ const privateIDName = name => '.#.' + name;
3113
+ const privateIdentifierToIdentifier = decl => ({
3114
+ type: 'Identifier',
3115
+ name: privateIDName(decl.name)
3116
+ });
3117
+
3118
+ const getProperty = decl => {
3119
+ const prop = decl.property ?? decl.key;
3120
+ if (decl.computed) return prop;
3262
3121
 
3263
- return {
3122
+ if (prop.name) return {
3264
3123
  type: 'Literal',
3265
- value: decl.property.name
3124
+ value: prop.type === 'PrivateIdentifier' ? privateIDName(prop.name) : prop.name,
3266
3125
  };
3126
+
3127
+ return prop;
3267
3128
  };
3268
3129
 
3269
3130
  // todo: optimize this func for valueUnused
@@ -3348,7 +3209,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
3348
3209
  const pointerTmp = localTmp(scope, '#member_setter_ptr_tmp', Valtype.i32);
3349
3210
 
3350
3211
  const object = decl.left.object;
3351
- const property = getMemberProperty(decl.left);
3212
+ const property = getProperty(decl.left);
3352
3213
 
3353
3214
  // todo/perf: use i32 object (and prop?) locals
3354
3215
  const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];
@@ -3751,7 +3612,7 @@ const generateUnary = (scope, decl) => {
3751
3612
  case 'delete': {
3752
3613
  if (decl.argument.type === 'MemberExpression') {
3753
3614
  const object = decl.argument.object;
3754
- const property = getMemberProperty(decl.argument);
3615
+ const property = getProperty(decl.argument);
3755
3616
 
3756
3617
  if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
3757
3618
 
@@ -5183,12 +5044,7 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
5183
5044
  continue;
5184
5045
  }
5185
5046
 
5186
- let k = key;
5187
- if (!computed && key.type !== 'Literal') k = {
5188
- type: 'Literal',
5189
- value: key.name
5190
- };
5191
-
5047
+ const k = getProperty(x);
5192
5048
  if (isFuncType(value.type)) {
5193
5049
  let id = value.id;
5194
5050
 
@@ -5287,7 +5143,7 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
5287
5143
  }
5288
5144
 
5289
5145
  const object = decl.object;
5290
- const property = getMemberProperty(decl);
5146
+ const property = getProperty(decl);
5291
5147
 
5292
5148
  // generate now so type is gotten correctly later (it gets cached)
5293
5149
  generate(scope, object);
@@ -5721,28 +5577,6 @@ const generateClass = (scope, decl) => {
5721
5577
 
5722
5578
  if (decl.superClass) {
5723
5579
  out.push(
5724
- // ...generateCall(scope, {
5725
- // type: 'CallExpression',
5726
- // callee: {
5727
- // type: 'Identifier',
5728
- // name: '__Porffor_object_assignAll'
5729
- // },
5730
- // arguments: [
5731
- // proto,
5732
- // {
5733
- // type: 'MemberExpression',
5734
- // object: decl.superClass,
5735
- // property: {
5736
- // type: 'Identifier',
5737
- // name: 'prototype'
5738
- // },
5739
- // computed: false,
5740
- // optional: false
5741
- // }
5742
- // ]
5743
- // }),
5744
- // [ Opcodes.drop ]
5745
-
5746
5580
  // class Foo {}
5747
5581
  // class Bar extends Foo {}
5748
5582
  // Bar.__proto__ = Foo
@@ -5760,11 +5594,7 @@ const generateClass = (scope, decl) => {
5760
5594
 
5761
5595
  let object = _static ? root : proto;
5762
5596
 
5763
- let k = key;
5764
- if (!computed && key.type !== 'Literal') k = {
5765
- type: 'Literal',
5766
- value: key.name
5767
- };
5597
+ const k = getProperty(x);
5768
5598
 
5769
5599
  let initKind = 'init';
5770
5600
  if (kind === 'get' || kind === 'set') initKind = kind;
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.34.21+7de83876c",
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.34.21+7de83876c';
3
+ globalThis.version = '0.35.1+160a05475';
4
4
 
5
5
  // deno compat
6
6
  if (typeof process === 'undefined' && typeof Deno !== 'undefined') {