1 (* Title: MathEngBasic/problem.sml
2 Author: Walther Neuper 2019
3 (c) due to copyright terms
11 type id = Probl_Def.id
14 val id_to_string: id -> string
18 val split_did: term -> term * term
19 val split_did_PIDE: term -> term * term
20 (* TODO: ---------- remove always empty --- vvvvvvvvvvv -- vvv*)
21 val prep_input : theory -> Check_Unique.id -> string list -> id -> input -> T * id
22 val prep_input_PIDE : theory -> Check_Unique.id -> string list -> id -> input -> T * id
24 val set_data: Rule_Def.rule_set -> theory -> theory
25 val the_data: theory -> Rule_Def.rule_set
27 val parse_item: string parser -> 'a parser -> 'a parser
28 val parse_item_name: string parser -> string -> string parser
29 val parse_item_names: string parser -> string list parser
30 val parse_model_input: model_input parser
31 val parse_authors: string list parser
32 val parse_cas: Token.T list -> string option * Token.T list
33 val parse_methods: string list parser
34 val ml: string -> ML_Lex.token Antiquote.antiquote list
36 val from_store: id -> T
40 structure Problem(**): PROBLEM(**) =
45 val empty = Probl_Def.empty
48 elements if the id are in reverse order as compared to MethodC:
49 e.g. ["linear", "univariate", "equation"] has "equation" as parent node --
50 -- this makes the id readable.
52 type id = Probl_Def.id;
53 (* same order as for MethodC (used in Store )*)
54 type id_reverse = Probl_Def.id;
56 val id_empty = Probl_Def.id_empty;
57 val id_to_string = Probl_Def.id_to_string;
60 (** prepare Problem for Store **)
63 (Model_Pattern.m_field * (* "#Given", "#Find", "#Where", "#Relate" *)
64 TermC.as_string list) (* list of items belonging to m_field *)
65 list; (* list of "#Given" .. "#Relate" *)
67 id * (* the key into the problem hierarchy *)
68 model_input * (* e.g. ("#Given", ["unsorted u_u"]) list *)
69 Rule_Set.T * (* for evaluating "#Where" *)
70 TermC.as_string option * (* CAS_Cmd *)
71 Meth_Def.id list; (* methods that can solve the problem *)
73 (* split a term into description and (id | structured variable) for pbt, met.ppc *)
76 val (hd, arg) = case strip_comb t of
77 (hd, [arg]) => (hd, arg)
78 | _ => raise ERROR ("split_did: doesn't match (hd,[arg]) for t = " ^ UnparseC.term t)
80 fun split_did_PIDE t =
82 val (hd, arg) = case strip_comb t of
83 (hd, [arg]) => (hd, arg)
84 | _ => raise ERROR ("split_did_PIDE: doesn't match (hd,[arg]) for t = xxxxx" (*^ UnparseC.term t*))
87 (* prepare problem-types before storing in pbltypes;
88 dont forget to "check_guh_unique" before ins *)
89 fun prep_input thy guh maa init ((pblID, dsc_dats, ev, ca, metIDs): input) : T * id =
91 fun eq f (f', _) = f = f';
92 val gi = filter (eq "#Given") dsc_dats;
96 (case \<^try>\<open> map (split_did o (TermC.parseNEW'' thy)) gi'\<close> of
98 | NONE => raise ERROR ("prep_input: syntax raise ERROR in '#Given' of " ^ strs2str pblID))
99 | _ => raise ERROR ("prep_input: more than one '#Given' in " ^ strs2str pblID));
100 val gi = map (pair "#Given") gi;
102 val fi = filter (eq "#Find") dsc_dats;
105 | ((_, fi') :: []) =>
106 (case \<^try>\<open> map (split_did o (TermC.parseNEW'' thy)) fi'\<close> of
108 | NONE => raise ERROR ("prep_input: syntax raise ERROR in '#Find' of " ^ strs2str pblID))
109 | _ => raise ERROR ("prep_input: more than one '#Find' in " ^ strs2str pblID));
110 val fi = map (pair "#Find") fi;
112 val re = filter (eq "#Relate") dsc_dats;
115 | ((_, re') :: []) =>
116 (case \<^try>\<open> map (split_did o (TermC.parseNEW'' thy)) re'\<close> of
118 | NONE => raise ERROR ("prep_input: syntax raise ERROR in '#Relate' of " ^ strs2str pblID))
119 | _ => raise ERROR ("prep_input: more than one '#Relate' in " ^ strs2str pblID));
120 val re = map (pair "#Relate") re;
122 val wh = filter (eq "#Where") dsc_dats;
125 | ((_, wh') :: []) =>
126 (case \<^try>\<open> map (TermC.parse_patt thy) wh'\<close> of
128 | NONE => raise ERROR ("prep_input: syntax raise ERROR in '#Where' of " ^ strs2str pblID))
129 | _ => raise ERROR ("prep_input: more than one '#Where' in " ^ strs2str pblID));
131 ({guh = guh, mathauthors = maa, init = init, thy = thy,
132 cas = Option.map (TermC.parseNEW'' thy) ca,
133 prls = ev, where_ = wh, ppc = gi @ fi @ re, met = metIDs}, pblID)
135 fun prep_input_PIDE thy guh maa init (pblID, dsc_dats, ev, ca, metIDs) =
137 fun eq f (f', _) = f = f';
138 val _ = writeln "#prep_input_PIDE 1";
139 val gi = filter (eq "#Given") dsc_dats;
140 val _ = writeln "#prep_input_PIDE 1a";
143 | ((_, gi') :: []) =>
144 (*(case \<^try>\<open> *)map (split_did_PIDE o (Syntax.read_term_global thy)) gi'(*\<close> of
146 | NONE => raise ERROR ("prep_input_PIDE: syntax raise ERROR in '#Given' of " ^ strs2str pblID))*)
147 | _ => raise ERROR ("prep_input_PIDE: more than one '#Given' in xxxxx" (*^ strs2str pblID*)));
148 val _ = writeln "#prep_input_PIDE 1b";
149 val gi = map (pair "#Given") gi;
151 val _ = writeln "#prep_input_PIDE 2";
152 val fi = filter (eq "#Find") dsc_dats;
155 | ((_, fi') :: []) =>
156 (*(case \<^try>\<open> *)map (split_did_PIDE o (Syntax.read_term_global thy)) fi'(*\<close> of
158 | NONE => raise ERROR ("prep_input_PIDE: syntax raise ERROR in '#Find' of " ^ strs2str pblID))*)
159 | _ => raise ERROR ("prep_input_PIDE: more than one '#Find' in xxxxx" (*^ strs2str pblID*)));
160 val fi = map (pair "#Find") fi;
162 val _ = writeln "#prep_input_PIDE 3";
163 val re = filter (eq "#Relate") dsc_dats;
166 | ((_, re') :: []) =>
167 (*(case \<^try>\<open> *)map (split_did_PIDE o (Syntax.read_term_global thy)) re'(*\<close> of
169 | NONE => raise ERROR ("prep_input_PIDE: syntax raise ERROR in '#Relate' of " ^ strs2str pblID))*)
170 | _ => raise ERROR ("prep_input_PIDE: more than one '#Relate' in xxxxx" (*^ strs2str pblID*)));
171 val re = map (pair "#Relate") re;
173 val _ = writeln "#prep_input_PIDE 4";
174 val wh = filter (eq "#Where") dsc_dats;
177 | ((_, wh') :: []) =>
178 (*(case \<^try>\<open> *)map (TermC.parse_patt thy) wh'(*\<close> of
180 | NONE => raise ERROR ("prep_input_PIDE: syntax raise ERROR in '#Where' of " ^ strs2str pblID))*)
181 | _ => raise ERROR ("prep_input_PIDE: more than one '#Where' in xxxxx" (*^ strs2str pblID*)));
183 ({guh = guh, mathauthors = maa, init = init, thy = thy,
184 cas = Option.map (Syntax.read_term_global thy) ca,
185 prls = ev, where_ = wh, ppc = gi @ fi @ re, met = metIDs}, pblID)
193 structure Data = Theory_Data
195 type T = Rule_Set.T option;
201 val set_data = Data.put o SOME;
202 val the_data = the o Data.get;
205 (* auxiliary parsers *)
207 fun parse_item (keyword: string parser) (parse: 'a parser) =
208 (keyword -- Args.colon) |-- Parse.!!! parse;
210 fun parse_item_name keyword =
211 Scan.optional (parse_item keyword Parse.name);
213 fun parse_item_names (keyword: string parser) =
214 Scan.optional (parse_item keyword (Scan.repeat1 Parse.name)) [];
216 fun parse_tagged_terms keyword (tag: string) =
217 Scan.optional (parse_item keyword (Scan.repeat Parse.term) >> (fn ts => [(tag, ts)])) [];
219 val parse_model_input : model_input parser =
220 parse_tagged_terms \<^keyword>\<open>Given\<close> "#Given" @@@
221 parse_tagged_terms \<^keyword>\<open>Where\<close> "#Where" @@@
222 parse_tagged_terms \<^keyword>\<open>Find\<close> "#Find" @@@
223 parse_tagged_terms \<^keyword>\<open>Relate\<close> "#Relate";
225 val parse_authors = parse_item_names \<^keyword>\<open>Author\<close>;
226 val parse_cas = Scan.option (parse_item \<^keyword>\<open>CAS\<close> Parse.term);
227 val parse_methods = parse_item_names \<^keyword>\<open>Method_Ref\<close>;
228 val ml = ML_Lex.read;
231 (* command definition *)
236 Outer_Syntax.command \<^command_keyword>\<open>problem\<close>
237 "prepare ISAC problem type and register it to Knowledge Store"
238 (Parse.name -- Parse.!!! (\<^keyword>\<open>:\<close> |-- Parse.name --
239 Parse.!!! (\<^keyword>\<open>=\<close> |-- Parse.ML_source -- parse_authors --
240 parse_methods -- parse_cas -- parse_model_input)) >>
241 (fn (name, (id, ((((source, maa), mets), cas), model_input))) =>
242 Toplevel.theory (fn thy =>
244 (*Ouptut from Biegelinie.problem pbl_bieg : "Biegelinien":*)
245 val pblID = References_Def.explode_id id;
246 val metIDs = map References_Def.explode_id mets;
247 (*val _ = writeln ("#problem source: " ^ @{make_string} source)*)
249 ML_Context.expression (Input.pos_of source)
250 (ml "Theory.setup (Problem.set_data (" @ ML_Lex.read_source source @ ml "))")
251 |> Context.theory_map;
252 (*val _ = writeln ("#problem set_data: " ^ @{make_string} set_data)*)
253 (* Context.theory_map HAS STORED THE ml-source IN Theory_Data ALREADY,
254 BUT prep_input_PIDE REQUIRES ml-source AGAIN ... *)
255 val input = the_data (set_data thy);
256 (*val _ = writeln ("#problem input: " ^ @{make_string} input)*)
259 val _ = writeln ("#problem model_input: " ^ @{make_string} model_input)
260 val (m1, m2) = case model_input of
261 ("#Given", [m1, m2]) :: _ => (m1, m2) (*=("<markup>", "<markup>")*)
262 | _ => ("different case model_input", "different case model_input")
263 val _ = writeln ("#problem m1: " ^ m1) (*= Traegerlaenge l_l*)
264 val _ = writeln ("#problem m2: " ^ m2) (*= Streckenlast q_q *)
266 * parse_model_input should preserve Position.T, Position.range, etc
267 * ? preserve Position.T etc within ML_Lex.token Antiquote.antiquote list ?..
268 ..in analogy to set_data ?!?
269 * by Context.theory_map notify Isabelle/PIDE of errors from model_input at Position.T
270 * in case there are no errors, do prep_input_PIDE (to be simplified)
272 val arg = prep_input_PIDE thy name maa id_empty (pblID, model_input, input, cas, metIDs);
273 in KEStore_Elems.add_pbls @{context} [arg] thy end)))
279 (** get Problem from Store **)
281 fun from_store id = Store.get (get_pbls ()) id (rev id);