1 # ezsys/src/dir: every decision dir.list makes. It does no IO; src/sys.bend 2 # reads a directory's raw entry names with its own effect (SYS-TRUST-5) and 3 # hands them here. The answer drops exactly "." and ".." and sorts the rest 4 # ascending by String.order, which compares code points one by one: that is 5 # the bytewise order of their UTF-8 encodings. 6 import Base 7 8 # whether a name is "." or ".." 9 def dir.dot(+name: String) -> Bool: 10 Bool.or(String.eq(name, "."), String.eq(name, "..")) 11 12 # name before next when it sorts first, else next and the rest with name put 13 # in them 14 def dir.insert.pick( 15 first: Bool, 16 +name: String, 17 +next: String, 18 +ys: List<&2, String>, 19 rest: Unit -> List<&2, String> 20 ) -> List<&2, String>: 21 match first: 22 case True{}: 23 Con{name, Con{next, ys}} 24 case False{}: 25 Con{next, rest(Unit{})} 26 27 # a name put into a sorted list, before the first name it does not sort after 28 def dir.insert(+name: String, xs: List<&2, String>) -> List<&2, String>: 29 match xs: 30 case Nil{}: 31 [name] 32 case Con{+next, +ys}: 33 dir.insert.pick(String.is_le(name, next), name, next, ys, 34 _u => dir.insert(name, ys)) 35 36 # a list sorted ascending by String.order (insertion sort) 37 def dir.sort(xs: List<&2, String>) -> List<&2, String>: 38 match xs: 39 case Nil{}: 40 Nil{} 41 case Con{+name, xt}: 42 dir.insert(name, dir.sort(xt)) 43 44 # a name kept unless it is "." or ".." 45 def dir.keep.pick( 46 dot: Bool, 47 +name: String, 48 rest: Unit -> List<&2, String> 49 ) -> List<&2, String>: 50 match dot: 51 case True{}: 52 rest(Unit{}) 53 case False{}: 54 Con{name, rest(Unit{})} 55 56 # the names that are not "." or "..", in their order 57 def dir.keep(xs: List<&2, String>) -> List<&2, String>: 58 match xs: 59 case Nil{}: 60 Nil{} 61 case Con{+name, xt}: 62 dir.keep.pick(dir.dot(name), name, _u => dir.keep(xt)) 63 64 # what dir.list answers for the raw names a directory read gave 65 def dir.names(raw: List<&2, String>) -> List<&2, String>: 66 dir.sort(dir.keep(raw)) 67 68 # what dir.list answers for a directory read's answer: its names, or the 69 # failure unchanged 70 def dir.step( 71 res: Result<&1, &1, U32 & String, List<&2, String>> 72 ) -> Result<&1, &1, U32 & String, List<&2, String>>: 73 match res: 74 case Fail{error}: 75 Fail{error} 76 case Done{raw}: 77 Done{dir.names(raw)}