@calcit/procs 0.5.0-a6 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/calcit-data.js +37 -18
- package/lib/calcit.procs.js +77 -76
- package/lib/custom-formatter.js +11 -11
- package/lib/js-cirru.js +20 -20
- package/lib/js-list.js +190 -117
- package/lib/js-map.js +194 -130
- package/lib/js-record.js +7 -7
- package/lib/js-set.js +5 -5
- package/lib/js-tuple.js +4 -4
- package/package.json +6 -6
- package/ts-src/calcit-data.ts +37 -18
- package/ts-src/calcit.procs.ts +99 -98
- package/ts-src/custom-formatter.ts +10 -10
- package/ts-src/js-cirru.ts +22 -22
- package/ts-src/js-list.ts +195 -121
- package/ts-src/js-map.ts +216 -135
- package/ts-src/js-primes.ts +5 -3
- package/ts-src/js-record.ts +6 -6
- package/ts-src/js-set.ts +18 -5
- package/ts-src/js-tuple.ts +4 -4
package/ts-src/js-map.ts
CHANGED
|
@@ -3,7 +3,19 @@ import * as ternaryTree from "@calcit/ternary-tree";
|
|
|
3
3
|
import { CalcitValue } from "./js-primes";
|
|
4
4
|
import { CalcitSet } from "./js-set";
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
TernaryTreeMap,
|
|
8
|
+
initTernaryTreeMap,
|
|
9
|
+
mapLen,
|
|
10
|
+
assocMap,
|
|
11
|
+
dissocMap,
|
|
12
|
+
isMapEmpty,
|
|
13
|
+
Hash,
|
|
14
|
+
toPairsArray,
|
|
15
|
+
mapGetDefault,
|
|
16
|
+
initEmptyTernaryTreeMap,
|
|
17
|
+
initTernaryTreeMapFromArray,
|
|
18
|
+
} from "@calcit/ternary-tree";
|
|
7
19
|
|
|
8
20
|
import { isNestedCalcitData, tipNestedCalcitData, toString } from "./calcit-data";
|
|
9
21
|
|
|
@@ -21,62 +33,192 @@ let fakeUniqueSymbol = [] as any;
|
|
|
21
33
|
|
|
22
34
|
export class CalcitMap {
|
|
23
35
|
cachedHash: Hash;
|
|
24
|
-
/** in arrayMode, only flatten values, not tree structure */
|
|
25
|
-
arrayMode: boolean;
|
|
26
|
-
arrayValue: CalcitValue[];
|
|
27
36
|
value: TernaryTreeMap<CalcitValue, CalcitValue>;
|
|
28
|
-
|
|
29
|
-
constructor(value: CalcitValue[] | TernaryTreeMap<CalcitValue, CalcitValue>) {
|
|
37
|
+
constructor(value: TernaryTreeMap<CalcitValue, CalcitValue>) {
|
|
30
38
|
if (value == null) {
|
|
31
|
-
this.
|
|
32
|
-
this.arrayValue = [];
|
|
33
|
-
} else if (Array.isArray(value)) {
|
|
34
|
-
this.arrayMode = true;
|
|
35
|
-
this.arrayValue = value;
|
|
39
|
+
this.value = initEmptyTernaryTreeMap();
|
|
36
40
|
} else {
|
|
37
|
-
this.arrayMode = false;
|
|
38
41
|
this.value = value;
|
|
39
42
|
}
|
|
40
43
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
len() {
|
|
45
|
+
return mapLen(this.value);
|
|
46
|
+
}
|
|
47
|
+
get(k: CalcitValue) {
|
|
48
|
+
return mapGetDefault(this.value, k, null);
|
|
49
|
+
}
|
|
50
|
+
assoc(...args: CalcitValue[]) {
|
|
51
|
+
if (args.length % 2 !== 0) throw new Error("expected even arguments");
|
|
52
|
+
let size = Math.floor(args.length / 2);
|
|
53
|
+
|
|
54
|
+
let result = this.value;
|
|
55
|
+
for (let idx = 0; idx < size; idx++) {
|
|
56
|
+
let k = args[idx << 1];
|
|
57
|
+
let v = args[(idx << 1) + 1];
|
|
58
|
+
result = assocMap(result, k, v);
|
|
59
|
+
}
|
|
60
|
+
return new CalcitMap(result);
|
|
61
|
+
}
|
|
62
|
+
dissoc(...args: CalcitValue[]) {
|
|
63
|
+
let ret = this.value;
|
|
64
|
+
for (let idx = 0; idx < args.length; idx++) {
|
|
65
|
+
ret = dissocMap(ret, args[idx]);
|
|
66
|
+
}
|
|
67
|
+
return new CalcitMap(ret);
|
|
68
|
+
}
|
|
69
|
+
toString(shorter = false) {
|
|
70
|
+
let itemsCode = "";
|
|
71
|
+
for (let [k, v] of this.pairs()) {
|
|
72
|
+
if (shorter) {
|
|
73
|
+
let keyPart = isNestedCalcitData(k) ? tipNestedCalcitData(k) : toString(k, true);
|
|
74
|
+
let valuePart = isNestedCalcitData(v) ? tipNestedCalcitData(v) : toString(v, true);
|
|
75
|
+
itemsCode = `${itemsCode} (${keyPart} ${valuePart})`;
|
|
76
|
+
} else {
|
|
77
|
+
itemsCode = `${itemsCode} (${toString(k, true)} ${toString(v, true)})`;
|
|
47
78
|
}
|
|
48
|
-
this.value = initTernaryTreeMap(dict);
|
|
49
|
-
this.arrayMode = false;
|
|
50
|
-
this.arrayValue = null;
|
|
51
79
|
}
|
|
80
|
+
return `({}${itemsCode})`;
|
|
52
81
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
82
|
+
isEmpty() {
|
|
83
|
+
return isMapEmpty(this.value);
|
|
84
|
+
}
|
|
85
|
+
pairs(): Array<[CalcitValue, CalcitValue]> {
|
|
86
|
+
return toPairsArray(this.value);
|
|
87
|
+
}
|
|
88
|
+
keysArray(): Array<CalcitValue> {
|
|
89
|
+
return [...ternaryTree.toKeys(this.value)];
|
|
90
|
+
}
|
|
91
|
+
contains(k: CalcitValue) {
|
|
92
|
+
return ternaryTree.contains(this.value, k);
|
|
93
|
+
}
|
|
94
|
+
merge(ys: CalcitMap | CalcitSliceMap) {
|
|
95
|
+
return this.mergeSkip(ys, fakeUniqueSymbol);
|
|
96
|
+
}
|
|
97
|
+
mergeSkip(ys: CalcitMap | CalcitSliceMap, v: CalcitValue) {
|
|
98
|
+
if (ys == null) {
|
|
99
|
+
return this;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (!(ys instanceof CalcitMap || ys instanceof CalcitSliceMap)) {
|
|
103
|
+
console.error("value:", v);
|
|
104
|
+
throw new Error("Expected map to merge");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (ys instanceof CalcitSliceMap) {
|
|
108
|
+
let ret = this.value;
|
|
109
|
+
let size = ys.chunk.length >> 1;
|
|
110
|
+
for (let i = 0; i < size; i++) {
|
|
111
|
+
let pos = i << 1;
|
|
112
|
+
if (ys.chunk[pos + 1] === v) {
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
ret = assocMap(ret, ys.chunk[pos], ys.chunk[pos + 1]);
|
|
116
|
+
}
|
|
117
|
+
return new CalcitMap(ret);
|
|
56
118
|
} else {
|
|
57
|
-
return
|
|
119
|
+
return new CalcitMap(ternaryTree.mergeSkip(this.value, ys.value, v));
|
|
58
120
|
}
|
|
59
121
|
}
|
|
122
|
+
|
|
123
|
+
/** TODO implement diff with low level code, opens opportunity for future optimizations */
|
|
124
|
+
diffNew(ys: CalcitMap | CalcitSliceMap): CalcitMap {
|
|
125
|
+
let zs = this.value;
|
|
126
|
+
if (ys instanceof CalcitSliceMap) {
|
|
127
|
+
let size = ys.chunk.length >> 1;
|
|
128
|
+
for (let i = 0; i < size; i++) {
|
|
129
|
+
let pos = i << 1;
|
|
130
|
+
let k = ys.chunk[pos];
|
|
131
|
+
if (ternaryTree.contains(zs, k)) {
|
|
132
|
+
zs = ternaryTree.dissocMap(zs, k);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return new CalcitMap(zs);
|
|
136
|
+
} else if (ys instanceof CalcitMap) {
|
|
137
|
+
let ysKeys = ys.keysArray();
|
|
138
|
+
for (let i = 0; i < ysKeys.length; i++) {
|
|
139
|
+
let k = ysKeys[i];
|
|
140
|
+
if (ternaryTree.contains(zs, k)) {
|
|
141
|
+
zs = ternaryTree.dissocMap(zs, k);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return new CalcitMap(zs);
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error("unknown data to diff");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** TODO implement diff with low level code, opens opportunity for future optimizations */
|
|
151
|
+
diffKeys(ys: CalcitMap | CalcitSliceMap): CalcitSet {
|
|
152
|
+
let ret: Array<CalcitValue> = [];
|
|
153
|
+
let ks = this.keysArray();
|
|
154
|
+
for (let i = 0; i < ks.length; i++) {
|
|
155
|
+
let k = ks[i];
|
|
156
|
+
if (!ys.contains(k)) {
|
|
157
|
+
ret.push(k);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return new CalcitSet(ret);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** TODO implement diff with low level code, opens opportunity for future optimizations */
|
|
164
|
+
commonKeys(ys: CalcitMap | CalcitSliceMap): CalcitSet {
|
|
165
|
+
let ret: Array<CalcitValue> = [];
|
|
166
|
+
let ks = this.keysArray();
|
|
167
|
+
for (let i = 0; i < ks.length; i++) {
|
|
168
|
+
let k = ks[i];
|
|
169
|
+
if (ys.contains(k)) {
|
|
170
|
+
ret.push(k);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return new CalcitSet(ret);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// store small map in linear array to reduce cost of building tree
|
|
178
|
+
export class CalcitSliceMap {
|
|
179
|
+
cachedHash: Hash;
|
|
180
|
+
/** in arrayMode, only flatten values, instead of tree structure */
|
|
181
|
+
chunk: CalcitValue[];
|
|
182
|
+
constructor(value: CalcitValue[]) {
|
|
183
|
+
if (value == null) {
|
|
184
|
+
this.chunk = [];
|
|
185
|
+
} else if (Array.isArray(value)) {
|
|
186
|
+
this.chunk = value;
|
|
187
|
+
} else {
|
|
188
|
+
throw new Error("unknown data for map");
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
turnMap(): CalcitMap {
|
|
192
|
+
var dict: Array<[CalcitValue, CalcitValue]> = [];
|
|
193
|
+
let halfLength = this.chunk.length >> 1;
|
|
194
|
+
for (let idx = 0; idx < halfLength; idx++) {
|
|
195
|
+
dict.push([this.chunk[idx << 1], this.chunk[(idx << 1) + 1]]);
|
|
196
|
+
}
|
|
197
|
+
let value = initTernaryTreeMapFromArray(dict);
|
|
198
|
+
return new CalcitMap(value);
|
|
199
|
+
}
|
|
200
|
+
len() {
|
|
201
|
+
return this.chunk.length >> 1;
|
|
202
|
+
}
|
|
60
203
|
get(k: CalcitValue) {
|
|
61
|
-
if (this.
|
|
62
|
-
let size = this.
|
|
204
|
+
if (this.chunk.length <= 16) {
|
|
205
|
+
let size = this.chunk.length >> 1;
|
|
63
206
|
for (let i = 0; i < size; i++) {
|
|
64
207
|
let pos = i << 1;
|
|
65
|
-
if (DATA_EQUAL(this.
|
|
66
|
-
return this.
|
|
208
|
+
if (DATA_EQUAL(this.chunk[pos], k)) {
|
|
209
|
+
return this.chunk[pos + 1];
|
|
67
210
|
}
|
|
68
211
|
}
|
|
69
212
|
return null;
|
|
70
213
|
} else {
|
|
71
|
-
this.turnMap();
|
|
72
|
-
return mapGetDefault(this.value, k, null);
|
|
214
|
+
return this.turnMap().get(k);
|
|
73
215
|
}
|
|
74
216
|
}
|
|
75
217
|
assoc(...args: CalcitValue[]) {
|
|
76
218
|
if (args.length % 2 !== 0) throw new Error("expected even arguments");
|
|
77
219
|
let size = Math.floor(args.length / 2);
|
|
78
|
-
if (this.
|
|
79
|
-
let ret = this.
|
|
220
|
+
if (this.chunk.length <= 16) {
|
|
221
|
+
let ret = this.chunk.slice(0);
|
|
80
222
|
outer: for (let j = 0; j < size; j++) {
|
|
81
223
|
let k = args[j << 1];
|
|
82
224
|
let v = args[(j << 1) + 1];
|
|
@@ -88,38 +230,26 @@ export class CalcitMap {
|
|
|
88
230
|
}
|
|
89
231
|
ret.push(k, v);
|
|
90
232
|
}
|
|
91
|
-
return new
|
|
233
|
+
return new CalcitSliceMap(ret);
|
|
92
234
|
} else {
|
|
93
|
-
this.turnMap();
|
|
94
|
-
let result = this.value;
|
|
95
|
-
for (let idx = 0; idx < size; idx++) {
|
|
96
|
-
let k = args[idx << 1];
|
|
97
|
-
let v = args[(idx << 1) + 1];
|
|
98
|
-
result = assocMap(result, k, v);
|
|
99
|
-
}
|
|
100
|
-
return new CalcitMap(result);
|
|
235
|
+
return this.turnMap().assoc(...args);
|
|
101
236
|
}
|
|
102
237
|
}
|
|
103
238
|
dissoc(...args: CalcitValue[]) {
|
|
104
|
-
if (this.
|
|
239
|
+
if (this.chunk.length <= 16) {
|
|
105
240
|
let ret: CalcitValue[] = [];
|
|
106
|
-
outer: for (let i = 0; i < this.
|
|
241
|
+
outer: for (let i = 0; i < this.chunk.length; i += 2) {
|
|
107
242
|
for (let j = 0; j < args.length; j++) {
|
|
108
243
|
let k = args[j];
|
|
109
|
-
if (DATA_EQUAL(k, this.
|
|
244
|
+
if (DATA_EQUAL(k, this.chunk[i])) {
|
|
110
245
|
continue outer;
|
|
111
246
|
}
|
|
112
247
|
}
|
|
113
|
-
ret.push(this.
|
|
248
|
+
ret.push(this.chunk[i], this.chunk[i + 1]);
|
|
114
249
|
}
|
|
115
|
-
return new
|
|
250
|
+
return new CalcitSliceMap(ret);
|
|
116
251
|
} else {
|
|
117
|
-
this.turnMap();
|
|
118
|
-
let ret = this.value;
|
|
119
|
-
for (let idx = 0; idx < args.length; idx++) {
|
|
120
|
-
ret = dissocMap(ret, args[idx]);
|
|
121
|
-
}
|
|
122
|
-
return new CalcitMap(ret);
|
|
252
|
+
return this.turnMap().dissoc(...args);
|
|
123
253
|
}
|
|
124
254
|
}
|
|
125
255
|
toString(shorter = false) {
|
|
@@ -136,131 +266,82 @@ export class CalcitMap {
|
|
|
136
266
|
return `({}${itemsCode})`;
|
|
137
267
|
}
|
|
138
268
|
isEmpty() {
|
|
139
|
-
|
|
140
|
-
return this.arrayValue.length === 0;
|
|
141
|
-
} else {
|
|
142
|
-
return isMapEmpty(this.value);
|
|
143
|
-
}
|
|
269
|
+
return this.chunk.length === 0;
|
|
144
270
|
}
|
|
145
271
|
pairs(): Array<[CalcitValue, CalcitValue]> {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
ret.push([this.arrayValue[pos], this.arrayValue[pos + 1]]);
|
|
152
|
-
}
|
|
153
|
-
return ret;
|
|
154
|
-
} else {
|
|
155
|
-
return toPairsArray(this.value);
|
|
272
|
+
let ret: Array<[CalcitValue, CalcitValue]> = [];
|
|
273
|
+
let size = this.chunk.length >> 1;
|
|
274
|
+
for (let i = 0; i < size; i++) {
|
|
275
|
+
let pos = i << 1;
|
|
276
|
+
ret.push([this.chunk[pos], this.chunk[pos + 1]]);
|
|
156
277
|
}
|
|
278
|
+
return ret;
|
|
157
279
|
}
|
|
158
280
|
keysArray(): Array<CalcitValue> {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
ret.push(this.arrayValue[pos]);
|
|
165
|
-
}
|
|
166
|
-
return ret;
|
|
167
|
-
} else {
|
|
168
|
-
return [...ternaryTree.toKeys(this.value)];
|
|
281
|
+
let ret: Array<CalcitValue> = [];
|
|
282
|
+
let size = this.chunk.length >> 1;
|
|
283
|
+
for (let i = 0; i < size; i++) {
|
|
284
|
+
let pos = i << 1;
|
|
285
|
+
ret.push(this.chunk[pos]);
|
|
169
286
|
}
|
|
287
|
+
return ret;
|
|
170
288
|
}
|
|
171
289
|
contains(k: CalcitValue) {
|
|
172
|
-
if (this.
|
|
290
|
+
if (this.chunk.length <= 16) {
|
|
173
291
|
// guessed number
|
|
174
|
-
let size = this.
|
|
292
|
+
let size = this.chunk.length >> 1;
|
|
175
293
|
for (let i = 0; i < size; i++) {
|
|
176
294
|
let pos = i << 1;
|
|
177
|
-
if (DATA_EQUAL(this.
|
|
295
|
+
if (DATA_EQUAL(this.chunk[pos], k)) {
|
|
178
296
|
return true;
|
|
179
297
|
}
|
|
180
298
|
}
|
|
181
299
|
return false;
|
|
182
300
|
} else {
|
|
183
|
-
this.turnMap();
|
|
184
|
-
return ternaryTree.contains(this.value, k);
|
|
301
|
+
return this.turnMap().contains(k);
|
|
185
302
|
}
|
|
186
303
|
}
|
|
187
|
-
merge(ys: CalcitMap) {
|
|
304
|
+
merge(ys: CalcitMap | CalcitSliceMap) {
|
|
188
305
|
return this.mergeSkip(ys, fakeUniqueSymbol);
|
|
189
306
|
}
|
|
190
|
-
mergeSkip(ys: CalcitMap, v: CalcitValue) {
|
|
307
|
+
mergeSkip(ys: CalcitMap | CalcitSliceMap, v: CalcitValue) {
|
|
191
308
|
if (ys == null) {
|
|
192
309
|
return this;
|
|
193
310
|
}
|
|
194
311
|
|
|
195
|
-
if (!(ys instanceof CalcitMap)) {
|
|
312
|
+
if (!(ys instanceof CalcitMap || ys instanceof CalcitSliceMap)) {
|
|
196
313
|
console.error("value:", v);
|
|
197
314
|
throw new Error("Expected map to merge");
|
|
198
315
|
}
|
|
199
316
|
|
|
200
|
-
if (
|
|
317
|
+
if (ys instanceof CalcitSliceMap && this.chunk.length + ys.len() <= 24) {
|
|
201
318
|
// probably this length < 16, ys length < 8
|
|
202
|
-
let ret = this.
|
|
203
|
-
outer: for (let i = 0; i < ys.
|
|
204
|
-
if (ys.
|
|
319
|
+
let ret = this.chunk.slice(0);
|
|
320
|
+
outer: for (let i = 0; i < ys.chunk.length; i = i + 2) {
|
|
321
|
+
if (ys.chunk[i + 1] === v) {
|
|
205
322
|
continue;
|
|
206
323
|
}
|
|
207
324
|
for (let k = 0; k < ret.length; k = k + 2) {
|
|
208
|
-
if (DATA_EQUAL(ys.
|
|
209
|
-
ret[k + 1] = ys.
|
|
325
|
+
if (DATA_EQUAL(ys.chunk[i], ret[k])) {
|
|
326
|
+
ret[k + 1] = ys.chunk[i + 1];
|
|
210
327
|
continue outer;
|
|
211
328
|
}
|
|
212
329
|
}
|
|
213
|
-
ret.push(ys.
|
|
330
|
+
ret.push(ys.chunk[i], ys.chunk[i + 1]);
|
|
214
331
|
}
|
|
215
|
-
return new
|
|
332
|
+
return new CalcitSliceMap(ret);
|
|
216
333
|
}
|
|
217
334
|
|
|
218
|
-
this.turnMap();
|
|
219
|
-
|
|
220
|
-
if (ys.arrayMode) {
|
|
221
|
-
let ret = this.value;
|
|
222
|
-
let size = ys.arrayValue.length >> 1;
|
|
223
|
-
for (let i = 0; i < size; i++) {
|
|
224
|
-
let pos = i << 1;
|
|
225
|
-
if (ys.arrayValue[pos + 1] === v) {
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
ret = assocMap(ret, ys.arrayValue[pos], ys.arrayValue[pos + 1]);
|
|
229
|
-
}
|
|
230
|
-
return new CalcitMap(ret);
|
|
231
|
-
} else {
|
|
232
|
-
return new CalcitMap(ternaryTree.mergeSkip(this.value, ys.value, v));
|
|
233
|
-
}
|
|
335
|
+
return this.turnMap().mergeSkip(ys, v);
|
|
234
336
|
}
|
|
235
337
|
|
|
236
338
|
/** TODO implement diff with low level code, opens opportunity for future optimizations */
|
|
237
|
-
diffNew(ys: CalcitMap): CalcitMap {
|
|
238
|
-
this.turnMap();
|
|
239
|
-
let zs = this.value;
|
|
240
|
-
if (ys.arrayMode) {
|
|
241
|
-
let size = ys.arrayValue.length >> 1;
|
|
242
|
-
for (let i = 0; i < size; i++) {
|
|
243
|
-
let pos = i << 1;
|
|
244
|
-
let k = ys.arrayValue[pos];
|
|
245
|
-
if (ternaryTree.contains(zs, k)) {
|
|
246
|
-
zs = ternaryTree.dissocMap(zs, k);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
return new CalcitMap(zs);
|
|
250
|
-
} else {
|
|
251
|
-
let ysKeys = ys.keysArray();
|
|
252
|
-
for (let i = 0; i < ysKeys.length; i++) {
|
|
253
|
-
let k = ysKeys[i];
|
|
254
|
-
if (ternaryTree.contains(zs, k)) {
|
|
255
|
-
zs = ternaryTree.dissocMap(zs, k);
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
return new CalcitMap(zs);
|
|
259
|
-
}
|
|
339
|
+
diffNew(ys: CalcitSliceMap | CalcitMap): CalcitMap {
|
|
340
|
+
return this.turnMap().diffNew(ys);
|
|
260
341
|
}
|
|
261
342
|
|
|
262
343
|
/** TODO implement diff with low level code, opens opportunity for future optimizations */
|
|
263
|
-
diffKeys(ys: CalcitMap): CalcitSet {
|
|
344
|
+
diffKeys(ys: CalcitMap | CalcitSliceMap): CalcitSet {
|
|
264
345
|
let ret: Array<CalcitValue> = [];
|
|
265
346
|
let ks = this.keysArray();
|
|
266
347
|
for (let i = 0; i < ks.length; i++) {
|
|
@@ -273,7 +354,7 @@ export class CalcitMap {
|
|
|
273
354
|
}
|
|
274
355
|
|
|
275
356
|
/** TODO implement diff with low level code, opens opportunity for future optimizations */
|
|
276
|
-
commonKeys(ys: CalcitMap): CalcitSet {
|
|
357
|
+
commonKeys(ys: CalcitMap | CalcitSliceMap): CalcitSet {
|
|
277
358
|
let ret: Array<CalcitValue> = [];
|
|
278
359
|
let ks = this.keysArray();
|
|
279
360
|
for (let i = 0; i < ks.length; i++) {
|
package/ts-src/js-primes.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { CalcitKeyword, CalcitSymbol
|
|
2
|
-
import { CalcitList } from "./js-list";
|
|
1
|
+
import { CalcitKeyword, CalcitSymbol, CalcitRef, CalcitFn, CalcitRecur } from "./calcit-data";
|
|
2
|
+
import { CalcitList, CalcitSliceList } from "./js-list";
|
|
3
3
|
import { CalcitRecord } from "./js-record";
|
|
4
|
-
import { CalcitMap } from "./js-map";
|
|
4
|
+
import { CalcitMap, CalcitSliceMap } from "./js-map";
|
|
5
5
|
import { CalcitSet as CalcitSet } from "./js-set";
|
|
6
6
|
import { CalcitTuple } from "./js-tuple";
|
|
7
7
|
|
|
@@ -10,7 +10,9 @@ export type CalcitValue =
|
|
|
10
10
|
| number
|
|
11
11
|
| boolean
|
|
12
12
|
| CalcitMap
|
|
13
|
+
| CalcitSliceMap
|
|
13
14
|
| CalcitList
|
|
15
|
+
| CalcitSliceList
|
|
14
16
|
| CalcitSet
|
|
15
17
|
| CalcitKeyword
|
|
16
18
|
| CalcitSymbol
|
package/ts-src/js-record.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { initTernaryTreeMap, Hash, insert } from "@calcit/ternary-tree";
|
|
|
2
2
|
import { CalcitValue } from "./js-primes";
|
|
3
3
|
import { kwd, castKwd, toString, CalcitKeyword, getStringName, findInFields } from "./calcit-data";
|
|
4
4
|
|
|
5
|
-
import { CalcitMap } from "./js-map";
|
|
5
|
+
import { CalcitMap, CalcitSliceMap } from "./js-map";
|
|
6
6
|
|
|
7
7
|
export class CalcitRecord {
|
|
8
8
|
name: CalcitKeyword;
|
|
@@ -11,7 +11,7 @@ export class CalcitRecord {
|
|
|
11
11
|
cachedHash: Hash;
|
|
12
12
|
constructor(name: CalcitKeyword, fields: Array<CalcitKeyword>, values?: Array<CalcitValue>) {
|
|
13
13
|
this.name = name;
|
|
14
|
-
let fieldNames = fields.map(
|
|
14
|
+
let fieldNames = fields.map(castKwd);
|
|
15
15
|
this.fields = fields;
|
|
16
16
|
if (values != null) {
|
|
17
17
|
if (values.length !== fields.length) {
|
|
@@ -152,7 +152,7 @@ export let _$n_record_$o_from_map = (proto: CalcitValue, data: CalcitValue): Cal
|
|
|
152
152
|
}
|
|
153
153
|
return new CalcitRecord(proto.name, proto.fields, values);
|
|
154
154
|
}
|
|
155
|
-
} else if (data instanceof CalcitMap) {
|
|
155
|
+
} else if (data instanceof CalcitMap || data instanceof CalcitSliceMap) {
|
|
156
156
|
let pairs: Array<[CalcitKeyword, CalcitValue]> = [];
|
|
157
157
|
for (let [k, v] of data.pairs()) {
|
|
158
158
|
pairs.push([castKwd(k), v]);
|
|
@@ -179,11 +179,11 @@ export let _$n_record_$o_from_map = (proto: CalcitValue, data: CalcitValue): Cal
|
|
|
179
179
|
|
|
180
180
|
export let _$n_record_$o_to_map = (x: CalcitValue): CalcitValue => {
|
|
181
181
|
if (x instanceof CalcitRecord) {
|
|
182
|
-
var dict: Array<
|
|
182
|
+
var dict: Array<CalcitValue> = [];
|
|
183
183
|
for (let idx = 0; idx < x.fields.length; idx++) {
|
|
184
|
-
dict.push(
|
|
184
|
+
dict.push(x.fields[idx], x.values[idx]);
|
|
185
185
|
}
|
|
186
|
-
return new
|
|
186
|
+
return new CalcitSliceMap(dict);
|
|
187
187
|
} else {
|
|
188
188
|
throw new Error("Expected record");
|
|
189
189
|
}
|
package/ts-src/js-set.ts
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
1
|
import { CalcitValue } from "./js-primes";
|
|
2
2
|
import { toString } from "./calcit-data";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
TernaryTreeMap,
|
|
5
|
+
initTernaryTreeMap,
|
|
6
|
+
mapLen,
|
|
7
|
+
assocMap,
|
|
8
|
+
dissocMap,
|
|
9
|
+
isMapEmpty,
|
|
10
|
+
Hash,
|
|
11
|
+
toPairsArray,
|
|
12
|
+
mapGetDefault,
|
|
13
|
+
contains,
|
|
14
|
+
initTernaryTreeMapFromArray,
|
|
15
|
+
initEmptyTernaryTreeMap,
|
|
16
|
+
} from "@calcit/ternary-tree";
|
|
4
17
|
import * as ternaryTree from "@calcit/ternary-tree";
|
|
5
18
|
|
|
6
19
|
/** need to compare by Calcit */
|
|
@@ -28,7 +41,7 @@ export class CalcitSet {
|
|
|
28
41
|
}
|
|
29
42
|
pairs.push([value[idx], true]);
|
|
30
43
|
}
|
|
31
|
-
this.value =
|
|
44
|
+
this.value = initTernaryTreeMapFromArray(pairs);
|
|
32
45
|
} else {
|
|
33
46
|
this.value = value;
|
|
34
47
|
}
|
|
@@ -65,7 +78,7 @@ export class CalcitSet {
|
|
|
65
78
|
return new CalcitSet(result);
|
|
66
79
|
}
|
|
67
80
|
intersection(ys: CalcitSet): CalcitSet {
|
|
68
|
-
let result: TernaryTreeMap<CalcitValue, boolean> =
|
|
81
|
+
let result: TernaryTreeMap<CalcitValue, boolean> = initEmptyTernaryTreeMap();
|
|
69
82
|
for (let k of ternaryTree.toKeys(this.value)) {
|
|
70
83
|
if (ys.contains(k)) {
|
|
71
84
|
result = assocMap(result, k, true);
|
|
@@ -77,14 +90,14 @@ export class CalcitSet {
|
|
|
77
90
|
first(): CalcitValue {
|
|
78
91
|
// rather suspicious solution since set has no logical order
|
|
79
92
|
|
|
80
|
-
if (mapLen(this.value)
|
|
93
|
+
if (mapLen(this.value) === 0) {
|
|
81
94
|
return null;
|
|
82
95
|
}
|
|
83
96
|
|
|
84
97
|
return toPairsArray(this.value)[0][0];
|
|
85
98
|
}
|
|
86
99
|
rest(): CalcitSet {
|
|
87
|
-
if (mapLen(this.value)
|
|
100
|
+
if (mapLen(this.value) === 0) {
|
|
88
101
|
return null;
|
|
89
102
|
}
|
|
90
103
|
let x0 = this.first();
|
package/ts-src/js-tuple.ts
CHANGED
|
@@ -12,18 +12,18 @@ export class CalcitTuple {
|
|
|
12
12
|
this.cachedHash = null;
|
|
13
13
|
}
|
|
14
14
|
get(n: number) {
|
|
15
|
-
if (n
|
|
15
|
+
if (n === 0) {
|
|
16
16
|
return this.fst;
|
|
17
|
-
} else if (n
|
|
17
|
+
} else if (n === 1) {
|
|
18
18
|
return this.snd;
|
|
19
19
|
} else {
|
|
20
20
|
throw new Error("Tuple only have 2 elements");
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
assoc(n: number, v: CalcitValue) {
|
|
24
|
-
if (n
|
|
24
|
+
if (n === 0) {
|
|
25
25
|
return new CalcitTuple(v, this.snd);
|
|
26
|
-
} else if (n
|
|
26
|
+
} else if (n === 1) {
|
|
27
27
|
return new CalcitTuple(this.fst, v);
|
|
28
28
|
} else {
|
|
29
29
|
throw new Error("Tuple only have 2 elements");
|