This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); } | |
function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; } | |
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); } | |
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } | |
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); } | |
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } | |
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; } | |
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } | |
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } | |
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } | |
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } | |
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; } | |
function _possibleConstructorReturn(self, call) { if (call && (_typeof2(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); } | |
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } | |
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } } | |
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } | |
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } | |
function _typeof2(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); } | |
Object.defineProperty(exports, '__esModule', { | |
value: true | |
}); | |
/** | |
* Returns a non-cryptographic hash code for any object. | |
* Suitable for use in hash tables. | |
* | |
* Primitives are hashed based on their value. | |
* Everything else is hashed based on its identity (a basically unique ID). | |
* | |
* If two values are equal with `===` (ECMAScript spec: SameValueZero), | |
* their hash codes are guaranteed to be the same, | |
* with the exception of Symbol values. | |
* | |
* @param {*} o | |
* @return {!number} a 32-bit integer | |
*/ | |
function hash(o) { | |
if (o === null) return 0; | |
if (o && o.sym) return hashString("sym_".concat(o.toString())); | |
switch (_typeof2(o)) { | |
case 'number': | |
return hashNumber(o); | |
case 'string': | |
return hashString(o); | |
case 'boolean': | |
return o ? 1 : -1; | |
case 'undefined': | |
return 0; | |
case 'object': | |
case 'function': | |
return hashObjectIdentity(o); | |
default: | |
return hashString(o.toString()); | |
} | |
} | |
/** | |
* Calculates the given string's hash. | |
* | |
* Uses the same algorithm as the JVM string hash. | |
* | |
* @param {!String} s | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashString(s) { | |
var h = 0; | |
var n = s.length; | |
for (var i = 0; i < n; ++i) { | |
// Benchmarks of various ways to do this: | |
// https://run.perf.zone/view/String-Hashing-Performance-1504040177726 | |
h = ~~((h << 5) - h + s.charCodeAt(i)); | |
} | |
return h; | |
} // Buffers and arrays for {hashNumber}. | |
var kBuf = new ArrayBuffer(8); | |
var kBufAsF64 = new Float64Array(kBuf); | |
var kBufAsI32 = new Int32Array(kBuf); | |
/** | |
* Calculates the given number's hash. | |
* | |
* If two numbers are equal with `===` (ECMAScript spec: SameValueZero), | |
* the returned hash codes will be the same for them. | |
* | |
* @param {!number} n any number | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashNumber(n) { | |
// Benchmarks of various ways to do this: | |
// https://run.perf.zone/view/Number-Hashing-Performance-v9-1504054910628 | |
// For small numbers, return the number directly. | |
// This slightly increases the potential number of collisions | |
// with large numbers and floats, but increases the performance by 20%. | |
if (~~n === n) { | |
// If `n` is -0, the above check will pass. | |
// `~~` is here only to convert the potential -0 to 0. | |
return ~~n; | |
} | |
kBufAsF64[0] = n; | |
return kBufAsI32[0] ^ kBufAsI32[1]; | |
} | |
/** | |
* A weak map to the object's ID for {hashObjectIdentity}. | |
* | |
* @type {!WeakMap<Object, number>} | |
*/ | |
var objectIds = new WeakMap(); | |
var currentId = 0; | |
/** | |
* Returns an object ID. | |
* | |
* @param {!(Object|null)} o | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashObjectIdentity(o) { | |
var result = objectIds.get(o); | |
if (result === undefined) { | |
currentId = ~~(currentId + 1); | |
objectIds.set(o, currentId); | |
return currentId; | |
} | |
return result; | |
} //= The functions below are not called by `hash`. | |
/** | |
* Returns a hash of the array. | |
* | |
* The elements of the array must either be integers or objects | |
* with `valueOf` that returns an integer. | |
* | |
* @template T | |
* @param {T[]} a | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashIntArray(a) { | |
var h = 0; | |
var n = a.length; | |
for (var i = 0; i < n; ++i) { | |
h = ~~((h << 5) - h + a[i]); | |
} | |
return h; | |
} | |
/** | |
* Base class for various compound data types | |
* such as structs, pairs, values, ... | |
* | |
* Subclasses must override the following methods: | |
* * displayNativeString | |
* * isImmutable | |
* * equals | |
* | |
* @abstract | |
*/ | |
var Primitive = /*#__PURE__*/function () { | |
function Primitive() { | |
_classCallCheck(this, Primitive); | |
} | |
_createClass(Primitive, [{ | |
key: "hashForEqual", | |
value: | |
/** @abstract isImmutable(): boolean; */ | |
/** @abstract equals(*): boolean; */ | |
/** | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashForEqual() { | |
return hashString(this.toString()); | |
} | |
}]); | |
return Primitive; | |
}(); | |
function check(v) { | |
return v instanceof Primitive; | |
} | |
/** | |
* A simplified internal-only version of Ports.NativeOutputStringPort. | |
* | |
* This can be used where dependency on Ports is not possible, | |
* e.g. because Ports are Printable, | |
* and provides a faster no-frills internal implementation. | |
*/ | |
var MiniNativeOutputStringPort = /*#__PURE__*/function () { | |
function MiniNativeOutputStringPort() { | |
_classCallCheck(this, MiniNativeOutputStringPort); | |
this._buffer = []; | |
} | |
/** | |
* @param {String} nativeString | |
*/ | |
_createClass(MiniNativeOutputStringPort, [{ | |
key: "consume", | |
value: function consume(nativeString) { | |
this._buffer.push(nativeString); | |
} | |
/** | |
* @return {String} nativeString | |
*/ | |
}, { | |
key: "getOutputString", | |
value: function getOutputString() { | |
return this._buffer.join(''); | |
} | |
}]); | |
return MiniNativeOutputStringPort; | |
}(); | |
/** | |
* @param {*} bs | |
* @return {!boolean} | |
*/ | |
function check$1(bs) { | |
return _typeof2(bs) === 'object' && bs !== null && bs.constructor === Uint8Array; | |
} | |
/** | |
* @param {!number} non-negative int length | |
* @param {!number} non-negative int less than 256 | |
* @return {!Uint8Array} | |
*/ | |
function make(len, init) { | |
return new Uint8Array(len).fill(init); | |
} | |
/** | |
* | |
* @param {!Uint8Array} a | |
* @param {!Uint8Array} b | |
* @return {!boolean} | |
*/ | |
function eq(a, b) { | |
if (a.length !== b.length) return false; | |
var n = a.length; | |
for (var i = 0; i < n; i++) { | |
if (a[i] !== b[i]) return false; | |
} | |
return true; | |
} | |
var utf8Decoder = new TextDecoder('utf-8'); | |
/** | |
* @param {!Uint8Array} bytes | |
* @return {!String} | |
*/ | |
function toString(bytes) { | |
return utf8Decoder.decode(bytes); | |
} | |
/** | |
* Writes a string representation similar to Racket's `display` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
* @param {!Uint8Array} bytes | |
*/ | |
function displayNativeString(out, bytes) { | |
out.consume(toString(bytes)); | |
} | |
/** | |
* Writes a string representation similar to Racket's `print` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
* @param {!Uint8Array} bytes | |
*/ | |
function printNativeString(out, bytes) { | |
out.consume('#"'); | |
out.consume(toString(bytes)); | |
out.consume('"'); | |
} | |
/** | |
* @param {!Uint8Array} bytes | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashForEqual(bytes) { | |
return hashIntArray(bytes); | |
} | |
/** | |
* A single Unicode character. | |
* Value type semantics, immutable and final. | |
* | |
* The parameter type signatures in this class and file are enforced | |
* by RacketScript when called from RacketScript. | |
* | |
* No checks are performed here, allowing us to use it internally | |
* without paying the cost of runtime type checking. | |
* | |
* @property {!number} codepoint | |
* @final | |
*/ | |
var Char = /*#__PURE__*/function (_Primitive) { | |
_inherits(Char, _Primitive); | |
var _super = _createSuper(Char); | |
/** | |
* @param {!number} codepoint a non-negative integer. | |
* @param {(!string|null)} nativeString | |
* @private | |
*/ | |
function Char(codepoint, nativeString) { | |
var _this; | |
_classCallCheck(this, Char); | |
_this = _super.call(this); | |
_this.codepoint = codepoint; | |
_this._nativeString = nativeString; | |
return _this; | |
} | |
/** | |
* @param {*} v | |
* @return {!boolean} | |
*/ | |
_createClass(Char, [{ | |
key: "equals", | |
value: function equals(v) { | |
return check$2(v) && eq$1(this, v); | |
} | |
/** | |
* @return {true} | |
*/ | |
}, { | |
key: "isImmutable", | |
value: function isImmutable() { | |
return true; | |
} | |
/** | |
* @return {!number} this.codepoint. | |
* @override | |
*/ | |
}, { | |
key: "valueOf", | |
value: function valueOf() { | |
return this.codepoint; | |
} | |
/** | |
* @return {!String} | |
* @override | |
*/ | |
}, { | |
key: "toString", | |
value: function toString() { | |
if (this._nativeString === null) { | |
this._nativeString = String.fromCodePoint(this.codepoint); | |
} | |
return this._nativeString; | |
} | |
/** | |
* @return {!number} a non-negative integer. | |
* @override | |
*/ | |
}, { | |
key: "hashForEqual", | |
value: function hashForEqual() { | |
return this.codepoint; | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "displayNativeString", | |
value: function displayNativeString(out) { | |
out.consume(this.toString()); | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "writeNativeString", | |
value: function writeNativeString(out) { | |
var c = this.codepoint; | |
switch (c) { | |
// Reference implementation: | |
// https://github.com/racket/racket/blob/cbfcc904ab621a338627e77d8f5a34f930ead0ab/racket/src/racket/src/print.c#L4089 | |
case 0: | |
out.consume('#\\nul'); | |
break; | |
case 8: | |
out.consume('#\\backspace'); | |
break; | |
case 9: | |
out.consume('#\\tab'); | |
break; | |
case 10: | |
out.consume('#\\newline'); | |
break; | |
case 11: | |
out.consume('#\\vtab'); | |
break; | |
case 12: | |
out.consume('#\\page'); | |
break; | |
case 13: | |
out.consume('#\\return'); | |
break; | |
case 32: | |
out.consume('#\\space'); | |
break; | |
case 127: | |
out.consume('#\\rubout'); | |
break; | |
default: | |
if (isGraphic(this)) { | |
out.consume("#\\".concat(this.toString())); | |
} else { | |
out.consume(c > 0xFFFF ? "#\\U".concat(c.toString(16).toUpperCase().padStart(8, '0')) : "#\\u".concat(c.toString(16).toUpperCase().padStart(4, '0'))); | |
} | |
} | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "printNativeString", | |
value: function printNativeString(out) { | |
this.writeNativeString(out); | |
} // displayUstring is defined in unicode_string.js to avoid a circular dependency. | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "printUString", | |
value: function printUString(out) { | |
this.writeUString(out); | |
} | |
}]); | |
return Char; | |
}(Primitive | |
/* implements Printable */ | |
); | |
var INTERN_CACHE_SIZE = 256; | |
/** | |
* @type {!Array<Char|undefined>} A cache for chars with small codepoints. | |
*/ | |
var internedCache = new Array(INTERN_CACHE_SIZE); | |
/** | |
* @param {!number} codepoint a non-negative integer. | |
* @return {!Char} | |
*/ | |
function charFromCodepoint(codepoint) { | |
if (codepoint < INTERN_CACHE_SIZE) { | |
if (internedCache[codepoint] === undefined) { | |
internedCache[codepoint] = new Char(codepoint, null); | |
} | |
return internedCache[codepoint]; | |
} | |
return new Char(codepoint, null); | |
} | |
/** | |
* @param {!string} s A native string exactly one Unicode codepoint long. | |
*/ | |
function charFromNativeString(s) { | |
var codepoint = s.codePointAt(0); | |
if (codepoint < INTERN_CACHE_SIZE) { | |
if (internedCache[codepoint] === undefined) { | |
internedCache[codepoint] = new Char(codepoint, s); | |
} | |
return internedCache[codepoint]; | |
} | |
return new Char(codepoint, s); | |
} | |
/** | |
* @param {*} char | |
* @return {!boolean} | |
*/ | |
function check$2(_char) { | |
// Because Char is final, we can compare the constructor directly | |
// instead of using the much slower `instanceof` operator. | |
return _typeof2(_char) === 'object' && _char !== null && _char.constructor === Char; | |
} // NOTE: | |
// "The Racket documentation only promises `eq?` for characters with | |
// scalar values in the range 0 to 255, but Chez Scheme characters | |
// are always `eq?` when they are `eqv?`." | |
// see: https://groups.google.com/g/racket-users/c/LFFV-xNq1SU/m/s6eoC35qAgAJ | |
// https://docs.racket-lang.org/reference/characters.html | |
/** | |
* @param {!Char} a | |
* @param {!Char} b | |
* @return {!boolean} | |
*/ | |
function eq$1(a, b) { | |
return a.codepoint === b.codepoint; | |
} | |
var IS_GRAPHIC = new RegExp('[\\p{L}\\p{N}\\p{M}\\p{S}\\p{P}\\p{Alphabetic}]', 'u'); | |
var IS_BLANK = new RegExp('[\\p{Zs}\\t]', 'u'); | |
/** | |
* @param {!Char} c | |
* @return {!boolean} | |
*/ | |
function isGraphic(c) { | |
return IS_GRAPHIC.test(c.toString()); | |
} | |
/** | |
* @param {!Char} c | |
* @return {!boolean} | |
*/ | |
function isBlank(c) { | |
return IS_BLANK.test(c.toString()); | |
} // Copyright (C) 2016-2021 Matt Bierner, RacketScript Authors | |
// | |
// Original source and copyright clause: https://github.com/mattbierner/hamt_plus | |
var _typeof = typeof Symbol === 'function' && _typeof2(Symbol.iterator) === 'symbol' ? function (obj) { | |
return _typeof2(obj); | |
} : function (obj) { | |
return obj && typeof Symbol === 'function' && obj.constructor === Symbol && obj !== Symbol.prototype ? 'symbol' : _typeof2(obj); | |
}; | |
/** | |
@fileOverview Hash Array Mapped Trie. | |
Code based on: https://github.com/exclipy/pdata | |
*/ | |
var hamt = {}; // export | |
/* Configuration | |
***************************************************************************** */ | |
var SIZE = 5; | |
var BUCKET_SIZE = Math.pow(2, SIZE); | |
var MASK = BUCKET_SIZE - 1; | |
var MAX_INDEX_NODE = BUCKET_SIZE / 2; | |
var MIN_ARRAY_NODE = BUCKET_SIZE / 4; | |
/* | |
***************************************************************************** */ | |
var nothing = {}; | |
var constant = function constant(x) { | |
return function () { | |
return x; | |
}; | |
}; | |
/** | |
Get 32 bit hash of string. | |
Based on: | |
http://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript-jquery | |
*/ | |
hamt.hash = function (str) { | |
var type = typeof str === 'undefined' ? 'undefined' : _typeof(str); | |
if (type === 'number') return str; | |
if (type !== 'string') str += ''; | |
var hash = 0; | |
for (var i = 0, len = str.length; i < len; ++i) { | |
var c = str.charCodeAt(i); | |
hash = (hash << 5) - hash + c | 0; | |
} | |
return hash; | |
}; | |
/* Bit Ops | |
***************************************************************************** */ | |
/** | |
Hamming weight. | |
Taken from: http://jsperf.com/hamming-weight | |
*/ | |
var popcount = function popcount(x) { | |
x -= x >> 1 & 0x55555555; | |
x = (x & 0x33333333) + (x >> 2 & 0x33333333); | |
x = x + (x >> 4) & 0x0f0f0f0f; | |
x += x >> 8; | |
x += x >> 16; | |
return x & 0x7f; | |
}; | |
var hashFragment = function hashFragment(shift, h) { | |
return h >>> shift & MASK; | |
}; | |
var toBitmap = function toBitmap(x) { | |
return 1 << x; | |
}; | |
var fromBitmap = function fromBitmap(bitmap, bit) { | |
return popcount(bitmap & bit - 1); | |
}; | |
/* Array Ops | |
***************************************************************************** */ | |
/** | |
Set a value in an array. | |
@param mutate Should the input array be mutated? | |
@param at Index to change. | |
@param v New value | |
@param arr Array. | |
*/ | |
var arrayUpdate = function arrayUpdate(mutate, at, v, arr) { | |
var out = arr; | |
if (!mutate) { | |
var len = arr.length; | |
out = new Array(len); | |
for (var i = 0; i < len; ++i) { | |
out[i] = arr[i]; | |
} | |
} | |
out[at] = v; | |
return out; | |
}; | |
/** | |
Remove a value from an array. | |
@param mutate Should the input array be mutated? | |
@param at Index to remove. | |
@param arr Array. | |
*/ | |
var arraySpliceOut = function arraySpliceOut(mutate, at, arr) { | |
var newLen = arr.length - 1; | |
var i = 0; | |
var g = 0; | |
var out = arr; | |
if (mutate) { | |
i = at; | |
g = at; | |
} else { | |
out = new Array(newLen); | |
while (i < at) { | |
out[g++] = arr[i++]; | |
} | |
} | |
++i; | |
while (i <= newLen) { | |
out[g++] = arr[i++]; | |
} | |
if (mutate) { | |
out.length = newLen; | |
} | |
return out; | |
}; | |
/** | |
Insert a value into an array. | |
@param mutate Should the input array be mutated? | |
@param at Index to insert at. | |
@param v Value to insert, | |
@param arr Array. | |
*/ | |
var arraySpliceIn = function arraySpliceIn(mutate, at, v, arr) { | |
var len = arr.length; | |
if (mutate) { | |
var _i = len; | |
while (_i >= at) { | |
arr[_i--] = arr[_i]; | |
} | |
arr[at] = v; | |
return arr; | |
} | |
var i = 0; | |
var g = 0; | |
var out = new Array(len + 1); | |
while (i < at) { | |
out[g++] = arr[i++]; | |
} | |
out[at] = v; | |
while (i < len) { | |
out[++g] = arr[i++]; | |
} | |
return out; | |
}; | |
/* Node Structures | |
***************************************************************************** */ | |
var LEAF = 1; | |
var COLLISION = 2; | |
var INDEX = 3; | |
var ARRAY = 4; | |
/** | |
Empty node. | |
*/ | |
var empty = { | |
__hamt_isEmpty: true | |
}; | |
var isEmptyNode = function isEmptyNode(x) { | |
return x === empty || x && x.__hamt_isEmpty; | |
}; | |
/** | |
Leaf holding a value. | |
@member edit Edit of the node. | |
@member hash Hash of key. | |
@member key Key. | |
@member value Value stored. | |
*/ | |
var Leaf = function Leaf(edit, hash, key, value) { | |
return { | |
type: LEAF, | |
edit: edit, | |
hash: hash, | |
key: key, | |
value: value, | |
// eslint-disable-next-line no-use-before-define | |
_modify: LeafModify | |
}; | |
}; | |
/** | |
Leaf holding multiple values with the same hash but different keys. | |
@member edit Edit of the node. | |
@member hash Hash of key. | |
@member children Array of collision children node. | |
*/ | |
var Collision = function Collision(edit, hash, children) { | |
return { | |
type: COLLISION, | |
edit: edit, | |
hash: hash, | |
children: children, | |
// eslint-disable-next-line no-use-before-define | |
_modify: CollisionModify | |
}; | |
}; | |
/** | |
Internal node with a sparse set of children. | |
Uses a bitmap and array to pack children. | |
@member edit Edit of the node. | |
@member mask Bitmap that encode the positions of children in the array. | |
@member children Array of child nodes. | |
*/ | |
var IndexedNode = function IndexedNode(edit, mask, children) { | |
return { | |
type: INDEX, | |
edit: edit, | |
mask: mask, | |
children: children, | |
// eslint-disable-next-line no-use-before-define | |
_modify: IndexedNodeModify | |
}; | |
}; | |
/** | |
Internal node with many children. | |
@member edit Edit of the node. | |
@member size Number of children. | |
@member children Array of child nodes. | |
*/ | |
var ArrayNode = function ArrayNode(edit, size, children) { | |
return { | |
type: ARRAY, | |
edit: edit, | |
size: size, | |
children: children, | |
// eslint-disable-next-line no-use-before-define | |
_modify: ArrayNodeModify | |
}; | |
}; | |
/** | |
Is `node` a leaf node? | |
*/ | |
var isLeaf = function isLeaf(node) { | |
return node === empty || node.type === LEAF || node.type === COLLISION; | |
}; | |
/* Internal node operations. | |
***************************************************************************** */ | |
/** | |
Expand an indexed node into an array node. | |
@param edit Current edit. | |
@param frag Index of added child. | |
@param child Added child. | |
@param mask Index node mask before child added. | |
@param subNodes Index node children before child added. | |
*/ | |
var expand = function expand(edit, frag, child, bitmap, subNodes) { | |
var arr = []; | |
var bit = bitmap; | |
var count = 0; | |
for (var i = 0; bit; ++i) { | |
if (bit & 1) arr[i] = subNodes[count++]; | |
bit >>>= 1; | |
} | |
arr[frag] = child; | |
return ArrayNode(edit, count + 1, arr); | |
}; | |
/** | |
Collapse an array node into a indexed node. | |
@param edit Current edit. | |
@param count Number of elements in new array. | |
@param removed Index of removed element. | |
@param elements Array node children before remove. | |
*/ | |
var pack = function pack(edit, count, removed, elements) { | |
var children = new Array(count - 1); | |
var g = 0; | |
var bitmap = 0; | |
for (var i = 0, len = elements.length; i < len; ++i) { | |
if (i !== removed) { | |
var elem = elements[i]; | |
if (elem && !isEmptyNode(elem)) { | |
children[g++] = elem; | |
bitmap |= 1 << i; | |
} | |
} | |
} | |
return IndexedNode(edit, bitmap, children); | |
}; | |
/** | |
Merge two leaf nodes. | |
@param shift Current shift. | |
@param h1 Node 1 hash. | |
@param n1 Node 1. | |
@param h2 Node 2 hash. | |
@param n2 Node 2. | |
*/ | |
var mergeLeaves = function mergeLeaves(edit, shift, h1, n1, h2, n2) { | |
if (h1 === h2) return Collision(edit, h1, [n2, n1]); | |
var subH1 = hashFragment(shift, h1); | |
var subH2 = hashFragment(shift, h2); // eslint-disable-next-line no-nested-ternary,max-len | |
return IndexedNode(edit, toBitmap(subH1) | toBitmap(subH2), subH1 === subH2 ? [mergeLeaves(edit, shift + SIZE, h1, n1, h2, n2)] : subH1 < subH2 ? [n1, n2] : [n2, n1]); | |
}; | |
/** | |
Update an entry in a collision list. | |
@param mutate Should mutation be used? | |
@param edit Current edit. | |
@param keyEq Key compare function. | |
@param hash Hash of collision. | |
@param list Collision list. | |
@param f Update function. | |
@param k Key to update. | |
@param size Size ref. | |
*/ | |
var updateCollisionList = function updateCollisionList(mutate, edit, keyEq, h, list, f, k, size) { | |
var len = list.length; | |
for (var i = 0; i < len; ++i) { | |
var child = list[i]; | |
if (keyEq(k, child.key)) { | |
var value = child.value; | |
var _newValue = f(value); | |
if (_newValue === value) return list; | |
if (_newValue === nothing) { | |
--size.value; | |
return arraySpliceOut(mutate, i, list); | |
} | |
return arrayUpdate(mutate, i, Leaf(edit, h, k, _newValue), list); | |
} | |
} | |
var newValue = f(); | |
if (newValue === nothing) return list; | |
++size.value; | |
return arrayUpdate(mutate, len, Leaf(edit, h, k, newValue), list); | |
}; | |
var canEditNode = function canEditNode(edit, node) { | |
return edit === node.edit; | |
}; | |
/* Editing | |
***************************************************************************** */ | |
var LeafModify = function LeafModify(edit, keyEq, shift, f, h, k, size) { | |
if (keyEq(k, this.key)) { | |
var _v = f(this.value); | |
if (_v === this.value) return this;else if (_v === nothing) { | |
--size.value; | |
return empty; | |
} | |
if (canEditNode(edit, this)) { | |
this.value = _v; | |
return this; | |
} | |
return Leaf(edit, h, k, _v); | |
} | |
var v = f(); | |
if (v === nothing) return this; | |
++size.value; | |
return mergeLeaves(edit, shift, this.hash, this, h, Leaf(edit, h, k, v)); | |
}; | |
var CollisionModify = function CollisionModify(edit, keyEq, shift, f, h, k, size) { | |
if (h === this.hash) { | |
var canEdit = canEditNode(edit, this); | |
var list = updateCollisionList(canEdit, edit, keyEq, this.hash, this.children, f, k, size); | |
if (list === this.children) return this; | |
return list.length > 1 ? Collision(edit, this.hash, list) : list[0]; // collapse single element collision list | |
} | |
var v = f(); | |
if (v === nothing) return this; | |
++size.value; | |
return mergeLeaves(edit, shift, this.hash, this, h, Leaf(edit, h, k, v)); | |
}; | |
var IndexedNodeModify = function IndexedNodeModify(edit, keyEq, shift, f, h, k, size) { | |
var children = this.children, | |
mask = this.mask; | |
var frag = hashFragment(shift, h); | |
var bit = toBitmap(frag); | |
var indx = fromBitmap(mask, bit); | |
var exists = mask & bit; | |
var current = exists ? children[indx] : empty; | |
var child = current._modify(edit, keyEq, shift + SIZE, f, h, k, size); | |
if (current === child) return this; | |
var canEdit = canEditNode(edit, this); | |
var bitmap = mask; | |
var newChildren; | |
if (exists && isEmptyNode(child)) { | |
// remove | |
bitmap &= ~bit; | |
if (!bitmap) return empty; | |
if (children.length <= 2 && isLeaf(children[indx ^ 1])) return children[indx ^ 1]; // collapse | |
newChildren = arraySpliceOut(canEdit, indx, children); | |
} else if (!exists && !isEmptyNode(child)) { | |
// add | |
if (children.length >= MAX_INDEX_NODE) return expand(edit, frag, child, mask, children); | |
bitmap |= bit; | |
newChildren = arraySpliceIn(canEdit, indx, child, children); | |
} else { | |
// modify | |
newChildren = arrayUpdate(canEdit, indx, child, children); | |
} | |
if (canEdit) { | |
this.mask = bitmap; | |
this.children = newChildren; | |
return this; | |
} | |
return IndexedNode(edit, bitmap, newChildren); | |
}; | |
var ArrayNodeModify = function ArrayNodeModify(edit, keyEq, shift, f, h, k, size) { | |
var count = this.size; | |
var children = this.children; | |
var frag = hashFragment(shift, h); | |
var child = children[frag]; | |
var newChild = (child || empty)._modify(edit, keyEq, shift + SIZE, f, h, k, size); | |
if (child === newChild) return this; | |
var canEdit = canEditNode(edit, this); | |
var newChildren; | |
if (isEmptyNode(child) && !isEmptyNode(newChild)) { | |
// add | |
++count; | |
newChildren = arrayUpdate(canEdit, frag, newChild, children); | |
} else if (!isEmptyNode(child) && isEmptyNode(newChild)) { | |
// remove | |
--count; | |
if (count <= MIN_ARRAY_NODE) return pack(edit, count, frag, children); | |
newChildren = arrayUpdate(canEdit, frag, empty, children); | |
} else { | |
// modify | |
newChildren = arrayUpdate(canEdit, frag, newChild, children); | |
} | |
if (canEdit) { | |
this.size = count; | |
this.children = newChildren; | |
return this; | |
} | |
return ArrayNode(edit, count, newChildren); | |
}; | |
empty._modify = function (edit, keyEq, shift, f, h, k, size) { | |
var v = f(); | |
if (v === nothing) return empty; | |
++size.value; | |
return Leaf(edit, h, k, v); | |
}; | |
/* | |
***************************************************************************** */ | |
function Map$1(editable, edit, config, root, size) { | |
this._editable = editable; | |
this._edit = edit; | |
this._config = config; | |
this._root = root; | |
this._size = size; | |
} | |
Map$1.prototype.setTree = function (newRoot, newSize) { | |
if (this._editable) { | |
this._root = newRoot; | |
this._size = newSize; | |
return this; | |
} | |
return newRoot === this._root ? this : new Map$1(this._editable, this._edit, this._config, newRoot, newSize); | |
}; | |
/* Queries | |
***************************************************************************** */ | |
/** | |
Lookup the value for `key` in `map` using a custom `hash`. | |
Returns the value or `alt` if none. | |
*/ | |
hamt.tryGetHash = function (alt, hash, key, map) { | |
var node = map._root; | |
var shift = 0; | |
var keyEq = map._config.keyEq; | |
while (true) { | |
switch (node.type) { | |
case LEAF: | |
{ | |
return keyEq(key, node.key) ? node.value : alt; | |
} | |
case COLLISION: | |
{ | |
if (hash === node.hash) { | |
for (var i = 0, len = node.children.length; i < len; ++i) { | |
var child = node.children[i]; | |
if (keyEq(key, child.key)) return child.value; | |
} | |
} | |
return alt; | |
} | |
case INDEX: | |
{ | |
var frag = hashFragment(shift, hash); | |
var bit = toBitmap(frag); | |
if (node.mask & bit) { | |
node = node.children[fromBitmap(node.mask, bit)]; | |
shift += SIZE; | |
break; | |
} | |
return alt; | |
} | |
case ARRAY: | |
{ | |
node = node.children[hashFragment(shift, hash)]; | |
if (node) { | |
shift += SIZE; | |
break; | |
} | |
return alt; | |
} | |
default: | |
return alt; | |
} | |
} | |
}; | |
Map$1.prototype.tryGetHash = function (alt, hash, key) { | |
return hamt.tryGetHash(alt, hash, key, this); | |
}; | |
/** | |
Lookup the value for `key` in `map` using internal hash function. | |
@see `tryGetHash` | |
*/ | |
hamt.tryGet = function (alt, key, map) { | |
return hamt.tryGetHash(alt, map._config.hash(key), key, map); | |
}; | |
Map$1.prototype.tryGet = function (alt, key) { | |
return hamt.tryGet(alt, key, this); | |
}; | |
/** | |
Lookup the value for `key` in `map` using a custom `hash`. | |
Returns the value or `undefined` if none. | |
*/ | |
hamt.getHash = function (hash, key, map) { | |
return hamt.tryGetHash(undefined, hash, key, map); | |
}; | |
Map$1.prototype.getHash = function (hash, key) { | |
return hamt.getHash(hash, key, this); | |
}; | |
/** | |
Lookup the value for `key` in `map` using internal hash function. | |
@see `get` | |
*/ | |
hamt.get = function (key, map) { | |
return hamt.tryGetHash(undefined, map._config.hash(key), key, map); | |
}; | |
Map$1.prototype.get = function (key, alt) { | |
return hamt.tryGet(alt, key, this); | |
}; | |
/** | |
Does an entry exist for `key` in `map`? Uses custom `hash`. | |
*/ | |
hamt.hasHash = function (hash, key, map) { | |
return hamt.tryGetHash(nothing, hash, key, map) !== nothing; | |
}; | |
Map$1.prototype.hasHash = function (hash, key) { | |
return hamt.hasHash(hash, key, this); | |
}; | |
/** | |
Does an entry exist for `key` in `map`? Uses internal hash function. | |
*/ | |
var has = function has(key, map) { | |
return hamt.hasHash(map._config.hash(key), key, map); | |
}; | |
Map$1.prototype.has = function (key) { | |
return has(key, this); | |
}; | |
var defKeyCompare = function defKeyCompare(x, y) { | |
return x === y; | |
}; | |
/** | |
Create an empty map. | |
@param config Configuration. | |
*/ | |
hamt.make = function (config) { | |
return new Map$1(0, 0, { | |
keyEq: config && config.keyEq || defKeyCompare, | |
hash: config && config.hash || hamt.hash | |
}, empty, 0); | |
}; | |
/** | |
Empty map. | |
*/ | |
hamt.empty = hamt.make(); | |
/** | |
Does `map` contain any elements? | |
*/ | |
hamt.isEmpty = function (map) { | |
return map && !!isEmptyNode(map._root); | |
}; | |
Map$1.prototype.isEmpty = function () { | |
return hamt.isEmpty(this); | |
}; | |
/* Updates | |
***************************************************************************** */ | |
/** | |
Alter the value stored for `key` in `map` using function `f` using | |
custom hash. | |
`f` is invoked with the current value for `k` if it exists, | |
or no arguments if no such value exists. `modify` will always either | |
update or insert a value into the map. | |
Returns a map with the modified value. Does not alter `map`. | |
*/ | |
hamt.modifyHash = function (f, hash, key, map) { | |
var size = { | |
value: map._size | |
}; | |
var newRoot = map._root._modify(map._editable ? map._edit : NaN, map._config.keyEq, 0, f, hash, key, size); | |
return map.setTree(newRoot, size.value); | |
}; | |
Map$1.prototype.modifyHash = function (hash, key, f) { | |
return hamt.modifyHash(f, hash, key, this); | |
}; | |
/** | |
Alter the value stored for `key` in `map` using function `f` using | |
internal hash function. | |
@see `modifyHash` | |
*/ | |
hamt.modify = function (f, key, map) { | |
return hamt.modifyHash(f, map._config.hash(key), key, map); | |
}; | |
Map$1.prototype.modify = function (key, f) { | |
return hamt.modify(f, key, this); | |
}; | |
/** | |
Store `value` for `key` in `map` using custom `hash`. | |
Returns a map with the modified value. Does not alter `map`. | |
*/ | |
hamt.setHash = function (hash, key, value, map) { | |
return hamt.modifyHash(constant(value), hash, key, map); | |
}; | |
Map$1.prototype.setHash = function (hash, key, value) { | |
return hamt.setHash(hash, key, value, this); | |
}; | |
/** | |
Store `value` for `key` in `map` using internal hash function. | |
@see `setHash` | |
*/ | |
hamt.set = function (key, value, map) { | |
return hamt.setHash(map._config.hash(key), key, value, map); | |
}; | |
Map$1.prototype.set = function (key, value) { | |
return hamt.set(key, value, this); | |
}; | |
/** | |
Remove the entry for `key` in `map`. | |
Returns a map with the value removed. Does not alter `map`. | |
*/ | |
var del = constant(nothing); | |
hamt.removeHash = function (hash, key, map) { | |
return hamt.modifyHash(del, hash, key, map); | |
}; | |
Map$1.prototype.removeHash = function (hash, key) { | |
return hamt.removeHash(hash, key, this); | |
}; | |
Map$1.prototype.deleteHash = Map$1.prototype.removeHash; | |
/** | |
Remove the entry for `key` in `map` using internal hash function. | |
@see `removeHash` | |
*/ | |
hamt.remove = function (key, map) { | |
return hamt.removeHash(map._config.hash(key), key, map); | |
}; | |
Map$1.prototype.remove = function (key) { | |
return hamt.remove(key, this); | |
}; | |
Map$1.prototype["delete"] = Map$1.prototype.remove; | |
/* Mutation | |
***************************************************************************** */ | |
/** | |
Mark `map` as mutable. | |
*/ | |
hamt.beginMutation = function (map) { | |
return new Map$1(map._editable + 1, map._edit + 1, map._config, map._root, map._size); | |
}; | |
Map$1.prototype.beginMutation = function () { | |
return hamt.beginMutation(this); | |
}; | |
/** | |
Mark `map` as immutable. | |
*/ | |
hamt.endMutation = function (map) { | |
map._editable = map._editable && map._editable - 1; | |
return map; | |
}; | |
Map$1.prototype.endMutation = function () { | |
return hamt.endMutation(this); | |
}; | |
/** | |
Mutate `map` within the context of `f`. | |
@param f | |
@param map HAMT | |
*/ | |
hamt.mutate = function (f, map) { | |
var _transient = hamt.beginMutation(map); | |
f(_transient); | |
return hamt.endMutation(_transient); | |
}; | |
Map$1.prototype.mutate = function (f) { | |
return hamt.mutate(f, this); | |
}; | |
/* Traversal | |
***************************************************************************** */ | |
/** | |
Apply a continuation. | |
*/ | |
var appk = function appk(k) { | |
// eslint-disable-next-line no-use-before-define | |
return k && lazyVisitChildren(k[0], k[1], k[2], k[3], k[4]); | |
}; | |
/** | |
Recursively visit all values stored in an array of nodes lazily. | |
*/ | |
var lazyVisitChildren = function lazyVisitChildren(len, children, i, f, k) { | |
while (i < len) { | |
var child = children[i++]; // eslint-disable-next-line no-use-before-define | |
if (child && !isEmptyNode(child)) return lazyVisit(child, f, [len, children, i, f, k]); | |
} | |
return appk(k); | |
}; | |
/** | |
Recursively visit all values stored in `node` lazily. | |
*/ | |
var lazyVisit = function lazyVisit(node, f, k) { | |
switch (node.type) { | |
case LEAF: | |
return { | |
value: f(node), | |
rest: k | |
}; | |
case COLLISION: | |
case ARRAY: | |
case INDEX: | |
return lazyVisitChildren(node.children.length, node.children, 0, f, k); | |
default: | |
return appk(k); | |
} | |
}; | |
var DONE = { | |
done: true | |
}; | |
/** | |
Javascript iterator over a map. | |
*/ | |
function MapIterator(v) { | |
this.v = v; | |
} | |
MapIterator.prototype.next = function () { | |
if (!this.v) return DONE; | |
var v0 = this.v; | |
this.v = appk(v0.rest); | |
return v0; | |
}; | |
MapIterator.prototype[Symbol.iterator] = function () { | |
return this; | |
}; | |
/** | |
Lazily visit each value in map with function `f`. | |
*/ | |
var visit = function visit(map, f) { | |
return new MapIterator(lazyVisit(map._root, f)); | |
}; | |
/** | |
Get a Javascsript iterator of `map`. | |
Iterates over `[key, value]` arrays. | |
*/ | |
hamt.entries = function (map) { | |
return visit(map, function (x) { | |
return [x.key, x.value]; | |
}); | |
}; | |
Map$1.prototype.entries = function () { | |
return hamt.entries(this); | |
}; | |
Map$1.prototype[Symbol.iterator] = Map$1.prototype.entries; | |
/** | |
Get array of all keys in `map`. | |
Order is not guaranteed. | |
*/ | |
hamt.keys = function (map) { | |
return visit(map, function (x) { | |
return x.key; | |
}); | |
}; | |
Map$1.prototype.keys = function () { | |
return hamt.keys(this); | |
}; | |
/** | |
Get array of all values in `map`. | |
Order is not guaranteed, duplicates are preserved. | |
*/ | |
hamt.values = function (map) { | |
return visit(map, function (x) { | |
return x.value; | |
}); | |
}; | |
Map$1.prototype.values = function () { | |
return hamt.values(this); | |
}; | |
/* Fold | |
***************************************************************************** */ | |
/** | |
Visit every entry in the map, aggregating data. | |
Order of nodes is not guaranteed. | |
@param f Function mapping accumulated value, value, and key to new value. | |
@param z Starting value. | |
@param m HAMT | |
*/ | |
hamt.fold = function (f, z, m) { | |
var root = m._root; | |
if (root.type === LEAF) return f(z, root.value, root.key); | |
var toVisit = [root.children]; | |
var children = toVisit.pop(); | |
while (children) { | |
for (var i = 0, len = children.length; i < len;) { | |
var child = children[i++]; | |
if (child && child.type) { | |
if (child.type === LEAF) z = f(z, child.value, child.key);else toVisit.push(child.children); | |
} | |
} | |
children = toVisit.pop(); | |
} | |
return z; | |
}; | |
Map$1.prototype.fold = function (f, z) { | |
return hamt.fold(f, z, this); | |
}; | |
/** | |
Visit every entry in the map, aggregating data. | |
Order of nodes is not guaranteed. | |
@param f Function invoked with value and key | |
@param map HAMT | |
*/ | |
hamt.forEach = function (f, map) { | |
return hamt.fold(function (_, value, key) { | |
return f(value, key, map); | |
}, null, map); | |
}; | |
Map$1.prototype.forEach = function (f) { | |
return hamt.forEach(f, this); | |
}; | |
/* Aggregate | |
***************************************************************************** */ | |
/** | |
Get the number of entries in `map`. | |
*/ | |
hamt.count = function (map) { | |
return map._size; | |
}; | |
Map$1.prototype.count = function () { | |
return hamt.count(this); | |
}; | |
Object.defineProperty(Map$1.prototype, 'size', { | |
get: Map$1.prototype.count | |
}); // # sourceMappingURL=hamt.js.map | |
/* --------------------------------------------------------------------------*/ | |
/* Other Helpers */ | |
function argumentsToArray(args) { | |
return Array.prototype.slice.call(args, 0); | |
} | |
function attachReadOnlyProperty(o, k, v) { | |
return Object.defineProperty(o, k, { | |
value: v, | |
writable: false, | |
configurable: false | |
}); | |
} | |
/** | |
* @param {function(String|UString.UString)} f | |
* @return {function(String)} | |
*/ | |
function internedMake(f) { | |
var cache = new Map(); | |
return function (v) { | |
v = v.toString(); | |
var result = cache.get(v); | |
if (result === undefined) { | |
result = f(v); | |
cache.set(v, result); | |
} | |
return result; | |
}; | |
} | |
/** | |
* A sequence of {Char.Char}s. | |
* | |
* See {Char.Char} for implementation notes. | |
* | |
* @abstract | |
*/ | |
var UString = /*#__PURE__*/function (_Primitive2) { | |
_inherits(UString, _Primitive2); | |
var _super2 = _createSuper(UString); | |
/** | |
* @param {!Char.Char[]} chars | |
* @param {(string|null)} nativeString | |
* @private | |
*/ | |
function UString(chars, nativeString) { | |
var _this2; | |
_classCallCheck(this, UString); | |
_this2 = _super2.call(this); | |
_this2.chars = chars; | |
_this2._nativeString = nativeString; | |
_this2._cachedHashCode = null; | |
return _this2; | |
} | |
/** | |
* @return {!number} | |
*/ | |
_createClass(UString, [{ | |
key: "length", | |
get: function get() { | |
return this.chars.length; | |
} | |
/** | |
* @return {!string} | |
*/ | |
}, { | |
key: "toString", | |
value: function toString() { | |
if (this._nativeString === null) { | |
this._nativeString = this.chars.join(''); | |
} | |
return this._nativeString; | |
} | |
/** | |
* @param {!number} i | |
* @return {!Char.Char} | |
*/ | |
}, { | |
key: "charAt", | |
value: function charAt(i) { | |
return this.chars[i]; | |
} | |
/** | |
* @return {!MutableUString} | |
*/ | |
}, { | |
key: "toLowerCase", | |
value: function toLowerCase() { | |
// TODO: Improve Racket compatibility. | |
return makeMutable(this.toString().toLowerCase()); | |
} | |
/** | |
* @return {!MutableUString} | |
*/ | |
}, { | |
key: "toUpperCase", | |
value: function toUpperCase() { | |
// TODO: Improve Racket compatibility. | |
return makeMutable(this.toString().toUpperCase()); | |
} | |
/** | |
* @param {!number} start | |
* @param {!number} end | |
* @return {!MutableUString} | |
*/ | |
}, { | |
key: "substring", | |
value: function substring(start, end) { | |
// RacketScript guarantees: | |
// start >= 0, end >= 0, end <= length, end >= start. | |
// This might be faster if we keep the indices with the chars. | |
return new MutableUString(this.chars.slice(start, end), null); | |
} | |
/** | |
* @param {!(string|RegExp)} sep | |
*/ | |
}, { | |
key: "split", | |
value: function split(sep) { | |
// Known issue: if sep is a regex, it will not support Unicode fully. | |
return this.toString().split(sep).map(function (s) { | |
return makeMutable(s); | |
}); | |
} | |
/** | |
* @param {!number} i | |
*/ | |
}, { | |
key: "isValidIndex", | |
value: function isValidIndex(i) { | |
return i < this.length; | |
} | |
/** | |
* @param {!number} i | |
*/ | |
}, { | |
key: "isEmpty", | |
value: function isEmpty() { | |
return this.length === 0; | |
} | |
/** | |
* Warning: JavaScript string comparison does not work correctly | |
* for Unicode strings with non-BMP characters. | |
* | |
* @return {!string} | |
*/ | |
}, { | |
key: "valueOf", | |
value: function valueOf() { | |
return this.toString(); | |
} | |
/** | |
* @param {*} v | |
* @return {!boolean} | |
*/ | |
}, { | |
key: "equals", | |
value: function equals(v) { | |
return check$3(v) && this.toString() === v.toString(); | |
} | |
/** | |
* @return {!number} a 32-bit integer | |
*/ | |
}, { | |
key: "hashForEqual", | |
value: function hashForEqual() { | |
if (this._cachedHashCode === null) { | |
this._cachedHashCode = hashIntArray(this.chars); | |
} | |
return this._cachedHashCode; | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "displayNativeString", | |
value: function displayNativeString(out) { | |
out.consume(this.toString()); | |
} | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "displayUString", | |
value: function displayUString(out) { | |
out.consume(this); | |
} | |
/** | |
* Writes a string representation that can be read by Racket's `read` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "writeNativeString", | |
value: function writeNativeString(out) { | |
// The JSON representation happens to be readable by Racket's `read`. | |
out.consume('"'); | |
var _iterator = _createForOfIteratorHelper(this.chars), | |
_step; | |
try { | |
for (_iterator.s(); !(_step = _iterator.n()).done;) { | |
var _char2 = _step.value; | |
var c = _char2.codepoint; | |
switch (c) { | |
// Reference implementation: | |
// https://github.com/racket/racket/blob/cbfcc904ab621a338627e77d8f5a34f930ead0ab/racket/src/racket/src/print.c#L3690 | |
case 7: | |
out.consume('\\a'); | |
break; | |
case 8: | |
out.consume('\\b'); | |
break; | |
case 9: | |
out.consume('\\t'); | |
break; | |
case 11: | |
out.consume('\\v'); | |
break; | |
case 12: | |
out.consume('\\f'); | |
break; | |
case 10: | |
out.consume('\\n'); | |
break; | |
case 13: | |
out.consume('\\r'); | |
break; | |
case 27: | |
out.consume('\\e'); | |
break; | |
case 34: | |
out.consume('\\"'); | |
break; | |
case 92: | |
out.consume('\\\\'); | |
break; | |
default: | |
if (isGraphic(_char2) || isBlank(_char2)) { | |
out.consume(_char2.toString()); | |
} else { | |
out.consume(c > 0xFFFF ? "\\U".concat(c.toString(16).toUpperCase().padStart(8, '0')) : "\\u".concat(c.toString(16).toUpperCase().padStart(4, '0'))); | |
} | |
} | |
} | |
} catch (err) { | |
_iterator.e(err); | |
} finally { | |
_iterator.f(); | |
} | |
out.consume('"'); | |
} | |
/** | |
* Writes a UString representation that can be read by Racket's `read` to the given port. | |
* | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "writeUString", | |
value: function writeUString(out) { | |
var stringOut = new MiniNativeOutputStringPort(); | |
this.writeNativeString(stringOut); | |
out.consume(makeMutable(stringOut.getOutputString())); | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "printNativeString", | |
value: function printNativeString(out) { | |
this.writeNativeString(out); | |
} | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "printUString", | |
value: function printUString(out) { | |
this.writeUString(out); | |
} | |
/** | |
* Whether the string can be parsed as an integer as defined by | |
* Racket's string->number. | |
* | |
* @param {!number} radix an integer in [2, 16] range. | |
* @return {!boolean} | |
*/ | |
}, { | |
key: "isValidInteger", | |
value: function isValidInteger(radix) { | |
var startFrom = this.chars[0].codepoint === | |
/* '-' */ | |
45 ? 1 : 0; | |
if (radix > 10) { | |
var maxLowercase = | |
/* 'a' - 11 */ | |
86 + radix; | |
var maxUppercase = maxLowercase - 32; | |
for (var i = startFrom; i < this.chars.length; ++i) { | |
var cp = this.chars[i].codepoint; | |
if (cp < | |
/* '0' */ | |
48 || cp > maxLowercase || cp > maxUppercase && cp < | |
/* 'a' */ | |
97 || cp > | |
/* '9' */ | |
57 && cp < | |
/* 'A' */ | |
65) return false; | |
} | |
} else { | |
var max = | |
/* '0' - 1 */ | |
47 + radix; | |
for (var _i2 = startFrom; _i2 < this.chars.length; ++_i2) { | |
var _cp = this.chars[_i2].codepoint; | |
if (_cp < | |
/* '0' */ | |
48 || _cp > max) return false; | |
} | |
} | |
return true; | |
} | |
}]); | |
return UString; | |
}(Primitive | |
/* implements Printable */ | |
); | |
/** | |
* An immutable sequence of {Char.Char}s. | |
*/ | |
var ImmutableUString = /*#__PURE__*/function (_UString) { | |
_inherits(ImmutableUString, _UString); | |
var _super3 = _createSuper(ImmutableUString); | |
function ImmutableUString() { | |
_classCallCheck(this, ImmutableUString); | |
return _super3.apply(this, arguments); | |
} | |
_createClass(ImmutableUString, [{ | |
key: "isImmutable", | |
value: | |
/** | |
* @return {true} | |
*/ | |
function isImmutable() { | |
return true; | |
} | |
}]); | |
return ImmutableUString; | |
}(UString); | |
/** | |
* An immutable sequence of {Char.Char}s. | |
* All {Char.Char}s must be in the BMP Unicode plane. | |
* | |
* See {Char.Char} for implementation notes. | |
*/ | |
var ImmutableBMPString = /*#__PURE__*/function (_ImmutableUString) { | |
_inherits(ImmutableBMPString, _ImmutableUString); | |
var _super4 = _createSuper(ImmutableBMPString); | |
function ImmutableBMPString() { | |
_classCallCheck(this, ImmutableBMPString); | |
return _super4.apply(this, arguments); | |
} | |
_createClass(ImmutableBMPString, [{ | |
key: "substring", | |
value: | |
/** | |
* @param {!number} start | |
* @param {!number} end | |
* @return {!MutableUString} | |
* @override | |
*/ | |
function substring(start, end) { | |
return new MutableUString(this.chars.slice(start, end), this.toString().substring(start, end)); | |
} | |
/** | |
* Writes a string representation that can be read by Racket's `read` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "writeNativeString", | |
value: function writeNativeString(out) { | |
// The JSON representation for BMP strings happens to be readable by Racket's `read`. | |
out.consume(JSON.stringify(this.toString())); | |
} | |
}]); | |
return ImmutableBMPString; | |
}(ImmutableUString); | |
/** | |
* An mutable sequence of {Char.Char}s. | |
*/ | |
var MutableUString = /*#__PURE__*/function (_UString2) { | |
_inherits(MutableUString, _UString2); | |
var _super5 = _createSuper(MutableUString); | |
function MutableUString() { | |
_classCallCheck(this, MutableUString); | |
return _super5.apply(this, arguments); | |
} | |
_createClass(MutableUString, [{ | |
key: "isImmutable", | |
value: | |
/** | |
* @return {false} | |
*/ | |
function isImmutable() { | |
return false; | |
} | |
}, { | |
key: "setCharAt", | |
value: function setCharAt(i, _char3) { | |
if (!eq$1(_char3, this.chars[i])) { | |
this.chars[i] = _char3; | |
this._nativeString = null; | |
this._cachedHashCode = null; | |
} | |
} | |
}]); | |
return MutableUString; | |
}(UString); | |
/** | |
* @param {!string} nativeString | |
* @return {!Char.Char[]} | |
*/ | |
function nativeStringToChars(nativeString) { | |
// Array.from splits on codepoints (as per the String iterator spec). | |
return Array.from(nativeString, charFromNativeString); | |
} | |
/** | |
* @param {!string} nativeString | |
* @return {!ImmutableUString} | |
*/ | |
var makeInternedImmutable = internedMake(function (nativeString) { | |
return makeImmutable(nativeString); | |
}); | |
/** | |
* @param {!string} nativeString | |
* @return {!ImmutableUString} | |
*/ | |
var make$1 = makeInternedImmutable; | |
/** | |
* @param {!string} nativeString | |
* @return {!ImmutableUString} | |
*/ | |
function makeImmutable(nativeString) { | |
return makeImmutableFromCharsAndNativeString(nativeStringToChars(nativeString), nativeString); | |
} | |
/** | |
* @param {!Char.Char[]} chars | |
* @param {!string} nativeString | |
* @return {!ImmutableUString} | |
*/ | |
function makeImmutableFromCharsAndNativeString(chars, nativeString) { | |
return chars.length === nativeString.length ? new ImmutableBMPString(chars, nativeString) : new ImmutableUString(chars, nativeString); | |
} | |
/** | |
* @param {!string} nativeString | |
* @return {!MutableUString} | |
*/ | |
function makeMutable(nativeString) { | |
return new MutableUString(nativeStringToChars(nativeString), nativeString); | |
} | |
/** | |
* @param {!Char.Char[]} chars | |
* @return {!MutableUString} | |
*/ | |
function makeMutableFromChars(chars) { | |
return new MutableUString(chars, null); | |
} | |
/** | |
* @param {!UString} str | |
* @return {!MutableUString} | |
*/ | |
function copyAsMutable(str) { | |
return new MutableUString(str.chars, str._nativeString); | |
} | |
function makeMutableFromCharsVarArgs() { | |
for (var _len = arguments.length, chars = new Array(_len), _key = 0; _key < _len; _key++) { | |
chars[_key] = arguments[_key]; | |
} | |
return makeMutableFromChars(chars); | |
} | |
/** | |
* @param {!UString} v | |
* @return {!ImmutableUString} | |
*/ | |
function stringToImmutableString(v) { | |
return v instanceof ImmutableUString ? v : makeImmutableFromCharsAndNativeString(v.chars, v.toString()); | |
} | |
/** | |
* @param {*} v | |
* @return {!boolean} | |
*/ | |
function check$3(v) { | |
return v instanceof UString; | |
} | |
/** | |
* @param {!number} k | |
* @param {!Char.Char} c | |
*/ | |
function repeatChar(k, c) { | |
var chars = new Array(k); | |
chars.fill(c.toString()); | |
return new MutableUString(chars, null); | |
} | |
new TextEncoder(); | |
/** | |
* @param {!UString[]} strs | |
* @return {!MutableUString} | |
*/ | |
function stringAppend() { | |
var _ref; | |
for (var _len2 = arguments.length, strs = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | |
strs[_key2] = arguments[_key2]; | |
} | |
return makeMutableFromChars((_ref = []).concat.apply(_ref, _toConsumableArray(strs.map(function (s) { | |
return s.chars; | |
})))); | |
} // The Char Printable *UString methods are defined here, | |
// because Char cannot depend on UString. | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
Char.prototype.displayUString = function (out) { | |
out.consume(new MutableUString([this], this._nativeString)); | |
}; | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
Char.prototype.writeUString = function (out) { | |
var stringOut = new MiniNativeOutputStringPort(); | |
this.writeNativeString(stringOut); | |
out.consume(makeMutable(stringOut.getOutputString())); | |
}; // PrintablePrimitive subclass avoids circular dependency with UString and Ports. | |
var PRINT_PREFIX_USTRING = makeInternedImmutable("'"); | |
var PrintablePrimitive = /*#__PURE__*/function (_Primitive3) { | |
_inherits(PrintablePrimitive, _Primitive3); | |
var _super6 = _createSuper(PrintablePrimitive); | |
function PrintablePrimitive() { | |
_classCallCheck(this, PrintablePrimitive); | |
return _super6.apply(this, arguments); | |
} | |
_createClass(PrintablePrimitive, [{ | |
key: "displayUString", | |
value: | |
/** | |
* Writes a String representation similar to Racket's `display` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
/* abstract displayNativeString(out); */ | |
/** | |
* Writes a UString representation similar to Racket's `display` to the given port. | |
* | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
function displayUString(out) { | |
var stringOut = new MiniNativeOutputStringPort(); | |
this.displayNativeString(stringOut); | |
out.consume(makeMutable(stringOut.getOutputString())); | |
} | |
/** | |
* Writes a string representation that can be read by Racket's `read` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "writeNativeString", | |
value: function writeNativeString(out) { | |
this.displayNativeString(out); | |
} | |
/** | |
* Writes a UString representation that can be read by Racket's `read` to the given port. | |
* | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "writeUString", | |
value: function writeUString(out) { | |
var stringOut = new MiniNativeOutputStringPort(); | |
this.writeNativeString(stringOut); | |
out.consume(makeMutable(stringOut.getOutputString())); | |
} | |
/** | |
* Writes a string representation similar to Racket's `print` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "printNativeString", | |
value: function printNativeString(out) { | |
out.consume("'"); | |
this.writeNativeString(out); | |
} | |
/** | |
* Writes a UString representation similar to Racket's `print` to the given port. | |
* | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "printUString", | |
value: function printUString(out) { | |
out.consume(PRINT_PREFIX_USTRING); | |
this.writeUString(out); | |
} | |
/** | |
* @return {!String} a string representation similar to Racket's `display`. | |
*/ | |
}, { | |
key: "toString", | |
value: function toString() { | |
var out = new MiniNativeOutputStringPort(); | |
this.displayNativeString(out); | |
return out.getOutputString(); | |
} | |
}]); | |
return PrintablePrimitive; | |
}(Primitive | |
/* implements Printable */ | |
); | |
var counter = 0; | |
var PrimitiveSymbol = /*#__PURE__*/function (_PrintablePrimitive, _Symbol$toPrimitive) { | |
_inherits(PrimitiveSymbol, _PrintablePrimitive); | |
var _super7 = _createSuper(PrimitiveSymbol); | |
function PrimitiveSymbol(name) { | |
var _this3; | |
_classCallCheck(this, PrimitiveSymbol); | |
_this3 = _super7.call(this); | |
if (name) { | |
// interned | |
_this3.name = name; | |
_this3.sym = Symbol["for"](name); | |
} else { | |
// uninterned | |
_this3.sym = Symbol("_".concat(counter++)); | |
} | |
return _this3; | |
} | |
_createClass(PrimitiveSymbol, [{ | |
key: "isInterned", | |
get: function get() { | |
return Boolean(this.name); | |
} | |
}, { | |
key: "value", | |
get: function get() { | |
return this.sym; | |
} | |
}, { | |
key: "equals", | |
value: function equals(s) { | |
if (s.sym) { | |
return s.value === this.value; | |
} | |
return s === this.value; | |
} | |
}, { | |
key: "lt", | |
value: function lt(s) { | |
if (s === this) { | |
return false; | |
} | |
return this.toString() < s.toString(); | |
} | |
}, { | |
key: "hashForEqual", | |
value: function hashForEqual() { | |
return hashString(this.toString()); | |
} | |
/* String printing */ | |
}, { | |
key: _Symbol$toPrimitive, | |
value: function value(hint) { | |
if (hint === 'number') { | |
return 0; | |
} | |
return this.toString(); | |
} | |
}, { | |
key: "displayNativeString", | |
value: function displayNativeString(out) { | |
if (this.isInterned) { | |
out.consume(Symbol.keyFor(this.sym)); | |
} else { | |
out.consume(this.sym.toString()); | |
} | |
} | |
}]); | |
return PrimitiveSymbol; | |
}(PrintablePrimitive, Symbol.toPrimitive); | |
function make$2(v) { | |
return new PrimitiveSymbol(v ? v.toString() : ''); | |
} | |
function check$4(v) { | |
return v instanceof PrimitiveSymbol; | |
} | |
/** | |
* @param {*} v1 | |
* @param {*} v2 | |
* @return {!boolean} | |
*/ | |
function isEq(v1, v2) { | |
// Handle Symbols | |
if (check$4(v1)) { | |
return v1.equals(v2); | |
} | |
return v1 === v2; | |
} | |
/** | |
* @param {*} v1 | |
* @param {*} v2 | |
* @return {!boolean} | |
*/ | |
function isEqual(v1, v2) { | |
if (v1 === v2) return true; | |
if (check(v1)) return v1.equals(v2); // Bytes are not a Primitive. | |
if (check$1(v1) && check$1(v2)) return eq(v1, v2); | |
return false; | |
} | |
/** | |
* @param {*} o | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashForEq(o) { | |
return hash(o); | |
} | |
/** | |
* @param {*} o | |
* @return {!number} a 32-bit integer | |
*/ | |
function hashForEqual$1(o) { | |
if (check(o)) return o.hashForEqual(); | |
if (check$1(o)) return hashForEqual(o); | |
return hash(o); | |
} | |
/** | |
* @param {!Function} fn | |
* @param {*} arity | |
*/ | |
// arity is either: | |
// - array of exact arities, | |
// - a number, meaning "arity of at least" | |
function attachProcedureArity(fn, arity) { | |
fn.__rjs_arityValue = arity || fn.length; | |
return fn; | |
} | |
/** | |
* @param {!Function} fn | |
* @param {!String} name | |
*/ | |
// need this to get some fns to print correct Racket name, | |
// eg "cons" instead of "makePair" | |
function attachProcedureName(fn, name) { | |
fn.__rjs_name = name; | |
return fn; | |
} | |
/** | |
* @param {*} v | |
* @return {!boolean} | |
*/ | |
function check$5(v) { | |
return typeof v === 'function'; | |
} | |
/** | |
* @param {!Function} f | |
* @return {!String} A string representation similar to Racket's `display`. | |
*/ | |
function toString$1(f) { | |
var notRjsName = f.name ? "#<procedure:".concat(f.name, ">") : '#<procedure>'; | |
return f.__rjs_name ? "#<procedure:".concat(f.__rjs_name, ">") : notRjsName; | |
} | |
/** | |
* Writes a string representation similar to Racket's `display` to the given port. | |
* | |
* @param {!Ports.NativeStringOutputPort} out | |
* @param {!Function} f | |
*/ | |
function displayNativeString$1(out, f) { | |
out.consume(toString$1(f)); | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
* @param {!(Primitive.Primitive|Uint8Array|Function|String|number|boolean|undefined|null)} v | |
*/ | |
function displayNativeString$2(out, v) { | |
if (v === true) { | |
out.consume('#t'); | |
} else if (v === false) { | |
out.consume('#f'); | |
} else if (v === undefined || v === null) { | |
out.consume('#<void>'); | |
} else if (check(v)) { | |
v.displayNativeString(out); | |
} else if (check$1(v)) { | |
displayNativeString(out, v); | |
} else if (check$5(v)) { | |
if (v.__rjs_struct_object) { | |
v.__rjs_struct_object.displayNativeString(out); | |
} else { | |
displayNativeString$1(out, v); | |
} | |
} else | |
/* if (typeof v === 'number' || typeof v === 'string') */ | |
{ | |
out.consume(v.toString()); | |
} | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
* @param {!(Primitive.Primitive|Uint8Array|Function|String|number|boolean|undefined|null)} v | |
*/ | |
function _writeNativeString(out, v) { | |
if (check(v)) { | |
// Assume `v` implements Printable, as only Values does not, | |
// and it cannot be passed here. | |
v.writeNativeString(out); | |
} else { | |
displayNativeString$2(out, v); | |
} | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
* @param {!(Primitive.Primitive|Uint8Array|Function|String|number|boolean|undefined|null)} v | |
* @param {!boolean} printAsExpression | |
* @param {!(0|1)} quoteDepth | |
*/ | |
function printNativeString$1(out, v, printAsExpression, quoteDepth) { | |
if (printAsExpression && quoteDepth !== 1 && check(v)) { | |
v.printNativeString(out); | |
} else if (check$1(v)) { | |
printNativeString(out, v); | |
} else { | |
_writeNativeString(out, v); | |
} | |
} | |
var TRUE_USTRING = makeInternedImmutable('#t'); | |
var FALSE_USTRING = makeInternedImmutable('#f'); | |
var VOID_USTRING = makeInternedImmutable('#<void>'); | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
* @param {!(Primitive.Primitive|Uint8Array|Function|String|number|boolean|undefined|null)} v | |
*/ | |
function _displayUString(out, v) { | |
if (v === true) { | |
out.consume(TRUE_USTRING); | |
} else if (v === false) { | |
out.consume(FALSE_USTRING); | |
} else if (v === undefined || v === null) { | |
out.consume(VOID_USTRING); | |
} else if (typeof v === 'number' || typeof v === 'string') { | |
out.consume(makeMutable(v.toString())); | |
} else if (check(v)) { | |
v.displayUString(out); | |
} else if (check$1(v)) { | |
out.consume(makeMutable(toString(v))); | |
} else if (check$5(v)) { | |
if (v.__rjs_struct_object) { | |
v.__rjs_struct_object.displayUString(out); | |
} else { | |
out.consume(makeMutable(toString$1(v))); | |
} | |
} else | |
/* if (typeof v === 'number' || typeof v === 'string') */ | |
{ | |
out.consume(makeMutable(v.toString())); | |
} | |
} | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
* @param {!(Primitive.Primitive|Uint8Array|Function|String|number|boolean|undefined|null)} v | |
*/ | |
function _writeUString(out, v) { | |
if (check(v)) { | |
// Assume `v` implements Printable, as only Values does not, | |
// and it cannot be passed here. | |
v.writeUString(out); | |
} else { | |
_displayUString(out, v); | |
} | |
} | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
* @param {!(Primitive.Primitive|Uint8Array|Function|String|number|boolean|undefined|null)} v | |
* @param {!boolean} printAsExpression | |
* @param {!(0|1)} quoteDepth | |
*/ | |
function printUString(out, v, printAsExpression, quoteDepth) { | |
if (printAsExpression && quoteDepth !== 1 && check(v)) { | |
v.printUString(out); | |
} else { | |
_writeUString(out, v); | |
} | |
} | |
var BOX_PREFIX_USTRING = makeInternedImmutable('#&'); | |
var Box = /*#__PURE__*/function (_PrintablePrimitive2) { | |
_inherits(Box, _PrintablePrimitive2); | |
var _super8 = _createSuper(Box); | |
function Box(v) { | |
var _this4; | |
_classCallCheck(this, Box); | |
_this4 = _super8.call(this); | |
_this4.value = v; | |
return _this4; | |
} | |
_createClass(Box, [{ | |
key: "set", | |
value: function set(v) { | |
this.value = v; | |
} | |
}, { | |
key: "get", | |
value: function get() { | |
return this.value; | |
} | |
/** | |
* @param {*} v | |
* @return {!boolean} | |
*/ | |
}, { | |
key: "equals", | |
value: function equals(v) { | |
return isEqual(v.value, this.value); | |
} | |
/** | |
* @return {!number} a 32-bit integer | |
*/ | |
}, { | |
key: "hashForEqual", | |
value: function hashForEqual() { | |
return hashForEqual$1(this.value); | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "displayNativeString", | |
value: function displayNativeString(out) { | |
out.consume('#&'); | |
displayNativeString$2(out, this.value); | |
} | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "displayUString", | |
value: function displayUString(out) { | |
out.consume(BOX_PREFIX_USTRING); | |
_displayUString(out, this.value); | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "writeNativeString", | |
value: function writeNativeString(out) { | |
out.consume('#&'); | |
_writeNativeString(out, this.value); | |
} | |
/** | |
* @param {!Ports.UStringOutputPort} out | |
*/ | |
}, { | |
key: "writeUString", | |
value: function writeUString(out) { | |
out.consume(BOX_PREFIX_USTRING); | |
_writeUString(out, this.value); | |
} | |
}]); | |
return Box; | |
}(PrintablePrimitive); | |
function make$3(v) { | |
return new Box(v); | |
} | |
/** @singleton */ | |
var Empty = /*#__PURE__*/function (_PrintablePrimitive3) { | |
_inherits(Empty, _PrintablePrimitive3); | |
var _super9 = _createSuper(Empty); | |
function Empty() { | |
_classCallCheck(this, Empty); | |
return _super9.apply(this, arguments); | |
} | |
_createClass(Empty, [{ | |
key: "equals", | |
value: function equals(v) { | |
return this === v; | |
} | |
}, { | |
key: "length", | |
get: function get() { | |
return 0; | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "displayNativeString", | |
value: function displayNativeString(out) { | |
out.consume('()'); | |
} | |
/** | |
* @return {false} | |
*/ | |
}, { | |
key: "isImmutable", | |
value: function isImmutable() { | |
// As per racket reference, this is always false for Pairs and Lists. | |
// https://docs.racket-lang.org/reference/booleans.html#%28def._%28%28quote._~23~25kernel%29._immutable~3f%29%29 | |
return false; | |
} | |
}]); | |
return Empty; | |
}(PrintablePrimitive); | |
var EMPTY = new Empty(); | |
/** | |
* @param {*} v | |
* @return {boolean} true iff v is the empty list. | |
*/ | |
function isEmpty(v) { | |
return v === EMPTY; | |
} | |
var Pair = /*#__PURE__*/function (_PrintablePrimitive4) { | |
_inherits(Pair, _PrintablePrimitive4); | |
var _super10 = _createSuper(Pair); | |
/** @private */ | |
function Pair(hd, tl) { | |
var _this5; | |
_classCallCheck(this, Pair); | |
_this5 = _super10.call(this); | |
_this5.hd = hd; | |
_this5.tl = tl; | |
_this5._listLength = isList(tl) ? tl.length + 1 : -1; | |
_this5._cachedHashCode = null; | |
return _this5; | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
* @param {function(Ports.NativeStringOutputPort, *)} itemFn | |
*/ | |
_createClass(Pair, [{ | |
key: "writeToPort", | |
value: function writeToPort(out, itemFn) { | |
out.consume('('); | |
var rest = this; | |
while (true) { | |
if (check$6(rest)) { | |
itemFn(out, rest.hd); | |
} else { | |
out.consume('. '); | |
itemFn(out, rest); | |
break; | |
} | |
rest = rest.tl; | |
if (isEmpty(rest)) { | |
break; | |
} else { | |
out.consume(' '); | |
} | |
} | |
out.consume(')'); | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "displayNativeString", | |
value: function displayNativeString(out) { | |
this.writeToPort(out, displayNativeString$2); | |
} | |
/** | |
* @param {!Ports.NativeStringOutputPort} out | |
*/ | |
}, { | |
key: "writeNativeString", | |
value: function writeNativeString(out) { | |
this.writeToPort(out, _writeNativeString); | |
} | |
}, { | |
key: "equals", | |
value: function equals(v) { | |
if (!check$6(v) || this.length !== v.length) { | |
return false; | |
} | |
var hd1 = this.hd; | |
var tl1 = this.tl; | |
var hd2 = v.hd; | |
var tl2 = v.tl; | |
while (true) { | |
if (!isEqual(hd1, hd2)) { | |
return false; | |
} | |
if (!check$6(tl1) || isEmpty(tl1)) { | |
return isEqual(tl1, tl2); | |
} | |
hd1 = tl1.hd; | |
tl1 = tl1.tl; | |
hd2 = tl2.hd; | |
tl2 = tl2.tl; | |
} | |
} | |
/** | |
* @return {!number} | |
*/ | |
}, { | |
key: "hashForEqual", | |
value: function hashForEqual() { | |
if (this._cachedHashCode === null) { | |
this._cachedHashCode = _get(_getPrototypeOf(Pair.prototype), "hashForEqual", this).call(this); | |
} | |
return this._cachedHashCode; | |
} | |
}, { | |
key: "car", | |
value: function car() { | |
return this.hd; | |
} | |
}, { | |
key: "cdr", | |
value: function cdr() { | |
return this.tl; | |
} | |
}, { | |
key: "length", | |
get: function get() { | |
return this._listLength; | |
} | |
/** | |
* @return {false} | |
*/ | |
}, { | |
key: "isImmutable", | |
value: function isImmutable() { | |
// As per racket reference, this is always false for Pairs and Lists. | |
// https://docs.racket-lang.org/reference/booleans.html#%28def._%28%28quote._~23~25kernel%29._immutable~3f%29%29 | |
return false; | |
} | |
}]); | |
return Pair; | |
}(PrintablePrimitive); | |
/** | |
* @param {*} v | |
* @return {boolean} true iff v is a non-empty list or pair. | |
*/ | |
function check$6(v) { | |
return _typeof2(v) === 'object' && v !== null && v.constructor === Pair; | |
} | |
function make$4(hd, tl) { | |
return new Pair(hd, tl); | |
} | |
function makeList() { | |
for (var _len3 = arguments.length, items = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | |
items[_key3] = arguments[_key3]; | |
} | |
return items.reduceRight(function (result, item) { | |
return make$4(item, result); | |
}, EMPTY); | |
} | |
function listToArray(lst) { | |
var r = []; | |
listForEach(lst, function (x) { | |
return r.push(x); | |
}); | |
return r; | |
} | |
function listFromArray(lst) { | |
return makeList.apply(void 0, _toConsumableArray(lst)); | |
} | |
function listForEach(lst, fn) { | |
while (!isEmpty(lst)) { | |
fn(lst.hd); | |
lst = lst.tl; | |
} | |
} | |
function listFind(lst, fn) { | |
while (!isEmpty(lst)) { | |
var result = fn(lst.hd); | |
if (result !== false) { | |
return result; | |
} | |
lst = lst.tl; | |
} | |
return false; | |
} | |
function listMap(lst, fn) { | |
var result = []; | |
var mapper = function mapper(x) { | |
return result.push(result, fn(x)); | |
}; | |
listForEach(lst, mapper); | |
return listFromArray(result); | |
} | |
/** | |
* @param {*} v | |
* @return {boolean} true iff v is a list. | |
*/ | |
function isList(v) { | |
return v === EMPTY || check$6(v) && v._listLength !== -1; | |
} | |
var pair = /*#__PURE__*/Object.freeze({ | |
__proto__: null, | |
EMPTY: EMPTY, | |
isEmpty: isEmpty, | |
Pair: Pair, | |
check: check$6, | |
make: make$4, | |
makeList: makeList, | |
listToArray: listToArray, | |
listFromArray: listFromArray, | |
listForEach: listForEach, | |
listFind: listFind, | |
listMap: listMap, | |
isList: isList | |
}); | |
function printError(out, msg, args) { | |
out.consume(msg); | |
var _iterator2 = _createForOfIteratorHelper(args), | |
_step2; | |
try { | |
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) { | |
var arg = _step2.value; | |
out.consume(' '); | |
if (typeof arg === 'string') { | |
out.consume(arg); | |
} else { | |
printNativeString$1(out, arg, | |
/* printAsExpression */ | |
true, | |
/* quoteDepth */ | |
0); | |
} | |
} | |
} catch (err) { | |
_iterator2.e(err); | |
} finally { | |
_iterator2.f(); | |
} | |
} | |
function makeError(name) { | |
var _this6 = this; | |
/** | |
* The "(error msg v ...)" form. | |
* Besides Racket values, also allows native strings. | |
*/ | |
var e = function e(msg) { | |
this.name = name; | |
var stringOut = new MiniNativeOutputStringPort(); | |
for (var _len4 = arguments.length, args = new Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) { | |
args[_key4 - 1] = arguments[_key4]; | |
} | |
printError(stringOut, msg, args); | |
this.message = stringOut.getOutputString(); | |
this.stack = new Error().stack; | |
if (Error.captureStackTrace) { | |
Error.captureStackTrace(this, this.constructor); | |
} else { | |
this.stack = new Error().stack; | |
} | |
}; | |
e.prototype = Object.create(Error.prototype); | |
e.prototype.constructor = e; | |
return function () { | |
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { | |
args[_key5] = arguments[_key5]; | |
} | |
return new (Function.prototype.bind.apply(e, [_this6].concat(args)))(); | |
}; | |
} | |
var racketCoreError = makeError('RacketCoreError'); | |
var racketContractError = makeError('RacketContractError'); // this must be here to avoid circular dependency with numbers.js | |
// copied from internet: | |
// https://gist.github.com/jlbruno/1535691/db35b4f3af3dcbb42babc01541410f291a8e8fac | |
function toOrdinal(i) { | |
var j = i % 10; | |
var k = i % 100; | |
if (j === 1 && k !== 11) { | |
return "".concat(i, "st"); | |
} | |
if (j === 2 && k !== 12) { | |
return "".concat(i, "nd"); | |
} | |
if (j === 3 && k !== 13) { | |
return "".concat(i, "rd"); | |
} | |
return "".concat(i, "th"); | |
} // format exn message to exactly match Racket raise-argument-error | |
function makeArgumentError(name, expected) { | |
var stringOut = new MiniNativeOutputStringPort(); // "other" args must be converted to string via `print` | |
// (not `write` or `display`) | |
stringOut.consume("".concat(name.toString(), ": contract violation\n")); | |
stringOut.consume(' expected: '); | |
stringOut.consume(expected.toString()); | |
stringOut.consume('\n'); | |
stringOut.consume(' given: '); | |
for (var _len6 = arguments.length, rest = new Array(_len6 > 2 ? _len6 - 2 : 0), _key6 = 2; _key6 < _len6; _key6++) { | |
rest[_key6 - 2] = arguments[_key6]; | |
} | |
if (rest.length === 1) { | |
printNativeString$1(stringOut, rest[0], true, 0); | |
} else { | |
printNativeString$1(stringOut, rest[rest[0] + 1], true, 0); | |
if (rest.length > 2) { | |
// only print if there are "other" args | |
stringOut.consume('\n'); | |
stringOut.consume(' argument position: '); | |
printNativeString$1(stringOut, toOrdinal(rest[0] + 1), true, 0); | |
stringOut.consume('\n'); | |
stringOut.consume(' other arguments...:'); | |
for (var i = 1; i < rest.length; i++) { | |
// eslint-disable-next-line no-continue | |
if (i === rest[0] + 1) { | |
continue; | |
} | |
stringOut.consume('\n '); | |
printNativeString$1(stringOut, rest[i], true, 0); | |
} | |
} | |
} | |
return racketContractError(stringOut.getOutputString()); | |
} // format exn message to exactly match Racket raise-arguments-error | |
function makeArgumentsError(name, msg, field) { | |
var stringOut = new MiniNativeOutputStringPort(); | |
stringOut.consume("".concat(name.toString(), ": ")); | |
stringOut.consume(msg); | |
stringOut.consume('\n '); | |
stringOut.consume(field); | |
stringOut.consume(': '); | |
printNativeString$1(stringOut, arguments.length <= 3 ? undefined : arguments[3], true, 0); | |
for (var i = 1; i < (arguments.length <= 3 ? 0 : arguments.length - 3); i += 2) { | |
stringOut.consume('\n '); | |
stringOut.consume(i + 3 < 3 || arguments.length <= i + 3 ? undefined : arguments[i + 3]); | |
stringOut.consume(': '); | |
printNativeString$1(stringOut, i + 1 + 3 < 3 || arguments.length <= i + 1 + 3 ? undefined : arguments[i + 1 + 3], true, 0); | |
} | |
return racketContractError(stringOut.getOutputString()); | |
} | |
var Values = /*#__PURE__*/function (_Primitive4) { | |
_inherits(Values, _Primitive4); | |
var _super11 = _createSuper(Values); | |
function Values(vals) { | |
var _this7; | |
_classCallCheck(this, Values); | |
_this7 = _super11.call(this); | |
_this7.v = vals; | |
return _this7; | |
} | |
_createClass(Values, [{ | |
key: "getAt", | |
value: function getAt(i) { | |
return this.v[i]; | |
} | |
}, { | |
key: "getAll", | |
value: function getAll() { | |
return this.v; | |
} | |
}]); | |
return Values; | |
}(Primitive); | |
function make$5(vals) { | |
return new Values(vals); | |
} | |
function check$7(v) { | |
return v instanceof Values; | |
} | |
var values = /*#__PURE__*/Object.freeze({ | |
__proto__: null, | |
make: make$5, | |
check: check$7 | |
}); // TODO: allow ordering of hash traversal | |
function map(hash, proc) { | |
var result = EMPTY; | |
hash._h.forEach(function (value, key) { | |
result = make$4(proc(key, value), result); | |
}); | |
return result; | |
} | |
/* Arithmetic */ | |
function add() { | |
for (var _len7 = arguments.length, operands = new Array(_len7), _key7 = 0; _key7 < _len7; _key7++) { | |
operands[_key7] = arguments[_key7]; | |
} | |
return [].reduce.call(operands, function (a, b) { | |
return a + b; | |
}, 0); | |
} | |
function sub() { | |
if (arguments.length === 1) { | |
return -(arguments.length <= 0 ? undefined : arguments[0]); | |
} | |
var result = arguments.length <= 0 ? undefined : arguments[0]; | |
for (var i = 1; i < arguments.length; ++i) { | |
result -= i < 0 || arguments.length <= i ? undefined : arguments[i]; | |
} | |
return result; | |
} | |
function mul() { | |
for (var _len8 = arguments.length, operands = new Array(_len8), _key8 = 0; _key8 < _len8; _key8++) { | |
operands[_key8] = arguments[_key8]; | |
} | |
return [].reduce.call(operands, function (a, b) { | |
return a * b; | |
}, 1); | |
} | |
function div() { | |
if (arguments.length === 1) { | |
return 1 / (arguments.length <= 0 ? undefined : arguments[0]); | |
} | |
var result = arguments.length <= 0 ? undefined : arguments[0]; | |
for (var i = 1; i < arguments.length; ++i) { | |
result /= i < 0 || arguments.length <= i ? undefined : arguments[i]; | |
} | |
return result; | |
} | |
/* Comparison */ | |
function compare(cmp, operands) { | |
if (operands.length < 1) { | |
throw racketCoreError.apply(void 0, ['compare: at least 1 argument required, given'].concat(_toConsumableArray(operands))); | |
} | |
if (operands.length === 1) { | |
return true; | |
} | |
for (var i = 1; i < operands.length; i++) { | |
if (!cmp(operands[i - 1], operands[i])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function lt() { | |
for (var _len9 = arguments.length, operands = new Array(_len9), _key9 = 0; _key9 < _len9; _key9++) { | |
operands[_key9] = arguments[_key9]; | |
} | |
return compare(function (a, b) { | |
return a < b; | |
}, operands); | |
} | |
function lte() { | |
for (var _len10 = arguments.length, operands = new Array(_len10), _key10 = 0; _key10 < _len10; _key10++) { | |
operands[_key10] = arguments[_key10]; | |
} | |
return compare(function (a, b) { | |
return a <= b; | |
}, operands); | |
} | |
function gt() { | |
for (var _len11 = arguments.length, operands = new Array(_len11), _key11 = 0; _key11 < _len11; _key11++) { | |
operands[_key11] = arguments[_key11]; | |
} | |
return compare(function (a, b) { | |
return a > b; | |
}, operands); | |
} | |
function gte() { | |
for (var _len12 = arguments.length, operands = new Array(_len12), _key12 = 0; _key12 < _len12; _key12++) { | |
operands[_key12] = arguments[_key12]; | |
} | |
return compare(function (a, b) { | |
return a >= b; | |
}, operands); | |
} | |
function equals() { | |
for (var _len13 = arguments.length, operands = new Array(_len13), _key13 = 0; _key13 < _len13; _key13++) { | |
operands[_key13] = arguments[_key13]; | |
} | |
return compare(function (a, b) { | |
return a === b; | |
}, operands); | |
} | |
function check$8(v) { | |
return typeof v === 'number'; | |
} | |
/* Bitwise operators */ | |
function bitwiseOr() { | |
for (var _len14 = arguments.length, operands = new Array(_len14), _key14 = 0; _key14 < _len14; _key14++) { | |
operands[_key14] = arguments[_key14]; | |
} | |
return [].reduce.call(operands, function (a, b) { | |
return a | b; | |
}, 0); | |
} | |
function bitwiseXor() { | |
for (var _len15 = arguments.length, operands = new Array(_len15), _key15 = 0; _key15 < _len15; _key15++) { | |
operands[_key15] = arguments[_key15]; | |
} | |
return [].reduce.call(operands, function (a, b) { | |
return a ^ b; | |
}, 0); | |
} | |
function bitwiseAnd() { | |
for (var _len16 = arguments.length, operands = new Array(_len16), _key16 = 0; _key16 < _len16; _key16++) { | |
operands[_key16] = arguments[_key16]; | |
} | |
return [].reduce.call(operands, function (a, b) { | |
return a & b; | |
}, -1); | |
} | |
/** @abstract */ | |
var Port = /*#__PURE__*/function (_PrintablePrimitive5) { | |
_inherits(Port, _PrintablePrimitive5); | |
var _super12 = _createSuper(Port); | |
function Port() { | |
_classCallCheck(this, Port); | |
return _super12.apply(this, arguments); | |
} | |
_createClass(Port, [{ | |
key: "isOutputPort", | |