@temperlang/core 0.0.4 → 0.0.6

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/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  export * from "./interface-types.js";
2
2
  export * from "./regex.js";
3
3
 
4
- export const noResultException = new (class NoResultException extends Error {
4
+ export const bubbleException = new (class BubbleException extends Error {
5
5
  constructor() {
6
- super("NoResult");
6
+ super("Bubble");
7
7
  }
8
8
  })();
9
9
 
@@ -114,7 +114,7 @@ class Utf8StringSlice extends TrickyStringSlice {
114
114
  let left = this.left;
115
115
  let right = this.right;
116
116
  if (left >= right) {
117
- throw noResultException;
117
+ throw bubbleException;
118
118
  }
119
119
 
120
120
  let content = this.content;
@@ -131,32 +131,53 @@ class Utf8StringSlice extends TrickyStringSlice {
131
131
  }
132
132
  }
133
133
 
134
- advance(count) {
135
- if (count <= 0) {
136
- return this;
137
- } else if (count === 1) {
138
- let left = this.left;
139
- let right = this.right;
140
- if (left >= right) {
141
- return this;
142
- }
143
- let content = this.content;
144
- let cp = content.codePointAt(left >> 2);
145
- let newLeft;
146
- if (cp < 0x80) {
147
- newLeft = left + 4;
134
+ /**
135
+ * @param {number} count
136
+ * @return {number}
137
+ */
138
+ _advanceLeft(count) {
139
+ let left = this.left;
140
+ let content = this.content;
141
+ let contentLen = content.length;
142
+ let idx = left >> 2;
143
+ let sub = left & 3;
144
+
145
+ while (count > 0 && idx < contentLen) {
146
+ let cp = content.codePointAt(idx);
147
+ let rem = nUtf8BytesInChar(cp) - sub;
148
+ if (rem > count) {
149
+ sub += count;
150
+ count = 0;
148
151
  } else {
149
- let byteOffset = left & 3;
150
- let nBytes = nUtf8BytesInChar(cp);
151
- newLeft =
152
- byteOffset + 1 < nBytes
153
- ? left + 1
154
- : (left & ~3) + ((nBytes + 4) & ~3);
152
+ count -= rem;
153
+ sub = 0;
154
+ idx += cp > 0x10000 ? 2 : 1;
155
155
  }
156
- return new Utf8StringSlice(content, newLeft, right);
157
- } else {
158
- throw new Error("TODO");
159
156
  }
157
+
158
+ return count ? this.right : Math.min(idx << 2 | sub, this.right);
159
+ }
160
+
161
+ /**
162
+ * @param {number} count
163
+ * @return {Utf8StringSlice}
164
+ */
165
+ advance(count) {
166
+ let newLeft = this._advanceLeft(count);
167
+ return (this.left === newLeft)
168
+ ? this
169
+ : new Utf8StringSlice(this.content, newLeft, this.right);
170
+ }
171
+
172
+ /**
173
+ * @param {number} count
174
+ * @return {Utf8StringSlice}
175
+ */
176
+ limit(count) {
177
+ let newRight = this._advanceLeft(count);
178
+ return (this.right === newRight)
179
+ ? this
180
+ : new Utf8StringSlice(this.content, this.left, newRight);
160
181
  }
161
182
 
162
183
  [Symbol.iterator]() {
@@ -217,26 +238,39 @@ class Utf16StringSlice {
217
238
  let left = this.left;
218
239
  let right = this.right;
219
240
  if (left >= right) {
220
- throw noResultException;
241
+ throw bubbleException;
221
242
  }
222
243
  return this.content.charCodeAt(left);
223
244
  }
224
245
 
246
+ /**
247
+ * @param {number} count
248
+ * @return {number}
249
+ */
250
+ _advanceLeft(count) {
251
+ return Math.min(this.left + count, this.right);
252
+ }
253
+
254
+ /**
255
+ * @param {number} count
256
+ * @return {Utf16StringSlice}
257
+ */
225
258
  advance(count) {
226
- if (count <= 0) {
227
- return this;
228
- } else {
229
- let left = this.left;
230
- let right = this.right;
231
- if (left >= right) {
232
- return this;
233
- }
234
- let newLeft = left + count;
235
- if (newLeft >= right) {
236
- newLeft = right;
237
- }
238
- return new Utf16StringSlice(this.content, newLeft, right);
239
- }
259
+ let newLeft = this._advanceLeft(count);
260
+ return this.left === newLeft
261
+ ? this
262
+ : new Utf16StringSlice(this.content, newLeft, this.right);
263
+ }
264
+
265
+ /**
266
+ * @param {number} count
267
+ * @return {Utf16StringSlice}
268
+ */
269
+ limit(count) {
270
+ let newRight = this._advanceLeft(count);
271
+ return this.right === newRight
272
+ ? this
273
+ : new Utf16StringSlice(this.content, this.left, newRight);
240
274
  }
241
275
 
242
276
  [Symbol.iterator]() {
@@ -295,35 +329,55 @@ class CodePointsStringSlice extends TrickyStringSlice {
295
329
 
296
330
  read() {
297
331
  if (this.left >= this.right) {
298
- throw noResultException;
332
+ throw bubbleException;
299
333
  }
300
334
  return this.content.codePointAt(this.left);
301
335
  }
302
336
 
303
- advance(count) {
304
- if (count <= 0) {
305
- return this;
306
- } else {
307
- let left = this.left;
308
- let right = this.right;
309
- let content = this.content;
310
- if (left >= right) {
311
- return this;
312
- }
313
- let newLeft = left;
314
- for (let i = count; i && newLeft < right; --i) {
315
- let cp = content.codePointAt(newLeft);
316
- if (cp > 0xffff) {
317
- newLeft += 2;
318
- } else {
319
- newLeft += 1;
320
- }
321
- }
322
- if (newLeft >= right) {
323
- newLeft = right;
337
+ /**
338
+ * @param {number} count
339
+ * @return {number}
340
+ */
341
+ _advanceLeft(count) {
342
+ let left = this.left;
343
+ let right = this.right;
344
+ let content = this.content;
345
+ if (count <= 0) { return left }
346
+ let newLeft = left;
347
+ for (let i = count; i && newLeft < right; --i) {
348
+ let cp = content.codePointAt(newLeft);
349
+ if (cp > 0xffff) {
350
+ newLeft += 2;
351
+ } else {
352
+ newLeft += 1;
324
353
  }
325
- return new CodePointsStringSlice(this.content, newLeft, right);
326
354
  }
355
+ if (newLeft >= right) {
356
+ newLeft = right;
357
+ }
358
+ return newLeft;
359
+ }
360
+
361
+ /**
362
+ * @param {number} count
363
+ * @return {CodePointsStringSlice}
364
+ */
365
+ advance(count) {
366
+ let newLeft = this._advanceLeft(count);
367
+ return (newLeft === this.left)
368
+ ? this
369
+ : new CodePointsStringSlice(this.content, newLeft, this.right);
370
+ }
371
+
372
+ /**
373
+ * @param {number} count
374
+ * @return {CodePointsStringSlice}
375
+ */
376
+ limit(count) {
377
+ let newRight = this._advanceLeft(count);
378
+ return (newRight === this.right)
379
+ ? this
380
+ : new CodePointsStringSlice(this.content, this.left, newRight);
327
381
  }
328
382
 
329
383
  [Symbol.iterator]() {
@@ -363,13 +417,25 @@ export function intToString(i, radix) {
363
417
  return i.toString(radix);
364
418
  }
365
419
 
420
+ // Implements extension method Float64::near
421
+ export function float64Near(x, y, relTol, absTol) {
422
+ if (relTol === undefined) {
423
+ relTol = 1e-9;
424
+ }
425
+ if (absTol === undefined) {
426
+ absTol = 0;
427
+ }
428
+ const margin = Math.max(Math.max(Math.abs(x), Math.abs(y)) * relTol, absTol);
429
+ return Math.abs(x - y) < margin;
430
+ }
431
+
366
432
  // Implements extension method Float64::toInt
367
433
  export function float64ToInt(n) {
368
434
  const i = float64ToIntUnsafe(n);
369
435
  if (Math.abs(n - i) < 1) {
370
436
  return i;
371
437
  } else {
372
- throw noResultException;
438
+ throw bubbleException;
373
439
  }
374
440
  }
375
441
 
@@ -458,7 +524,7 @@ export function listBuilderAdd(ls, newItem, at) {
458
524
  ls.push(newItem);
459
525
  } else {
460
526
  if (at < 0 || at > ls.length) {
461
- throw noResultException;
527
+ throw bubbleException;
462
528
  }
463
529
  ls.splice(at, 0, newItem);
464
530
  }
@@ -469,7 +535,7 @@ export function listBuilderAddAll(ls, newItems, at) {
469
535
  ls.push(...newItems);
470
536
  } else {
471
537
  if (at < 0 || at > ls.length) {
472
- throw noResultException;
538
+ throw bubbleException;
473
539
  }
474
540
  ls.splice(at, 0, ...newItems);
475
541
  }
@@ -505,7 +571,7 @@ export function listGet(ls, i) {
505
571
  if (0 <= i && i < length) {
506
572
  return ls[i];
507
573
  }
508
- throw noResultException;
574
+ throw bubbleException;
509
575
  }
510
576
  // Implements extension method List::getOr
511
577
  export function listGetOr(ls, i, fallback) {
@@ -548,12 +614,20 @@ export function listMap(ls, transform) {
548
614
  }
549
615
  return freeze(mapped);
550
616
  }
617
+ // Implements extension method Listed::toList
618
+ export function listedToList(ls) {
619
+ if (Object.isFrozen(ls)) {
620
+ return ls;
621
+ } else {
622
+ return listBuilderToList(ls);
623
+ }
624
+ }
551
625
  // Implements extension method ListBuilder::removeLast
552
626
  export function listBuilderRemoveLast(ls) {
553
627
  if (ls.length) {
554
628
  return ls.pop();
555
629
  } else {
556
- throw noResultException;
630
+ throw bubbleException;
557
631
  }
558
632
  }
559
633
  // Implements extension method ListBuilder::reverse
@@ -627,7 +701,7 @@ export function mapBuilderRemove(builder, key) {
627
701
  if (builder.delete(key)) {
628
702
  return result;
629
703
  } else {
630
- throw noResultException;
704
+ throw bubbleException;
631
705
  }
632
706
  }
633
707
  export function mapBuilderSet(builder, key, value) {
@@ -661,7 +735,7 @@ export function mappedGet(map, key) {
661
735
  // TODO Under compiler-error-free Temper, could undefined values get set?
662
736
  // TODO Would Map<?, Void> be impossible to feed once we get checks in place?
663
737
  if (result === undefined) {
664
- throw noResultException;
738
+ throw bubbleException;
665
739
  }
666
740
  return result;
667
741
  }
@@ -669,6 +743,47 @@ export function mappedToList(map) {
669
743
  return Array.from(map, ([key, value]) => new Pair(key, value));
670
744
  }
671
745
 
746
+ // Implements Date::constructor
747
+ export function dateConstructor(year, month, day) {
748
+ let d = new Date(0);
749
+ // If we were to pass year into `new Date`, then it would
750
+ // have 1900 added when in the range [0, 99].
751
+ // developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date#year
752
+ d.setUTCFullYear(year);
753
+ d.setUTCMonth(month - 1 /* JS months are zero indexed */);
754
+ d.setUTCDate(day); // UTCDay is day of the week
755
+ return d;
756
+ }
757
+
758
+ // Implements Date::today
759
+ /**
760
+ * @returns {Date}
761
+ */
762
+ export function dateToday() {
763
+ let d = new Date(Date.now());
764
+ // Get rid of the time component.
765
+ d.setTime(
766
+ Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate())
767
+ );
768
+ return d;
769
+ }
770
+
771
+ // Implements Date::yearsBetween
772
+ /**
773
+ * @param {Date} start
774
+ * @param {Date} end
775
+ *
776
+ * @returns {number}
777
+ */
778
+ export function dateYearsBetween(start, end) {
779
+ let yearDelta = end.getUTCFullYear() - start.getUTCFullYear();
780
+ let monthDelta = end.getUTCMonth() - start.getUTCMonth();
781
+ return yearDelta -
782
+ // If the end month/day is before the start's then we
783
+ // don't have a full year.
784
+ (monthDelta < 0 || monthDelta == 0 && end.getUTCDate() < start.getUTCDate());
785
+ }
786
+
672
787
  // Implements extension method Deque::constructor
673
788
  const DEQUE_NTAKEN = Symbol("Deque::nTaken");
674
789
  export function dequeConstructor() {
@@ -692,7 +807,7 @@ export function dequeRemoveFirst(deque) {
692
807
  if (length === nTaken) {
693
808
  deque[DEQUE_NTAKEN] = 0;
694
809
  deque.length = 0;
695
- throw noResultException;
810
+ throw bubbleException;
696
811
  }
697
812
  let item = deque[nTaken];
698
813
  let nShiftThreshhold = (length / 2) | 0;
@@ -774,35 +889,35 @@ export {
774
889
 
775
890
  export function requireIsArray(x) {
776
891
  if (!isArray(x)) {
777
- throw noResultException;
892
+ throw bubbleException;
778
893
  }
779
894
  return x;
780
895
  }
781
896
 
782
897
  export function requireInstanceOf(x, typeRequirement) {
783
898
  if (!(x instanceof typeRequirement)) {
784
- throw noResultException;
899
+ throw bubbleException;
785
900
  }
786
901
  return x;
787
902
  }
788
903
 
789
904
  export function requireIsSafeInteger(x) {
790
905
  if (!isSafeInteger(x)) {
791
- throw noResultException;
906
+ throw bubbleException;
792
907
  }
793
908
  return x;
794
909
  }
795
910
 
796
911
  export function requireSame(x, y) {
797
912
  if (x !== y) {
798
- throw noResultException;
913
+ throw bubbleException;
799
914
  }
800
915
  return x;
801
916
  }
802
917
 
803
918
  export function requireTypeOf(x, typeOfString) {
804
919
  if (typeof x !== typeOfString) {
805
- throw noResultException;
920
+ throw bubbleException;
806
921
  }
807
922
  return x;
808
923
  }
@@ -823,7 +938,7 @@ export function divDubDub(x, y) {
823
938
  export function divIntInt(x, y) {
824
939
  const result = trunc(x / y);
825
940
  if (!isSafeInteger(result)) {
826
- throw noResultException;
941
+ throw bubbleException;
827
942
  }
828
943
  /* not NaN or infinite */
829
944
  return result;
@@ -831,7 +946,7 @@ export function divIntInt(x, y) {
831
946
  export function modIntInt(x, y) {
832
947
  const result = trunc(x % y);
833
948
  if (!isSafeInteger(result)) {
834
- throw noResultException;
949
+ throw bubbleException;
835
950
  }
836
951
  /* not NaN or infinite */
837
952
  return result;
@@ -907,7 +1022,7 @@ export function cmpGeneric(a, b) {
907
1022
  if (typeof a === "boolean" && typeof b === "boolean") {
908
1023
  return a - b;
909
1024
  }
910
- throw noResultException;
1025
+ throw bubbleException;
911
1026
  };
912
1027
  export function ltGeneric(a, b) {
913
1028
  if (typeof a === "number" && typeof b === "number") {
@@ -951,8 +1066,8 @@ export function eqGeneric(a, b) {
951
1066
  export function neGeneric(a, b) {
952
1067
  return !Object.is(a, b);
953
1068
  }
954
- export function fail() {
955
- throw noResultException;
1069
+ export function bubble() {
1070
+ throw bubbleException;
956
1071
  }
957
1072
  export function print(a) {
958
1073
  console.log("%s", a);
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@temperlang/core",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Runtime support for JS generated by Temper",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/regex.js CHANGED
@@ -1,4 +1,4 @@
1
- import {noResultException} from "./index.js";
1
+ import {bubbleException} from "./index.js";
2
2
 
3
3
  export function compiledRegexCompiledFound(_, compiled, text) {
4
4
  return compiled.test(text);
@@ -9,13 +9,13 @@ export function compiledRegexCompiledFind(_, compiled, text, regexRefs) {
9
9
  }
10
10
 
11
11
  /**
12
- * @param {RegExp} compiled
13
- * @param {string} text
12
+ * @param {RegExp} compiled
13
+ * @param {string} text
14
14
  */
15
15
  function compiledRegexCompiledFindEx(_, compiled, text, regexRefs) {
16
16
  const match = compiled.exec(text);
17
17
  if (match === null) {
18
- throw noResultException;
18
+ throw bubbleException;
19
19
  }
20
20
  const { groups, indices: { groups: indexGroups } } = match;
21
21
  // Find the begin indices in code points for all matched groups.
@@ -64,9 +64,9 @@ function codePointIndices(text, unitNameIndexArray) {
64
64
  }
65
65
 
66
66
  /**
67
- * @param {RegExp} compiled
68
- * @param {string} text
69
- * @param {(groups: Map<string, any>) => string} format
67
+ * @param {RegExp} compiled
68
+ * @param {string} text
69
+ * @param {(groups: Map<string, any>) => string} format
70
70
  * @returns {string}
71
71
  */
72
72
  export function compiledRegexCompiledReplace(
@@ -84,7 +84,7 @@ export function compiledRegexCompiledReplace(
84
84
  try {
85
85
  match = compiledRegexCompiledFindEx(_, compiled, text, regexRefs);
86
86
  } catch (e) {
87
- if (e === noResultException) {
87
+ if (e === bubbleException) {
88
88
  // Manually handle no match case for our manual replace logic.
89
89
  return text;
90
90
  } else {