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 |
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; |