src/Pure/System/options.ML
changeset 56465 6ad693903e22
parent 51990 cc66addbba6d
child 56467 8d7d6f17c6a7
equal deleted inserted replaced
56464:555f4be59be6 56465:6ad693903e22
    11   val realT: string
    11   val realT: string
    12   val stringT: string
    12   val stringT: string
    13   val unknownT: string
    13   val unknownT: string
    14   type T
    14   type T
    15   val empty: T
    15   val empty: T
       
    16   val position: T -> string -> Position.T
    16   val typ: T -> string -> string
    17   val typ: T -> string -> string
    17   val bool: T -> string -> bool
    18   val bool: T -> string -> bool
    18   val int: T -> string -> int
    19   val int: T -> string -> int
    19   val real: T -> string -> real
    20   val real: T -> string -> real
    20   val string: T -> string -> string
    21   val string: T -> string -> string
    21   val put_bool: string -> bool -> T -> T
    22   val put_bool: string -> bool -> T -> T
    22   val put_int: string -> int -> T -> T
    23   val put_int: string -> int -> T -> T
    23   val put_real: string -> real -> T -> T
    24   val put_real: string -> real -> T -> T
    24   val put_string: string -> string -> T -> T
    25   val put_string: string -> string -> T -> T
    25   val declare: {name: string, typ: string, value: string} -> T -> T
    26   val declare: {pos: Position.T, name: string, typ: string, value: string} -> T -> T
    26   val update: string -> string -> T -> T
    27   val update: string -> string -> T -> T
    27   val decode: XML.body -> T
    28   val decode: XML.body -> T
    28   val default: unit -> T
    29   val default: unit -> T
       
    30   val default_position: string -> Position.T
    29   val default_typ: string -> string
    31   val default_typ: string -> string
    30   val default_bool: string -> bool
    32   val default_bool: string -> bool
    31   val default_int: string -> int
    33   val default_int: string -> int
    32   val default_real: string -> real
    34   val default_real: string -> real
    33   val default_string: string -> string
    35   val default_string: string -> string
    51 val intT = "int";
    53 val intT = "int";
    52 val realT = "real";
    54 val realT = "real";
    53 val stringT = "string";
    55 val stringT = "string";
    54 val unknownT = "unknown";
    56 val unknownT = "unknown";
    55 
    57 
    56 datatype T = Options of {typ: string, value: string} Symtab.table;
    58 datatype T = Options of {pos: Position.T, typ: string, value: string} Symtab.table;
    57 
    59 
    58 val empty = Options Symtab.empty;
    60 val empty = Options Symtab.empty;
    59 
    61 
    60 
    62 
    61 (* check *)
    63 (* check *)
    71     if #typ opt = typ then opt
    73     if #typ opt = typ then opt
    72     else error ("Ill-typed system option " ^ quote name ^ " : " ^ #typ opt ^ " vs. " ^ typ)
    74     else error ("Ill-typed system option " ^ quote name ^ " : " ^ #typ opt ^ " vs. " ^ typ)
    73   end;
    75   end;
    74 
    76 
    75 
    77 
    76 (* typ *)
    78 (* declaration *)
    77 
    79 
       
    80 fun position options name = #pos (check_name options name);
    78 fun typ options name = #typ (check_name options name);
    81 fun typ options name = #typ (check_name options name);
    79 
    82 
    80 
    83 
    81 (* basic operations *)
    84 (* basic operations *)
    82 
    85 
    83 fun put T print name x (options as Options tab) =
    86 fun put T print name x (options as Options tab) =
    84   let val opt = check_type options name T
    87   let val opt = check_type options name T
    85   in Options (Symtab.update (name, {typ = #typ opt, value = print x}) tab) end;
    88   in Options (Symtab.update (name, {pos = #pos opt, typ = #typ opt, value = print x}) tab) end;
    86 
    89 
    87 fun get T parse options name =
    90 fun get T parse options name =
    88   let val opt = check_type options name T in
    91   let val opt = check_type options name T in
    89     (case parse (#value opt) of
    92     (case parse (#value opt) of
    90       SOME x => x
    93       SOME x => x
   116     else if #typ opt = realT then ignore (real options name)
   119     else if #typ opt = realT then ignore (real options name)
   117     else if #typ opt = stringT then ignore (string options name)
   120     else if #typ opt = stringT then ignore (string options name)
   118     else ()
   121     else ()
   119   end;
   122   end;
   120 
   123 
   121 fun declare {name, typ, value} (Options tab) =
   124 fun declare {pos, name, typ, value} (Options tab) =
   122   let
   125   let
   123     val options' = Options (Symtab.update_new (name, {typ = typ, value = value}) tab)
   126     val options' =
   124       handle Symtab.DUP _ => error ("Duplicate declaration of system option " ^ quote name);
   127       (case Symtab.lookup tab name of
       
   128         SOME other =>
       
   129           error ("Duplicate declaration of system option " ^ quote name ^ Position.here pos ^
       
   130             Position.here (#pos other))
       
   131       | NONE => Options (Symtab.update (name, {pos = pos, typ = typ, value = value}) tab));
   125     val _ =
   132     val _ =
   126       typ = boolT orelse typ = intT orelse typ = realT orelse typ = stringT orelse
   133       typ = boolT orelse typ = intT orelse typ = realT orelse typ = stringT orelse
   127         error ("Unknown type for system option " ^ quote name ^ " : " ^ quote typ);
   134         error ("Unknown type for system option " ^ quote name ^ " : " ^ quote typ ^
       
   135           Position.here pos);
   128     val _ = check_value options' name;
   136     val _ = check_value options' name;
   129   in options' end;
   137   in options' end;
   130 
   138 
   131 fun update name value (options as Options tab) =
   139 fun update name value (options as Options tab) =
   132   let
   140   let
   133     val opt = check_name options name;
   141     val opt = check_name options name;
   134     val options' = Options (Symtab.update (name, {typ = #typ opt, value = value}) tab);
   142     val options' =
       
   143       Options (Symtab.update (name, {pos = #pos opt, typ = #typ opt, value = value}) tab);
   135     val _ = check_value options' name;
   144     val _ = check_value options' name;
   136   in options' end;
   145   in options' end;
   137 
   146 
   138 
   147 
   139 (* decode *)
   148 (* decode *)
   140 
   149 
   141 fun decode body =
   150 fun decode_opt body =
   142   fold (declare o (fn (name, typ, value) => {name = name, typ = typ, value = value}))
   151   let open XML.Decode
   143     (let open XML.Decode in list (triple string string string) end body) empty;
   152   in list (pair properties (pair string (pair string string))) end body
       
   153   |> map (fn (props, (name, (typ, value))) =>
       
   154       {pos = Position.of_properties props, name = name, typ = typ, value = value});
       
   155 
       
   156 fun decode body = fold declare (decode_opt body) empty;
   144 
   157 
   145 
   158 
   146 
   159 
   147 (** global default **)
   160 (** global default **)
   148 
   161 
   158 fun default () =
   171 fun default () =
   159   (case Synchronized.value global_default of
   172   (case Synchronized.value global_default of
   160     SOME options => options
   173     SOME options => options
   161   | NONE => err_no_default ());
   174   | NONE => err_no_default ());
   162 
   175 
       
   176 fun default_position name = position (default ()) name;
   163 fun default_typ name = typ (default ()) name;
   177 fun default_typ name = typ (default ()) name;
   164 fun default_bool name = bool (default ()) name;
   178 fun default_bool name = bool (default ()) name;
   165 fun default_int name = int (default ()) name;
   179 fun default_int name = int (default ()) name;
   166 fun default_real name = real (default ()) name;
   180 fun default_real name = real (default ()) name;
   167 fun default_string name = string (default ()) name;
   181 fun default_string name = string (default ()) name;