17 val basic: string -> T |
17 val basic: string -> T |
18 val variable: string -> T |
18 val variable: string -> T |
19 val has_parent: T -> bool |
19 val has_parent: T -> bool |
20 val is_absolute: T -> bool |
20 val is_absolute: T -> bool |
21 val is_basic: T -> bool |
21 val is_basic: T -> bool |
22 val all_basic: T -> bool |
|
23 val starts_basic: T -> bool |
22 val starts_basic: T -> bool |
24 val append: T -> T -> T |
23 val append: T -> T -> T |
25 val appends: T list -> T |
24 val appends: T list -> T |
26 val implode: T -> string |
25 val implode: T -> string |
27 val explode: string -> T |
26 val explode: string -> T |
|
27 val explode_pos: string * Position.T -> T * Position.T |
28 val decode: T XML.Decode.T |
28 val decode: T XML.Decode.T |
29 val split: string -> T list |
29 val split: string -> T list |
30 val pretty: T -> Pretty.T |
30 val pretty: T -> Pretty.T |
31 val print: T -> string |
31 val print: T -> string |
32 val dir: T -> T |
32 val dir: T -> T |
36 val exe: T -> T |
36 val exe: T -> T |
37 val expand: T -> T |
37 val expand: T -> T |
38 val file_name: T -> string |
38 val file_name: T -> string |
39 val smart_implode: T -> string |
39 val smart_implode: T -> string |
40 val position: T -> Position.T |
40 val position: T -> Position.T |
|
41 eqtype binding |
|
42 val binding: T * Position.T -> binding |
|
43 val binding0: T -> binding |
|
44 val binding_map: (T -> T) -> binding -> binding |
|
45 val dest_binding: binding -> T * Position.T |
|
46 val implode_binding: binding -> string |
|
47 val explode_binding: string * Position.T -> binding |
|
48 val explode_binding0: string -> binding |
41 end; |
49 end; |
42 |
50 |
43 structure Path: PATH = |
51 structure Path: PATH = |
44 struct |
52 struct |
45 |
53 |
166 | (_, []) => ([Root ""], []) |
174 | (_, []) => ([Root ""], []) |
167 | (_, e :: es) => ([root_elem e], es)); |
175 | (_, e :: es) => ([root_elem e], es)); |
168 val elems = raw_elems |> filter_out (fn c => c = "" orelse c = ".") |> map explode_elem; |
176 val elems = raw_elems |> filter_out (fn c => c = "" orelse c = ".") |> map explode_elem; |
169 |
177 |
170 in Path (norm (rev elems @ roots)) end; |
178 in Path (norm (rev elems @ roots)) end; |
|
179 |
|
180 fun explode_pos (s, pos) = |
|
181 (explode_path s handle ERROR msg => error (msg ^ Position.here pos), pos); |
171 |
182 |
172 fun split str = |
183 fun split str = |
173 space_explode ":" str |
184 space_explode ":" str |
174 |> map_filter (fn s => if s = "" then NONE else SOME (explode_path s)); |
185 |> map_filter (fn s => if s = "" then NONE else SOME (explode_path s)); |
175 |
186 |
241 | NONE => implode_path path) |
252 | NONE => implode_path path) |
242 end; |
253 end; |
243 |
254 |
244 val position = Position.file o smart_implode; |
255 val position = Position.file o smart_implode; |
245 |
256 |
|
257 |
|
258 (* binding: strictly monotonic path with position *) |
|
259 |
|
260 datatype binding = Binding of T * Position.T; |
|
261 |
|
262 fun binding (path, pos) = |
|
263 if not (is_current path) andalso all_basic path then Binding (path, pos) |
|
264 else error ("Bad path binding: " ^ print path ^ Position.here pos); |
|
265 |
|
266 fun binding0 path = binding (path, Position.none); |
|
267 fun binding_map f (Binding (path, pos)) = binding (f path, pos); |
|
268 |
|
269 fun dest_binding (Binding args) = args; |
|
270 |
|
271 val implode_binding = dest_binding #> #1 #> implode_path; |
|
272 |
|
273 val explode_binding = binding o explode_pos; |
|
274 fun explode_binding0 s = explode_binding (s, Position.none); |
|
275 |
|
276 |
246 (*final declarations of this structure!*) |
277 (*final declarations of this structure!*) |
247 val implode = implode_path; |
278 val implode = implode_path; |
248 val explode = explode_path; |
279 val explode = explode_path; |
249 |
280 |
250 end; |
281 end; |