@calcit/procs
Advanced tools
Comparing version 0.2.44 to 0.2.45
var _a; | ||
import { overwriteComparator, initTernaryTreeList, initTernaryTreeMap, listLen, mapLen, listGet, mapGet, assocMap, assocList, dissocMap, isMapEmpty, listToItems, dissocList, overwriteHashGenerator, valueHash, mergeValueHash, toPairsArray, } from "@calcit/ternary-tree"; | ||
import * as ternaryTree from "@calcit/ternary-tree"; | ||
import { overwriteComparator, initTernaryTreeMap } from "@calcit/ternary-tree"; | ||
import { CrDataSymbol, CrDataKeyword, CrDataList, CrDataMap, CrDataAtom, CrDataRecur, kwd, atomsRegistry, toString, CrDataSet, } from "./calcit-data"; | ||
export * from "./calcit-data"; | ||
let inNodeJs = typeof process !== "undefined" && ((_a = process === null || process === void 0 ? void 0 : process.release) === null || _a === void 0 ? void 0 : _a.name) === "node"; | ||
class CrDataKeyword { | ||
constructor(x) { | ||
this.value = x; | ||
} | ||
toString() { | ||
return `:${this.value}`; | ||
} | ||
} | ||
export class CrDataSymbol { | ||
constructor(x) { | ||
this.value = x; | ||
} | ||
toString() { | ||
return `'${this.value}`; | ||
} | ||
} | ||
class CrDataRecur { | ||
constructor(xs) { | ||
this.args = xs; | ||
} | ||
toString() { | ||
return `(&recur ...)`; | ||
} | ||
} | ||
class CrDataAtom { | ||
constructor(x, path) { | ||
this.value = x; | ||
this.path = path; | ||
this.listeners = new Map(); | ||
} | ||
toString() { | ||
return `(&atom ${this.value.toString()})`; | ||
} | ||
} | ||
class CrDataList { | ||
constructor(value) { | ||
if (Array.isArray(value)) { | ||
this.arrayMode = true; | ||
this.arrayValue = value; | ||
this.arrayStart = 0; | ||
this.arrayEnd = value.length; | ||
this.value = null; | ||
} | ||
else { | ||
this.arrayMode = false; | ||
this.value = value; | ||
this.arrayValue = []; | ||
this.arrayStart = null; | ||
this.arrayEnd = null; | ||
} | ||
} | ||
turnListMode() { | ||
if (this.arrayMode) { | ||
this.value = initTernaryTreeList(this.arrayValue.slice(this.arrayStart, this.arrayEnd)); | ||
this.arrayValue = null; | ||
this.arrayStart = null; | ||
this.arrayEnd = null; | ||
this.arrayMode = false; | ||
} | ||
} | ||
len() { | ||
if (this.arrayMode) { | ||
return this.arrayEnd - this.arrayStart; | ||
} | ||
else { | ||
return listLen(this.value); | ||
} | ||
} | ||
get(idx) { | ||
if (this.arrayMode) { | ||
return this.arrayValue[this.arrayStart + idx]; | ||
} | ||
else { | ||
return listGet(this.value, idx); | ||
} | ||
} | ||
assoc(idx, v) { | ||
this.turnListMode(); | ||
return new CrDataList(assocList(this.value, idx, v)); | ||
} | ||
dissoc(idx) { | ||
this.turnListMode(); | ||
return new CrDataList(dissocList(this.value, idx)); | ||
} | ||
slice(from, to) { | ||
if (this.arrayMode) { | ||
if (from < 0) { | ||
throw new Error(`from index too small: ${from}`); | ||
} | ||
if (to > this.len()) { | ||
throw new Error(`end index too large: ${to}`); | ||
} | ||
let result = new CrDataList(this.arrayValue); | ||
result.arrayStart = this.arrayStart + from; | ||
result.arrayEnd = this.arrayStart + to; | ||
return result; | ||
} | ||
else { | ||
return new CrDataList(ternaryTree.slice(this.value, from, to)); | ||
} | ||
} | ||
toString() { | ||
let result = ""; | ||
for (let item of this.items()) { | ||
if (result !== "") { | ||
result = `${result}, `; | ||
} | ||
result = `${result}${toString(item, true)}`; | ||
} | ||
return `(${result})`; | ||
} | ||
isEmpty() { | ||
return this.len() === 0; | ||
} | ||
/** usage: `for of` */ | ||
items() { | ||
if (this.arrayMode) { | ||
return sliceGenerator(this.arrayValue, this.arrayStart, this.arrayEnd); | ||
} | ||
else { | ||
return listToItems(this.value); | ||
} | ||
} | ||
append(v) { | ||
this.turnListMode(); | ||
return new CrDataList(ternaryTree.append(this.value, v)); | ||
} | ||
prepend(v) { | ||
this.turnListMode(); | ||
return new CrDataList(ternaryTree.prepend(this.value, v)); | ||
} | ||
first() { | ||
if (this.arrayMode) { | ||
if (this.arrayValue.length > this.arrayStart) { | ||
return this.arrayValue[this.arrayStart]; | ||
} | ||
else { | ||
return null; | ||
} | ||
} | ||
else { | ||
return ternaryTree.first(this.value); | ||
} | ||
} | ||
rest() { | ||
if (this.arrayMode) { | ||
return this.slice(1, this.arrayEnd - this.arrayStart); | ||
} | ||
else { | ||
return new CrDataList(ternaryTree.rest(this.value)); | ||
} | ||
} | ||
concat(ys) { | ||
if (!(ys instanceof CrDataList)) { | ||
throw new Error("Expected list"); | ||
} | ||
this.turnListMode(); | ||
ys.turnListMode(); | ||
return new CrDataList(ternaryTree.concat(this.value, ys.value)); | ||
} | ||
map(f) { | ||
let result = []; | ||
for (let item of this.items()) { | ||
result.push(f(item)); | ||
} | ||
return new CrDataList(result); | ||
} | ||
toArray() { | ||
if (this.arrayMode) { | ||
return this.arrayValue.slice(this.arrayStart, this.arrayEnd); | ||
} | ||
else { | ||
return [...ternaryTree.listToItems(this.value)]; | ||
} | ||
} | ||
reverse() { | ||
this.turnListMode(); | ||
return new CrDataList(ternaryTree.reverse(this.value)); | ||
} | ||
} | ||
// just create a reference that equals to no other value | ||
let fakeUniqueSymbol = []; | ||
class CrDataMap { | ||
constructor(value) { | ||
this.chain = { value: value, next: null }; | ||
this.depth = 1; | ||
this.skipValue = fakeUniqueSymbol; | ||
} | ||
turnSingleMap() { | ||
if (this.depth === 1) { | ||
return; | ||
} | ||
// squash down to a single level of map | ||
let ret = this.chain.value; | ||
let cursor = this.chain.next; | ||
while (cursor != null) { | ||
if (!isMapEmpty(cursor.value)) { | ||
ret = ternaryTree.mergeSkip(cursor.value, ret, this.skipValue); | ||
} | ||
cursor = cursor.next; | ||
} | ||
this.chain = { | ||
value: ret, | ||
next: null, | ||
}; | ||
this.depth = 1; | ||
} | ||
len() { | ||
this.turnSingleMap(); | ||
return mapLen(this.chain.value); | ||
} | ||
get(k) { | ||
let cursor = this.chain; | ||
while (cursor != null) { | ||
let v = mapGet(cursor.value, k); | ||
if (v != null && v !== this.skipValue) { | ||
return v; | ||
} | ||
else { | ||
cursor = cursor.next; | ||
} | ||
} | ||
return null; | ||
} | ||
assoc(k, v) { | ||
let cursor = this.chain; | ||
// mutable way of creating another map value | ||
let result = new CrDataMap(null); | ||
result.chain = { | ||
value: assocMap(cursor.value, k, v), | ||
next: cursor.next, | ||
}; | ||
return result; | ||
} | ||
dissoc(k) { | ||
this.turnSingleMap(); | ||
return new CrDataMap(dissocMap(this.chain.value, k)); | ||
} | ||
toString() { | ||
let itemsCode = ""; | ||
for (let [k, v] of this.pairs()) { | ||
if (itemsCode !== "") { | ||
itemsCode = `${itemsCode}, `; | ||
} | ||
itemsCode = `${itemsCode}${toString(k, true)} ${toString(v, true)}`; | ||
} | ||
return `{${itemsCode}}`; | ||
} | ||
isEmpty() { | ||
let cursor = this.chain; | ||
while (cursor != null) { | ||
if (!isMapEmpty(cursor.value)) { | ||
return false; | ||
} | ||
cursor = cursor.next; | ||
} | ||
return true; | ||
} | ||
pairs() { | ||
this.turnSingleMap(); | ||
return toPairsArray(this.chain.value); | ||
} | ||
contains(k) { | ||
let cursor = this.chain; | ||
while (cursor != null) { | ||
if (ternaryTree.contains(cursor.value, k)) { | ||
return true; | ||
} | ||
cursor = cursor.next; | ||
} | ||
return false; | ||
} | ||
merge(ys) { | ||
return this.mergeSkip(ys, fakeUniqueSymbol); | ||
} | ||
mergeSkip(ys, v) { | ||
if (!(ys instanceof CrDataMap)) { | ||
throw new Error("Expected map"); | ||
} | ||
let result = new CrDataMap(null); | ||
result.skipValue = v; | ||
ys.turnSingleMap(); | ||
result.chain = { | ||
value: ys.chain.value, | ||
next: this.chain, | ||
}; | ||
result.depth = this.depth + 1; | ||
if (result.depth > 5) { | ||
// 5 by experience, limit to suqash linked list to value | ||
result.turnSingleMap(); | ||
} | ||
return result; | ||
} | ||
} | ||
var keywordRegistery = {}; | ||
export let kwd = (content) => { | ||
let item = keywordRegistery[content]; | ||
if (item != null) { | ||
return item; | ||
} | ||
else { | ||
let v = new CrDataKeyword(content); | ||
keywordRegistery[content] = v; | ||
return v; | ||
} | ||
}; | ||
var atomsRegistry = new Map(); | ||
function* sliceGenerator(xs, start, end) { | ||
for (let idx = start; idx < end; idx++) { | ||
yield xs[idx]; | ||
} | ||
} | ||
export let type_DASH_of = (x) => { | ||
@@ -342,3 +31,3 @@ if (typeof x === "string") { | ||
} | ||
if (x instanceof Set) { | ||
if (x instanceof CrDataSet) { | ||
return kwd("set"); | ||
@@ -378,4 +67,4 @@ } | ||
} | ||
if (x instanceof Set) { | ||
return x.size; | ||
if (x instanceof CrDataSet) { | ||
return x.len(); | ||
} | ||
@@ -428,5 +117,5 @@ throw new Error(`Unknown data ${x}`); | ||
} | ||
if (xs instanceof Set) { | ||
if (xs instanceof CrDataSet) { | ||
let result = acc; | ||
xs.forEach((item) => { | ||
xs.value.forEach((item) => { | ||
result = f(result, item); | ||
@@ -517,11 +206,9 @@ }); | ||
} | ||
if (x instanceof Set) { | ||
if (y instanceof Set) { | ||
let x2 = x; | ||
let y2 = y; | ||
if (x2.size !== y2.size) { | ||
if (x instanceof CrDataSet) { | ||
if (y instanceof CrDataSet) { | ||
if (x.len() !== y.len()) { | ||
return false; | ||
} | ||
for (let v in x2.values()) { | ||
if (!y2.has(v)) { | ||
for (let v in x.value.values()) { | ||
if (!y.contains(v)) { | ||
return false; | ||
@@ -571,7 +258,5 @@ } | ||
} | ||
if (xs instanceof Set) { | ||
// TODO structure inside set | ||
return xs.has(x); | ||
if (xs instanceof CrDataSet) { | ||
return xs.contains(x); | ||
} | ||
// TODO set not handled | ||
throw new Error("Does not support contains? on this type"); | ||
@@ -615,4 +300,28 @@ }; | ||
} | ||
throw new Error("Does not support `get` on this type"); | ||
throw new Error("Does not support `assoc` on this type"); | ||
}; | ||
export let assoc_DASH_before = function (xs, k, v) { | ||
if (arguments.length !== 3) { | ||
throw new Error("assoc takes 3 arguments"); | ||
} | ||
if (xs instanceof CrDataList) { | ||
if (typeof k !== "number") { | ||
throw new Error("Expected number index for lists"); | ||
} | ||
return xs.assocBefore(k, v); | ||
} | ||
throw new Error("Does not support `assoc-before` on this type"); | ||
}; | ||
export let assoc_DASH_after = function (xs, k, v) { | ||
if (arguments.length !== 3) { | ||
throw new Error("assoc takes 3 arguments"); | ||
} | ||
if (xs instanceof CrDataList) { | ||
if (typeof k !== "number") { | ||
throw new Error("Expected number index for lists"); | ||
} | ||
return xs.assocAfter(k, v); | ||
} | ||
throw new Error("Does not support `assoc-after` on this type"); | ||
}; | ||
export let dissoc = function (xs, k) { | ||
@@ -692,4 +401,4 @@ if (arguments.length !== 2) { | ||
} | ||
if (xs instanceof Set) { | ||
return xs.size === 0; | ||
if (xs instanceof CrDataSet) { | ||
return xs.len() === 0; | ||
} | ||
@@ -741,9 +450,4 @@ if (xs == null) { | ||
} | ||
if (xs instanceof Set) { | ||
if (xs.size === 0) { | ||
return null; | ||
} | ||
for (let x of xs) { | ||
return x; | ||
} | ||
if (xs instanceof CrDataSet) { | ||
return xs.first(); | ||
} | ||
@@ -773,11 +477,4 @@ console.error(xs); | ||
} | ||
if (xs instanceof Set) { | ||
if (xs.size == 0) { | ||
return null; | ||
} | ||
let it = xs.values(); | ||
let x0 = it.next().value; | ||
let ys = cloneSet(xs); | ||
ys.delete(x0); | ||
return ys; | ||
if (xs instanceof CrDataSet) { | ||
return xs.rest(); | ||
} | ||
@@ -849,3 +546,3 @@ console.error(xs); | ||
} | ||
return result; | ||
return new CrDataSet(result); | ||
}; | ||
@@ -994,4 +691,5 @@ let idCounter = 0; | ||
} | ||
return result; | ||
return new CrDataSet(result); | ||
}; | ||
// Math functions | ||
export let sin = (n) => { | ||
@@ -1015,48 +713,47 @@ return Math.sin(n); | ||
}; | ||
export let cloneSet = (xs) => { | ||
if (!(xs instanceof Set)) { | ||
// Set functions | ||
export let _AND_include = (xs, y) => { | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
var result = new Set(); | ||
for (let v of xs) { | ||
result.add(v); | ||
if (y == null) { | ||
return xs; | ||
} | ||
return result; | ||
return xs.include(y); | ||
}; | ||
export let _AND_include = (xs, y) => { | ||
var result = cloneSet(xs); | ||
result.add(y); | ||
return result; | ||
}; | ||
export let _AND_exclude = (xs, y) => { | ||
var result = cloneSet(xs); | ||
result.delete(y); | ||
return result; | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (y == null) { | ||
return xs; | ||
} | ||
return xs.exclude(y); | ||
}; | ||
export let _AND_difference = (xs, ys) => { | ||
var result = cloneSet(xs); | ||
ys.forEach((y) => { | ||
if (result.has(y)) { | ||
result.delete(y); | ||
} | ||
}); | ||
return result; | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (!(ys instanceof CrDataSet)) { | ||
throw new Error("Expected a set for ys"); | ||
} | ||
return xs.difference(ys); | ||
}; | ||
export let _AND_union = (xs, ys) => { | ||
var result = cloneSet(xs); | ||
ys.forEach((y) => { | ||
if (!result.has(y)) { | ||
result.add(y); | ||
} | ||
}); | ||
return result; | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (!(ys instanceof CrDataSet)) { | ||
throw new Error("Expected a set for ys"); | ||
} | ||
return xs.union(ys); | ||
}; | ||
export let _AND_intersection = (xs, ys) => { | ||
var result = new Set(); | ||
ys.forEach((y) => { | ||
if (xs.has(y)) { | ||
result.add(y); | ||
} | ||
}); | ||
return result; | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (!(ys instanceof CrDataSet)) { | ||
throw new Error("Expected a set for ys"); | ||
} | ||
return xs.intersection(ys); | ||
}; | ||
@@ -1201,3 +898,3 @@ export let replace = (x, y, z) => { | ||
}); | ||
return result; | ||
return new CrDataSet(result); | ||
} | ||
@@ -1223,3 +920,3 @@ // detects object | ||
var result = []; | ||
x.forEach((item) => { | ||
x.value.forEach((item) => { | ||
result.push(item); | ||
@@ -1271,48 +968,2 @@ }); | ||
}; | ||
let toString = (x, escaped) => { | ||
if (x == null) { | ||
return "nil"; | ||
} | ||
if (typeof x === "string") { | ||
if (escaped) { | ||
return JSON.stringify(x); | ||
} | ||
else { | ||
return x; | ||
} | ||
} | ||
if (typeof x === "number") { | ||
return x.toString(); | ||
} | ||
if (typeof x === "boolean") { | ||
return x.toString(); | ||
} | ||
if (typeof x === "function") { | ||
return `(&fn ...)`; | ||
} | ||
if (x instanceof CrDataSymbol) { | ||
return x.toString(); | ||
} | ||
if (x instanceof CrDataKeyword) { | ||
return x.toString(); | ||
} | ||
if (x instanceof CrDataList) { | ||
return x.toString(); | ||
} | ||
if (x instanceof CrDataMap) { | ||
return x.toString(); | ||
} | ||
if (x instanceof Set) { | ||
let itemsCode = ""; | ||
x.forEach((child, idx) => { | ||
if (idx > 0) { | ||
itemsCode = `${itemsCode} `; | ||
} | ||
itemsCode = `${itemsCode}${toString(child, true)}`; | ||
}); | ||
return `#{${itemsCode}}`; | ||
} | ||
console.error(x); | ||
throw new Error("Unexpected data for toString"); | ||
}; | ||
export let pr_DASH_str = (...args) => { | ||
@@ -1454,3 +1105,3 @@ return args.map((x) => toString(x, true)).join(" "); | ||
if (x[0] === "#{}") { | ||
return new Set(x.slice(1).map(extract_DASH_cirru_DASH_edn)); | ||
return new CrDataSet(new Set(x.slice(1).map(extract_DASH_cirru_DASH_edn))); | ||
} | ||
@@ -1504,85 +1155,2 @@ if (x[0] === "do" && x.length === 2) { | ||
}; | ||
let defaultHash_nil = valueHash("nil:"); | ||
let defaultHash_number = valueHash("number:"); | ||
let defaultHash_string = valueHash("string:"); | ||
let defaultHash_keyword = valueHash("keyword:"); | ||
let defaultHash_true = valueHash("true:"); | ||
let defaultHash_false = valueHash("false:"); | ||
let defaultHash_symbol = valueHash("symbol:"); | ||
let defaultHash_fn = valueHash("fn:"); | ||
let defaultHash_atom = valueHash("atom:"); | ||
let defaultHash_set = valueHash("set:"); | ||
let defaultHash_list = valueHash("list:"); | ||
let defaultHash_map = valueHash("map:"); | ||
let fnHashCounter = 0; | ||
let hashFunction = (x) => { | ||
if (x == null) { | ||
return defaultHash_nil; | ||
} | ||
if (typeof x === "number") { | ||
return mergeValueHash(defaultHash_number, x); | ||
} | ||
if (typeof x === "string") { | ||
return mergeValueHash(defaultHash_string, x); | ||
} | ||
// dirty solution of caching, trying to reduce cost | ||
if (x.cachedHash != null) { | ||
return x.cachedHash; | ||
} | ||
if (x instanceof CrDataKeyword) { | ||
let h = mergeValueHash(defaultHash_keyword, x.value); | ||
x.cachedHash = h; | ||
return h; | ||
} | ||
if (x === true) { | ||
return defaultHash_true; | ||
} | ||
if (x === false) { | ||
return defaultHash_false; | ||
} | ||
if (x instanceof CrDataSymbol) { | ||
let h = mergeValueHash(defaultHash_symbol, x.value); | ||
x.cachedHash = h; | ||
return h; | ||
} | ||
if (typeof x === "function") { | ||
fnHashCounter = fnHashCounter + 1; | ||
let h = mergeValueHash(defaultHash_fn, fnHashCounter); | ||
x.cachedHash = h; | ||
return h; | ||
} | ||
if (x instanceof CrDataAtom) { | ||
let h = mergeValueHash(defaultHash_atom, x.path); | ||
x.cachedHash = h; | ||
return h; | ||
} | ||
if (x instanceof Set) { | ||
// TODO not using dirty solution for code | ||
let base = defaultHash_set; | ||
for (let item of x) { | ||
base = mergeValueHash(base, hashFunction(item)); | ||
} | ||
return base; | ||
} | ||
if (x instanceof CrDataList) { | ||
let base = defaultHash_list; | ||
for (let item of x.items()) { | ||
base = mergeValueHash(base, hashFunction(item)); | ||
} | ||
x.cachedHash = base; | ||
return base; | ||
} | ||
if (x instanceof CrDataMap) { | ||
let base = defaultHash_map; | ||
for (let [k, v] of x.pairs()) { | ||
base = mergeValueHash(base, hashFunction(k)); | ||
base = mergeValueHash(base, hashFunction(v)); | ||
} | ||
x.cachedHash = base; | ||
return base; | ||
} | ||
throw new Error("Unknown data for hashing"); | ||
}; | ||
// Dirty code to change ternary-tree behavior | ||
overwriteHashGenerator(hashFunction); | ||
export let number_QUES_ = (x) => { | ||
@@ -1610,3 +1178,3 @@ return typeof x === "number"; | ||
export let set_QUES_ = (x) => { | ||
return x instanceof Set; | ||
return x instanceof CrDataSet; | ||
}; | ||
@@ -1619,25 +1187,42 @@ export let fn_QUES_ = (x) => { | ||
}; | ||
export let escape = (x) => JSON.stringify(x); | ||
export let read_DASH_file = (path) => { | ||
var _a; | ||
if (inNodeJs) { | ||
// TODO | ||
globalThis["__calcit_injections__"].read_DASH_file(path); | ||
} | ||
else { | ||
// no actual File API in browser | ||
return (_a = localStorage.get(path)) !== null && _a !== void 0 ? _a : ""; | ||
} | ||
}; | ||
export let write_DASH_file = (path, content) => { | ||
if (inNodeJs) { | ||
// TODO | ||
globalThis["__calcit_injections__"].write_DASH_file(path, content); | ||
} | ||
else { | ||
// no actual File API in browser | ||
localStorage.setItem(path, content); | ||
} | ||
}; | ||
// special procs have to be defined manually | ||
export let reduce = foldl; | ||
export let conj = append; | ||
let placeholder = (...xs) => { | ||
/* placeholder */ | ||
let unavailableProc = (...xs) => { | ||
console.warn("NOT available for calcit-js"); | ||
}; | ||
// TODO these functions are not used by calcit-js, but added to fix missing imports | ||
export let _AND_reset_DASH_gensym_DASH_index_BANG_ = placeholder; | ||
export let assoc_DASH_after = placeholder; | ||
export let assoc_DASH_before = placeholder; | ||
export let dbt_DASH__GT_point = placeholder; | ||
export let dbt_DASH_digits = placeholder; | ||
export let dual_DASH_balanced_DASH_ternary = placeholder; | ||
export let escape = placeholder; | ||
export let format_DASH_time = placeholder; | ||
export let gensym = placeholder; | ||
export let macroexpand = placeholder; | ||
export let macroexpand_DASH_all = placeholder; | ||
export let now_BANG_ = placeholder; | ||
export let parse_DASH_cirru = placeholder; | ||
export let parse_DASH_cirru_DASH_edn = placeholder; | ||
export let parse_DASH_time = placeholder; | ||
export let read_DASH_file = placeholder; | ||
export let write_DASH_file = placeholder; | ||
export let format_DASH_time = unavailableProc; // TODO | ||
export let now_BANG_ = unavailableProc; // TODO | ||
export let parse_DASH_time = unavailableProc; // TODO | ||
export let parse_DASH_cirru = unavailableProc; // TODO | ||
export let parse_DASH_cirru_DASH_edn = unavailableProc; // TODO | ||
// not available for calcit-js | ||
export let _AND_reset_DASH_gensym_DASH_index_BANG_ = unavailableProc; | ||
export let dbt_DASH__GT_point = unavailableProc; | ||
export let dbt_DASH_digits = unavailableProc; | ||
export let dual_DASH_balanced_DASH_ternary = unavailableProc; | ||
export let gensym = unavailableProc; | ||
export let macroexpand = unavailableProc; | ||
export let macroexpand_DASH_all = unavailableProc; |
@@ -0,392 +1,23 @@ | ||
import { overwriteComparator, initTernaryTreeMap } from "@calcit/ternary-tree"; | ||
import { | ||
TernaryTreeList, | ||
TernaryTreeMap, | ||
overwriteComparator, | ||
initTernaryTreeList, | ||
initTernaryTreeMap, | ||
listLen, | ||
mapLen, | ||
listGet, | ||
mapGet, | ||
assocMap, | ||
assocList, | ||
dissocMap, | ||
isMapEmpty, | ||
toPairs, | ||
contains, | ||
listToItems, | ||
dissocList, | ||
Hash, | ||
overwriteHashGenerator, | ||
valueHash, | ||
mergeValueHash, | ||
toPairsArray, | ||
} from "@calcit/ternary-tree"; | ||
CrDataSymbol, | ||
CrDataValue, | ||
CrDataKeyword, | ||
CrDataList, | ||
CrDataMap, | ||
CrDataAtom, | ||
CrDataFn, | ||
CrDataRecur, | ||
kwd, | ||
atomsRegistry, | ||
toString, | ||
CrDataSet, | ||
cloneSet, | ||
} from "./calcit-data"; | ||
import * as ternaryTree from "@calcit/ternary-tree"; | ||
export * from "./calcit-data"; | ||
let inNodeJs = | ||
typeof process !== "undefined" && process?.release?.name === "node"; | ||
let inNodeJs = typeof process !== "undefined" && process?.release?.name === "node"; | ||
class CrDataKeyword { | ||
value: string; | ||
cachedHash: Hash; | ||
constructor(x: string) { | ||
this.value = x; | ||
} | ||
toString() { | ||
return `:${this.value}`; | ||
} | ||
} | ||
export class CrDataSymbol { | ||
value: string; | ||
cachedHash: Hash; | ||
constructor(x: string) { | ||
this.value = x; | ||
} | ||
toString() { | ||
return `'${this.value}`; | ||
} | ||
} | ||
class CrDataRecur { | ||
args: CrDataValue[]; | ||
constructor(xs: CrDataValue[]) { | ||
this.args = xs; | ||
} | ||
toString() { | ||
return `(&recur ...)`; | ||
} | ||
} | ||
class CrDataAtom { | ||
value: CrDataValue; | ||
path: string; | ||
listeners: Map<CrDataValue, CrDataFn>; | ||
cachedHash: Hash; | ||
constructor(x: CrDataValue, path: string) { | ||
this.value = x; | ||
this.path = path; | ||
this.listeners = new Map(); | ||
} | ||
toString(): string { | ||
return `(&atom ${this.value.toString()})`; | ||
} | ||
} | ||
type CrDataFn = (...xs: CrDataValue[]) => CrDataValue; | ||
class CrDataList { | ||
value: TernaryTreeList<CrDataValue>; | ||
// array mode store bare array for performance | ||
arrayValue: Array<CrDataValue>; | ||
arrayMode: boolean; | ||
arrayStart: number; | ||
arrayEnd: number; | ||
cachedHash: Hash; | ||
constructor(value: Array<CrDataValue> | TernaryTreeList<CrDataValue>) { | ||
if (Array.isArray(value)) { | ||
this.arrayMode = true; | ||
this.arrayValue = value; | ||
this.arrayStart = 0; | ||
this.arrayEnd = value.length; | ||
this.value = null; | ||
} else { | ||
this.arrayMode = false; | ||
this.value = value; | ||
this.arrayValue = []; | ||
this.arrayStart = null; | ||
this.arrayEnd = null; | ||
} | ||
} | ||
turnListMode() { | ||
if (this.arrayMode) { | ||
this.value = initTernaryTreeList( | ||
this.arrayValue.slice(this.arrayStart, this.arrayEnd) | ||
); | ||
this.arrayValue = null; | ||
this.arrayStart = null; | ||
this.arrayEnd = null; | ||
this.arrayMode = false; | ||
} | ||
} | ||
len() { | ||
if (this.arrayMode) { | ||
return this.arrayEnd - this.arrayStart; | ||
} else { | ||
return listLen(this.value); | ||
} | ||
} | ||
get(idx: number) { | ||
if (this.arrayMode) { | ||
return this.arrayValue[this.arrayStart + idx]; | ||
} else { | ||
return listGet(this.value, idx); | ||
} | ||
} | ||
assoc(idx: number, v: CrDataValue) { | ||
this.turnListMode(); | ||
return new CrDataList(assocList(this.value, idx, v)); | ||
} | ||
dissoc(idx: number) { | ||
this.turnListMode(); | ||
return new CrDataList(dissocList(this.value, idx)); | ||
} | ||
slice(from: number, to: number) { | ||
if (this.arrayMode) { | ||
if (from < 0) { | ||
throw new Error(`from index too small: ${from}`); | ||
} | ||
if (to > this.len()) { | ||
throw new Error(`end index too large: ${to}`); | ||
} | ||
let result = new CrDataList(this.arrayValue); | ||
result.arrayStart = this.arrayStart + from; | ||
result.arrayEnd = this.arrayStart + to; | ||
return result; | ||
} else { | ||
return new CrDataList(ternaryTree.slice(this.value, from, to)); | ||
} | ||
} | ||
toString() { | ||
let result = ""; | ||
for (let item of this.items()) { | ||
if (result !== "") { | ||
result = `${result}, `; | ||
} | ||
result = `${result}${toString(item, true)}`; | ||
} | ||
return `(${result})`; | ||
} | ||
isEmpty() { | ||
return this.len() === 0; | ||
} | ||
/** usage: `for of` */ | ||
items(): Generator<CrDataValue> { | ||
if (this.arrayMode) { | ||
return sliceGenerator(this.arrayValue, this.arrayStart, this.arrayEnd); | ||
} else { | ||
return listToItems(this.value); | ||
} | ||
} | ||
append(v: CrDataValue) { | ||
this.turnListMode(); | ||
return new CrDataList(ternaryTree.append(this.value, v)); | ||
} | ||
prepend(v: CrDataValue) { | ||
this.turnListMode(); | ||
return new CrDataList(ternaryTree.prepend(this.value, v)); | ||
} | ||
first() { | ||
if (this.arrayMode) { | ||
if (this.arrayValue.length > this.arrayStart) { | ||
return this.arrayValue[this.arrayStart]; | ||
} else { | ||
return null; | ||
} | ||
} else { | ||
return ternaryTree.first(this.value); | ||
} | ||
} | ||
rest() { | ||
if (this.arrayMode) { | ||
return this.slice(1, this.arrayEnd - this.arrayStart); | ||
} else { | ||
return new CrDataList(ternaryTree.rest(this.value)); | ||
} | ||
} | ||
concat(ys: CrDataList) { | ||
if (!(ys instanceof CrDataList)) { | ||
throw new Error("Expected list"); | ||
} | ||
this.turnListMode(); | ||
ys.turnListMode(); | ||
return new CrDataList(ternaryTree.concat(this.value, ys.value)); | ||
} | ||
map(f: (v: CrDataValue) => CrDataValue) { | ||
let result: Array<CrDataValue> = []; | ||
for (let item of this.items()) { | ||
result.push(f(item)); | ||
} | ||
return new CrDataList(result); | ||
} | ||
toArray(): CrDataValue[] { | ||
if (this.arrayMode) { | ||
return this.arrayValue.slice(this.arrayStart, this.arrayEnd); | ||
} else { | ||
return [...ternaryTree.listToItems(this.value)]; | ||
} | ||
} | ||
reverse() { | ||
this.turnListMode(); | ||
return new CrDataList(ternaryTree.reverse(this.value)); | ||
} | ||
} | ||
type MapChain = { | ||
value: TernaryTreeMap<CrDataValue, CrDataValue>; | ||
next: MapChain | null; | ||
}; | ||
// just create a reference that equals to no other value | ||
let fakeUniqueSymbol = [] as any; | ||
class CrDataMap { | ||
cachedHash: Hash; | ||
chain: MapChain; | ||
depth: number; | ||
skipValue: CrDataValue; | ||
constructor(value: TernaryTreeMap<CrDataValue, CrDataValue>) { | ||
this.chain = { value: value, next: null }; | ||
this.depth = 1; | ||
this.skipValue = fakeUniqueSymbol; | ||
} | ||
turnSingleMap() { | ||
if (this.depth === 1) { | ||
return; | ||
} | ||
// squash down to a single level of map | ||
let ret = this.chain.value; | ||
let cursor = this.chain.next; | ||
while (cursor != null) { | ||
if (!isMapEmpty(cursor.value)) { | ||
ret = ternaryTree.mergeSkip(cursor.value, ret, this.skipValue); | ||
} | ||
cursor = cursor.next; | ||
} | ||
this.chain = { | ||
value: ret, | ||
next: null, | ||
}; | ||
this.depth = 1; | ||
} | ||
len() { | ||
this.turnSingleMap(); | ||
return mapLen(this.chain.value); | ||
} | ||
get(k: CrDataValue) { | ||
let cursor = this.chain; | ||
while (cursor != null) { | ||
let v = mapGet(cursor.value, k); | ||
if (v != null && v !== this.skipValue) { | ||
return v; | ||
} else { | ||
cursor = cursor.next; | ||
} | ||
} | ||
return null; | ||
} | ||
assoc(k: CrDataValue, v: CrDataValue) { | ||
let cursor = this.chain; | ||
// mutable way of creating another map value | ||
let result = new CrDataMap(null); | ||
result.chain = { | ||
value: assocMap(cursor.value, k, v), | ||
next: cursor.next, | ||
}; | ||
return result; | ||
} | ||
dissoc(k: CrDataValue) { | ||
this.turnSingleMap(); | ||
return new CrDataMap(dissocMap(this.chain.value, k)); | ||
} | ||
toString() { | ||
let itemsCode = ""; | ||
for (let [k, v] of this.pairs()) { | ||
if (itemsCode !== "") { | ||
itemsCode = `${itemsCode}, `; | ||
} | ||
itemsCode = `${itemsCode}${toString(k, true)} ${toString(v, true)}`; | ||
} | ||
return `{${itemsCode}}`; | ||
} | ||
isEmpty() { | ||
let cursor = this.chain; | ||
while (cursor != null) { | ||
if (!isMapEmpty(cursor.value)) { | ||
return false; | ||
} | ||
cursor = cursor.next; | ||
} | ||
return true; | ||
} | ||
pairs(): Array<[CrDataValue, CrDataValue]> { | ||
this.turnSingleMap(); | ||
return toPairsArray(this.chain.value); | ||
} | ||
contains(k: CrDataValue) { | ||
let cursor = this.chain; | ||
while (cursor != null) { | ||
if (ternaryTree.contains(cursor.value, k)) { | ||
return true; | ||
} | ||
cursor = cursor.next; | ||
} | ||
return false; | ||
} | ||
merge(ys: CrDataMap) { | ||
return this.mergeSkip(ys, fakeUniqueSymbol); | ||
} | ||
mergeSkip(ys: CrDataMap, v: CrDataValue) { | ||
if (!(ys instanceof CrDataMap)) { | ||
throw new Error("Expected map"); | ||
} | ||
let result = new CrDataMap(null); | ||
result.skipValue = v; | ||
ys.turnSingleMap(); | ||
result.chain = { | ||
value: ys.chain.value, | ||
next: this.chain, | ||
}; | ||
result.depth = this.depth + 1; | ||
if (result.depth > 5) { | ||
// 5 by experience, limit to suqash linked list to value | ||
result.turnSingleMap(); | ||
} | ||
return result; | ||
} | ||
} | ||
type CrDataValue = | ||
| string | ||
| number | ||
| boolean | ||
| CrDataMap | ||
| CrDataList | ||
// TODO set | ||
| Set<CrDataValue> | ||
| CrDataKeyword | ||
| CrDataSymbol | ||
| CrDataAtom | ||
| CrDataFn | ||
| CrDataRecur // should not be exposed to function | ||
| null; | ||
var keywordRegistery: Record<string, CrDataKeyword> = {}; | ||
export let kwd = (content: string) => { | ||
let item = keywordRegistery[content]; | ||
if (item != null) { | ||
return item; | ||
} else { | ||
let v = new CrDataKeyword(content); | ||
keywordRegistery[content] = v; | ||
return v; | ||
} | ||
}; | ||
var atomsRegistry = new Map<string, CrDataAtom>(); | ||
function* sliceGenerator( | ||
xs: Array<CrDataValue>, | ||
start: number, | ||
end: number | ||
): Generator<CrDataValue> { | ||
for (let idx = start; idx < end; idx++) { | ||
yield xs[idx]; | ||
} | ||
} | ||
export let type_DASH_of = (x: any): CrDataKeyword => { | ||
@@ -417,3 +48,3 @@ if (typeof x === "string") { | ||
} | ||
if (x instanceof Set) { | ||
if (x instanceof CrDataSet) { | ||
return kwd("set"); | ||
@@ -455,4 +86,4 @@ } | ||
} | ||
if (x instanceof Set) { | ||
return (x as Set<CrDataValue>).size; | ||
if (x instanceof CrDataSet) { | ||
return x.len(); | ||
} | ||
@@ -495,7 +126,3 @@ throw new Error(`Unknown data ${x}`); | ||
export let foldl = function ( | ||
f: CrDataFn, | ||
acc: CrDataValue, | ||
xs: CrDataValue | ||
): CrDataValue { | ||
export let foldl = function (f: CrDataFn, acc: CrDataValue, xs: CrDataValue): CrDataValue { | ||
if (arguments.length !== 3) { | ||
@@ -517,5 +144,5 @@ throw new Error("foldl takes 3 arguments"); | ||
} | ||
if (xs instanceof Set) { | ||
if (xs instanceof CrDataSet) { | ||
let result = acc; | ||
xs.forEach((item) => { | ||
xs.value.forEach((item) => { | ||
result = f(result, item); | ||
@@ -612,11 +239,9 @@ }); | ||
} | ||
if (x instanceof Set) { | ||
if (y instanceof Set) { | ||
let x2 = x as Set<CrDataValue>; | ||
let y2 = y as Set<CrDataValue>; | ||
if (x2.size !== y2.size) { | ||
if (x instanceof CrDataSet) { | ||
if (y instanceof CrDataSet) { | ||
if (x.len() !== y.len()) { | ||
return false; | ||
} | ||
for (let v in x2.values()) { | ||
if (!y2.has(v)) { | ||
for (let v in x.value.values()) { | ||
if (!y.contains(v)) { | ||
return false; | ||
@@ -670,8 +295,6 @@ } | ||
} | ||
if (xs instanceof Set) { | ||
// TODO structure inside set | ||
return xs.has(x); | ||
if (xs instanceof CrDataSet) { | ||
return xs.contains(x); | ||
} | ||
// TODO set not handled | ||
throw new Error("Does not support contains? on this type"); | ||
@@ -720,5 +343,33 @@ }; | ||
throw new Error("Does not support `get` on this type"); | ||
throw new Error("Does not support `assoc` on this type"); | ||
}; | ||
export let assoc_DASH_before = function (xs: CrDataList, k: number, v: CrDataValue): CrDataList { | ||
if (arguments.length !== 3) { | ||
throw new Error("assoc takes 3 arguments"); | ||
} | ||
if (xs instanceof CrDataList) { | ||
if (typeof k !== "number") { | ||
throw new Error("Expected number index for lists"); | ||
} | ||
return xs.assocBefore(k, v); | ||
} | ||
throw new Error("Does not support `assoc-before` on this type"); | ||
}; | ||
export let assoc_DASH_after = function (xs: CrDataList, k: number, v: CrDataValue): CrDataList { | ||
if (arguments.length !== 3) { | ||
throw new Error("assoc takes 3 arguments"); | ||
} | ||
if (xs instanceof CrDataList) { | ||
if (typeof k !== "number") { | ||
throw new Error("Expected number index for lists"); | ||
} | ||
return xs.assocAfter(k, v); | ||
} | ||
throw new Error("Does not support `assoc-after` on this type"); | ||
}; | ||
export let dissoc = function (xs: CrDataValue, k: CrDataValue) { | ||
@@ -754,7 +405,3 @@ if (arguments.length !== 2) { | ||
export let add_DASH_watch = ( | ||
a: CrDataAtom, | ||
k: CrDataKeyword, | ||
f: CrDataFn | ||
): null => { | ||
export let add_DASH_watch = (a: CrDataAtom, k: CrDataKeyword, f: CrDataFn): null => { | ||
if (!(a instanceof CrDataAtom)) { | ||
@@ -809,4 +456,4 @@ throw new Error("Expected atom for add-watch!"); | ||
} | ||
if (xs instanceof Set) { | ||
return xs.size === 0; | ||
if (xs instanceof CrDataSet) { | ||
return xs.len() === 0; | ||
} | ||
@@ -862,9 +509,4 @@ if (xs == null) { | ||
} | ||
if (xs instanceof Set) { | ||
if (xs.size === 0) { | ||
return null; | ||
} | ||
for (let x of xs) { | ||
return x; | ||
} | ||
if (xs instanceof CrDataSet) { | ||
return xs.first(); | ||
} | ||
@@ -896,11 +538,4 @@ console.error(xs); | ||
} | ||
if (xs instanceof Set) { | ||
if (xs.size == 0) { | ||
return null; | ||
} | ||
let it = xs.values(); | ||
let x0 = it.next().value; | ||
let ys = cloneSet(xs); | ||
ys.delete(x0); | ||
return ys; | ||
if (xs instanceof CrDataSet) { | ||
return xs.rest(); | ||
} | ||
@@ -983,3 +618,3 @@ console.error(xs); | ||
} | ||
return result; | ||
return new CrDataSet(result); | ||
}; | ||
@@ -1115,6 +750,3 @@ | ||
export let _AND_merge_DASH_non_DASH_nil = ( | ||
a: CrDataMap, | ||
b: CrDataMap | ||
): CrDataMap => { | ||
export let _AND_merge_DASH_non_DASH_nil = (a: CrDataMap, b: CrDataMap): CrDataMap => { | ||
if (a == null) { | ||
@@ -1136,3 +768,3 @@ return b; | ||
export let to_DASH_pairs = (xs: CrDataMap): Set<CrDataList> => { | ||
export let to_DASH_pairs = (xs: CrDataMap): CrDataSet => { | ||
if (!(xs instanceof CrDataMap)) { | ||
@@ -1145,5 +777,7 @@ throw new Error("Expected a map"); | ||
} | ||
return result; | ||
return new CrDataSet(result); | ||
}; | ||
// Math functions | ||
export let sin = (n: number) => { | ||
@@ -1168,67 +802,53 @@ return Math.sin(n); | ||
export let cloneSet = (xs: Set<CrDataValue>): Set<CrDataValue> => { | ||
if (!(xs instanceof Set)) { | ||
// Set functions | ||
export let _AND_include = (xs: CrDataSet, y: CrDataValue): CrDataSet => { | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
var result: Set<CrDataValue> = new Set(); | ||
for (let v of xs) { | ||
result.add(v); | ||
if (y == null) { | ||
return xs; | ||
} | ||
return result; | ||
return xs.include(y); | ||
}; | ||
export let _AND_include = ( | ||
xs: Set<CrDataValue>, | ||
y: CrDataValue | ||
): Set<CrDataValue> => { | ||
var result = cloneSet(xs); | ||
result.add(y); | ||
return result; | ||
export let _AND_exclude = (xs: CrDataSet, y: CrDataValue): CrDataSet => { | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (y == null) { | ||
return xs; | ||
} | ||
return xs.exclude(y); | ||
}; | ||
export let _AND_exclude = ( | ||
xs: Set<CrDataValue>, | ||
y: CrDataValue | ||
): Set<CrDataValue> => { | ||
var result = cloneSet(xs); | ||
result.delete(y); | ||
return result; | ||
export let _AND_difference = (xs: CrDataSet, ys: CrDataSet): CrDataSet => { | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (!(ys instanceof CrDataSet)) { | ||
throw new Error("Expected a set for ys"); | ||
} | ||
return xs.difference(ys); | ||
}; | ||
export let _AND_difference = ( | ||
xs: Set<CrDataValue>, | ||
ys: Set<CrDataValue> | ||
): Set<CrDataValue> => { | ||
var result = cloneSet(xs); | ||
ys.forEach((y) => { | ||
if (result.has(y)) { | ||
result.delete(y); | ||
} | ||
}); | ||
return result; | ||
export let _AND_union = (xs: CrDataSet, ys: CrDataSet): CrDataSet => { | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (!(ys instanceof CrDataSet)) { | ||
throw new Error("Expected a set for ys"); | ||
} | ||
return xs.union(ys); | ||
}; | ||
export let _AND_union = ( | ||
xs: Set<CrDataValue>, | ||
ys: Set<CrDataValue> | ||
): Set<CrDataValue> => { | ||
var result = cloneSet(xs); | ||
ys.forEach((y) => { | ||
if (!result.has(y)) { | ||
result.add(y); | ||
} | ||
}); | ||
return result; | ||
export let _AND_intersection = (xs: CrDataSet, ys: CrDataSet): CrDataSet => { | ||
if (!(xs instanceof CrDataSet)) { | ||
throw new Error("Expected a set"); | ||
} | ||
if (!(ys instanceof CrDataSet)) { | ||
throw new Error("Expected a set for ys"); | ||
} | ||
return xs.intersection(ys); | ||
}; | ||
export let _AND_intersection = ( | ||
xs: Set<CrDataValue>, | ||
ys: Set<CrDataValue> | ||
): Set<CrDataValue> => { | ||
var result: Set<CrDataValue> = new Set(); | ||
ys.forEach((y) => { | ||
if (xs.has(y)) { | ||
result.add(y); | ||
} | ||
}); | ||
return result; | ||
}; | ||
@@ -1306,13 +926,7 @@ export let replace = (x: string, y: string, z: string): string => { | ||
export let re_DASH_find_DASH_all = ( | ||
re: string, | ||
content: string | ||
): CrDataList => { | ||
export let re_DASH_find_DASH_all = (re: string, content: string): CrDataList => { | ||
return new CrDataList(content.match(new RegExp(re, "g"))); | ||
}; | ||
export let to_DASH_js_DASH_data = ( | ||
x: CrDataValue, | ||
addColon: boolean = false | ||
): any => { | ||
export let to_DASH_js_DASH_data = (x: CrDataValue, addColon: boolean = false): any => { | ||
if (x == null) { | ||
@@ -1362,3 +976,3 @@ return null; | ||
export let to_DASH_calcit_DASH_data = (x: any, noKeyword: boolean = false) => { | ||
export let to_DASH_calcit_DASH_data = (x: any, noKeyword: boolean = false): CrDataValue => { | ||
if (x == null) { | ||
@@ -1391,3 +1005,3 @@ return null; | ||
}); | ||
return result; | ||
return new CrDataSet(result); | ||
} | ||
@@ -1398,6 +1012,3 @@ // detects object | ||
Object.keys(x).forEach((k) => { | ||
result.set( | ||
to_DASH_calcit_DASH_data(k, noKeyword), | ||
to_DASH_calcit_DASH_data(x[k], noKeyword) | ||
); | ||
result.set(to_DASH_calcit_DASH_data(k, noKeyword), to_DASH_calcit_DASH_data(x[k], noKeyword)); | ||
}); | ||
@@ -1415,12 +1026,9 @@ return new CrDataMap(initTernaryTreeMap(result)); | ||
export let stringify_DASH_json = ( | ||
x: CrDataValue, | ||
addColon: boolean = false | ||
): string => { | ||
export let stringify_DASH_json = (x: CrDataValue, addColon: boolean = false): string => { | ||
return JSON.stringify(to_DASH_js_DASH_data(x, addColon)); | ||
}; | ||
export let set_DASH__GT_list = (x: Set<CrDataValue>): CrDataList => { | ||
export let set_DASH__GT_list = (x: CrDataSet): CrDataList => { | ||
var result: CrDataValue[] = []; | ||
x.forEach((item) => { | ||
x.value.forEach((item) => { | ||
result.push(item); | ||
@@ -1477,49 +1085,2 @@ }); | ||
let toString = (x: CrDataValue, escaped: boolean): string => { | ||
if (x == null) { | ||
return "nil"; | ||
} | ||
if (typeof x === "string") { | ||
if (escaped) { | ||
return JSON.stringify(x); | ||
} else { | ||
return x; | ||
} | ||
} | ||
if (typeof x === "number") { | ||
return x.toString(); | ||
} | ||
if (typeof x === "boolean") { | ||
return x.toString(); | ||
} | ||
if (typeof x === "function") { | ||
return `(&fn ...)`; | ||
} | ||
if (x instanceof CrDataSymbol) { | ||
return x.toString(); | ||
} | ||
if (x instanceof CrDataKeyword) { | ||
return x.toString(); | ||
} | ||
if (x instanceof CrDataList) { | ||
return x.toString(); | ||
} | ||
if (x instanceof CrDataMap) { | ||
return x.toString(); | ||
} | ||
if (x instanceof Set) { | ||
let itemsCode = ""; | ||
x.forEach((child, idx) => { | ||
if (idx > 0) { | ||
itemsCode = `${itemsCode} `; | ||
} | ||
itemsCode = `${itemsCode}${toString(child, true)}`; | ||
}); | ||
return `#{${itemsCode}}`; | ||
} | ||
console.error(x); | ||
throw new Error("Unexpected data for toString"); | ||
}; | ||
export let pr_DASH_str = (...args: CrDataValue[]): string => { | ||
@@ -1599,5 +1160,3 @@ return args.map((x) => toString(x, true)).join(" "); | ||
// TODO can be faster | ||
return (["[]"] as CirruEdnFormat[]).concat( | ||
x.toArray().map(to_DASH_cirru_DASH_edn) | ||
); | ||
return (["[]"] as CirruEdnFormat[]).concat(x.toArray().map(to_DASH_cirru_DASH_edn)); | ||
} | ||
@@ -1660,6 +1219,3 @@ if (x instanceof CrDataMap) { | ||
if (pair instanceof Array && pair.length == 2) { | ||
result.set( | ||
extract_DASH_cirru_DASH_edn(pair[0]), | ||
extract_DASH_cirru_DASH_edn(pair[1]) | ||
); | ||
result.set(extract_DASH_cirru_DASH_edn(pair[0]), extract_DASH_cirru_DASH_edn(pair[1])); | ||
} else { | ||
@@ -1675,3 +1231,3 @@ throw new Error("Expected pairs for map"); | ||
if (x[0] === "#{}") { | ||
return new Set(x.slice(1).map(extract_DASH_cirru_DASH_edn)); | ||
return new CrDataSet(new Set(x.slice(1).map(extract_DASH_cirru_DASH_edn))); | ||
} | ||
@@ -1728,89 +1284,2 @@ if (x[0] === "do" && x.length === 2) { | ||
let defaultHash_nil = valueHash("nil:"); | ||
let defaultHash_number = valueHash("number:"); | ||
let defaultHash_string = valueHash("string:"); | ||
let defaultHash_keyword = valueHash("keyword:"); | ||
let defaultHash_true = valueHash("true:"); | ||
let defaultHash_false = valueHash("false:"); | ||
let defaultHash_symbol = valueHash("symbol:"); | ||
let defaultHash_fn = valueHash("fn:"); | ||
let defaultHash_atom = valueHash("atom:"); | ||
let defaultHash_set = valueHash("set:"); | ||
let defaultHash_list = valueHash("list:"); | ||
let defaultHash_map = valueHash("map:"); | ||
let fnHashCounter = 0; | ||
let hashFunction = (x: CrDataValue): Hash => { | ||
if (x == null) { | ||
return defaultHash_nil; | ||
} | ||
if (typeof x === "number") { | ||
return mergeValueHash(defaultHash_number, x); | ||
} | ||
if (typeof x === "string") { | ||
return mergeValueHash(defaultHash_string, x); | ||
} | ||
// dirty solution of caching, trying to reduce cost | ||
if ((x as any).cachedHash != null) { | ||
return (x as any).cachedHash; | ||
} | ||
if (x instanceof CrDataKeyword) { | ||
let h = mergeValueHash(defaultHash_keyword, x.value); | ||
x.cachedHash = h; | ||
return h; | ||
} | ||
if (x === true) { | ||
return defaultHash_true; | ||
} | ||
if (x === false) { | ||
return defaultHash_false; | ||
} | ||
if (x instanceof CrDataSymbol) { | ||
let h = mergeValueHash(defaultHash_symbol, x.value); | ||
x.cachedHash = h; | ||
return h; | ||
} | ||
if (typeof x === "function") { | ||
fnHashCounter = fnHashCounter + 1; | ||
let h = mergeValueHash(defaultHash_fn, fnHashCounter); | ||
(x as any).cachedHash = h; | ||
return h; | ||
} | ||
if (x instanceof CrDataAtom) { | ||
let h = mergeValueHash(defaultHash_atom, x.path); | ||
x.cachedHash = h; | ||
return h; | ||
} | ||
if (x instanceof Set) { | ||
// TODO not using dirty solution for code | ||
let base = defaultHash_set; | ||
for (let item of x) { | ||
base = mergeValueHash(base, hashFunction(item)); | ||
} | ||
return base; | ||
} | ||
if (x instanceof CrDataList) { | ||
let base = defaultHash_list; | ||
for (let item of x.items()) { | ||
base = mergeValueHash(base, hashFunction(item)); | ||
} | ||
x.cachedHash = base; | ||
return base; | ||
} | ||
if (x instanceof CrDataMap) { | ||
let base = defaultHash_map; | ||
for (let [k, v] of x.pairs()) { | ||
base = mergeValueHash(base, hashFunction(k)); | ||
base = mergeValueHash(base, hashFunction(v)); | ||
} | ||
x.cachedHash = base; | ||
return base; | ||
} | ||
throw new Error("Unknown data for hashing"); | ||
}; | ||
// Dirty code to change ternary-tree behavior | ||
overwriteHashGenerator(hashFunction); | ||
export let number_QUES_ = (x: CrDataValue): boolean => { | ||
@@ -1838,3 +1307,3 @@ return typeof x === "number"; | ||
export let set_QUES_ = (x: CrDataValue): boolean => { | ||
return x instanceof Set; | ||
return x instanceof CrDataSet; | ||
}; | ||
@@ -1848,2 +1317,23 @@ export let fn_QUES_ = (x: CrDataValue): boolean => { | ||
export let escape = (x: string) => JSON.stringify(x); | ||
export let read_DASH_file = (path: string): string => { | ||
if (inNodeJs) { | ||
// TODO | ||
(globalThis as any)["__calcit_injections__"].read_DASH_file(path); | ||
} else { | ||
// no actual File API in browser | ||
return localStorage.get(path) ?? ""; | ||
} | ||
}; | ||
export let write_DASH_file = (path: string, content: string): void => { | ||
if (inNodeJs) { | ||
// TODO | ||
(globalThis as any)["__calcit_injections__"].write_DASH_file(path, content); | ||
} else { | ||
// no actual File API in browser | ||
localStorage.setItem(path, content); | ||
} | ||
}; | ||
// special procs have to be defined manually | ||
@@ -1853,23 +1343,20 @@ export let reduce = foldl; | ||
let placeholder = (...xs: []) => { | ||
/* placeholder */ | ||
let unavailableProc = (...xs: []) => { | ||
console.warn("NOT available for calcit-js"); | ||
}; | ||
// TODO these functions are not used by calcit-js, but added to fix missing imports | ||
export let _AND_reset_DASH_gensym_DASH_index_BANG_ = placeholder; | ||
export let assoc_DASH_after = placeholder; | ||
export let assoc_DASH_before = placeholder; | ||
export let dbt_DASH__GT_point = placeholder; | ||
export let dbt_DASH_digits = placeholder; | ||
export let dual_DASH_balanced_DASH_ternary = placeholder; | ||
export let escape = placeholder; | ||
export let format_DASH_time = placeholder; | ||
export let gensym = placeholder; | ||
export let macroexpand = placeholder; | ||
export let macroexpand_DASH_all = placeholder; | ||
export let now_BANG_ = placeholder; | ||
export let parse_DASH_cirru = placeholder; | ||
export let parse_DASH_cirru_DASH_edn = placeholder; | ||
export let parse_DASH_time = placeholder; | ||
export let read_DASH_file = placeholder; | ||
export let write_DASH_file = placeholder; | ||
export let format_DASH_time = unavailableProc; // TODO | ||
export let now_BANG_ = unavailableProc; // TODO | ||
export let parse_DASH_time = unavailableProc; // TODO | ||
export let parse_DASH_cirru = unavailableProc; // TODO | ||
export let parse_DASH_cirru_DASH_edn = unavailableProc; // TODO | ||
// not available for calcit-js | ||
export let _AND_reset_DASH_gensym_DASH_index_BANG_ = unavailableProc; | ||
export let dbt_DASH__GT_point = unavailableProc; | ||
export let dbt_DASH_digits = unavailableProc; | ||
export let dual_DASH_balanced_DASH_ternary = unavailableProc; | ||
export let gensym = unavailableProc; | ||
export let macroexpand = unavailableProc; | ||
export let macroexpand_DASH_all = unavailableProc; |
{ | ||
"name": "@calcit/procs", | ||
"version": "v0.2.44", | ||
"version": "0.2.45", | ||
"main": "./lib/calcit.procs.js", | ||
@@ -5,0 +5,0 @@ "devDependencies": { |
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
96195
9
3552
0