Skip to content

Instantly share code, notes, and snippets.

@samth
Created Sep 22, 2021
Embed
What would you like to do?
'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 <