1 (* Title: BaseDefinitions/model-pattern.sml
3 (c) due to copyright terms
5 A \<open>Model_Pattern\<close> defines a -> \<open>Problem\<close>-type: its \<open>variables\<close> are to be instantiated
6 by the values for particular \<open>Problem\<close>s in a \<open>Formalise.model\<close>.
7 The \<open>variables\<close> are used twice, in a model and as formal arguments in a \<open>Program\<close>.
8 The \<open>descriptor\<close>s are unique identifiers within one \<open>Model_Pattern\<close>.
10 signature MODEL_PATTERN =
14 val to_string: Proof.context -> single list -> string
18 val empty_input: empty_input list
24 type descriptor = term
25 val parse_pos: Proof.context -> (m_field * (string * Position.T) list) list ->
26 pre_model * (term * Position.T) list
27 val parse_pos_TEST: Proof.context -> (m_field * (string * Position.T) list) list ->
28 pre_model_TEST * (term * Position.T) list
30 val variables: T -> term list
31 val get_field: descriptor -> T -> m_field option
32 datatype for = Problem | Method | Undef
34 val adapt_to_type: Proof.context -> single -> single
35 (*from isac_test for Minisubpbl*)
36 val split_descriptor: Proof.context -> m_field * term * Position.T ->
37 (m_field * (descriptor * term) * Position.T)
38 val split_descriptor': string -> (*TermC.as_*)string * empty_input
39 datatype pre_model_single_TEST =
40 Empty of (m_field * (descriptor * empty_input) * Position.T)
41 | Proper of (m_field * (descriptor * term) * Position.T)
42 val parse_pattern: Proof.context -> 'a * (string * Position.T) -> 'a * term * Position.T
43 val empty_for: typ -> string
44 val parse_term: Proof.context -> m_field * ((*TermC.as_*)string * Position.T) ->
45 m_field * term * Position.T
46 val parse_term_TEST: Proof.context -> m_field * (string * Position.T) -> pre_model_single_TEST
54 structure Model_Pattern(**): MODEL_PATTERN(**) =
58 (* the pattern for an item of a problems model or a methods guard *)
59 type m_field = string;
60 type descriptor = term;
62 (m_field * (* field Given, Find, Relate *)
63 (descriptor * (* for snd term *)
64 term)) (* id | arbitrary term *);
65 (* does NOT contain pre-conditions, because these have no \<open>descriptor\<close> *)
68 type model_input_pos = (* for internal use *)
69 (m_field * (* "#Given", "#Find", "#Where", "#Relate" *)
70 ((*TermC.as_*)string * Position.T) list) (* list of items belonging to m_field *)
71 list; (* list of "#Given" .. "#Relate" *)
72 type empty_input = string
73 val empty_bool_list_input = "[__=__, __=__]"
74 val empty_reallist_input = "[__, __]"
75 val empty_bool_input = "(__=__)"
76 val empty_item_input = "__"
77 val empty_input = [empty_bool_list_input, empty_reallist_input, empty_bool_input, empty_item_input]
78 fun empty_for (Type ("fun", [Type ("List.list", [Type ("HOL.bool", [])]), _])) = empty_bool_list_input
79 | empty_for (Type ("fun", [Type ("List.list", [Type ("Real.real", [])]), _])) = empty_reallist_input
80 | empty_for (Type ("HOL.bool", [])) = empty_bool_input
81 | empty_for _ = empty_item_input
82 type pre_model_single = (m_field * (descriptor * term) * Position.T)
83 datatype pre_model_single_TEST =
84 Empty of (m_field * (descriptor * empty_input) * Position.T)
85 | Proper of (m_field * (descriptor * term) * Position.T)
86 type pre_model = pre_model_single list
87 type pre_model_TEST = pre_model_single_TEST list
89 (*val split_descriptor: Proof.context -> m_field * term * Position.T ->
90 m_field * (descriptor * term)(* * Position.T*)*)
91 fun split_descriptor ctxt (m_field: string, dsc_tm, pos) =
93 val (m_field, (hd, arg)) = case strip_comb dsc_tm of
94 (hd, [arg]) => (m_field, (hd, arg))
95 | _ => error ("Wrong descriptor " ^ quote (UnparseC.term ctxt dsc_tm) ^ Position.here pos)
96 in (m_field, (hd, arg), pos) end
99 if Term.exists_subterm (fn Const ("HOL.undefined", _) => true | _ => false) tm then true else false
100 fun is_empty_input arg = member (op =) empty_input arg
101 fun split_descriptor' str =
103 val chars = Symbol.explode str
104 val end_descr = find_index (fn str => (if str = " " then true else false)) chars
105 (*^^^ TODO find parser for identifier*)
107 (implode (take (end_descr, chars)), implode (drop (end_descr + 1, chars)))
108 (* 1 blank inbetween descriptor and argument, I_Model.feedback_to_string_TEST *)
111 (*val parse_term: Proof.context -> m_field * ((*TermC.as_*)string * Position.T) -> m_field * term*)
112 fun parse_term ctxt (m_field, (str, pos)) =
113 (m_field, ParseC.term_position ctxt (str, pos), pos)
114 fun parse_term_TEST ctxt (m_field, (str, pos)) =
116 val (m_field, term, pos) = parse_term ctxt (m_field, (str, pos))
117 val (m_field, (descr, arg), pos) = split_descriptor ctxt (m_field, term, pos)
120 then Empty (m_field, (descr, descr |> type_of |> empty_for), pos)
121 else Proper (m_field, (descr, arg), pos)
124 fun parse_pattern ctxt (m_field, (str, pos)) =
125 (m_field, ParseC.pattern_position ctxt (str, pos), pos)
127 fun parse_pos ctxt model_input =
129 val items = model_input |> map (fn (m_field, items) => map (pair m_field) items) |> flat;
131 |> filter_out ((fn f => (fn (f', _) => f = f')) "#Where")
132 |> map (parse_term ctxt)
133 |> map (split_descriptor ctxt)
135 |> filter ((fn f => (fn (f', _) => f = f')) "#Where")
136 |> map (parse_pattern ctxt)
137 |> map (fn (_, a, b) => (a, b))
138 in (model, where_) end
139 fun parse_pos_TEST ctxt model_input =
141 val items = model_input |> map (fn (m_field, items) => map (pair m_field) items) |> flat;
143 |> filter_out ((fn f => (fn (f', _) => f = f')) "#Where")
144 |> map (parse_term_TEST ctxt)
146 |> filter ((fn f => (fn (f', _) => f = f')) "#Where")
147 |> map (parse_pattern ctxt)
148 |> map (fn (_, a, b) => (a, b))
149 in (model, where_) end
151 fun pat2str ctxt (field, (dsc, id)) =
152 pair2str (field, pair2str (UnparseC.term ctxt dsc, UnparseC.term ctxt id));
153 fun to_string ctxt pats = (strs2str o (map (pat2str ctxt))) pats;
159 (* get the variables out of a pbl_; FIXME.WN.0311: is_copy_named ...obscure!!! *)
162 fun var_of_pbl_ (_, (_, t)) = t: term
163 in ((map var_of_pbl_)(* o (filter_out is_copy_named)*)) pbl_ end
165 fun get_field descriptor m_patt =
166 (filter ((curry (fn (desc, (_, (desc', _))) => desc = desc')) descriptor) m_patt
168 |> (fn (a, _) => SOME a))
169 handle List.Empty => NONE
170 datatype for = Problem | Method | Undef
173 (* adapt type of terms with most general type to a more specific one *)
174 fun adapt_to_type ctxt (field, (descr, term_as_string)) =
175 (field, (ParseC.adapt_term_to_type ctxt descr, ParseC.adapt_term_to_type ctxt term_as_string))