src/series.bend
bend-visgraph@2.0.0.0 · 121 lines · 15 definitions
1
2
3
4
5import Base
6
7type Parsed is Data:
8 Values{rev: List<&2, F32>, n: U32}
9 Bad{line: U32}
10
11def add(blank: Bool, m: Maybe<&2, F32>, +line: U32, rev: List<&2, F32>, +n: U32) -> Parsed:
12 match blank m:
13 case True{} _:
14 Values{rev, n}
15 case False{} Some{v}:
16 Values{v <> rev, (n + 1 : U32)}
17 case False{} None{}:
18 Bad{line}
19
20def step(s: String, +line: U32, st: Parsed) -> Parsed:
21 match st:
22 case Values{rev, +n}:
23 +t = String.trim(s)
24 add(String.is_empty(t), F32.read(t), line, rev, n)
25 case Bad{l}:
26 Bad{l}
27
28
29
30
31
32def scan(s: String, nl: Bool, +h: Char, cur: String, +line: U32, st: Parsed) -> Parsed:
33 match s nl:
34 case SNil{} True{}:
35 step(String.reverse(cur), line, st)
36 case SNil{} False{}:
37 step(String.reverse(SCon{h, cur}), line, st)
38 case SCon{+h2, t} True{}:
39 scan(t, Char.is_eq(h2, '\n'), h2, SNil{}, (line + 1 : U32), step(String.reverse(cur), line, st))
40 case SCon{+h2, t} False{}:
41 scan(t, Char.is_eq(h2, '\n'), h2, SCon{h, cur}, line, st)
42
43
44
45def parse(text: String) -> Parsed:
46 match text:
47 case SNil{}:
48 Values{Nil{}, 0}
49 case SCon{+h, t}:
50 scan(t, Char.is_eq(h, '\n'), h, SNil{}, 1, Values{Nil{}, 0})
51
52def column(rev: List<&2, F32>, +i: U32, ys: Array<F32>) -> Array<F32>:
53 match rev:
54 case Nil{}:
55 ys
56 case Con{y, rest}:
57 column(rest, (i - 1 : U32), Array.set(F32, ys, i, y))
58
59
60def ys(rev: List<&2, F32>, +n: U32) -> Array<F32>:
61 column(rev, (n - 1 : U32), Array.new(F32, Nat.add(1n, U32.log2(n)), 0.0))
62
63def read_text.done(m: File & Result<&1, &1, U32 & String, String>) -> IO(String):
64 (f, r) = m
65 do IO<String>:
66 text : String <- IO.pass(String, r)
67 File.close(f)
68 return text
69
70def read_text.sized(m: File & Result<&1, &1, U32 & String, U32>) -> IO(String):
71 (f, r) = m
72 do IO<String>:
73 size : U32 <- IO.pass(U32, r)
74 got : File & Result<&1, &1, U32 & String, String> <- File.read(f, size)
75 read_text.done(got)
76
77def read_text(path: String) -> IO(String):
78 do IO<String>:
79 f : File <- IO.try(File, File.open(path, "r"))
80 sized : File & Result<&1, &1, U32 & String, U32> <- File.size(f)
81 read_text.sized(sized)
82
83
84
85type XsCheck is Data:
86 XsOk{rev: List<&2, F32>}
87 XsBad{msg: String}
88
89
90
91def increasing(rest: List<&2, F32>, +a: F32, ok: Bool) -> Bool:
92 match rest:
93 case Nil{}:
94 ok
95 case Con{+b, t}:
96 increasing(t, b, ok && Bool.not(F32.is_le(F32.sub(a, b), 0.0)))
97
98def increases(xrev: List<&2, F32>) -> Bool:
99 match xrev:
100 case Nil{}:
101 True{}
102 case Con{+a, t}:
103 increasing(t, a, True{})
104
105def xs_check(same: Bool, up: Bool, rev: List<&2, F32>, +n: U32, +m: U32) -> XsCheck:
106 match same up:
107 case False{} _:
108 XsBad{"the x coordinates hold " ++ U32.show(m) ++ " values and the series " ++ U32.show(n)}
109 case True{} False{}:
110 XsBad{"the x coordinates must increase"}
111 case True{} True{}:
112 XsOk{rev}
113
114
115
116def xs(p: Parsed, +n: U32) -> XsCheck:
117 match p:
118 case Bad{line}:
119 XsBad{"line " ++ U32.show(line) ++ " of the x coordinates holds no number"}
120 case Values{+rev, +m}:
121 xs_check(U32.is_eq(n, m), increases(rev), rev, n, m)