porffor 0.17.0-048c6f2ee โ†’ 0.17.0-0564424f4

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/README.md CHANGED
@@ -148,27 +148,29 @@ These include some early (stage 1/0) and/or dead (last commit years ago) proposa
148
148
  - Array constructor (`Array(5)`, `new Array(1, 2, 3)`)
149
149
  - Labelled statements (`foo: while (...)`)
150
150
  - `do...while` loops
151
+ - Optional parameters (`(foo = 'bar') => { ... }`)
151
152
 
152
153
  ### Built-ins
153
154
 
154
155
  - `NaN` and `Infinity`
155
156
  - `isNaN()` and `isFinite()`
156
157
  - Most of `Number` (`MAX_VALUE`, `MIN_VALUE`, `MAX_SAFE_INTEGER`, `MIN_SAFE_INTEGER`, `POSITIVE_INFINITY`, `NEGATIVE_INFINITY`, `EPSILON`, `NaN`, `isNaN`, `isFinite`, `isInteger`, `isSafeInteger`)
157
- - Some `Math` funcs (`sqrt`, `abs`, `floor`, `sign`, `round`, `trunc`, `clz32`, `fround`, `random`)
158
+ - Most `Math` funcs (`sqrt`, `abs`, `floor`, `sign`, `round`, `trunc`, `clz32`, `fround`, `random`, `exp`, `log`, `log2`, `log10`, `pow`, `expm1`, `log1p`, `sqrt`, `cbrt`, `hypot`, `sin`, `cos`, `tan`, `sinh`, `cosh`, `tanh`, `asinh`, `acosh`, `atanh`, `asin`, `acos`, `atan`, `atan2`)
158
159
  - Basic `globalThis` support
159
160
  - Basic `Boolean` and `Number`
160
161
  - Basic `eval` for literals
161
162
  - `Math.random()` using self-made xorshift128+ PRNG
162
163
  - Some of `performance` (`now()`, `timeOrigin`)
163
- - Some of `Array.prototype` (`at`, `push`, `pop`, `shift`, `fill`, `slice`, `indexOf`, `lastIndexOf`, `includes`, `with`, `reverse`, `toReversed`)
164
- - Some of `Array` (`of`, `isArray`)
165
- - Most of `String.prototype` (`at`, `charAt`, `charCodeAt`, `toUpperCase`, `toLowerCase`, `startsWith`, `endsWith`, `indexOf`, `lastIndexOf`, `includes`, `padStart`, `padEnd`, `substring`, `substr`, `slice`, `trimStart`, `trimEnd`, `trim`, `toString`, `big`, `blink`, `bold`, `fixed`, `italics`, `small`, `strike`, `sub`, `sup`, `trimLeft`, `trimRight`, )
164
+ - Most of `Array.prototype` (`at`, `push`, `pop`, `shift`, `fill`, `slice`, `indexOf`, `lastIndexOf`, `includes`, `with`, `reverse`, `toReversed`, `forEach`, `filter`, `map`, `find`, `findLast`, `findIndex`, `findLastIndex`, `every`, `some`, `reduce`, `reduceRight`, `join`, `toString`)
165
+ - Most of `Array` (`of`, `isArray`)
166
+ - Most of `String.prototype` (`at`, `charAt`, `charCodeAt`, `toUpperCase`, `toLowerCase`, `startsWith`, `endsWith`, `indexOf`, `lastIndexOf`, `includes`, `padStart`, `padEnd`, `substring`, `substr`, `slice`, `trimStart`, `trimEnd`, `trim`, `toString`, `big`, `blink`, `bold`, `fixed`, `italics`, `small`, `strike`, `sub`, `sup`, `trimLeft`, `trimRight`, `trim`)
166
167
  - Some of `crypto` (`randomUUID`)
167
168
  - `escape`
168
169
  - `btoa`
169
170
  - Most of `Number.prototype` (`toString`, `toFixed`, `toExponential`)
170
171
  - `parseInt`
171
172
  - Spec-compliant `Date`
173
+ - WIP typed arrays (`Uint8Array`, `Int32Array`, etc)
172
174
 
173
175
  ### Custom
174
176
 
package/compiler/2c.js CHANGED
@@ -182,7 +182,15 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
182
182
  }, {});
183
183
  const invGlobals = inv(globals, x => x.idx);
184
184
 
185
- const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => String.fromCharCode(97 + _.charCodeAt(0) % 32));
185
+ const codeToSanitizedStr = code => {
186
+ let out = '';
187
+ while (code > 0) {
188
+ out += String.fromCharCode(97 + code % 26);
189
+ code -= 26;
190
+ }
191
+ return out;
192
+ };
193
+ const sanitize = str => str.replace(/[^0-9a-zA-Z_]/g, _ => codeToSanitizedStr(_.charCodeAt(0)));
186
194
 
187
195
  for (const x in invGlobals) {
188
196
  invGlobals[x] = sanitize(invGlobals[x]);
@@ -273,10 +281,11 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
273
281
  }
274
282
 
275
283
  const returns = f.returns.length > 0;
284
+ const typedReturns = f.returnType == null;
276
285
 
277
286
  const shouldInline = false; // f.internal;
278
287
  if (f.name === 'main') out += `int main(${prependMain.has('argv') ? 'int argc, char* argv[]' : ''}) {\n`;
279
- else out += `${f.internal ? (returns ? 'f64' : 'void') : 'struct ReturnValue'} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
288
+ else out += `${!typedReturns ? (returns ? CValtype[f.returns[0]] : 'void') : 'struct ReturnValue'} ${shouldInline ? 'inline ' : ''}${sanitize(f.name)}(${f.params.map((x, i) => `${CValtype[x]} ${invLocals[i]}`).join(', ')}) {\n`;
280
289
 
281
290
  if (f.name === 'main') {
282
291
  out += ' ' + [...prependMain.values()].join('\n ');
@@ -418,11 +427,14 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
418
427
  continue;
419
428
 
420
429
  case Opcodes.return:
421
- // line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
422
- const b = vals.pop();
423
- const a = vals.pop();
430
+ if (!typedReturns) {
431
+ line(`return${returns ? ` ${removeBrackets(vals.pop())}` : ''}`);
432
+ break;
433
+ }
434
+
435
+ const b = returns ? vals.pop() : -1;
436
+ const a = returns ? vals.pop() : -1;
424
437
  line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(a)}, ${removeBrackets(b)} }` : ''}`);
425
- // line(`return${returns ? ` (struct ReturnValue){ ${removeBrackets(vals.pop())}, ${removeBrackets(vals.pop())} }` : ''}`);
426
438
  break;
427
439
 
428
440
  case Opcodes.if: {
@@ -549,10 +561,15 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
549
561
 
550
562
  prepend.set('__Porffor_readFile',
551
563
  `i32 __Porffor_readFile(u32 pathPtr, u32 outPtr) {
552
- char* path = _memory + pathPtr + 4;
553
- FILE* fp = fopen(path, "r");
554
- if (fp == NULL) {
555
- return -1;
564
+ FILE* fp;
565
+ if (pathPtr == 0) {
566
+ fp = stdin;
567
+ } else {
568
+ char* path = _memory + pathPtr + 4;
569
+ fp = fopen(path, "r");
570
+ if (fp == NULL) {
571
+ return -1;
572
+ }
556
573
  }
557
574
 
558
575
  u32 read = 0;
@@ -585,7 +602,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
585
602
  for (let j = 0; j < func.params.length; j++) args.unshift(removeBrackets(vals.pop()));
586
603
 
587
604
  if (func.returns.length > 0) {
588
- if (func.internal) {
605
+ if (func.returnType != null) {
589
606
  vals.push(`${sanitize(func.name)}(${args.join(', ')})`);
590
607
  } else {
591
608
  const id = retTmpId++;
@@ -82,7 +82,17 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
82
82
  params.push(valtypeBinary, Valtype.i32);
83
83
  }
84
84
 
85
- const returns = [ valtypeBinary, Valtype.i32 ];
85
+ if (inst.at(-1) === 'constr') {
86
+ inst.pop();
87
+ params.unshift(Valtype.i32);
88
+ }
89
+
90
+ let returns = [ valtypeBinary, Valtype.i32 ];
91
+ if (inst.at(-1) === 'no_type_return') {
92
+ inst.pop();
93
+ returns = [ valtypeBinary ];
94
+ }
95
+
86
96
  inst[1] = getType(params, returns);
87
97
  }
88
98
  }
@@ -116,16 +126,21 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
116
126
  ] ])
117
127
  );
118
128
 
119
- if (pages.has('func argc lut') && !data.addedFuncArgcLut) {
120
- // generate func argc lut data
129
+ if (pages.has('func lut') && !data.addedFuncArgcLut) {
130
+ // generate func lut data
121
131
  const bytes = [];
122
132
  for (let i = 0; i < funcs.length; i++) {
123
133
  const argc = Math.floor(funcs[i].params.length / 2);
124
134
  bytes.push(argc % 256, (argc / 256 | 0) % 256);
135
+
136
+ let flags = 0b00000000; // 8 flag bits
137
+ if (funcs[i].returnType != null) flags |= 0b1;
138
+ if (funcs[i].constr) flags |= 0b10;
139
+ bytes.push(flags);
125
140
  }
126
141
 
127
142
  data.push({
128
- offset: pages.get('func argc lut').ind * pageSize,
143
+ offset: pages.get('func lut').ind * pageSize,
129
144
  bytes
130
145
  });
131
146
  data.addedFuncArgcLut = true;
@@ -4,6 +4,7 @@ export const __Array_isArray = (x: unknown): boolean =>
4
4
  // Porffor.wasm`local.get ${x+1}` == Porffor.TYPES.array;
5
5
  Porffor.rawType(x) == Porffor.TYPES.array;
6
6
 
7
+
7
8
  export const __Array_prototype_slice = (_this: any[], start: number, end: number) => {
8
9
  const len: i32 = _this.length;
9
10
  if (Porffor.rawType(end) == Porffor.TYPES.undefined) end = len;
@@ -22,7 +23,7 @@ export const __Array_prototype_slice = (_this: any[], start: number, end: number
22
23
  }
23
24
  if (end > len) end = len;
24
25
 
25
- let out: any[] = [];
26
+ let out: any[] = Porffor.allocate();
26
27
 
27
28
  if (start > end) return out;
28
29
 
@@ -42,10 +43,10 @@ export const __Array_prototype_slice = (_this: any[], start: number, end: number
42
43
  }
43
44
 
44
45
  out.length = end - start;
45
-
46
46
  return out;
47
47
  };
48
48
 
49
+ // @porf-typed-array
49
50
  export const __Array_prototype_indexOf = (_this: any[], searchElement: any, position: number) => {
50
51
  const len: i32 = _this.length;
51
52
  if (position > 0) {
@@ -60,6 +61,7 @@ export const __Array_prototype_indexOf = (_this: any[], searchElement: any, posi
60
61
  return -1;
61
62
  };
62
63
 
64
+ // @porf-typed-array
63
65
  export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any, position: number) => {
64
66
  const len: i32 = _this.length;
65
67
  if (position > 0) {
@@ -74,6 +76,7 @@ export const __Array_prototype_lastIndexOf = (_this: any[], searchElement: any,
74
76
  return -1;
75
77
  };
76
78
 
79
+ // @porf-typed-array
77
80
  export const __Array_prototype_includes = (_this: any[], searchElement: any, position: number) => {
78
81
  const len: i32 = _this.length;
79
82
  if (position > 0) {
@@ -88,6 +91,7 @@ export const __Array_prototype_includes = (_this: any[], searchElement: any, pos
88
91
  return false;
89
92
  };
90
93
 
94
+ // @porf-typed-array
91
95
  export const __Array_prototype_with = (_this: any[], index: number, value: any) => {
92
96
  const len: i32 = _this.length;
93
97
  if (index < 0) {
@@ -101,8 +105,7 @@ export const __Array_prototype_with = (_this: any[], index: number, value: any)
101
105
  throw new RangeError('Invalid index');
102
106
  }
103
107
 
104
- // todo: allocator is bad here?
105
- let out: any[] = [];
108
+ let out: any[] = Porffor.allocate();
106
109
 
107
110
  Porffor.clone(_this, out);
108
111
 
@@ -111,6 +114,7 @@ export const __Array_prototype_with = (_this: any[], index: number, value: any)
111
114
  return out;
112
115
  };
113
116
 
117
+ // @porf-typed-array
114
118
  export const __Array_prototype_reverse = (_this: any[]) => {
115
119
  const len: i32 = _this.length;
116
120
 
@@ -126,14 +130,14 @@ export const __Array_prototype_reverse = (_this: any[]) => {
126
130
  return _this;
127
131
  };
128
132
 
129
- // todo: this has memory/allocation bugs so sometimes crashes :(
133
+ // @porf-typed-array
130
134
  export const __Array_prototype_toReversed = (_this: any[]) => {
131
135
  const len: i32 = _this.length;
132
136
 
133
137
  let start: i32 = 0;
134
138
  let end: i32 = len - 1;
135
139
 
136
- let out: any[] = [];
140
+ let out: any[] = Porffor.allocate();
137
141
  out.length = len;
138
142
 
139
143
  while (start < end) {
@@ -144,11 +148,13 @@ export const __Array_prototype_toReversed = (_this: any[]) => {
144
148
  return out;
145
149
  };
146
150
 
151
+ // @porf-typed-array
147
152
  export const __Array_prototype_valueOf = (_this: any[]) => {
148
153
  return _this;
149
154
  };
150
155
 
151
156
 
157
+ // @porf-typed-array
152
158
  export const __Array_prototype_forEach = (_this: any[], callbackFn: any) => {
153
159
  const len: i32 = _this.length;
154
160
  let i: i32 = 0;
@@ -157,22 +163,26 @@ export const __Array_prototype_forEach = (_this: any[], callbackFn: any) => {
157
163
  }
158
164
  };
159
165
 
166
+ // @porf-typed-array
160
167
  export const __Array_prototype_filter = (_this: any[], callbackFn: any) => {
161
- const out: any[] = [];
168
+ const out: any[] = Porffor.allocate();
162
169
 
163
170
  const len: i32 = _this.length;
164
171
  let i: i32 = 0;
172
+ let j: i32 = 0;
165
173
  while (i < len) {
166
174
  const el: any = _this[i];
167
- if (Boolean(callbackFn(el, i++, _this))) out.push(el);
175
+ if (Boolean(callbackFn(el, i++, _this))) out[j++] = el;
168
176
  }
169
177
 
178
+ out.length = j;
170
179
  return out;
171
180
  };
172
181
 
182
+ // @porf-typed-array
173
183
  export const __Array_prototype_map = (_this: any[], callbackFn: any) => {
174
184
  const len: i32 = _this.length;
175
- const out: any[] = [];
185
+ const out: any[] = Porffor.allocate();
176
186
  out.length = len;
177
187
 
178
188
  let i: i32 = 0;
@@ -183,6 +193,7 @@ export const __Array_prototype_map = (_this: any[], callbackFn: any) => {
183
193
  return out;
184
194
  };
185
195
 
196
+ // @porf-typed-array
186
197
  export const __Array_prototype_find = (_this: any[], callbackFn: any) => {
187
198
  const len: i32 = _this.length;
188
199
  let i: i32 = 0;
@@ -192,6 +203,7 @@ export const __Array_prototype_find = (_this: any[], callbackFn: any) => {
192
203
  }
193
204
  };
194
205
 
206
+ // @porf-typed-array
195
207
  export const __Array_prototype_findLast = (_this: any[], callbackFn: any) => {
196
208
  let i: i32 = _this.length;
197
209
  while (i > 0) {
@@ -200,6 +212,7 @@ export const __Array_prototype_findLast = (_this: any[], callbackFn: any) => {
200
212
  }
201
213
  };
202
214
 
215
+ // @porf-typed-array
203
216
  export const __Array_prototype_findIndex = (_this: any[], callbackFn: any) => {
204
217
  const len: i32 = _this.length;
205
218
  let i: i32 = 0;
@@ -208,6 +221,7 @@ export const __Array_prototype_findIndex = (_this: any[], callbackFn: any) => {
208
221
  }
209
222
  };
210
223
 
224
+ // @porf-typed-array
211
225
  export const __Array_prototype_findLastIndex = (_this: any[], callbackFn: any) => {
212
226
  let i: i32 = _this.length;
213
227
  while (i > 0) {
@@ -215,6 +229,7 @@ export const __Array_prototype_findLastIndex = (_this: any[], callbackFn: any) =
215
229
  }
216
230
  };
217
231
 
232
+ // @porf-typed-array
218
233
  export const __Array_prototype_every = (_this: any[], callbackFn: any) => {
219
234
  const len: i32 = _this.length;
220
235
  let i: i32 = 0;
@@ -225,6 +240,18 @@ export const __Array_prototype_every = (_this: any[], callbackFn: any) => {
225
240
  return true;
226
241
  };
227
242
 
243
+ // @porf-typed-array
244
+ export const __Array_prototype_some = (_this: any[], callbackFn: any) => {
245
+ const len: i32 = _this.length;
246
+ let i: i32 = 0;
247
+ while (i < len) {
248
+ if (Boolean(callbackFn(_this[i], i++, _this))) return true;
249
+ }
250
+
251
+ return false;
252
+ };
253
+
254
+ // @porf-typed-array
228
255
  export const __Array_prototype_reduce = (_this: any[], callbackFn: any, initialValue: any) => {
229
256
  let acc: any = initialValue ?? _this[0];
230
257
 
@@ -237,6 +264,20 @@ export const __Array_prototype_reduce = (_this: any[], callbackFn: any, initialV
237
264
  return acc;
238
265
  };
239
266
 
267
+ // @porf-typed-array
268
+ export const __Array_prototype_reduceRight = (_this: any[], callbackFn: any, initialValue: any) => {
269
+ const len: i32 = _this.length;
270
+ let acc: any = initialValue ?? _this[len - 1];
271
+
272
+ let i: i32 = len;
273
+ while (i > 0) {
274
+ acc = callbackFn(acc, _this[--i], i, _this);
275
+ }
276
+
277
+ return acc;
278
+ };
279
+
280
+ // @porf-typed-array
240
281
  export const __Array_prototype_toString = (_this: any[]) => {
241
282
  // todo: this is bytestring only!
242
283
 
@@ -261,6 +302,7 @@ export const __Array_prototype_toString = (_this: any[]) => {
261
302
  return out;
262
303
  };
263
304
 
305
+ // @porf-typed-array
264
306
  export const __Array_prototype_join = (_this: any[], _separator: any) => {
265
307
  // todo: this is bytestring only!
266
308
  // todo/perf: optimize single char separators
@@ -718,108 +718,6 @@ export const __Porffor_date_write = (ptr: Date, val: number) => {
718
718
  Porffor.wasm.f64.store(ptr, val, 0, 0);
719
719
  };
720
720
 
721
- // 21.4.2.1 Date (...values)
722
- // https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date
723
- export const Date$constructor = (v0: unknown, v1: unknown, v2: unknown, v3: unknown, v4: unknown, v5: unknown, v6: unknown): Date => {
724
- // todo: passing undefined to params should not act like no arg was passed
725
-
726
- // 2. Let numberOfArgs be the number of elements in values.
727
- // sorry.
728
- const numberOfArgs: i32 =
729
- (Porffor.rawType(v0) != Porffor.TYPES.undefined) +
730
- (Porffor.rawType(v1) != Porffor.TYPES.undefined) +
731
- (Porffor.rawType(v2) != Porffor.TYPES.undefined) +
732
- (Porffor.rawType(v3) != Porffor.TYPES.undefined) +
733
- (Porffor.rawType(v4) != Porffor.TYPES.undefined) +
734
- (Porffor.rawType(v5) != Porffor.TYPES.undefined) +
735
- (Porffor.rawType(v6) != Porffor.TYPES.undefined);
736
-
737
- let dv: number = 0;
738
-
739
- // 3. If numberOfArgs = 0, then
740
- if (numberOfArgs == 0) {
741
- // a. Let dv be the time value (UTC) identifying the current time.
742
- dv = __Date_now();
743
- } else if (numberOfArgs == 1) {
744
- // 4. Else if numberOfArgs = 1, the n
745
- // a. Let value be values[0].
746
- const value: any = v0;
747
-
748
- const valueType: i32 = Porffor.rawType(v0);
749
-
750
- let tv: number = 0;
751
-
752
- // b. If value is an Object and value has a [[DateValue]] internal slot, then
753
- if (valueType == Porffor.TYPES.date) {
754
- // i. Let tv be value.[[DateValue]].
755
- tv = __Porffor_date_read(value);
756
- } else {
757
- // c. Else,
758
- // ii. If v is a String, then
759
- if (Porffor.fastOr(valueType == Porffor.TYPES.string, valueType == Porffor.TYPES.bytestring)) {
760
- // 1. Assert: The next step never returns an abrupt completion because v is a String.
761
-
762
- // 2. Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (21.4.3.2).
763
- tv = __Date_parse(value);
764
- } else {
765
- // iii. Else,
766
- // 1. Let tv be ? ToNumber(v).
767
- tv = Number(value);
768
- }
769
- }
770
-
771
- // d. Let dv be TimeClip(tv).
772
- dv = __ecma262_TimeClip(tv);
773
- } else {
774
- // 5. Else,
775
- // a. Assert: numberOfArgs โ‰ฅ 2.
776
-
777
- // b. Let y be ? ToNumber(values[0]).
778
- const y: number = Number(v0);
779
-
780
- // c. Let m be ? ToNumber(values[1]).
781
- const m: number = Number(v1);
782
-
783
- // d. If numberOfArgs > 2, let dt be ? ToNumber(values[2]); else let dt be 1๐”ฝ.
784
- let dt: number = 1;
785
- if (numberOfArgs > 2) dt = Number(v2);
786
-
787
- // e. If numberOfArgs > 3, let h be ? ToNumber(values[3]); else let h be +0๐”ฝ.
788
- let h: number = 0;
789
- if (numberOfArgs > 3) h = Number(v3);
790
-
791
- // f. If numberOfArgs > 4, let min be ? ToNumber(values[4]); else let min be +0๐”ฝ.
792
- let min: number = 0;
793
- if (numberOfArgs > 4) min = Number(v4);
794
-
795
- // g. If numberOfArgs > 5, let s be ? ToNumber(values[5]); else let s be +0๐”ฝ.
796
- let s: number = 0;
797
- if (numberOfArgs > 5) s = Number(v5);
798
-
799
- // h. If numberOfArgs > 6, let milli be ? ToNumber(values[6]); else let milli be +0๐”ฝ.
800
- let milli: number = 0;
801
- if (numberOfArgs > 6) milli = Number(v6);
802
-
803
- // i. Let yr be MakeFullYear(y).
804
- const yr: number = __ecma262_MakeFullYear(y);
805
-
806
- // j. Let finalDate be MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)).
807
- const finalDate: number = __ecma262_MakeDate(__ecma262_MakeDay(yr, m, dt), __ecma262_MakeTime(h, min, s, milli));
808
-
809
- // k. Let dv be TimeClip(UTC(finalDate)).
810
- dv = __ecma262_TimeClip(__ecma262_UTC(finalDate));
811
- }
812
-
813
- // 6. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", ยซ [[DateValue]] ยป).
814
- const O: Date = __Porffor_date_allocate();
815
-
816
- // 7. Set O.[[DateValue]] to dv.
817
- __Porffor_date_write(O, dv);
818
-
819
- // 8. Return O.
820
- return O;
821
- };
822
-
823
721
 
824
722
  // 21.4.4 Properties of the Date Prototype Object
825
723
  // https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-properties-of-the-date-prototype-object
@@ -2034,9 +1932,109 @@ export const __Date_prototype_valueOf = (_this: Date) => {
2034
1932
 
2035
1933
  // 21.4.2.1 Date (...values)
2036
1934
  // https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date
2037
- export const Date = (): bytestring => {
1935
+ export const Date = function (v0: unknown, v1: unknown, v2: unknown, v3: unknown, v4: unknown, v5: unknown, v6: unknown): bytestring|Date {
2038
1936
  // 1. If NewTarget is undefined, then
2039
- // a. Let now be the time value (UTC) identifying the current time.
2040
- // b. Return ToDateString(now).
2041
- return __ecma262_ToDateString(__Date_now());
1937
+ if (!new.target) {
1938
+ // a. Let now be the time value (UTC) identifying the current time.
1939
+ // b. Return ToDateString(now).
1940
+ return __ecma262_ToDateString(__Date_now());
1941
+ }
1942
+
1943
+ // todo: passing undefined to params should not act like no arg was passed
1944
+
1945
+ // 2. Let numberOfArgs be the number of elements in values.
1946
+ // sorry.
1947
+ const numberOfArgs: i32 =
1948
+ (Porffor.rawType(v0) != Porffor.TYPES.undefined) +
1949
+ (Porffor.rawType(v1) != Porffor.TYPES.undefined) +
1950
+ (Porffor.rawType(v2) != Porffor.TYPES.undefined) +
1951
+ (Porffor.rawType(v3) != Porffor.TYPES.undefined) +
1952
+ (Porffor.rawType(v4) != Porffor.TYPES.undefined) +
1953
+ (Porffor.rawType(v5) != Porffor.TYPES.undefined) +
1954
+ (Porffor.rawType(v6) != Porffor.TYPES.undefined);
1955
+
1956
+ let dv: number = 0;
1957
+
1958
+ // 3. If numberOfArgs = 0, then
1959
+ if (numberOfArgs == 0) {
1960
+ // a. Let dv be the time value (UTC) identifying the current time.
1961
+ dv = __Date_now();
1962
+ } else if (numberOfArgs == 1) {
1963
+ // 4. Else if numberOfArgs = 1, the n
1964
+ // a. Let value be values[0].
1965
+ const value: any = v0;
1966
+
1967
+ const valueType: i32 = Porffor.rawType(v0);
1968
+
1969
+ let tv: number = 0;
1970
+
1971
+ // b. If value is an Object and value has a [[DateValue]] internal slot, then
1972
+ if (valueType == Porffor.TYPES.date) {
1973
+ // i. Let tv be value.[[DateValue]].
1974
+ tv = __Porffor_date_read(value);
1975
+ } else {
1976
+ // c. Else,
1977
+ // ii. If v is a String, then
1978
+ if (Porffor.fastOr(valueType == Porffor.TYPES.string, valueType == Porffor.TYPES.bytestring)) {
1979
+ // 1. Assert: The next step never returns an abrupt completion because v is a String.
1980
+
1981
+ // 2. Let tv be the result of parsing v as a date, in exactly the same manner as for the parse method (21.4.3.2).
1982
+ tv = __Date_parse(value);
1983
+ } else {
1984
+ // iii. Else,
1985
+ // 1. Let tv be ? ToNumber(v).
1986
+ tv = Number(value);
1987
+ }
1988
+ }
1989
+
1990
+ // d. Let dv be TimeClip(tv).
1991
+ dv = __ecma262_TimeClip(tv);
1992
+ } else {
1993
+ // 5. Else,
1994
+ // a. Assert: numberOfArgs โ‰ฅ 2.
1995
+
1996
+ // b. Let y be ? ToNumber(values[0]).
1997
+ const y: number = Number(v0);
1998
+
1999
+ // c. Let m be ? ToNumber(values[1]).
2000
+ const m: number = Number(v1);
2001
+
2002
+ // d. If numberOfArgs > 2, let dt be ? ToNumber(values[2]); else let dt be 1๐”ฝ.
2003
+ let dt: number = 1;
2004
+ if (numberOfArgs > 2) dt = Number(v2);
2005
+
2006
+ // e. If numberOfArgs > 3, let h be ? ToNumber(values[3]); else let h be +0๐”ฝ.
2007
+ let h: number = 0;
2008
+ if (numberOfArgs > 3) h = Number(v3);
2009
+
2010
+ // f. If numberOfArgs > 4, let min be ? ToNumber(values[4]); else let min be +0๐”ฝ.
2011
+ let min: number = 0;
2012
+ if (numberOfArgs > 4) min = Number(v4);
2013
+
2014
+ // g. If numberOfArgs > 5, let s be ? ToNumber(values[5]); else let s be +0๐”ฝ.
2015
+ let s: number = 0;
2016
+ if (numberOfArgs > 5) s = Number(v5);
2017
+
2018
+ // h. If numberOfArgs > 6, let milli be ? ToNumber(values[6]); else let milli be +0๐”ฝ.
2019
+ let milli: number = 0;
2020
+ if (numberOfArgs > 6) milli = Number(v6);
2021
+
2022
+ // i. Let yr be MakeFullYear(y).
2023
+ const yr: number = __ecma262_MakeFullYear(y);
2024
+
2025
+ // j. Let finalDate be MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)).
2026
+ const finalDate: number = __ecma262_MakeDate(__ecma262_MakeDay(yr, m, dt), __ecma262_MakeTime(h, min, s, milli));
2027
+
2028
+ // k. Let dv be TimeClip(UTC(finalDate)).
2029
+ dv = __ecma262_TimeClip(__ecma262_UTC(finalDate));
2030
+ }
2031
+
2032
+ // 6. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", ยซ [[DateValue]] ยป).
2033
+ const O: Date = __Porffor_date_allocate();
2034
+
2035
+ // 7. Set O.[[DateValue]] to dv.
2036
+ __Porffor_date_write(O, dv);
2037
+
2038
+ // 8. Return O.
2039
+ return O;
2042
2040
  };
@@ -1,11 +1,8 @@
1
1
  export default () => {
2
2
  let out = '';
3
3
 
4
- const error = name => out += `export const ${name} = (message: bytestring) => {
5
- return {};
6
- };
7
-
8
- export const ${name}$constructor = (message: bytestring) => {
4
+ const error = name => out += `export const ${name} = function (message: bytestring) {
5
+ new.target;
9
6
  return {};
10
7
  };`;
11
8
 
@@ -16,7 +16,7 @@ export const __Math_exp = (x: number): number => {
16
16
  return 1 / Math.exp(-x);
17
17
  }
18
18
 
19
- const k: number = Math.floor(x / Math.LN2);
19
+ let k: number = Math.floor(x / Math.LN2);
20
20
  const r: number = x - k * Math.LN2;
21
21
 
22
22
  // Taylor series via Horner's method
@@ -30,7 +30,11 @@ export const __Math_exp = (x: number): number => {
30
30
  i++;
31
31
  }
32
32
 
33
- return sum * (1 << k);
33
+ while (k-- > 0) {
34
+ sum *= 2;
35
+ }
36
+
37
+ return sum;
34
38
  };
35
39
 
36
40
  export const __Math_log2 = (y: number): number => {
@@ -8,6 +8,7 @@ memory.grow 0
8
8
  i32.const 65536
9
9
  i32.mul
10
10
  i32.from_u
11
+ i32.const 0
11
12
  return`;
12
13
  };
13
14
 
@@ -163,22 +164,13 @@ export const __Set_prototype_clear = (_this: Set) => {
163
164
  Porffor.wasm.i32.store(_this, 0, 0, 0);
164
165
  };
165
166
 
166
- export const Set = () => {
167
- throw new TypeError("Constructor Set requires 'new'");
168
- };
167
+ export const Set = function (iterable: any): any {
168
+ if (!new.target) throw new TypeError("Constructor Set requires 'new'");
169
169
 
170
- export const Set$constructor = (iterable: any): Set => {
171
170
  const out: Set = __Porffor_allocate();
172
171
 
173
- const type: number = Porffor.rawType(iterable);
174
- if (Porffor.fastOr(
175
- type == Porffor.TYPES.array,
176
- type == Porffor.TYPES.string, type == Porffor.TYPES.bytestring,
177
- type == Porffor.TYPES.set
178
- )) {
179
- for (const x of iterable) {
180
- __Set_prototype_add(out, x);
181
- }
172
+ if (Porffor.rawType(iterable) != Porffor.TYPES.undefined) for (const x of iterable) {
173
+ __Set_prototype_add(out, x);
182
174
  }
183
175
 
184
176
  return out;
@@ -189,7 +181,7 @@ export const __Set_prototype_union = (_this: Set, other: any) => {
189
181
  throw new TypeError("Set.prototype.union\'s \'other\' argument must be a Set");
190
182
  }
191
183
 
192
- const out: Set = Set$constructor(_this);
184
+ const out: Set = new Set(_this);
193
185
  for (const x of other) {
194
186
  out.add(x);
195
187
  }