@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.
@@ -3,8 +3,8 @@ import { CalcitRef, CalcitSymbol, CalcitKeyword } from "./calcit-data";
3
3
  import { toPairs } from "@calcit/ternary-tree";
4
4
 
5
5
  import { CalcitRecord } from "./js-record";
6
- import { CalcitMap } from "./js-map";
7
- import { CalcitList } from "./js-list";
6
+ import { CalcitMap, CalcitSliceMap } from "./js-map";
7
+ import { CalcitList, CalcitSliceList } from "./js-list";
8
8
  import { CalcitSet } from "./js-set";
9
9
  import { CalcitTuple } from "./js-tuple";
10
10
 
@@ -41,7 +41,7 @@ export let load_console_formatter_$x_ = () => {
41
41
  if (obj instanceof CalcitSymbol) {
42
42
  return ["div", { style: "color: hsl(340, 80%, 60%)" }, obj.toString()];
43
43
  }
44
- if (obj instanceof CalcitList) {
44
+ if (obj instanceof CalcitList || obj instanceof CalcitSliceList) {
45
45
  return [
46
46
  "div",
47
47
  { style: "color: hsl(280, 80%, 60%, 0.4)" },
@@ -49,7 +49,7 @@ export let load_console_formatter_$x_ = () => {
49
49
  ["span", { style: "font-size: 80%; vertical-align: 0.7em; color: hsl(280, 80%, 60%, 0.8)" }, `${obj.len()}`],
50
50
  ];
51
51
  }
52
- if (obj instanceof CalcitMap) {
52
+ if (obj instanceof CalcitMap || obj instanceof CalcitSliceMap) {
53
53
  return ["div", { style: "color: hsl(280, 80%, 60%, 0.4)" }, obj.toString(true)];
54
54
  }
55
55
  if (obj instanceof CalcitSet) {
@@ -78,10 +78,10 @@ export let load_console_formatter_$x_ = () => {
78
78
  return null;
79
79
  },
80
80
  hasBody: (obj) => {
81
- if (obj instanceof CalcitList) {
81
+ if (obj instanceof CalcitList || obj instanceof CalcitSliceList) {
82
82
  return obj.len() > 0;
83
83
  }
84
- if (obj instanceof CalcitMap) {
84
+ if (obj instanceof CalcitMap || obj instanceof CalcitSliceMap) {
85
85
  return obj.len() > 0;
86
86
  }
87
87
  if (obj instanceof CalcitSet) {
@@ -90,7 +90,7 @@ export let load_console_formatter_$x_ = () => {
90
90
  return false;
91
91
  },
92
92
  body: (obj, config) => {
93
- if (obj instanceof CalcitList) {
93
+ if (obj instanceof CalcitList || obj instanceof CalcitSliceList) {
94
94
  return ["div", { style: "color: hsl(280, 80%, 60%)" }].concat(
95
95
  obj.toArray().map((x, idx) => {
96
96
  return [
@@ -117,10 +117,10 @@ export let load_console_formatter_$x_ = () => {
117
117
  ret.push(["div", { style: "margin-left: 8px; display: inline-block;" }, embedObject(obj.snd)]);
118
118
  return ret;
119
119
  }
120
- if (obj instanceof CalcitMap) {
120
+ if (obj instanceof CalcitMap || obj instanceof CalcitSliceMap) {
121
121
  let ret: any[] = ["div", { style: "color: hsl(280, 80%, 60%)" }];
122
- obj.turnMap();
123
- for (let [k, v] of toPairs(obj.value)) {
122
+ let pairs = obj.pairs();
123
+ for (let [k, v] of pairs) {
124
124
  ret.push([
125
125
  "div",
126
126
  { style: "margin-left: 8px; display: flex;" },
@@ -2,9 +2,9 @@ import { overwriteComparator, initTernaryTreeMap } from "@calcit/ternary-tree";
2
2
  import { CirruWriterNode, writeCirruCode } from "@cirru/writer.ts";
3
3
 
4
4
  import { CalcitValue } from "./js-primes";
5
- import { CalcitList } from "./js-list";
5
+ import { CalcitList, CalcitSliceList } from "./js-list";
6
6
  import { CalcitRecord } from "./js-record";
7
- import { CalcitMap } from "./js-map";
7
+ import { CalcitMap, CalcitSliceMap } from "./js-map";
8
8
  import { CalcitSet } from "./js-set";
9
9
  import { CalcitKeyword, CalcitSymbol, CalcitRecur, CalcitRef, kwd } from "./calcit-data";
10
10
  import { CalcitTuple } from "./js-tuple";
@@ -44,11 +44,11 @@ export let to_cirru_edn = (x: CalcitValue): CirruEdnFormat => {
44
44
  if (x instanceof CalcitSymbol) {
45
45
  return x.toString();
46
46
  }
47
- if (x instanceof CalcitList) {
47
+ if (x instanceof CalcitList || x instanceof CalcitSliceList) {
48
48
  // TODO can be faster
49
49
  return (["[]"] as CirruEdnFormat[]).concat(x.toArray().map(to_cirru_edn));
50
50
  }
51
- if (x instanceof CalcitMap) {
51
+ if (x instanceof CalcitMap || x instanceof CalcitSliceMap) {
52
52
  let buffer: CirruEdnFormat = ["{}"];
53
53
  for (let [k, v] of x.pairs()) {
54
54
  buffer.push([to_cirru_edn(k), to_cirru_edn(v)]);
@@ -105,7 +105,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat): CalcitValue => {
105
105
  if (x === "false") {
106
106
  return false;
107
107
  }
108
- if (x == "") {
108
+ if (x === "") {
109
109
  throw new Error("cannot be empty");
110
110
  }
111
111
  if (x[0] === "|" || x[0] === '"') {
@@ -129,18 +129,18 @@ export let extract_cirru_edn = (x: CirruEdnFormat): CalcitValue => {
129
129
  throw new Error("Cannot be empty");
130
130
  }
131
131
  if (x[0] === "{}") {
132
- let result: Array<[CalcitValue, CalcitValue]> = [];
132
+ let result: Array<CalcitValue> = [];
133
133
  x.forEach((pair, idx) => {
134
- if (idx == 0) {
134
+ if (idx === 0) {
135
135
  return; // skip first `{}` symbol
136
136
  }
137
- if (pair instanceof Array && pair.length == 2) {
138
- result.push([extract_cirru_edn(pair[0]), extract_cirru_edn(pair[1])]);
137
+ if (pair instanceof Array && pair.length === 2) {
138
+ result.push(extract_cirru_edn(pair[0]), extract_cirru_edn(pair[1]));
139
139
  } else {
140
140
  throw new Error("Expected pairs for map");
141
141
  }
142
142
  });
143
- return new CalcitMap(initTernaryTreeMap(result));
143
+ return new CalcitSliceMap(result);
144
144
  }
145
145
  if (x[0] === "%{}") {
146
146
  let name = x[1];
@@ -154,7 +154,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat): CalcitValue => {
154
154
  return; // skip %{} name
155
155
  }
156
156
 
157
- if (pair instanceof Array && pair.length == 2) {
157
+ if (pair instanceof Array && pair.length === 2) {
158
158
  if (typeof pair[0] === "string") {
159
159
  entries.push([extractFieldKwd(pair[0]), extract_cirru_edn(pair[1])]);
160
160
  } else {
@@ -177,7 +177,7 @@ export let extract_cirru_edn = (x: CirruEdnFormat): CalcitValue => {
177
177
  return new CalcitRecord(extractFieldKwd(name), fields, values);
178
178
  }
179
179
  if (x[0] === "[]") {
180
- return new CalcitList(x.slice(1).map(extract_cirru_edn));
180
+ return new CalcitSliceList(x.slice(1).map(extract_cirru_edn));
181
181
  }
182
182
  if (x[0] === "#{}") {
183
183
  return new CalcitSet(x.slice(1).map(extract_cirru_edn));
@@ -209,10 +209,10 @@ export let format_cirru_edn = (data: CalcitValue, useInline: boolean = true): st
209
209
  if (typeof data === "string") {
210
210
  return "\ndo " + to_cirru_edn(data) + "\n";
211
211
  }
212
- if (typeof data == "boolean") {
212
+ if (typeof data === "boolean") {
213
213
  return "\ndo " + to_cirru_edn(data) + "\n";
214
214
  }
215
- if (typeof data == "string") {
215
+ if (typeof data === "string") {
216
216
  return "\ndo " + to_cirru_edn(data) + "\n";
217
217
  }
218
218
  if (data instanceof CalcitSymbol) {
@@ -244,7 +244,7 @@ export let to_calcit_data = (x: any, noKeyword: boolean = false): CalcitValue =>
244
244
  x.forEach((v) => {
245
245
  result.push(to_calcit_data(v, noKeyword));
246
246
  });
247
- return new CalcitList(result);
247
+ return new CalcitSliceList(result);
248
248
  }
249
249
  if (x instanceof Set) {
250
250
  let result: Array<CalcitValue> = [];
@@ -254,8 +254,8 @@ export let to_calcit_data = (x: any, noKeyword: boolean = false): CalcitValue =>
254
254
  return new CalcitSet(result);
255
255
  }
256
256
 
257
- if (x instanceof CalcitList) return x;
258
- if (x instanceof CalcitMap) return x;
257
+ if (x instanceof CalcitList || x instanceof CalcitSliceList) return x;
258
+ if (x instanceof CalcitMap || x instanceof CalcitSliceMap) return x;
259
259
  if (x instanceof CalcitSet) return x;
260
260
  if (x instanceof CalcitRecord) return x;
261
261
  if (x instanceof CalcitRecur) return x;
@@ -266,22 +266,22 @@ export let to_calcit_data = (x: any, noKeyword: boolean = false): CalcitValue =>
266
266
 
267
267
  // detects object
268
268
  if (x === Object(x)) {
269
- let result: Array<[CalcitValue, CalcitValue]> = [];
269
+ let result: Array<CalcitValue> = [];
270
270
  Object.keys(x).forEach((k) => {
271
- result.push([to_calcit_data(k, noKeyword), to_calcit_data(x[k], noKeyword)]);
271
+ result.push(to_calcit_data(k, noKeyword), to_calcit_data(x[k], noKeyword));
272
272
  });
273
- return new CalcitMap(initTernaryTreeMap(result));
273
+ return new CalcitSliceMap(result);
274
274
  }
275
275
 
276
276
  console.error(x);
277
277
  throw new Error("Unexpected data for converting");
278
278
  };
279
279
 
280
- let toWriterNode = (xs: CalcitList): CirruWriterNode => {
280
+ let toWriterNode = (xs: CalcitList | CalcitSliceList): CirruWriterNode => {
281
281
  if (typeof xs === "string") {
282
282
  return xs;
283
283
  }
284
- if (xs instanceof CalcitList) {
284
+ if (xs instanceof CalcitList || xs instanceof CalcitSliceList) {
285
285
  return xs.toArray().map(toWriterNode);
286
286
  } else {
287
287
  throw new Error("Unexpected type for CirruWriteNode");
package/ts-src/js-list.ts CHANGED
@@ -5,6 +5,7 @@ import { CalcitValue } from "./js-primes";
5
5
  import {
6
6
  TernaryTreeList,
7
7
  initTernaryTreeList,
8
+ initTernaryTreeListFromRange,
8
9
  listLen,
9
10
  listGet,
10
11
  assocList,
@@ -15,97 +16,157 @@ import {
15
16
  assocAfter,
16
17
  } from "@calcit/ternary-tree";
17
18
 
18
- import { CalcitMap } from "./js-map";
19
+ import { CalcitMap, CalcitSliceMap } from "./js-map";
19
20
  import { CalcitSet } from "./js-set";
20
21
  import { CalcitTuple } from "./js-tuple";
21
- import { CalcitFn } from "./calcit.procs";
22
22
 
23
- import { isNestedCalcitData, tipNestedCalcitData, toString } from "./calcit-data";
23
+ import { isNestedCalcitData, tipNestedCalcitData, toString, CalcitFn } from "./calcit-data";
24
24
 
25
+ // two list implementations, should offer same interface
25
26
  export class CalcitList {
26
27
  value: TernaryTreeList<CalcitValue>;
27
- // array mode store bare array for performance
28
- arrayValue: Array<CalcitValue>;
29
- arrayMode: boolean;
30
- arrayStart: number;
31
- arrayEnd: number;
32
28
  cachedHash: Hash;
33
- constructor(value: Array<CalcitValue> | TernaryTreeList<CalcitValue>) {
34
- if (value == null) {
35
- value = []; // dirty, better handled from outside
36
- }
29
+ constructor(value: TernaryTreeList<CalcitValue>) {
37
30
  this.cachedHash = null;
38
- if (Array.isArray(value)) {
39
- this.arrayMode = true;
40
- this.arrayValue = value;
41
- this.arrayStart = 0;
42
- this.arrayEnd = value.length;
43
- this.value = null;
31
+ if (value == null) {
32
+ this.value = initTernaryTreeList([]);
44
33
  } else {
45
- this.arrayMode = false;
46
34
  this.value = value;
47
- this.arrayValue = [];
48
- this.arrayStart = null;
49
- this.arrayEnd = null;
50
- }
51
- }
52
- turnListMode() {
53
- if (this.arrayMode) {
54
- this.value = initTernaryTreeList(this.arrayValue.slice(this.arrayStart, this.arrayEnd));
55
- this.arrayValue = null;
56
- this.arrayStart = null;
57
- this.arrayEnd = null;
58
- this.arrayMode = false;
59
35
  }
60
36
  }
61
37
  len() {
62
- if (this.arrayMode) {
63
- return this.arrayEnd - this.arrayStart;
64
- } else {
65
- return listLen(this.value);
66
- }
38
+ return listLen(this.value);
67
39
  }
68
40
  get(idx: number) {
69
- if (this.arrayMode) {
70
- return this.arrayValue[this.arrayStart + idx];
71
- } else {
72
- return listGet(this.value, idx);
73
- }
41
+ return listGet(this.value, idx);
74
42
  }
75
43
  assoc(idx: number, v: CalcitValue) {
76
- this.turnListMode();
77
44
  return new CalcitList(assocList(this.value, idx, v));
78
45
  }
79
46
  assocBefore(idx: number, v: CalcitValue) {
80
- this.turnListMode();
81
47
  return new CalcitList(assocBefore(this.value, idx, v));
82
48
  }
83
49
  assocAfter(idx: number, v: CalcitValue) {
84
- this.turnListMode();
85
50
  return new CalcitList(assocAfter(this.value, idx, v));
86
51
  }
87
52
  dissoc(idx: number) {
88
- this.turnListMode();
89
53
  return new CalcitList(dissocList(this.value, idx));
90
54
  }
91
55
  slice(from: number, to: number) {
92
- if (this.arrayMode) {
93
- if (from < 0) {
94
- throw new Error(`from index too small: ${from}`);
95
- }
96
- if (to > this.len()) {
97
- throw new Error(`end index too large: ${to}`);
98
- }
99
- if (to < from) {
100
- throw new Error("end index too small");
56
+ return new CalcitList(ternaryTree.slice(this.value, from, to));
57
+ }
58
+ toString(shorter = false): string {
59
+ let result = "";
60
+ for (let item of this.items()) {
61
+ if (shorter && isNestedCalcitData(item)) {
62
+ result = `${result} ${tipNestedCalcitData(item)}`;
63
+ } else {
64
+ result = `${result} ${toString(item, true)}`;
101
65
  }
102
- let result = new CalcitList(this.arrayValue);
103
- result.arrayStart = this.arrayStart + from;
104
- result.arrayEnd = this.arrayStart + to;
105
- return result;
66
+ }
67
+ return `([]${result})`;
68
+ }
69
+ isEmpty() {
70
+ return this.len() === 0;
71
+ }
72
+ /** usage: `for of` */
73
+ items(): Generator<CalcitValue> {
74
+ return listToItems(this.value);
75
+ }
76
+ append(v: CalcitValue) {
77
+ return new CalcitList(ternaryTree.append(this.value, v));
78
+ }
79
+ prepend(v: CalcitValue) {
80
+ return new CalcitList(ternaryTree.prepend(this.value, v));
81
+ }
82
+ first() {
83
+ return ternaryTree.first(this.value);
84
+ }
85
+ rest() {
86
+ return new CalcitList(ternaryTree.rest(this.value));
87
+ }
88
+ concat(ys: CalcitList | CalcitSliceList) {
89
+ if (ys instanceof CalcitSliceList) {
90
+ return new CalcitList(ternaryTree.concat(this.value, ys.turnListMode().value));
91
+ } else if (ys instanceof CalcitList) {
92
+ return new CalcitList(ternaryTree.concat(this.value, ys.value));
93
+ } else {
94
+ throw new Error(`Unknown data to concat: ${ys}`);
95
+ }
96
+ }
97
+ map(f: (v: CalcitValue) => CalcitValue): CalcitList {
98
+ return new CalcitList(ternaryTree.listMapValues(this.value, f));
99
+ }
100
+ toArray(): CalcitValue[] {
101
+ return [...ternaryTree.listToItems(this.value)];
102
+ }
103
+ reverse() {
104
+ return new CalcitList(ternaryTree.reverse(this.value));
105
+ }
106
+ }
107
+
108
+ // represent append-only immutable list in Array slices
109
+ export class CalcitSliceList {
110
+ // array mode store bare array for performance
111
+ value: Array<CalcitValue>;
112
+ start: number;
113
+ end: number;
114
+ cachedHash: Hash;
115
+ constructor(value: Array<CalcitValue>) {
116
+ if (value == null) {
117
+ value = []; // dirty, better handled from outside
118
+ }
119
+ this.cachedHash = null;
120
+
121
+ this.value = value;
122
+ this.start = 0;
123
+ this.end = value.length;
124
+ }
125
+ turnListMode(): CalcitList {
126
+ return new CalcitList(initTernaryTreeListFromRange(this.value, this.start, this.end));
127
+ }
128
+ len() {
129
+ return this.end - this.start;
130
+ }
131
+ get(idx: number) {
132
+ return this.value[this.start + idx];
133
+ }
134
+ assoc(idx: number, v: CalcitValue) {
135
+ return this.turnListMode().assoc(idx, v);
136
+ }
137
+ assocBefore(idx: number, v: CalcitValue) {
138
+ return this.turnListMode().assocBefore(idx, v);
139
+ }
140
+ assocAfter(idx: number, v: CalcitValue) {
141
+ if (idx === this.len() - 1) {
142
+ return this.append(v);
106
143
  } else {
107
- return new CalcitList(ternaryTree.slice(this.value, from, to));
144
+ return this.turnListMode().assocAfter(idx, v);
145
+ }
146
+ }
147
+ dissoc(idx: number) {
148
+ if (idx === 0) {
149
+ return this.rest();
150
+ } else if (idx === this.len() - 1) {
151
+ return this.slice(0, idx);
152
+ } else {
153
+ return this.turnListMode().dissoc(idx);
154
+ }
155
+ }
156
+ slice(from: number, to: number) {
157
+ if (from < 0) {
158
+ throw new Error(`from index too small: ${from}`);
159
+ }
160
+ if (to > this.len()) {
161
+ throw new Error(`end index too large: ${to}`);
162
+ }
163
+ if (to < from) {
164
+ throw new Error("end index too small");
108
165
  }
166
+ let result = new CalcitSliceList(this.value);
167
+ result.start = this.start + from;
168
+ result.end = this.start + to;
169
+ return result;
109
170
  }
110
171
  toString(shorter = false): string {
111
172
  let result = "";
@@ -123,54 +184,38 @@ export class CalcitList {
123
184
  }
124
185
  /** usage: `for of` */
125
186
  items(): Generator<CalcitValue> {
126
- if (this.arrayMode) {
127
- return sliceGenerator(this.arrayValue, this.arrayStart, this.arrayEnd);
128
- } else {
129
- return listToItems(this.value);
130
- }
187
+ return sliceGenerator(this.value, this.start, this.end);
131
188
  }
132
- append(v: CalcitValue) {
133
- if (this.arrayMode && this.arrayEnd === this.arrayValue.length && this.arrayStart < 32) {
189
+ append(v: CalcitValue): CalcitSliceList | CalcitList {
190
+ if (this.end === this.value.length && this.start < 32) {
134
191
  // dirty trick to reuse list memory, data storage actually appended at existing array
135
- this.arrayValue.push(v);
136
- let newList = new CalcitList(this.arrayValue);
137
- newList.arrayStart = this.arrayStart;
138
- newList.arrayEnd = this.arrayEnd + 1;
192
+ this.value.push(v);
193
+ let newList = new CalcitSliceList(this.value);
194
+ newList.start = this.start;
195
+ newList.end = this.end + 1;
139
196
  return newList;
140
197
  } else {
141
- this.turnListMode();
142
- return new CalcitList(ternaryTree.append(this.value, v));
198
+ return this.turnListMode().append(v);
143
199
  }
144
200
  }
145
201
  prepend(v: CalcitValue) {
146
- this.turnListMode();
147
- return new CalcitList(ternaryTree.prepend(this.value, v));
202
+ return this.turnListMode().prepend(v);
148
203
  }
149
204
  first() {
150
- if (this.arrayMode) {
151
- if (this.arrayValue.length > this.arrayStart) {
152
- return this.arrayValue[this.arrayStart];
153
- } else {
154
- return null;
155
- }
205
+ if (this.value.length > this.start) {
206
+ return this.value[this.start];
156
207
  } else {
157
- return ternaryTree.first(this.value);
208
+ return null;
158
209
  }
159
210
  }
160
211
  rest() {
161
- if (this.arrayMode) {
162
- return this.slice(1, this.arrayEnd - this.arrayStart);
163
- } else {
164
- return new CalcitList(ternaryTree.rest(this.value));
165
- }
212
+ return this.slice(1, this.end - this.start);
166
213
  }
167
- concat(ys: CalcitList) {
168
- if (!(ys instanceof CalcitList)) {
169
- throw new Error("Expected list");
170
- }
171
- if (this.arrayMode && ys.arrayMode) {
172
- let size = this.arrayEnd - this.arrayStart;
173
- let otherSize = ys.arrayEnd - ys.arrayStart;
214
+ // TODO
215
+ concat(ys: CalcitSliceList | CalcitList) {
216
+ if (ys instanceof CalcitSliceList) {
217
+ let size = this.end - this.start;
218
+ let otherSize = ys.end - ys.start;
174
219
  let combined = new Array(size + otherSize);
175
220
  for (let i = 0; i < size; i++) {
176
221
  combined[i] = this.get(i);
@@ -178,36 +223,38 @@ export class CalcitList {
178
223
  for (let i = 0; i < otherSize; i++) {
179
224
  combined[i + size] = ys.get(i);
180
225
  }
181
- return new CalcitList(combined);
226
+ return new CalcitSliceList(combined);
227
+ } else if (ys instanceof CalcitList) {
228
+ return this.turnListMode().concat(ys);
182
229
  } else {
183
- this.turnListMode();
184
- ys.turnListMode();
185
- return new CalcitList(ternaryTree.concat(this.value, ys.value));
230
+ throw new Error("Expected list");
186
231
  }
187
232
  }
188
- map(f: (v: CalcitValue) => CalcitValue): CalcitList {
189
- if (this.arrayMode) {
190
- return new CalcitList(this.arrayValue.slice(this.arrayStart, this.arrayEnd).map(f));
191
- } else {
192
- return new CalcitList(ternaryTree.listMapValues(this.value, f));
233
+ map(f: (v: CalcitValue) => CalcitValue): CalcitSliceList {
234
+ let ys: CalcitValue[] = [];
235
+ for (let x in sliceGenerator(this.value, this.start, this.end)) {
236
+ ys.push(f(x));
193
237
  }
238
+
239
+ return new CalcitSliceList(ys);
194
240
  }
195
241
  toArray(): CalcitValue[] {
196
- if (this.arrayMode) {
197
- return this.arrayValue.slice(this.arrayStart, this.arrayEnd);
198
- } else {
199
- return [...ternaryTree.listToItems(this.value)];
200
- }
242
+ return this.value.slice(this.start, this.end);
201
243
  }
202
244
  reverse() {
203
- this.turnListMode();
204
- return new CalcitList(ternaryTree.reverse(this.value));
245
+ return this.turnListMode().reverse();
205
246
  }
206
247
  }
207
248
 
208
249
  function* sliceGenerator(xs: Array<CalcitValue>, start: number, end: number): Generator<CalcitValue> {
209
- for (let idx = start; idx < end; idx++) {
210
- yield xs[idx];
250
+ if (xs == null) {
251
+ if (end <= start) {
252
+ throw new Error("invalid list to slice");
253
+ }
254
+ } else {
255
+ for (let idx = start; idx < end; idx++) {
256
+ yield xs[idx];
257
+ }
211
258
  }
212
259
  }
213
260
 
@@ -217,10 +264,9 @@ export let foldl = function (xs: CalcitValue, acc: CalcitValue, f: CalcitFn): Ca
217
264
  }
218
265
 
219
266
  if (f == null) {
220
- debugger;
221
267
  throw new Error("Expected function for folding");
222
268
  }
223
- if (xs instanceof CalcitList) {
269
+ if (xs instanceof CalcitSliceList || xs instanceof CalcitList) {
224
270
  var result = acc;
225
271
  for (let idx = 0; idx < xs.len(); idx++) {
226
272
  let item = xs.get(idx);
@@ -235,10 +281,20 @@ export let foldl = function (xs: CalcitValue, acc: CalcitValue, f: CalcitFn): Ca
235
281
  });
236
282
  return result;
237
283
  }
284
+ if (xs instanceof CalcitSliceMap) {
285
+ let result = acc;
286
+ // low-level code for performance
287
+ let size = xs.chunk.length >> 1;
288
+ for (let i = 0; i < size; i++) {
289
+ let pos = i << 1;
290
+ result = f(result, new CalcitSliceList([xs.chunk[pos], xs.chunk[pos + 1]]));
291
+ }
292
+ return result;
293
+ }
238
294
  if (xs instanceof CalcitMap) {
239
295
  let result = acc;
240
- xs.pairs().forEach(([k, item]) => {
241
- result = f(result, new CalcitList([k, item]));
296
+ xs.pairs().forEach((pair) => {
297
+ result = f(result, new CalcitSliceList(pair));
242
298
  });
243
299
  return result;
244
300
  }
@@ -251,10 +307,9 @@ export let foldl_shortcut = function (xs: CalcitValue, acc: CalcitValue, v0: Cal
251
307
  }
252
308
 
253
309
  if (f == null) {
254
- debugger;
255
310
  throw new Error("Expected function for folding");
256
311
  }
257
- if (xs instanceof CalcitList) {
312
+ if (xs instanceof CalcitList || xs instanceof CalcitSliceList) {
258
313
  var state = acc;
259
314
  for (let idx = 0; idx < xs.len(); idx++) {
260
315
  let item = xs.get(idx);
@@ -291,11 +346,31 @@ export let foldl_shortcut = function (xs: CalcitValue, acc: CalcitValue, v0: Cal
291
346
  }
292
347
  return v0;
293
348
  }
294
-
349
+ if (xs instanceof CalcitSliceMap) {
350
+ let state = acc;
351
+ // low-level code for performance
352
+ let size = xs.chunk.length >> 1;
353
+ for (let i = 0; i < size; i++) {
354
+ let pos = i << 1;
355
+ let pair = f(state, new CalcitSliceList([xs.chunk[pos], xs.chunk[pos + 1]]));
356
+ if (pair instanceof CalcitTuple) {
357
+ if (typeof pair.fst === "boolean") {
358
+ if (pair.fst) {
359
+ return pair.snd;
360
+ } else {
361
+ state = pair.snd;
362
+ }
363
+ }
364
+ } else {
365
+ throw new Error("Expected return value in `:: bool acc` structure");
366
+ }
367
+ }
368
+ return v0;
369
+ }
295
370
  if (xs instanceof CalcitMap) {
296
371
  let state = acc;
297
372
  for (let item of xs.pairs()) {
298
- let pair = f(state, new CalcitList(item));
373
+ let pair = f(state, new CalcitSliceList(item));
299
374
  if (pair instanceof CalcitTuple) {
300
375
  if (typeof pair.fst === "boolean") {
301
376
  if (pair.fst) {
@@ -318,10 +393,9 @@ export let foldr_shortcut = function (xs: CalcitValue, acc: CalcitValue, v0: Cal
318
393
  }
319
394
 
320
395
  if (f == null) {
321
- debugger;
322
396
  throw new Error("Expected function for folding");
323
397
  }
324
- if (xs instanceof CalcitList) {
398
+ if (xs instanceof CalcitList || xs instanceof CalcitSliceList) {
325
399
  var state = acc;
326
400
  // iterate from right
327
401
  for (let idx = xs.len() - 1; idx >= 0; idx--) {