1 import Base 2 import ./lists.bend as Lists 3 4 # A value, with the name it is written as. 5 type Named<-A: Data> is Data: 6 Named{name: String, value: A} 7 8 def lookup.go( 9 -A: Data, 10 +key: String, 11 table: List<&2, Named>, 12 found: Maybe<&2, A> 13 ) -> Maybe<&2, A>: 14 match table found: 15 case _ Some{v}: 16 Some{v} 17 case Nil{} None{}: 18 None{} 19 case Con{Named{k, v}, rest} None{}: 20 lookup.go(A, key, rest, Lists.when(A, String.eq(k, key), v)) 21 22 # Each of `xs` with the name `show` gives it: a table for `lookup`, so that each name is written once, in `show`. 23 def table(~A: Data, ~show: A -> String, xs: List<&2, A>) -> List<&2, Named>: 24 match xs: 25 case Nil{}: 26 [] 27 case Con{+x, rest}: 28 Named{show(x), x} <> table(~A, ~show, rest) 29 30 # The value `key` names in `table`: the first, read no further. 31 def lookup(-A: Data, key: String, table: List<&2, Named>) -> Maybe<&2, A>: 32 lookup.go(A, key, table, None{}) 33 34 # The value `key` names in `table`, a map by name (as `Lint.definitions` makes): one pass over the name, however many 35 # names there are. 36 def find(-A: Data, table: Map<&2, Maybe<&2, A>>, key: String) -> Maybe<&2, A>: 37 Pair.snd(Map<&2, Maybe<&2, A>>, Maybe<&2, A>, Map.get(Maybe<&2, A>, None{}, table, key)) 38 39 # Groups 40 # ====== 41 # Values by name, in a map: each name's values, last first. 42 def Group.add.of( 43 -A: Data, 44 got: Map<&2, List<&2, A>> & List<&2, A>, 45 key: String, 46 x: A 47 ) -> Map<&2, List<&2, A>>: 48 match got: 49 case Tuple{groups, old}: 50 Map.set(&2, List<&2, A>, groups, key, x <> old) 51 52 # `groups` with `x` added under `key`. A key's list is last first; `Group.get` gives it in order. 53 def Group.add(-A: Data, groups: Map<&2, List<&2, A>>, +key: String, x: A) -> Map<&2, List<&2, A>>: 54 Group.add.of(A, Map.get(List<&2, A>, [], groups, key), key, x) 55 56 # What is added under `key`, in the order added. 57 def Group.get(-A: Data, groups: Map<&2, List<&2, A>>, key: String) -> List<&2, A>: 58 List.reverse( 59 &2, 60 A, 61 Pair.snd(Map<&2, List<&2, A>>, List<&2, A>, Map.get(List<&2, A>, [], groups, key)) 62 ) 63 64 def Group.of( 65 ~A: Data, 66 ~key: A -> String, 67 xs: List<&2, A>, 68 groups: Map<&2, List<&2, A>> 69 ) -> Map<&2, List<&2, A>>: 70 match xs: 71 case Nil{}: 72 groups 73 case Con{+x, rest}: 74 Group.of(~A, ~key, rest, Group.add(A, groups, key(x), x))