functionalscript 0.0.186 → 0.0.194

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/btree/index.js CHANGED
@@ -305,28 +305,25 @@ const replaceVisitor = {
305
305
  notFound: notFoundGet,
306
306
  }
307
307
 
308
- /** @type {<T>(...array: readonly seq.Sequence<T>[]) => seq.Sequence<T>} */
309
- const flatArray = (...array) => seq.flat(seq.fromArray(array))
310
-
311
308
  /** @type {<T>(node: Node<T>) => seq.Sequence<T>} */
312
- const valuesList = node => () => {
309
+ const values = node => () => {
313
310
  const f = () => {
314
311
  switch (node.length) {
315
- case 1: case 2: { return seq.fromArray(node) }
312
+ case 1: case 2: { return seq.list(...node) }
316
313
  case 3: {
317
- return flatArray(
318
- valuesList(node[0]),
319
- seq.one(node[1]),
320
- valuesList(node[2])
314
+ return seq.concat(
315
+ values(node[0]),
316
+ seq.list(node[1]),
317
+ values(node[2])
321
318
  )
322
319
  }
323
320
  default: {
324
- return flatArray(
325
- valuesList(node[0]),
326
- seq.one(node[1]),
327
- valuesList(node[2]),
328
- seq.one(node[3]),
329
- valuesList(node[4])
321
+ return seq.concat(
322
+ values(node[0]),
323
+ seq.list(node[1]),
324
+ values(node[2]),
325
+ seq.list(node[3]),
326
+ values(node[4])
330
327
  )
331
328
  }
332
329
  }
@@ -336,7 +333,7 @@ const valuesList = node => () => {
336
333
 
337
334
  module.exports = {
338
335
  /** @readonly */
339
- valuesList,
336
+ values,
340
337
  /**
341
338
  * @readonly
342
339
  * @type { <T>(cmp: Cmp<T>) => (node: Node<T>) => T|undefined }
package/btree/test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const btree = require('.')
2
- const { setVisitor, valuesList } = btree
2
+ const { setVisitor, values: valuesList } = btree
3
3
  const { cmp } = require('../cmp')
4
4
  const list = require('../sequence')
5
5
 
@@ -24,8 +24,6 @@ const test = () => {
24
24
  /** @type {import('../sequence').Result<string>} */
25
25
  let result = list.next(valuesList(node))
26
26
  while (result !== undefined) {
27
- const t = result[0]
28
- console.log(t)
29
27
  result = list.next(result[1])
30
28
  }
31
29
  }
package/cmp/index.js CHANGED
@@ -18,8 +18,8 @@ const index3 = cmp => value => /** @type {Index3} */ (cmp(value) + 1)
18
18
 
19
19
  /** @type {<T>(cmp: Cmp<T>) => (v2: Array2<T>) => Index5} */
20
20
  const index5 = cmp => ([v0, v1]) => {
21
- const i = cmp(v0)
22
- return /** @type {Index5} */ (i <= 0 ? i + 1 : cmp(v1) + 3)
21
+ const cmpV0 = cmp(v0)
22
+ return /** @type {Index5} */ (cmpV0 <= 0 ? cmpV0 + 1 : cmp(v1) + 3)
23
23
  }
24
24
 
25
25
  /** @type {(a: string) => (b: string) => Sign} */
package/function/index.js CHANGED
@@ -7,9 +7,6 @@
7
7
  /** @type {<X, O>(f: Func<X, O>) => <I>(g: Func<I, X>) => Func<I, O>} */
8
8
  const combine = f => g => x => f(g(x))
9
9
 
10
- /** @type {<I, X>(g: Func<I, X>) => <O>(g: Func<X, O>) => Func<I, O>} */
11
- const pipe = g => f => x => f(g(x))
12
-
13
10
  /** @type {<T>(value: T) => T} */
14
11
  const id = value => value
15
12
 
@@ -17,7 +14,5 @@ module.exports = {
17
14
  /** @readonly */
18
15
  id,
19
16
  /** @readonly */
20
- pipe,
21
- /** @readonly */
22
17
  combine,
23
18
  }
package/json/index.js ADDED
@@ -0,0 +1,105 @@
1
+ const seq = require('../sequence')
2
+ const map = require('../map')
3
+ const op = require('../sequence/operator')
4
+ const option = require('../option')
5
+
6
+ /**
7
+ * @typedef {{
8
+ * readonly [k in string]: Json
9
+ * }} Object
10
+ */
11
+
12
+ /** @typedef {readonly Json[]} Array */
13
+
14
+ /** @typedef {Object|boolean|string|number|null|Array} Json */
15
+
16
+ /** @type {(value: Json) => (path: readonly string[]) => (src: Json|undefined) => Json} */
17
+ const addProperty = value => {
18
+ /** @type {(path: seq.Sequence<string>) => (src: Json|undefined) => Json} */
19
+ const f = path => src => {
20
+ const result = seq.next(path)
21
+ if (result === undefined) { return value }
22
+ const srcObject = (src === undefined || src === null || typeof src !== 'object' || src instanceof Array) ? {} : src
23
+ const [name, tail] = result
24
+ return { ...srcObject, [name]: f(tail)(srcObject[name]) }
25
+ }
26
+ return path => f(seq.fromArray(path))
27
+ }
28
+
29
+ /** @type {(kv: readonly[string, Json]) => seq.Sequence<string>} */
30
+ const property = ([k, v]) => seq.concat(
31
+ seq.list(JSON.stringify(k)),
32
+ seq.list(':'),
33
+ stringSequence(v))
34
+
35
+ const comma = seq.list(',')
36
+
37
+ /** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
38
+ const commaValue = a => [seq.concat(comma, a), commaValue]
39
+
40
+ /** @type {op.Scan<seq.Sequence<string>, seq.Sequence<string>>} */
41
+ const joinScan = value => [value, commaValue]
42
+
43
+ /** @type {seq.SequenceMap<seq.Sequence<string>, string>} */
44
+ const join = input => {
45
+ const _0 = seq.scan(joinScan)(input)
46
+ return seq.flat(_0)
47
+ }
48
+
49
+ /** @type {(open: string) => (close: string) => (input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
50
+ const list = open => close => {
51
+ const seqOpen = seq.list(open)
52
+ const seqClose = seq.list(close)
53
+ return input => seq.concat(seqOpen, join(input), seqClose)
54
+ }
55
+
56
+ const objectList = list('{')('}')
57
+
58
+ const arrayList = list('[')(']')
59
+
60
+ /** @type {(object: Object) => seq.Sequence<string>} */
61
+ const objectStringify = object => {
62
+ const _0 = Object.entries(object)
63
+ const _1 = seq.fromArray(_0)
64
+ const _2 = map.fromEntries(_1)
65
+ const _3 = _2.entries
66
+ const _4 = seq.map(property)(_3)
67
+ return objectList(_4)
68
+ }
69
+
70
+ /** @type {(array: Array) => seq.Sequence<string>} */
71
+ const arrayStringify = array => {
72
+ const _0 = seq.fromArray(array)
73
+ const _1 = seq.map(stringSequence)(_0)
74
+ return arrayList(_1)
75
+ }
76
+
77
+ /** @type {(value: Json) => seq.Sequence<string>} */
78
+ const stringSequence = value => {
79
+ const x = typeof value
80
+ switch (typeof value) {
81
+ case 'boolean': { return seq.list(value ? "true" : "false") }
82
+ // Note: we shouldn't use JSON.stringify since it has non determenistic behavior.
83
+ // In particular: property order could be different.
84
+ case 'number': case 'string': { return seq.list(JSON.stringify(value)) }
85
+ default: {
86
+ if (value === null) { return seq.list("null") }
87
+ if (value instanceof Array) { return arrayStringify(value) }
88
+ return objectStringify(value)
89
+ }
90
+ }
91
+ }
92
+
93
+ /**
94
+ * A deterministic version of `JSON.stringify`
95
+ *
96
+ * @type {(value: Json) => string}
97
+ */
98
+ const stringify = value => seq.join('')(stringSequence(value))
99
+
100
+ module.exports = {
101
+ /** @readonly */
102
+ addProperty,
103
+ /** @readonly */
104
+ stringify,
105
+ }
package/json/test.js ADDED
@@ -0,0 +1,20 @@
1
+ const json = require('.')
2
+
3
+ if (json.addProperty("Hello")([])({}) !== "Hello") { throw 'error' }
4
+
5
+ {
6
+ const x = json.stringify(json.addProperty("Hello")(['a'])({}))
7
+ if (x !== '{"a":"Hello"}') { throw x }
8
+ }
9
+
10
+ {
11
+ const x = json.stringify(json.addProperty("Hello")(['a'])({c:[],b:12}))
12
+ if (x !== '{"a":"Hello","b":12,"c":[]}') { throw x }
13
+ }
14
+
15
+ {
16
+ const _0 = { a: { y: [24] }, c: [], b: 12 }
17
+ const _1 = json.addProperty("Hello")(['a', 'x'])(_0)
18
+ const _2 = json.stringify(_1)
19
+ if (_2 !== '{"a":{"x":"Hello","y":[24]},"b":12,"c":[]}') { throw _2 }
20
+ }
package/map/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  const option = require("../option")
2
- const { getVisitor, setVisitor, valuesList } = require("../btree")
2
+ const { getVisitor, setVisitor, values } = require("../btree")
3
3
  const { cmp } = require("../cmp")
4
- const list = require("../sequence")
4
+ const seq = require("../sequence")
5
+ const op = require("../sequence/operator")
5
6
 
6
7
  /** @typedef {import("../cmp").Sign} Sign */
7
8
 
@@ -30,7 +31,7 @@ const list = require("../sequence")
30
31
  * @typedef {{
31
32
  * readonly get: (name: string) => T|undefined
32
33
  * readonly set: (name: string) => (value: T) => Map<T>
33
- * readonly entries: list.Sequence<Entry<T>>
34
+ * readonly entries: seq.Sequence<Entry<T>>
34
35
  * readonly root: undefined|TNode<Entry<T>>
35
36
  * }} Map
36
37
  */
@@ -47,7 +48,7 @@ const create = root => ({
47
48
  if ('overflow' in result) { return create(result.overflow) }
48
49
  throw ''
49
50
  },
50
- entries: valuesList(root),
51
+ entries: values(root),
51
52
  root,
52
53
  })
53
54
 
@@ -62,11 +63,22 @@ const create = root => ({
62
63
  const empty = {
63
64
  get: () => undefined,
64
65
  set: name => value => create([[name, value]]),
65
- entries: list.empty,
66
+ entries: seq.empty,
66
67
  root: undefined
67
68
  }
68
69
 
70
+ /** @type {<T>(map: Map<T>) => (entry: Entry<T>) => Map<T>} */
71
+ const setOperator = map => ([k, v]) => map.set(k)(v)
72
+
73
+ /** @type {<T>(entries: seq.Sequence<Entry<T>>) => Map<T>} */
74
+ const fromEntries = entries => {
75
+ /** @typedef {typeof entries extends seq.Sequence<Entry<infer T>> ? T : never} T */
76
+ return seq.fold(setOperator)(/** @type {Map<T>} */(empty))(entries)
77
+ }
78
+
69
79
  module.exports = {
70
80
  /** @readonly */
71
81
  empty,
82
+ /** @readonly */
83
+ fromEntries,
72
84
  }
@@ -1,5 +1,5 @@
1
1
  const array = require('../sequence/array')
2
- const { pipe } = require('../function')
2
+ const { combine } = require('../function')
3
3
  const option = require('../option')
4
4
  const { head, last, splitLast, splitFirst } = array
5
5
  const iter = require('../sequence/iterable')
@@ -88,9 +88,9 @@ const external = packages => {
88
88
  const defined = ([first, tail]) => externalOrInternal(packages(first))(tail)
89
89
  /** @type {(_: Path) => readonly [string, Path]|undefined} */
90
90
  const sf = splitFirst
91
- return pipe
92
- (sf)
91
+ return combine
93
92
  (option.map(defined))
93
+ (sf)
94
94
  }
95
95
 
96
96
  /** @type {(_: Location) => (_: string) => Module|undefined} */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.186",
3
+ "version": "0.0.194",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -86,10 +86,9 @@ const head = a => a.length === 0 ? undefined : uncheckHead(a)
86
86
 
87
87
  /** @type {<T>(_: Array<T>) => readonly [Array<T>, T]|undefined} */
88
88
  const splitLast = a => {
89
- /** @typedef {typeof a[0]} T*/
90
- /** @type {(_: T) => readonly [Array<T>, T]} */
91
- const split = x => [uncheckHead(a), x]
92
- return option.map(split)(last(a))
89
+ const lastA = last(a)
90
+ if (lastA === undefined) { return undefined }
91
+ return [uncheckHead(a), lastA]
93
92
  }
94
93
 
95
94
  /** @type {(index: number) => <T>(a: Array<T>) => readonly[T]|undefined} */
@@ -1,4 +1,4 @@
1
- const { pipe } = require('../../function')
1
+ const { combine } = require('../../function')
2
2
  const seq = require('../operator')
3
3
 
4
4
  /**
@@ -69,7 +69,7 @@ const reduce = ([first, s]) => async c => {
69
69
 
70
70
  const sum = reduce(seq.sum)
71
71
 
72
- const join = pipe(seq.join)(reduce)
72
+ const join = combine(reduce)(seq.join)
73
73
 
74
74
  const length = reduce(seq.length)
75
75
 
package/sequence/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  const array = require('./array')
2
2
  const seqOp = require('./operator')
3
- const { pipe } = require('../function')
3
+ const { combine } = require('../function')
4
+ const op = require('../function/operator')
4
5
  const { logicalNot, strictEqual } = require('../function/operator')
5
6
 
6
7
  /**
@@ -77,8 +78,20 @@ const first = input => {
77
78
  * @typedef {(list: Sequence<T>) => R} SequenceReduce
78
79
  */
79
80
 
80
- /** @type {<T>(first: T) => Sequence<T>} */
81
- const one = first => () => [first, empty]
81
+ /** @type {<T>(...array: readonly T[]) => Sequence<T>} */
82
+ const list = (...array) => {
83
+ /** @typedef {typeof array extends readonly(infer T)[] ? T : never} T */
84
+ let i = array.length
85
+ /** @type {Sequence<T>} */
86
+ let tail = empty
87
+ while (true) {
88
+ if (i === 0) { return tail }
89
+ i = i - 1
90
+ /** @type {FirstAndTail<T>} */
91
+ const result = [array[i], tail]
92
+ tail = () => result
93
+ }
94
+ }
82
95
 
83
96
  /** @type {<T>(array: array.Array<T>) => Sequence<T>} */
84
97
  const fromArray = a => {
@@ -92,8 +105,28 @@ const fromArray = a => {
92
105
  return at(0)
93
106
  }
94
107
 
95
- /** @type {<T>(a: Sequence<T>) => SequenceMap<T, T>} */
96
- const concat = a => b => [a, b]
108
+ /** @type {<T>(...array: readonly Sequence<T>[]) => Sequence<T>} */
109
+ const concat = (...array) => {
110
+ let i = array.length
111
+ if (i == 0) { return empty }
112
+ i = i - 1
113
+ let tail = array[i]
114
+ while (true) {
115
+ if (i === 0) { return tail }
116
+ i = i - 1
117
+ tail = [array[i], tail]
118
+ }
119
+ }
120
+
121
+ /** @type {(_: number) => Sequence<number>} */
122
+ const generate = n => {
123
+ /** @type {(_: number) => Sequence<number>} */
124
+ const f = i => () => {
125
+ if (n <= i) { return undefined }
126
+ return [i, f(i + 1)]
127
+ }
128
+ return f(0)
129
+ }
97
130
 
98
131
  /** @type {<T, R>(f: (value: T) => Sequence<R>) => SequenceMap<T, R>} */
99
132
  const flatMap = f => input => () => {
@@ -114,16 +147,16 @@ const flatMap = f => input => () => {
114
147
  const flat = flatMap(i => i)
115
148
 
116
149
  /** @type {<T, R>(f: (value: T) => R) => SequenceMap<T, R>} */
117
- const map = f => flatMap(i => one(f(i)))
150
+ const map = f => flatMap(i => list(f(i)))
118
151
 
119
152
  /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
120
- const filter = f => flatMap(i => f(i) ? one(i) : empty)
153
+ const filter = f => flatMap(i => f(i) ? list(i) : empty)
121
154
 
122
155
  /** @type {<T, R>(f: (value: T) => R|undefined) => (value: T) => Sequence<R>} */
123
156
  const filterMapFunc = f => i => {
124
157
  const result = f(i)
125
158
  if (result === undefined) { return empty }
126
- return one(result)
159
+ return list(result)
127
160
  }
128
161
 
129
162
  /** @type {<T, R>(f: (value: T) => R|undefined) => SequenceMap<T, R>} */
@@ -160,13 +193,17 @@ const last = def => input => {
160
193
  /** @type {<T, R>(s: seqOp.ExclusiveScan<T, R>) => (input: Sequence<T>) => R} */
161
194
  const reduce = ([first, s]) => input => last(first)(scan(s)(input))
162
195
 
196
+ /** @type {<T, R>(ro: op.ReduceOperator<R, T>) => (first: R) => (input: Sequence<T>) => R} */
197
+ const fold = ro => first => reduce(seqOp.exclusiveScan(ro)(first))
198
+
163
199
  const entries = scan(seqOp.entries)
164
200
 
165
201
  const sum = reduce(seqOp.sum)
166
202
 
167
203
  const length = reduce(seqOp.length)
168
204
 
169
- const join = pipe(seqOp.join)(reduce)
205
+ /** @type {(separator: string) => SequenceReduce<string, string>} */
206
+ const join = separator => reduce(seqOp.join(separator))
170
207
 
171
208
  /** @type {<T>(f: (value: T) => boolean) => SequenceMap<T, T>} */
172
209
  const takeWhile = f => input => () => {
@@ -200,7 +237,7 @@ const some = f => input => find(x => x)(map(f)(input)) !== undefined
200
237
  const includes = value => some(strictEqual(value))
201
238
 
202
239
  /** @type {<T>(f: (value: T) => boolean) => SequenceReduce<T, boolean>} */
203
- const every = f => input => !some(pipe(f)(logicalNot))(input)
240
+ const every = f => input => !some(combine(logicalNot)(f))(input)
204
241
 
205
242
  /** @type {<T>(list: Sequence<T>) => Iterable<T>} */
206
243
  const iterable = list => ({
@@ -244,7 +281,7 @@ module.exports = {
244
281
  /** @readonly */
245
282
  next,
246
283
  /** @readonly */
247
- one,
284
+ list,
248
285
  /** @readonly */
249
286
  empty,
250
287
  /** @readonly */
@@ -252,6 +289,8 @@ module.exports = {
252
289
  /** @readonly */
253
290
  concat,
254
291
  /** @readonly */
292
+ generate,
293
+ /** @readonly */
255
294
  first,
256
295
  /** @readonly */
257
296
  fromArray,
@@ -278,6 +317,8 @@ module.exports = {
278
317
  /** @readonly */
279
318
  last,
280
319
  /** @readonly */
320
+ fold,
321
+ /** @readonly */
281
322
  reduce,
282
323
  /** @readonly */
283
324
  entries,
@@ -1,4 +1,4 @@
1
- const { pipe } = require('../../function')
1
+ const { combine } = require('../../function')
2
2
  const seq = require('../operator')
3
3
 
4
4
  /** @type {<T>(a: Iterable<T>) => (b: Iterable<T>) => Iterable<T>} */
@@ -39,7 +39,7 @@ const sum = reduce(seq.sum)
39
39
 
40
40
  const length = reduce(seq.length)
41
41
 
42
- const join = pipe(seq.join)(reduce)
42
+ const join = combine(reduce)(seq.join)
43
43
 
44
44
  /** @type {<T, R>(f: (value: T) => Iterable<R>) => (c: Iterable<T>) => Iterable<R>} */
45
45
  const flatMap = f => c => ({
@@ -1,5 +1,5 @@
1
1
  const i = require('.')
2
- const { pipe } = require('../../function')
2
+ const { combine } = require('../../function')
3
3
 
4
4
  {
5
5
  const r = i.sum([120, 300, 42])
@@ -33,9 +33,9 @@ const { pipe } = require('../../function')
33
33
  /** @type {(_: string) => string|undefined} */
34
34
  const file = _ => 'x'
35
35
  /** @type {(_: string) => string|undefined} */
36
- const x = p => pipe
37
- (i.map(x => file(x())))
36
+ const x = p => combine
38
37
  (i.find(x => x !== undefined))
38
+ (i.map(x => file(x())))
39
39
  ([() => p, () => `${p}.js`, () => `${p}/index.js`])
40
40
  if (x('index.js') !== 'x') { throw 'error' }
41
41
  }
package/sequence/test.js CHANGED
@@ -1,5 +1,6 @@
1
1
  const seq = require('.')
2
2
  const { sum } = require('./operator')
3
+ const op = require('./operator')
3
4
 
4
5
  /** @type {<T>(input: seq.Sequence<T>) => void} */
5
6
  const print = input => {
@@ -7,7 +8,7 @@ const print = input => {
7
8
  while (true) {
8
9
  const result = seq.next(i)
9
10
  if (result === undefined) { return }
10
- // console.log(result[0])
11
+ console.log(result[0])
11
12
  i = result[1]
12
13
  }
13
14
  }
@@ -16,7 +17,7 @@ const print = input => {
16
17
  const big = seq.fromArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 42, 60])
17
18
  const list0 = seq.fromArray([0, 1, 2, 3])
18
19
  const list1 = seq.flatMap(x => seq.fromArray([x, x * 2, x * 3]))(list0)
19
- const list2 = seq.concat(list0)(list0)
20
+ const list2 = seq.concat(list0, list0)
20
21
  const list3 = seq.exclusiveScan(sum)(list0)
21
22
  const r = seq.find(x => x === 42)(big)
22
23
  if (seq.every(x => x > 0)(big) !== true) { throw 'x'}
@@ -24,10 +25,23 @@ const print = input => {
24
25
  if (seq.some(x => x > 100)(big) !== false) { throw 'x' }
25
26
  if (seq.some(x => x > 50)(big) !== true) { throw 'x' }
26
27
  if (seq.first(seq.drop(16)(big)) !== 42) { throw 'drop'}
28
+ {
29
+ const a = seq.toArray(seq.generate(1_000_000))
30
+ let x = seq.concat(seq.fromArray(a), big)
31
+ const r = seq.next(x)
32
+ // print(x)
33
+ }
34
+ {
35
+ const a = seq.map(seq.generate)(seq.generate(100_000))
36
+ const array = seq.toArray(a)
37
+ const x = seq.concat(...array)
38
+ const r = seq.next(x)
39
+ // print(x)
40
+ }
27
41
  {
28
42
  let x = big
29
43
  for (let i = 0; i < 1_000_000; ++i) {
30
- x = seq.concat(seq.empty)(x)
44
+ x = seq.concat(seq.empty, x)
31
45
  }
32
46
  const r = seq.next(x)
33
47
  // print(x)
@@ -35,9 +49,14 @@ const print = input => {
35
49
  {
36
50
  let x = big
37
51
  for (let i = 0; i < 1_000_000; ++i) {
38
- x = seq.concat(x)(seq.one(i))
52
+ x = seq.concat(x, seq.list(i))
39
53
  }
40
54
  const r = seq.next(x)
41
55
  // print(x)
42
56
  }
43
- }
57
+ }
58
+
59
+ {
60
+ const x = seq.join(':')(seq.fromArray(["1", "2", "3", "4", "5", "6"]))
61
+ if (x !== "1:2:3:4:5:6") { throw x }
62
+ }
package/test.js CHANGED
@@ -5,6 +5,7 @@ require('./btree/test')
5
5
  require('./sequence/iterable/test')
6
6
  require('./sequence/asyncIterable/test')
7
7
  require('./module-manager/test')
8
+ require('./json/test')
8
9
 
9
10
  /** @type {() => never} */
10
11
  const assert = () => { throw 'assert' }