porffor 0.35.0 → 0.35.2

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.
@@ -45,4 +45,78 @@ export const __Porffor_strcmp = (a: any, b: any): boolean => {
45
45
  return true;
46
46
  }
47
47
  }
48
+ };
49
+
50
+ export const __Porffor_strcat = (a: any, b: any): any => {
51
+ // a and b must be string or bytestring
52
+
53
+ const al: i32 = Porffor.wasm.i32.load(a, 0, 0);
54
+ const bl: i32 = Porffor.wasm.i32.load(b, 0, 0);
55
+
56
+ if (Porffor.wasm`local.get ${a+1}` == Porffor.TYPES.bytestring) {
57
+ if (Porffor.wasm`local.get ${b+1}` == Porffor.TYPES.bytestring) {
58
+ // bytestring, bytestring
59
+ const out: bytestring = Porffor.allocateBytes(4 + al + bl);
60
+
61
+ // out.length = a.length + b.length
62
+ Porffor.wasm.i32.store(out, al + bl, 0, 0);
63
+
64
+ // copy left (fast memcpy)
65
+ Porffor.wasm.memory.copy(Porffor.wasm`local.get ${out}` + 4, Porffor.wasm`local.get ${a}` + 4, al, 0, 0);
66
+
67
+ // copy right (fast memcpy)
68
+ Porffor.wasm.memory.copy(Porffor.wasm`local.get ${out}` + 4 + al, Porffor.wasm`local.get ${b}` + 4, bl, 0, 0);
69
+
70
+ return out;
71
+ } else {
72
+ // bytestring, string
73
+ const out: string = Porffor.allocateBytes(4 + (al + bl) * 2);
74
+
75
+ // out.length = a.length + b.length
76
+ Porffor.wasm.i32.store(out, al + bl, 0, 0);
77
+
78
+ // copy left (slow bytestring -> string)
79
+ for (let i: i32 = 0; i < al; i++) {
80
+ Porffor.wasm.i32.store16(Porffor.wasm`local.get ${out}` + i*2, Porffor.wasm.i32.load8_u(Porffor.wasm`local.get ${a}` + i, 0, 4), 0, 4);
81
+ }
82
+
83
+ // copy right (fast memcpy)
84
+ Porffor.wasm.memory.copy(Porffor.wasm`local.get ${out}` + 4 + al*2, Porffor.wasm`local.get ${b}` + 4, bl * 2, 0, 0);
85
+
86
+ return out;
87
+ }
88
+ } else {
89
+ if (Porffor.wasm`local.get ${b+1}` == Porffor.TYPES.bytestring) {
90
+ // string, bytestring
91
+ const out: string = Porffor.allocateBytes(4 + (al + bl) * 2);
92
+
93
+ // out.length = a.length + b.length
94
+ Porffor.wasm.i32.store(out, al + bl, 0, 0);
95
+
96
+ // copy left (fast memcpy)
97
+ Porffor.wasm.memory.copy(Porffor.wasm`local.get ${out}` + 4, Porffor.wasm`local.get ${a}` + 4, al * 2, 0, 0);
98
+
99
+ // copy right (slow bytestring -> string)
100
+ let ptr: i32 = Porffor.wasm`local.get ${out}` + al*2;
101
+ for (let i: i32 = 0; i < bl; i++) {
102
+ Porffor.wasm.i32.store16(ptr + i*2, Porffor.wasm.i32.load8_u(Porffor.wasm`local.get ${b}` + i, 0, 4), 0, 4);
103
+ }
104
+
105
+ return out;
106
+ } else {
107
+ // string, string
108
+ const out: string = Porffor.allocateBytes(4 + (al + bl) * 2);
109
+
110
+ // out.length = a.length + b.length
111
+ Porffor.wasm.i32.store(out, al + bl, 0, 0);
112
+
113
+ // copy left (fast memcpy)
114
+ Porffor.wasm.memory.copy(Porffor.wasm`local.get ${out}` + 4, Porffor.wasm`local.get ${a}` + 4, al * 2, 0, 0);
115
+
116
+ // copy right (fast memcpy)
117
+ Porffor.wasm.memory.copy(Porffor.wasm`local.get ${out}` + 4 + al*2, Porffor.wasm`local.get ${b}` + 4, bl * 2, 0, 0);
118
+
119
+ return out;
120
+ }
121
+ }
48
122
  };
@@ -35,4 +35,25 @@ export const __Porffor_compareStrings = (a: any, b: any): boolean => {
35
35
  }
36
36
 
37
37
  return Porffor.strcmp(a, b);
38
+ };
39
+
40
+ export const __Porffor_concatStrings = (a: any, b: any): boolean => {
41
+ let at: i32 = Porffor.rawType(a);
42
+ let bt: i32 = Porffor.rawType(b);
43
+
44
+ if ((at | 0b10000000) != Porffor.TYPES.bytestring) {
45
+ // a is not string or bytestring
46
+ // todo/perf: just use a.toString()?
47
+ a = ecma262.ToString(a);
48
+ at = Porffor.rawType(a);
49
+ }
50
+
51
+ if ((bt | 0b10000000) != Porffor.TYPES.bytestring) {
52
+ // b is not string or bytestring
53
+ // todo/perf: just use b.toString()?
54
+ b = ecma262.ToString(b);
55
+ bt = Porffor.rawType(b);
56
+ }
57
+
58
+ return Porffor.strcat(a, b);
38
59
  };
@@ -1,59 +1,14 @@
1
1
  export default () => {
2
- let out = `// @porf --funsafe-no-unlikely-proto-checks --valtype=i32
3
- `;
4
-
2
+ let out = ``;
5
3
  const noArgs = (a0, a1) => out += `
6
- export const __String_prototype_${a0} = (_this: string) => {
7
- let out: string = Porffor.s\`<${a1}>\`;
8
-
9
- let outPtr: i32 = Porffor.wasm\`local.get \${out}\` + ${(2 + a1.length) * 2};
10
- let thisPtr: i32 = Porffor.wasm\`local.get \${_this}\`;
11
- let thisLen: i32 = _this.length;
12
- let endPtr: i32 = thisPtr + thisLen * 2;
13
-
14
- while (thisPtr < endPtr) {
15
- let chr: i32 = Porffor.wasm.i32.load16_u(thisPtr, 0, 4);
16
- Porffor.wasm.i32.store16(outPtr, chr, 0, 4);
17
-
18
- thisPtr += 2;
19
- outPtr += 2;
20
- }
21
-
22
- Porffor.wasm.i32.store16(outPtr, 60, 0, 4); // <
23
- Porffor.wasm.i32.store16(outPtr, 47, 0, 6); // /
24
-
25
- ${[...a1].map((x, i) => ` Porffor.wasm.i32.store16(outPtr, ${x.charCodeAt(0)}, 0, ${8 + i * 2}); // ${x}`).join('\n')}
26
-
27
- Porffor.wasm.i32.store16(outPtr, 62, 0, ${8 + a1.length * 2}); // >
28
-
29
- out.length = thisLen + ${a1.length * 2 + 2 + 3};
30
-
31
- return out;
32
- };
33
- export const __ByteString_prototype_${a0} = (_this: bytestring) => {
34
- let out: bytestring = Porffor.bs\`<${a1}>\`;
35
-
36
- let outPtr: i32 = Porffor.wasm\`local.get \${out}\` + ${2 + a1.length};
37
- let thisPtr: i32 = Porffor.wasm\`local.get \${_this}\`;
38
- let thisLen: i32 = _this.length;
39
- let endPtr: i32 = thisPtr + thisLen;
40
-
41
- while (thisPtr < endPtr) {
42
- let chr: i32 = Porffor.wasm.i32.load8_u(thisPtr++, 0, 4);
43
- Porffor.wasm.i32.store8(outPtr++, chr, 0, 4);
44
- }
45
-
46
- Porffor.wasm.i32.store8(outPtr, 60, 0, 4); // <
47
- Porffor.wasm.i32.store8(outPtr, 47, 0, 5); // /
48
-
49
- ${[...a1].map((x, i) => ` Porffor.wasm.i32.store8(outPtr, ${x.charCodeAt(0)}, 0, ${6 + i}); // ${x}`).join('\n')}
50
-
51
- Porffor.wasm.i32.store8(outPtr, 62, 0, ${6 + a1.length}); // >
4
+ export const __String_prototype_${a0} = (_this: any) => {
5
+ const pre: bytestring = '<${a1}>';
6
+ const post: bytestring = '</${a1}>';
52
7
 
53
- out.length = thisLen + ${a1.length * 2 + 2 + 3};
54
-
55
- return out;
8
+ return Porffor.concatStrings(Porffor.concatStrings(pre, _this), post);
56
9
  };
10
+ export const __ByteString_prototype_${a0} = (_this: any) =>
11
+ __String_prototype_${a0}(_this);
57
12
  `;
58
13
 
59
14
  noArgs('big', 'big');
@@ -67,69 +22,15 @@ ${[...a1].map((x, i) => ` Porffor.wasm.i32.store8(outPtr, ${x.charCodeAt(0)}, 0
67
22
  noArgs('sup', 'sup');
68
23
 
69
24
  const arg = (name, s1, s2) => out += `
70
- export const __String_prototype_${name} = (_this: string, arg: any) => {
71
- let out: string = Porffor.s\`${`<${s1} ${s2}="`}\`;
72
- out += arg;
73
-
74
- let outPtr: i32 = Porffor.wasm\`local.get \${out}\` + ${(`<${s1} ${s2}="`.length + 2) * 2} + arg.length * 2;
75
-
76
- Porffor.wasm.i32.store16(outPtr, 34, 0, 0); // "
77
- Porffor.wasm.i32.store16(outPtr, 62, 0, 2); // >
78
-
79
- let thisPtr: i32 = Porffor.wasm\`local.get \${_this}\`;
80
- let thisLen: i32 = _this.length;
81
- let endPtr: i32 = thisPtr + thisLen * 2;
25
+ export const __String_prototype_${name} = (_this: any, arg: any) => {
26
+ const pre1: bytestring = '<${s1} ${s2}="';
27
+ const pre2: bytestring = '">';
28
+ const post: bytestring = '</${s1}>';
82
29
 
83
- while (thisPtr < endPtr) {
84
- let chr: i32 = Porffor.wasm.i32.load16_u(thisPtr, 0, 4);
85
- Porffor.wasm.i32.store16(outPtr, chr, 0, 4);
86
-
87
- thisPtr += 2;
88
- outPtr += 2;
89
- }
90
-
91
- Porffor.wasm.i32.store16(outPtr, 60, 0, 4); // <
92
- Porffor.wasm.i32.store16(outPtr, 47, 0, 6); // /
93
-
94
- ${[...s1].map((x, i) => ` Porffor.wasm.i32.store16(outPtr, ${x.charCodeAt(0)}, 0, ${8 + i * 2}); // ${x}`).join('\n')}
95
-
96
- Porffor.wasm.i32.store16(outPtr, 62, 0, ${8 + s1.length * 2}); // >
97
-
98
- out.length = thisLen + arg.length + ${`<${s1} ${s2}="`.length + s1.length + 5};
99
-
100
- return out;
101
- };
102
- export const __ByteString_prototype_${name} = (_this: bytestring, arg: any) => {
103
- let out: string = Porffor.s\`${`<${s1} ${s2}="`}\`;
104
- out += arg;
105
-
106
- let outPtr: i32 = Porffor.wasm\`local.get \${out}\` + ${(`<${s1} ${s2}="`.length + 2) * 2} + arg.length * 2;
107
-
108
- Porffor.wasm.i32.store16(outPtr, 34, 0, 0); // "
109
- Porffor.wasm.i32.store16(outPtr, 62, 0, 2); // >
110
-
111
- let thisPtr: i32 = Porffor.wasm\`local.get \${_this}\`;
112
- let thisLen: i32 = _this.length;
113
- let endPtr: i32 = thisPtr + thisLen;
114
-
115
- while (thisPtr < endPtr) {
116
- let chr: i32 = Porffor.wasm.i32.load8_u(thisPtr++, 0, 4);
117
- Porffor.wasm.i32.store16(outPtr, chr, 0, 4);
118
-
119
- outPtr += 2;
120
- }
121
-
122
- Porffor.wasm.i32.store16(outPtr, 60, 0, 4); // <
123
- Porffor.wasm.i32.store16(outPtr, 47, 0, 6); // /
124
-
125
- ${[...s1].map((x, i) => ` Porffor.wasm.i32.store16(outPtr, ${x.charCodeAt(0)}, 0, ${8 + i * 2}); // ${x}`).join('\n')}
126
-
127
- Porffor.wasm.i32.store16(outPtr, 62, 0, ${8 + s1.length * 2}); // >
128
-
129
- out.length = thisLen + arg.length + ${`<${s1} ${s2}="`.length + s1.length + 5};
130
-
131
- return out;
30
+ return Porffor.concatStrings(Porffor.concatStrings(Porffor.concatStrings(Porffor.concatStrings(pre1, arg), pre2), _this), post);
132
31
  };
32
+ export const __ByteString_prototype_${name} = (_this: any, arg: any) =>
33
+ __String_prototype_${name}(_this, arg);
133
34
  `;
134
35
 
135
36
  arg('fontcolor', 'font', 'color');
@@ -137,12 +38,10 @@ ${[...s1].map((x, i) => ` Porffor.wasm.i32.store16(outPtr, ${x.charCodeAt(0)},
137
38
  arg('anchor', 'a', 'name');
138
39
  arg('link', 'a', 'href');
139
40
 
140
- const prototypeAlias = (regular, annex) => `export const __String_prototype_${annex} = (_this: string) => {
141
- return __String_prototype_${regular}(_this);
142
- };
143
- export const __ByteString_prototype_${annex} = (_this: bytestring) => {
144
- return __ByteString_prototype_${regular}(_this);
145
- };
41
+ const prototypeAlias = (regular, annex) => `export const __String_prototype_${annex} = (_this: any) =>
42
+ __String_prototype_${regular}(_this);
43
+ export const __ByteString_prototype_${annex} = (_this: any) =>
44
+ __ByteString_prototype_${regular}(_this);
146
45
  `;
147
46
 
148
47
  prototypeAlias('trimStart', 'trimLeft');
@@ -1079,14 +1079,21 @@ export const __ByteString_prototype_trim = (_this: bytestring) => {
1079
1079
 
1080
1080
 
1081
1081
  export const __String_prototype_concat = (_this: string, ...vals: any[]) => {
1082
- // todo/perf: rewrite to use memory.copy?
1083
- let out: string = Porffor.allocate();
1084
- out += _this;
1082
+ let out = Porffor.allocate();
1083
+ Porffor.clone(_this, out);
1084
+
1085
+ // override type to string
1086
+ Porffor.wasm`
1087
+ i32.const 67 ;; string
1088
+ local.set ${out+1}`;
1085
1089
 
1086
1090
  const valsLen: i32 = vals.length;
1087
1091
  for (let i: i32 = 0; i < valsLen; i++) {
1088
- let x: any;
1089
1092
  Porffor.wasm`
1093
+ local.get ${out}
1094
+ f64.convert_i32_u
1095
+ local.get ${out+1}
1096
+
1090
1097
  local.get ${vals}
1091
1098
  local.get ${i}
1092
1099
  i32.const 9
@@ -1101,26 +1108,31 @@ i32.mul
1101
1108
  i32.add
1102
1109
  i32.load8_u 0 12
1103
1110
 
1104
- call __ecma262_ToString
1105
- local.set ${x+1}
1111
+ call __Porffor_concatStrings
1112
+ local.set ${out+1}
1106
1113
  i32.trunc_sat_f64_u
1107
- local.set ${x}`;
1108
-
1109
- out += x;
1114
+ local.set ${out}`;
1110
1115
  }
1111
1116
 
1112
1117
  return out;
1113
1118
  };
1114
1119
 
1115
1120
  export const __ByteString_prototype_concat = (_this: bytestring, ...vals: any[]) => {
1116
- // todo/perf: rewrite to use memory.copy?
1117
- let out: string = Porffor.allocate();
1118
- out += _this;
1121
+ let out = Porffor.allocate();
1122
+ Porffor.clone(_this, out);
1123
+
1124
+ // override type to bytestring
1125
+ Porffor.wasm`
1126
+ i32.const 195 ;; bytestring
1127
+ local.set ${out+1}`;
1119
1128
 
1120
1129
  const valsLen: i32 = vals.length;
1121
1130
  for (let i: i32 = 0; i < valsLen; i++) {
1122
- let x: any;
1123
1131
  Porffor.wasm`
1132
+ local.get ${out}
1133
+ f64.convert_i32_u
1134
+ local.get ${out+1}
1135
+
1124
1136
  local.get ${vals}
1125
1137
  local.get ${i}
1126
1138
  i32.const 9
@@ -1135,12 +1147,10 @@ i32.mul
1135
1147
  i32.add
1136
1148
  i32.load8_u 0 12
1137
1149
 
1138
- call __ecma262_ToString
1139
- local.set ${x+1}
1150
+ call __Porffor_concatStrings
1151
+ local.set ${out+1}
1140
1152
  i32.trunc_sat_f64_u
1141
- local.set ${x}`;
1142
-
1143
- out += x;
1153
+ local.set ${out}`;
1144
1154
  }
1145
1155
 
1146
1156
  return out;
@@ -160,19 +160,19 @@ export const BuiltinFuncs = function() {
160
160
  // add bitwise ops by converting operands to i32 first
161
161
  for (const [ char, op ] of [ ['&', Opcodes.i32_and], ['|', Opcodes.i32_or], ['^', Opcodes.i32_xor], ['<<', Opcodes.i32_shl], ['>>', Opcodes.i32_shr_s], ['>>>', Opcodes.i32_shr_u] ]) {
162
162
  this[`f64_${char}`] = {
163
- params: [ valtypeBinary, valtypeBinary ],
163
+ params: [ Valtype.f64, Valtype.f64 ],
164
164
  locals: [],
165
- returns: [ valtypeBinary ],
165
+ returns: [ Valtype.f64 ],
166
166
  returnType: TYPES.number,
167
167
  wasm: [
168
168
  [ Opcodes.local_get, 0 ],
169
- Opcodes.i32_to,
169
+ Opcodes.i32_trunc_sat_f64_s,
170
170
 
171
171
  [ Opcodes.local_get, 1 ],
172
- Opcodes.i32_to,
172
+ Opcodes.i32_trunc_sat_f64_s,
173
173
 
174
174
  [ op ],
175
- Opcodes.i32_from
175
+ [ Opcodes.f64_convert_i32_s ]
176
176
  ]
177
177
  };
178
178
  }