src/Pure/Thy/thy_load.ML
author wenzelm
Mon, 31 May 2010 21:06:57 +0200
changeset 37216 3165bc303f66
parent 33232 5bb809208876
child 38173 4e7864f3643d
permissions -rw-r--r--
modernized some structure names, keeping a few legacy aliases;
     1 (*  Title:      Pure/Thy/thy_load.ML
     2     Author:     Markus Wenzel, TU Muenchen
     3 
     4 Theory loader primitives, including load path.
     5 *)
     6 
     7 signature BASIC_THY_LOAD =
     8 sig
     9   val show_path: unit -> string list
    10   val add_path: string -> unit
    11   val path_add: string -> unit
    12   val del_path: string -> unit
    13   val with_path: string -> ('a -> 'b) -> 'a -> 'b
    14   val with_paths: string list -> ('a -> 'b) -> 'a -> 'b
    15   val reset_path: unit -> unit
    16 end;
    17 
    18 signature THY_LOAD =
    19 sig
    20   include BASIC_THY_LOAD
    21   val ml_exts: string list
    22   val ml_path: string -> Path.T
    23   val thy_path: string -> Path.T
    24   val split_thy_path: Path.T -> Path.T * string
    25   val check_file: Path.T -> Path.T -> (Path.T * File.ident) option
    26   val check_ml: Path.T -> Path.T -> (Path.T * File.ident) option
    27   val check_thy: Path.T -> string -> Path.T * File.ident
    28   val check_name: string -> string -> unit
    29   val deps_thy: Path.T -> string ->
    30    {master: Path.T * File.ident, text: string list, imports: string list, uses: Path.T list}
    31   val load_ml: Path.T -> Path.T -> Path.T * File.ident
    32 end;
    33 
    34 structure Thy_Load: THY_LOAD =
    35 struct
    36 
    37 (* maintain load path *)
    38 
    39 local val load_path = Unsynchronized.ref [Path.current] in
    40 
    41 fun show_path () = map Path.implode (! load_path);
    42 
    43 fun del_path s =
    44   CRITICAL (fn () => Unsynchronized.change load_path (remove (op =) (Path.explode s)));
    45 
    46 fun add_path s =
    47   CRITICAL (fn () => (del_path s; Unsynchronized.change load_path (cons (Path.explode s))));
    48 
    49 fun path_add s =
    50   CRITICAL (fn () =>
    51     (del_path s; Unsynchronized.change load_path (fn path => path @ [Path.explode s])));
    52 
    53 fun reset_path () = load_path := [Path.current];
    54 
    55 fun with_paths ss f x =
    56   CRITICAL (fn () =>
    57     setmp_CRITICAL load_path (! load_path @ map Path.explode ss) f x);
    58 
    59 fun with_path s f x = with_paths [s] f x;
    60 
    61 fun search_path dir path =
    62   distinct (op =) (dir :: (if Path.is_basic path then (! load_path) else [Path.current]));
    63 
    64 end;
    65 
    66 
    67 (* file formats *)
    68 
    69 val ml_exts = ["ML", "sml"];
    70 val ml_path = Path.ext "ML" o Path.basic;
    71 val thy_path = Path.ext "thy" o Path.basic;
    72 
    73 fun split_thy_path path =
    74   (case Path.split_ext path of
    75     (path', "thy") => (Path.dir path', Path.implode (Path.base path'))
    76   | _ => error ("Bad theory file specification " ^ Path.implode path));
    77 
    78 
    79 (* check files *)
    80 
    81 fun check_ext exts paths src_path =
    82   let
    83     val path = Path.expand src_path;
    84     val _ = Path.is_current path andalso error "Bad file specification";
    85 
    86     fun try_ext rel_path ext =
    87       let val ext_path = Path.expand (Path.ext ext rel_path)
    88       in Option.map (fn id => (File.full_path ext_path, id)) (File.ident ext_path) end;
    89     fun try_prfx prfx = get_first (try_ext (Path.append prfx path)) ("" :: exts);
    90   in get_first try_prfx paths end;
    91 
    92 fun check_file dir path = check_ext [] (search_path dir path) path;
    93 fun check_ml dir path = check_ext ml_exts (search_path dir path) path;
    94 
    95 fun check_thy dir name =
    96   let
    97     val thy_file = thy_path name;
    98     val paths = search_path dir thy_file;
    99   in
   100     (case check_ext [] paths thy_file of
   101       NONE => error ("Could not find theory file " ^ quote (Path.implode thy_file) ^
   102         " in " ^ commas_quote (map Path.implode paths))
   103     | SOME thy_id => thy_id)
   104   end;
   105 
   106 fun check_name name name' =
   107   if name = name' then ()
   108   else error ("Filename " ^ quote (Path.implode (thy_path name)) ^
   109     " does not agree with theory name " ^ quote name');
   110 
   111 
   112 (* theory deps *)
   113 
   114 fun deps_thy dir name =
   115   let
   116     val master as (path, _) = check_thy dir name;
   117     val text = explode (File.read path);
   118     val (name', imports, uses) =
   119       Thy_Header.read (Path.position path) (Source.of_list_limited 8000 text);
   120     val _ = check_name name name';
   121     val uses = map (Path.explode o #1) uses;
   122   in {master = master, text = text, imports = imports, uses = uses} end;
   123 
   124 
   125 (* load files *)
   126 
   127 fun load_ml dir raw_path =
   128   (case check_ml dir raw_path of
   129     NONE => error ("Could not find ML file " ^ quote (Path.implode raw_path))
   130   | SOME (path, id) => (ML_Context.eval_file path; (path, id)));
   131 
   132 end;
   133 
   134 structure Basic_Thy_Load: BASIC_THY_LOAD = Thy_Load;
   135 open Basic_Thy_Load;