| author | wenzelm | 
| Tue, 11 Mar 2008 22:31:09 +0100 | |
| changeset 26256 | 3e7939e978c6 | 
| parent 23863 | 8f3099589cfa | 
| child 26881 | bb68f50644a9 | 
| permissions | -rw-r--r-- | 
| 6118 | 1 | (* Title: Pure/General/path.ML | 
| 5011 | 2 | ID: $Id$ | 
| 3 | Author: Markus Wenzel, TU Muenchen | |
| 4 | ||
| 23863 | 5 | Abstract algebra of file paths (external encoding in Unix style). | 
| 5011 | 6 | *) | 
| 7 | ||
| 8 | signature PATH = | |
| 9 | sig | |
| 6183 | 10 | eqtype T | 
| 6460 | 11 | val is_current: T -> bool | 
| 6183 | 12 | val current: T | 
| 13 | val root: T | |
| 14 | val parent: T | |
| 15 | val basic: string -> T | |
| 16 | val variable: string -> T | |
| 17 | val is_absolute: T -> bool | |
| 18 | val is_basic: T -> bool | |
| 19 | val append: T -> T -> T | |
| 6270 | 20 | val appends: T list -> T | 
| 6319 | 21 | val make: string list -> T | 
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 22 | val implode: T -> string | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 23 | val explode: string -> T | 
| 14912 | 24 | val dir: T -> T | 
| 6183 | 25 | val base: T -> T | 
| 26 | val ext: string -> T -> T | |
| 14912 | 27 | val split_ext: T -> T * string | 
| 6183 | 28 | val expand: T -> T | 
| 5011 | 29 | end; | 
| 30 | ||
| 6187 | 31 | structure Path: PATH = | 
| 5011 | 32 | struct | 
| 33 | ||
| 6183 | 34 | |
| 35 | (* path elements *) | |
| 36 | ||
| 37 | datatype elem = Root | Parent | Basic of string | Variable of string; | |
| 38 | ||
| 6223 | 39 | fun err_elem msg chs = error (msg ^ " path element specification: " ^ quote (implode chs)); | 
| 6183 | 40 | |
| 6319 | 41 | fun check_elem (chs as []) = err_elem "Illegal" chs | 
| 42 | | check_elem (chs as ["~"]) = err_elem "Illegal" chs | |
| 6223 | 43 | | check_elem (chs as ["~", "~"]) = err_elem "Illegal" chs | 
| 44 | | check_elem chs = | |
| 45 | (case ["/", "\\", "$", ":"] inter_string chs of | |
| 46 | [] => chs | |
| 47 |       | bads => err_elem ("Illegal character(s) " ^ commas_quote bads ^ " in") chs);
 | |
| 48 | ||
| 49 | val basic_elem = Basic o implode o check_elem; | |
| 50 | val variable_elem = Variable o implode o check_elem; | |
| 6183 | 51 | |
| 52 | fun is_var (Variable _) = true | |
| 53 | | is_var _ = false; | |
| 54 | ||
| 55 | ||
| 5011 | 56 | (* type path *) | 
| 57 | ||
| 6183 | 58 | datatype T = Path of elem list; | 
| 59 | ||
| 60 | fun rep (Path xs) = xs; | |
| 5011 | 61 | |
| 6460 | 62 | fun is_current (Path []) = true | 
| 63 | | is_current _ = false; | |
| 64 | ||
| 5011 | 65 | val current = Path []; | 
| 6183 | 66 | val root = Path [Root]; | 
| 67 | val parent = Path [Parent]; | |
| 68 | fun basic s = Path [basic_elem (explode s)]; | |
| 69 | fun variable s = Path [variable_elem (explode s)]; | |
| 5011 | 70 | |
| 6183 | 71 | fun is_absolute (Path (Root :: _)) = true | 
| 72 | | is_absolute _ = false; | |
| 5011 | 73 | |
| 6183 | 74 | fun is_basic (Path [Basic _]) = true | 
| 75 | | is_basic _ = false; | |
| 5011 | 76 | |
| 77 | ||
| 78 | (* append and norm *) | |
| 79 | ||
| 80 | (*append non-normal path (2n arg) to reversed normal one, result is normal*) | |
| 81 | fun rev_app xs [] = rev xs | |
| 6183 | 82 | | rev_app _ (Root :: ys) = rev_app [Root] ys | 
| 83 | | rev_app (x :: xs) (Parent :: ys) = | |
| 84 | if x = Parent orelse is_var x then rev_app (Parent :: x :: xs) ys | |
| 85 | else if x = Root then rev_app (x :: xs) ys | |
| 5011 | 86 | else rev_app xs ys | 
| 87 | | rev_app xs (y :: ys) = rev_app (y :: xs) ys; | |
| 88 | ||
| 6183 | 89 | fun append (Path xs) (Path ys) = Path (rev_app (rev xs) ys); | 
| 15570 | 90 | fun appends paths = Library.foldl (uncurry append) (current, paths); | 
| 6319 | 91 | val make = appends o map basic; | 
| 5011 | 92 | fun norm path = rev_app [] path; | 
| 93 | ||
| 6183 | 94 | |
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 95 | (* implode *) | 
| 5011 | 96 | |
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 97 | fun implode_elem Root = "" | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 98 | | implode_elem Parent = ".." | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 99 | | implode_elem (Basic s) = s | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 100 | | implode_elem (Variable s) = "$" ^ s; | 
| 5011 | 101 | |
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 102 | fun implode_path (Path []) = "." | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 103 | | implode_path (Path (Root :: xs)) = "/" ^ space_implode "/" (map implode_elem xs) | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 104 | | implode_path (Path xs) = space_implode "/" (map implode_elem xs); | 
| 5011 | 105 | |
| 106 | ||
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 107 | (* explode *) | 
| 6183 | 108 | |
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 109 | fun explode_elem "" = Root | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 110 | | explode_elem ".." = Parent | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 111 | | explode_elem "~" = Variable "HOME" | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 112 | | explode_elem "~~" = Variable "ISABELLE_HOME" | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 113 | | explode_elem s = | 
| 6183 | 114 | (case explode s of | 
| 115 | "$" :: cs => variable_elem cs | |
| 116 | | cs => basic_elem cs); | |
| 117 | ||
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 118 | val explode_elems = map explode_elem o filter_out (fn c => c = "" orelse c = "."); | 
| 6183 | 119 | |
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 120 | fun explode_path str = Path (norm | 
| 6183 | 121 | (case space_explode "/" str of | 
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 122 | "" :: ss => Root :: explode_elems ss | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 123 | | ss => explode_elems ss)); | 
| 6183 | 124 | |
| 5011 | 125 | |
| 6183 | 126 | (* base element *) | 
| 127 | ||
| 7929 | 128 | fun split_path f (path as Path xs) = | 
| 129 | (case try split_last xs of | |
| 15531 | 130 | SOME (prfx, Basic s) => f (prfx, s) | 
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 131 |   | _ => error ("Cannot split path into dir/base: " ^ quote (implode_path path)));
 | 
| 6183 | 132 | |
| 14912 | 133 | val dir = split_path (fn (prfx, _) => Path prfx); | 
| 7929 | 134 | val base = split_path (fn (_, s) => Path [Basic s]); | 
| 6183 | 135 | |
| 7929 | 136 | fun ext "" path = path | 
| 137 | | ext e path = split_path (fn (prfx, s) => append (Path prfx) (basic (s ^ "." ^ e))) path; | |
| 6183 | 138 | |
| 14912 | 139 | val split_ext = split_path (fn (prfx, s) => apfst (append (Path prfx)) | 
| 19305 | 140 | (case take_suffix (fn c => c <> ".") (explode s) of | 
| 14912 | 141 | ([], _) => (Path [Basic s], "") | 
| 15570 | 142 | | (cs, e) => (Path [Basic (implode (Library.take (length cs - 1, cs)))], implode e))); | 
| 6319 | 143 | |
| 6183 | 144 | |
| 17827 | 145 | (* expand variables *) | 
| 5011 | 146 | |
| 17827 | 147 | fun eval (Variable s) = | 
| 148 | (case getenv s of | |
| 149 |       "" => error ("Undefined Isabelle environment variable: " ^ quote s)
 | |
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 150 | | path => rep (explode_path path)) | 
| 17827 | 151 | | eval x = [x]; | 
| 5011 | 152 | |
| 19482 
9f11af8f7ef9
tuned basic list operators (flat, maps, map_filter);
 wenzelm parents: 
19305diff
changeset | 153 | val expand = rep #> maps eval #> norm #> Path; | 
| 21858 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 154 | |
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 155 | |
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 156 | (*final declarations of this structure!*) | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 157 | val implode = implode_path; | 
| 
05f57309170c
avoid conflict with Alice keywords: renamed pack -> implode, unpack -> explode, any -> many, avoided assert;
 wenzelm parents: 
19482diff
changeset | 158 | val explode = explode_path; | 
| 5011 | 159 | |
| 160 | end; |