22 val map_global: 'a T -> ('a -> 'a) -> theory -> theory |
22 val map_global: 'a T -> ('a -> 'a) -> theory -> theory |
23 val put_global: 'a T -> 'a -> theory -> theory |
23 val put_global: 'a T -> 'a -> theory -> theory |
24 val get_generic: Context.generic -> 'a T -> 'a |
24 val get_generic: Context.generic -> 'a T -> 'a |
25 val map_generic: 'a T -> ('a -> 'a) -> Context.generic -> Context.generic |
25 val map_generic: 'a T -> ('a -> 'a) -> Context.generic -> Context.generic |
26 val put_generic: 'a T -> 'a -> Context.generic -> Context.generic |
26 val put_generic: 'a T -> 'a -> Context.generic -> Context.generic |
27 val declare: string -> (Context.generic -> value) -> raw |
27 val declare: string * Position.T -> (Context.generic -> value) -> raw |
28 val declare_global: string -> (Context.generic -> value) -> raw |
28 val declare_global: string * Position.T -> (Context.generic -> value) -> raw |
29 val declare_option: string -> raw |
29 val declare_option: string * Position.T -> raw |
30 val declare_option_global: string -> raw |
30 val declare_option_global: string * Position.T -> raw |
31 val name_of: 'a T -> string |
31 val name_of: 'a T -> string |
|
32 val pos_of: 'a T -> Position.T |
32 end; |
33 end; |
33 |
34 |
34 structure Config: CONFIG = |
35 structure Config: CONFIG = |
35 struct |
36 struct |
36 |
37 |
57 | same_type (Int _) (Int _) = true |
58 | same_type (Int _) (Int _) = true |
58 | same_type (Real _) (Real _) = true |
59 | same_type (Real _) (Real _) = true |
59 | same_type (String _) (String _) = true |
60 | same_type (String _) (String _) = true |
60 | same_type _ _ = false; |
61 | same_type _ _ = false; |
61 |
62 |
62 fun type_check name f value = |
63 fun type_check (name, pos) f value = |
63 let |
64 let |
64 val value' = f value; |
65 val value' = f value; |
65 val _ = same_type value value' orelse |
66 val _ = same_type value value' orelse |
66 error ("Ill-typed configuration option " ^ quote name ^ ": " ^ |
67 error ("Ill-typed configuration option " ^ quote name ^ Position.here pos ^ ": " ^ |
67 print_type value ^ " expected,\nbut " ^ print_type value' ^ " was found"); |
68 print_type value ^ " expected,\nbut " ^ print_type value' ^ " was found"); |
68 in value' end; |
69 in value' end; |
69 |
70 |
70 |
71 |
71 (* abstract configuration options *) |
72 (* abstract configuration options *) |
72 |
73 |
73 datatype 'a T = Config of |
74 datatype 'a T = Config of |
74 {name: string, |
75 {name: string, |
|
76 pos: Position.T, |
75 get_value: Context.generic -> 'a, |
77 get_value: Context.generic -> 'a, |
76 map_value: ('a -> 'a) -> Context.generic -> Context.generic}; |
78 map_value: ('a -> 'a) -> Context.generic -> Context.generic}; |
77 |
79 |
78 type raw = value T; |
80 type raw = value T; |
79 |
81 |
80 fun coerce make dest (Config {name, get_value, map_value}) = Config |
82 fun coerce make dest (Config {name, pos, get_value, map_value}) = Config |
81 {name = name, |
83 {name = name, |
|
84 pos = pos, |
82 get_value = dest o get_value, |
85 get_value = dest o get_value, |
83 map_value = fn f => map_value (make o f o dest)}; |
86 map_value = fn f => map_value (make o f o dest)}; |
84 |
87 |
85 val bool = coerce Bool (fn Bool b => b); |
88 val bool = coerce Bool (fn Bool b => b); |
86 val int = coerce Int (fn Int i => i); |
89 val int = coerce Int (fn Int i => i); |
110 fun merge data = Inttab.merge (K true) data; |
113 fun merge data = Inttab.merge (K true) data; |
111 ); |
114 ); |
112 |
115 |
113 local |
116 local |
114 |
117 |
115 fun declare_generic global name default = |
118 fun declare_generic global (name, pos) default = |
116 let |
119 let |
117 val id = serial (); |
120 val id = serial (); |
118 |
121 |
119 fun get_value context = |
122 fun get_value context = |
120 (case Inttab.lookup (Value.get context) id of |
123 (case Inttab.lookup (Value.get context) id of |
121 SOME value => value |
124 SOME value => value |
122 | NONE => default context); |
125 | NONE => default context); |
123 |
126 |
124 fun update_value f context = |
127 fun update_value f context = |
125 Value.map (Inttab.update (id, type_check name f (get_value context))) context; |
128 Value.map (Inttab.update (id, type_check (name, pos) f (get_value context))) context; |
126 |
129 |
127 fun map_value f (context as Context.Proof ctxt) = |
130 fun map_value f (context as Context.Proof ctxt) = |
128 let val context' = update_value f context in |
131 let val context' = update_value f context in |
129 if global andalso |
132 if global andalso |
130 Context_Position.is_visible ctxt andalso |
133 Context_Position.is_visible ctxt andalso |
135 warning ("Ignoring local change of global option " ^ quote name) |
138 warning ("Ignoring local change of global option " ^ quote name) |
136 else (); context) |
139 else (); context) |
137 else context' |
140 else context' |
138 end |
141 end |
139 | map_value f context = update_value f context; |
142 | map_value f context = update_value f context; |
140 in Config {name = name, get_value = get_value, map_value = map_value} end; |
143 in Config {name = name, pos = pos, get_value = get_value, map_value = map_value} end; |
141 |
144 |
142 fun declare_option_generic global name = |
145 fun declare_option_generic global (name, pos) = |
143 let |
146 let |
144 val typ = Options.default_typ name; |
147 val typ = Options.default_typ name; |
145 val default = |
148 val default = |
146 if typ = Options.boolT then fn _ => Bool (Options.default_bool name) |
149 if typ = Options.boolT then fn _ => Bool (Options.default_bool name) |
147 else if typ = Options.intT then fn _ => Int (Options.default_int name) |
150 else if typ = Options.intT then fn _ => Int (Options.default_int name) |
148 else if typ = Options.realT then fn _ => Real (Options.default_real name) |
151 else if typ = Options.realT then fn _ => Real (Options.default_real name) |
149 else if typ = Options.stringT then fn _ => String (Options.default_string name) |
152 else if typ = Options.stringT then fn _ => String (Options.default_string name) |
150 else error ("Unknown type for option " ^ quote name ^ " : " ^ quote typ); |
153 else error ("Unknown type for option " ^ quote name ^ Position.here pos ^ " : " ^ quote typ); |
151 in declare_generic global name default end; |
154 in declare_generic global (name, pos) default end; |
152 |
155 |
153 in |
156 in |
154 |
157 |
155 val declare = declare_generic false; |
158 val declare = declare_generic false; |
156 val declare_global = declare_generic true; |
159 val declare_global = declare_generic true; |