1 # lsp/path: just enough path arithmetic to follow a relative import. 2 import Base 3 4 # a segment lands on the stack (reversed): `..` pops, `.` and `` do nothing 5 def push(+seg: String, +acc: List<&2, String>) -> List<&2, String>: 6 Bool.pick(List<&2, String>, String.eq(seg, ".."), List.tail(&2, String, acc), 7 Bool.pick(List<&2, String>, Bool.or(String.eq(seg, "."), String.is_empty(seg)), acc, seg <> acc)) 8 9 # every segment pushed, in order 10 def norm(segs: List<&2, String>, acc: List<&2, String>) -> List<&2, String>: 11 match segs: 12 case Nil{}: 13 acc 14 case Con{s, t}: 15 norm(t, push(s, acc)) 16 17 # dir and rel as one absolute path, its `.` and `..` resolved 18 def join(dir: String, rel: String) -> String: 19 "/" ++ String.join(List.reverse(&2, String, norm(String.split(dir ++ "/" ++ rel, '/'), [])), "/") 20 21 # the directory of a file's path 22 def dir(path: String) -> String: 23 join(path, "..")