src/value.bend
emerging-ezjson@1.3.0.0 · 527 lines · 69 definitions
1
2
3
4import Base
5import emerging-ezjson@1.3.0.0/src/lazy.bend as Lazy
6
7
8
9
10type Json is Data:
11 JNull{}
12 JBool{b: Bool}
13 JNum{raw: String}
14 JStr{s: String}
15 JArr{items: Json}
16 JObj{pairs: Json}
17 JNil{}
18 JCons{head: Json, tail: Json}
19 JPair{key: String, val: Json, rest: Json}
20 JSpan{src: String, n: U32}
21 JBind{src: String, n: U32, val: Json, rest: Json}
22
23
24type Num is Data:
25 NStart{}
26 NInt{}
27 NZero{}
28 NDig{}
29 NDot{}
30 NFrac{}
31 NExp{}
32 NExpN{}
33 NExpD{}
34 NBad{}
35
36
37def span.str(src: String, +nn: U32, zero: Bool) -> String:
38 match src zero:
39 case s True{}:
40 ""
41 case SNil{} False{}:
42 ""
43 case SCon{h, t} False{}:
44 SCon{h, span.str(t, U32.sub(nn, 1), U32.is_zero(U32.sub(nn, 1)))}
45
46
47
48def span.eq.go(src: String, same: Bool, zero: Bool, key: String, +nn: U32) -> Bool:
49 match src same zero key:
50 case s False{} zero k:
51 False{}
52 case s True{} True{} SNil{}:
53 True{}
54 case s True{} True{} k:
55 False{}
56 case SCon{+a, as} True{} False{} SCon{+b, bs}:
57 span.eq.go(as, Char.is_eq(a, b), U32.is_zero(U32.sub(nn, 1)), bs, U32.sub(nn, 1))
58 case SNil{} True{} False{} SNil{}:
59 True{}
60 case s True{} False{} k:
61 False{}
62
63
64def span.eq(+src: String, +nn: U32, +key: String) -> Bool:
65 span.eq.go(src, True{}, U32.is_zero(nn), key, nn)
66
67
68def reverse(cells: Json, acc: Json) -> Json:
69 match cells:
70 case JCons{h, t}:
71 reverse(t, JCons{h, acc})
72 case JPair{k, v, r}:
73 reverse(r, JPair{k, v, acc})
74 case JBind{src, n, v, r}:
75 reverse(r, JBind{src, n, v, acc})
76 case _:
77 acc
78
79def arr.go(items: List<&2, Json>) -> Json:
80 match items:
81 case Nil{}:
82 JNil{}
83 case Con{h, t}:
84 JCons{h, arr.go(t)}
85
86
87def arr(items: List<&2, Json>) -> Json:
88 JArr{arr.go(items)}
89
90def obj.go(pairs: List<&1, String & Json>) -> Json:
91 match pairs:
92 case Nil{}:
93 JNil{}
94 case Con{(k, v), t}:
95 JPair{k, v, obj.go(t)}
96
97
98def obj(pairs: List<&1, String & Json>) -> Json:
99 JObj{obj.go(pairs)}
100
101
102def null() -> Json:
103 JNull{}
104
105
106def bool(flag: Bool) -> Json:
107 JBool{flag}
108
109
110def str(txt: String) -> Json:
111 JStr{txt}
112
113def num.go(raw: String, ok: Bool) -> Json:
114 match ok:
115 case True{}:
116 JNum{raw}
117 case False{}:
118 JNull{}
119
120def num.ok.digit(+cp: U32) -> Bool:
121 Bool.and(U32.is_ge(cp, 48), U32.is_le(cp, 57))
122
123def num.ok.expmark(+cp: U32) -> Bool:
124 Bool.or(U32.is_eq(cp, 101), U32.is_eq(cp, 69))
125
126def num.ok.lead(+cp: U32) -> Bool:
127 Bool.and(U32.is_ge(cp, 49), U32.is_le(cp, 57))
128
129def num.ok.step.lead(ok: Bool) -> Num:
130 match ok:
131 case True{}:
132 NDig{}
133 case False{}:
134 NBad{}
135
136def num.ok.step.int.go(+cp: U32, zero: Bool) -> Num:
137 match zero:
138 case True{}:
139 NZero{}
140 case False{}:
141 num.ok.step.lead(num.ok.lead(cp))
142
143def num.ok.step.int(+cp: U32) -> Num:
144 num.ok.step.int.go(cp, U32.is_eq(cp, 48))
145
146def num.ok.step.start.go(+cp: U32, minus: Bool) -> Num:
147 match minus:
148 case True{}:
149 NInt{}
150 case False{}:
151 num.ok.step.int(cp)
152
153def num.ok.step.start(+cp: U32) -> Num:
154 num.ok.step.start.go(cp, U32.is_eq(cp, 45))
155
156def num.ok.step.mark.go(mark: Bool) -> Num:
157 match mark:
158 case True{}:
159 NExp{}
160 case False{}:
161 NBad{}
162
163def num.ok.step.mark(+cp: U32) -> Num:
164 num.ok.step.mark.go(num.ok.expmark(cp))
165
166def num.ok.step.body.digit(more: Bool) -> Num:
167 match more:
168 case True{}:
169 NDig{}
170 case False{}:
171 NBad{}
172
173def num.ok.step.body.other.go(+cp: U32, dot: Bool) -> Num:
174 match dot:
175 case True{}:
176 NDot{}
177 case False{}:
178 num.ok.step.mark(cp)
179
180def num.ok.step.body.other(+cp: U32) -> Num:
181 num.ok.step.body.other.go(cp, U32.is_eq(cp, 46))
182
183def num.ok.step.body.go(+cp: U32, more: Bool, digit: Bool) -> Num:
184 match digit:
185 case True{}:
186 num.ok.step.body.digit(more)
187 case False{}:
188 num.ok.step.body.other(cp)
189
190def num.ok.step.body(+cp: U32, more: Bool) -> Num:
191 num.ok.step.body.go(cp, more, num.ok.digit(cp))
192
193def num.ok.step.frac.other(+cp: U32, have: Bool) -> Num:
194 match have:
195 case True{}:
196 num.ok.step.mark(cp)
197 case False{}:
198 NBad{}
199
200def num.ok.step.frac.go(+cp: U32, have: Bool, digit: Bool) -> Num:
201 match digit:
202 case True{}:
203 NFrac{}
204 case False{}:
205 num.ok.step.frac.other(cp, have)
206
207def num.ok.step.frac(+cp: U32, have: Bool) -> Num:
208 num.ok.step.frac.go(cp, have, num.ok.digit(cp))
209
210def num.ok.step.expd.go(digit: Bool) -> Num:
211 match digit:
212 case True{}:
213 NExpD{}
214 case False{}:
215 NBad{}
216
217def num.ok.step.expd(+cp: U32) -> Num:
218 num.ok.step.expd.go(num.ok.digit(cp))
219
220def num.ok.step.exps.minus.go(+cp: U32, minus: Bool) -> Num:
221 match minus:
222 case True{}:
223 NExpN{}
224 case False{}:
225 num.ok.step.expd(cp)
226
227def num.ok.step.exps.minus(+cp: U32) -> Num:
228 num.ok.step.exps.minus.go(cp, U32.is_eq(cp, 45))
229
230def num.ok.step.exps.go(+cp: U32, plus: Bool) -> Num:
231 match plus:
232 case True{}:
233 NExpN{}
234 case False{}:
235 num.ok.step.exps.minus(cp)
236
237def num.ok.step.exps(+cp: U32) -> Num:
238 num.ok.step.exps.go(cp, U32.is_eq(cp, 43))
239
240def num.ok.step(st: Num, +cp: U32) -> Num:
241 match st:
242 case NStart{}:
243 num.ok.step.start(cp)
244 case NInt{}:
245 num.ok.step.int(cp)
246 case NZero{}:
247 num.ok.step.body(cp, False{})
248 case NDig{}:
249 num.ok.step.body(cp, True{})
250 case NDot{}:
251 num.ok.step.frac(cp, False{})
252 case NFrac{}:
253 num.ok.step.frac(cp, True{})
254 case NExp{}:
255 num.ok.step.exps(cp)
256 case NExpN{}:
257 num.ok.step.expd(cp)
258 case NExpD{}:
259 num.ok.step.expd(cp)
260 case NBad{}:
261 NBad{}
262
263def num.ok.done(st: Num) -> Bool:
264 match st:
265 case NZero{}:
266 True{}
267 case NDig{}:
268 True{}
269 case NFrac{}:
270 True{}
271 case NExpD{}:
272 True{}
273 case other:
274 False{}
275
276def num.ok.go(cs: List<&2, Char>, st: Num) -> Bool:
277 match cs:
278 case Nil{}:
279 num.ok.done(st)
280 case Con{c, t}:
281 num.ok.go(t, num.ok.step(st, Char.to_u32(c)))
282
283
284def num.ok(txt: String) -> Bool:
285 num.ok.go(String.to_list(txt), NStart{})
286
287
288def num(+raw: String) -> Json:
289 num.go(raw, num.ok(raw))
290
291
292
293def find.eq.go(left: String, right: String, same: Bool) -> Bool:
294 match left right same:
295 case SNil{} SNil{} True{}:
296 True{}
297 case SCon{+x, xs} SCon{+y, ys} True{}:
298 find.eq.go(xs, ys, Char.is_eq(x, y))
299 case l r s:
300 False{}
301
302def find.eq(lhs: String, rhs: String) -> Bool:
303 find.eq.go(lhs, rhs, True{})
304
305
306def find.at(rest: Json, +key: String, eq: Bool, vv: Json) -> Json:
307 match rest key eq vv:
308 case r k True{} val:
309 val
310 case JPair{k2, v2, r2} k False{} val:
311 find.at(r2, k, find.eq(k2, k), v2)
312 case JBind{src, n, v2, r2} k False{} val:
313 find.at(r2, k, span.eq(src, n, k), v2)
314 case r k s val:
315 JNull{}
316
317
318def find(cells: Json, +key: String) -> Json:
319 match cells:
320 case JPair{k, v, r}:
321 find.at(r, key, find.eq(k, key), v)
322 case JBind{src, n, v, r}:
323 find.at(r, key, span.eq(src, n, key), v)
324 case other:
325 JNull{}
326
327
328
329def get(val: Json, key: String) -> Json:
330 match val:
331 case JObj{pairs}:
332 find(pairs, key)
333 case other:
334 JNull{}
335
336def at.go(cells: Json, +idx: U32) -> Json:
337 match cells:
338 case JCons{h, t}:
339 Lazy.stop(Json, U32.is_zero(idx), h, _u => at.go(t, U32.sub(idx, 1)))
340 case other:
341 JNull{}
342
343
344def at(val: Json, idx: U32) -> Json:
345 match val:
346 case JArr{items}:
347 at.go(items, idx)
348 case other:
349 JNull{}
350
351
352type Shape is Data:
353 WVal{}
354 WArr{}
355 WObj{}
356
357
358
359
360def wf.go(val: Json, shape: Shape) -> Bool:
361 match val shape:
362 case JNull{} WVal{}:
363 True{}
364 case JBool{_} WVal{}:
365 True{}
366 case JNum{raw} WVal{}:
367 num.ok(raw)
368 case JStr{_} WVal{}:
369 True{}
370 case JSpan{_, _} WVal{}:
371 True{}
372 case JArr{items} WVal{}:
373 wf.go(items, WArr{})
374 case JObj{pairs} WVal{}:
375 wf.go(pairs, WObj{})
376 case JNil{} WArr{}:
377 True{}
378 case JCons{hd, tl} WArr{}:
379 Lazy.stop(Bool, Bool.not(wf.go(hd, WVal{})), False{}, _u => wf.go(tl, WArr{}))
380 case JNil{} WObj{}:
381 True{}
382 case JPair{_, vv, rr} WObj{}:
383 Lazy.stop(Bool, Bool.not(wf.go(vv, WVal{})), False{}, _u => wf.go(rr, WObj{}))
384 case JBind{_, _, vv, rr} WObj{}:
385 Lazy.stop(Bool, Bool.not(wf.go(vv, WVal{})), False{}, _u => wf.go(rr, WObj{}))
386 case _ _:
387 False{}
388
389
390
391def wf(val: Json) -> Bool:
392 wf.go(val, WVal{})
393
394
395def has.go(cells: Json, +key: String) -> Bool:
396 match cells:
397 case JPair{k2, _, rr}:
398 Lazy.stop(Bool, find.eq(k2, key), True{}, _u => has.go(rr, key))
399 case JBind{src, nn, _, rr}:
400 Lazy.stop(Bool, span.eq(src, nn, key), True{}, _u => has.go(rr, key))
401 case _:
402 False{}
403
404
405def has(val: Json, key: String) -> Bool:
406 match val:
407 case JObj{pairs}:
408 has.go(pairs, key)
409 case _:
410 False{}
411
412
413def len.go(cells: Json) -> Nat:
414 match cells:
415 case JCons{_, tl}:
416 1n+len.go(tl)
417 case JPair{_, _, rr}:
418 1n+len.go(rr)
419 case JBind{_, _, _, rr}:
420 1n+len.go(rr)
421 case _:
422 0n
423
424
425def len(val: Json) -> U32:
426 match val:
427 case JArr{items}:
428 U32.from_nat(len.go(items))
429 case JObj{pairs}:
430 U32.from_nat(len.go(pairs))
431 case _:
432 0
433
434
435def items.go(cells: Json) -> List<&2, Json>:
436 match cells:
437 case JCons{hd, tl}:
438 hd <> items.go(tl)
439 case _:
440 []
441
442
443def items(val: Json) -> List<&2, Json>:
444 match val:
445 case JArr{cells}:
446 items.go(cells)
447 case _:
448 []
449
450
451def is_arr(val: Json) -> Bool:
452 match val:
453 case JArr{_}:
454 True{}
455 case _:
456 False{}
457
458
459def is_obj(val: Json) -> Bool:
460 match val:
461 case JObj{_}:
462 True{}
463 case _:
464 False{}
465
466
467def as_str(val: Json) -> Maybe<&2, String>:
468 match val:
469 case JStr{s}:
470 Some{s}
471 case JSpan{src, +n}:
472 Some{span.str(src, n, U32.is_zero(n))}
473 case other:
474 None{}
475
476
477def as_bool(val: Json) -> Maybe<&2, Bool>:
478 match val:
479 case JBool{b}:
480 Some{b}
481 case other:
482 None{}
483
484
485def as_num(val: Json) -> Maybe<&2, String>:
486 match val:
487 case JNum{raw}:
488 Some{raw}
489 case other:
490 None{}
491
492
493def as_u32(val: Json) -> Maybe<&2, U32>:
494 match val:
495 case JNum{raw}:
496 U32.read(raw)
497 case other:
498 None{}
499
500
501def f32.top() -> F32:
502 3.4028235e38
503
504
505
506def f32.fit.go(xx: F32, finite: Bool) -> Maybe<&2, F32>:
507 match finite:
508 case True{}:
509 Some{xx}
510 case False{}:
511 None{}
512
513
514def f32.fit(got: Maybe<&2, F32>) -> Maybe<&2, F32>:
515 match got:
516 case Some{+xx}:
517 f32.fit.go(xx, F32.is_le(F32.abs(xx), f32.top()))
518 case None{}:
519 None{}
520
521
522def as_f32(val: Json) -> Maybe<&2, F32>:
523 match val:
524 case JNum{raw}:
525 f32.fit(F32.read(raw))
526 case other:
527 None{}