src/Tools/isac/Specify/o-model.sml
author Walther Neuper <walther.neuper@jku.at>
Sat, 16 May 2020 12:40:09 +0200
changeset 59986 ecf545b44428
parent 59984 08296690e7a6
child 59987 73225ca9e0aa
permissions -rw-r--r--
shift code from Specification to O_Model
     1 (* Title:  Specify/o-model.sml
     2    Author: Walther Neuper 110226
     3    (c) due to copyright terms
     4 
     5 An original model is created initially from Formalise.T and Model_Pattern.T;
     6 This model makes student's editing via I_Model.T more efficient.
     7 TODO: revise with an example with more than 1 variant.
     8 *)
     9 
    10 signature ORIGINAL_MODEL =
    11 sig
    12   type T
    13   type single
    14   type variants
    15   type m_field
    16   type descriptor
    17   val to_string: T -> string
    18   val single_to_string: single -> string
    19   val single_empty: single
    20 
    21   val init: Formalise.model -> theory -> Model_Pattern.T -> T
    22   val add : theory -> Model_Pattern.T -> T -> T
    23   val values : T -> term list
    24 
    25 (*/--- use struct.id for appropriate names ..*)
    26   val match_ags: theory -> Model_Pattern.T -> term list -> T (*?\<rightarrow>M_Match?*)
    27   val match_ags_msg: Problem.id -> term -> term list -> unit (*?\<rightarrow>M_Match?*)
    28   val oris2fmz_vals: T -> string list * term list
    29 (*val variables: Model_Pattern.T -> term list*)              (*(*?\<rightarrow>Model_Pattern?*)*)
    30   val vars_of_pbl_': Model_Pattern.T -> term list            (*(*?\<rightarrow>Model_Pattern?*)*)
    31 
    32 (*put add_id into a new auxiliary fun..*)
    33   val add_id: 'a list -> (int * 'a) list
    34   type preori
    35 (* ---- for tests only: shifted from below to remove the Warning "unused" at fun.def. --------- *)
    36   val cpy_nam: Model_Pattern.T -> preori list -> Model_Pattern.single -> preori
    37   val is_copy_named: Model_Pattern.single -> bool
    38   val is_copy_named_idstr: string -> bool
    39   val is_copy_named_generating_idstr: string -> bool
    40   val is_copy_named_generating: Model_Pattern.single -> bool
    41   val matc: theory -> Model_Pattern.T -> term list -> preori list -> preori list
    42   val mtc: theory -> Model_Pattern.single -> term -> preori option
    43 
    44   val preoris2str : preori list -> string
    45 (*/-------------------------------------------------------- ! aktivate for Test_Isac BEGIN ---\* )
    46   val add_field: theory -> Model_Pattern.T -> term * 'b -> m_field * descriptor * 'b
    47   val add_variants: ('a * ''b * 'c) list -> (int * ('a * ''b * 'c)) list
    48   val max: variants -> int
    49   val coll_variants: ('a * ''b) list -> ('a list * ''b) list
    50   val replace_0: int -> int list -> int list
    51   val flattup: 'a * ('b * ('c * 'd * 'e)) -> 'a * 'b * 'c * 'd * 'e
    52 ( *\--- ! aktivate for Test_Isac END ----------------------------------------------------------/*)
    53 end
    54 
    55 (**)
    56 structure O_Model(**) : ORIGINAL_MODEL(**) =
    57 struct
    58 (**)
    59 
    60 (** types **)
    61 
    62 type variants =  Model_Def.variants;
    63 type m_field = Model_Def.m_field;
    64 type descriptor = Model_Def.descriptor;
    65 
    66 type T = Model_Def.o_model;
    67 type single = Model_Def.o_model_single
    68 val single_empty = Model_Def.o_model_empty;
    69 val single_to_string = Model_Def.o_model_single_to_string;
    70 val to_string = Model_Def.o_model_to_string;
    71 
    72 (* O_Model.single without leading integer *)
    73 type preori = (variants * m_field * term * term list);
    74 fun preori2str (vs, fi, t, ts) = 
    75   "(" ^ (strs2str o (map string_of_int)) vs ^ ", " ^ fi ^ ", " ^
    76   UnparseC.term t ^ ", " ^ (strs2str o (map UnparseC.term)) ts ^ ")";
    77 val preoris2str = (strs2str' o (map (linefeed o preori2str)));
    78 
    79 
    80 (** initialise O_Model **)
    81 
    82 (* compare d and dsc in pbt and transfer field to pre-ori *)
    83 fun add_field (_: theory) pbt (d,ts) = 
    84   let fun eq d pt = (d = (fst o snd) pt);
    85   in case filter (eq d) pbt of
    86        [(fi, (_, _))] => (fi, d, ts)
    87      | [] => ("#undef", d, ts)   (*may come with met.ppc*)
    88      | _ => raise ERROR ("add_field: " ^ UnparseC.term d ^ " more than once in pbt")
    89   end;
    90 
    91 (*
    92   mark an element with the position within a plateau;
    93   a plateau with length 1 is marked with 0
    94 *)
    95 fun mark _ [] = raise ERROR "mark []"
    96   | mark eq xs =
    97     let
    98       fun mar xx _ [x] n = xx @ [(if n = 1 then 0 else n, x)]
    99         | mar _ _ [] _ = raise ERROR "mark []"
   100         | mar xx eq (x:: x' :: xs) n = 
   101         if eq(x, x') then mar (xx @ [(n, x)]) eq (x' :: xs) (n + 1)
   102         else mar (xx @ [(if n = 1 then 0 else n, x)]) eq (x' :: xs) 1;
   103     in mar [] eq xs 1 end;
   104 
   105 (*
   106   assumes equal descriptions to be in adjacent 'plateaus',
   107   items at a certain position within the plateaus form a variant;
   108   length = 1 ... marked with 0: covers all variants
   109 *)
   110 fun add_variants fdts = 
   111   let 
   112     fun eq (a, b) = curry op= (snd3 a) (snd3 b);
   113   in mark eq fdts end;
   114 
   115 fun max [] = raise ERROR "max of []"
   116   | max (y :: ys) =
   117   let fun mx x [] = x
   118 	| mx x (y :: ys) = if x < y then mx y ys else mx x ys;
   119 in mx y ys end;
   120 
   121 fun coll_variants (((v,x) :: vxs)) =
   122     let
   123       fun col xs (vs, x) [] = xs @ [(vs, x)]
   124         | col xs (vs, x) ((v', x') :: vxs') = 
   125         if x = x' then col xs (vs @ [v'], x') vxs'
   126         else col (xs @ [(vs, x)]) ([v'], x') vxs';
   127     in col [] ([v], x) vxs end
   128   | coll_variants _ = raise ERROR "coll_variants: called with []";
   129 
   130 fun replace_0 vm [0] = intsto vm
   131   | replace_0 _ vs = vs;
   132 
   133 fun add_id [] = raise ERROR "O_Model.add_id []"
   134   | add_id xs =
   135     let
   136       fun add _ [] = []
   137         | add n (x :: xs) = (n, x) :: add (n + 1) xs;
   138     in add 1 xs end;
   139 
   140 fun flattup (a, (b, (c, d, e))) = (a, b, c, d, e);
   141 
   142 fun init [] _ _ = []
   143   | init fmz thy pbt =
   144     let
   145       val model = (map (fn str => str
   146                      |> TermC.parseNEW'' thy
   147                      |> Input_Descript.split
   148                      |> add_field thy pbt) fmz)
   149                   |> add_variants;
   150       val maxv = model |> map fst |> max;
   151       val maxv = if maxv = 0 then 1 else maxv;
   152       val model' = model
   153         |> coll_variants
   154         |> map (replace_0 maxv |> apfst)
   155         |> add_id
   156         |> map flattup;
   157     in model' end;
   158 
   159 
   160 (** add new m_field's from method **)
   161 
   162 fun add _ mpc ori =
   163   let
   164     fun eq d pt = (d = (fst o snd) pt);
   165     fun repl mpc (i, v, _, d, ts) = 
   166       case filter (eq d) mpc of
   167 	      [(fi, (_, _))] => [(i, v, fi, d, ts)]
   168       | [] => [] (*25.2.02: dsc in ori, but not in met -> superfluous*)    
   169       | _ => raise ERROR ("O_Model.add: " ^ UnparseC.term d ^ " more than once in met");
   170   in flat ((map (repl mpc)) ori) end;
   171 
   172 
   173 (** get the values **)
   174 
   175 fun mkval _(*dsc*) [] = raise ERROR "mkval called with []"
   176   | mkval _ [t] = t
   177   | mkval _ ts = TermC.list2isalist ((type_of o hd) ts) ts;
   178 fun mkval' x = mkval TermC.empty x;
   179 fun values oris =
   180   ((map (mkval' o (#5))) o (filter ((member_swap op= 1) o (#2)))) oris
   181 
   182 
   183 (** ? ? ? **)
   184 
   185 (* make oris from args of the stac SubProblem and from pbt.
   186    can this formal argument (of a model-pattern) be omitted in the arg-list
   187    of a SubProblem ? see calcelems.sml 'type met '                        *)
   188 fun is_copy_named_idstr str =
   189   case (rev o Symbol.explode) str of
   190 	  "'" :: _ :: "'" :: _ => true
   191   | _ => false
   192 fun is_copy_named (_, (_, t)) = (is_copy_named_idstr o TermC.free2str) t
   193 
   194 (* should this formal argument (of a model-pattern) create a new identifier? *)
   195 fun is_copy_named_generating_idstr str =
   196   if is_copy_named_idstr str
   197   then
   198     case (rev o Symbol.explode) str of
   199 	    "'" :: "'" :: "'" :: _ => false
   200     | _ => true
   201   else false
   202 fun is_copy_named_generating (_, (_, t)) = (is_copy_named_generating_idstr o TermC.free2str) t
   203 
   204 
   205 (* split type-wrapper from scr-arg and build part of an ori;
   206    an type-error is reported immediately, raises an exn, 
   207    subsequent handling of exn provides 2nd part of error message *)
   208 fun mtc thy (str, (dsc, _)) (ty $ var) =
   209     ((Thm.global_cterm_of thy (dsc $ var);(*type check*)
   210       SOME (([1], str, dsc, (*[var]*)
   211 	    Input_Descript.split' (dsc, var))) (*:ori without leading #*))
   212       handle e as TYPE _ => 
   213 	      (tracing (dashs 70 ^ "\n"
   214 	        ^ "*** ERROR while creating the items for the model of the ->problem\n"
   215 	        ^ "*** from the ->stac with ->typeconstructor in arglist:\n"
   216 	        ^ "*** item (->description ->value): " ^ UnparseC.term dsc ^ " " ^ UnparseC.term var ^ "\n"
   217 	        ^ "*** description: " ^ TermC.term_detail2str dsc
   218 	        ^ "*** value: " ^ TermC.term_detail2str var
   219 	        ^ "*** typeconstructor in script: " ^ TermC.term_detail2str ty
   220 	        ^ "*** checked by theory: " ^ Context.theory_name thy ^ "\n"
   221 	        ^ "*** " ^ dots 66);
   222           writeln (@{make_string} e);
   223           Exn.reraise e; (*raise ERROR "actual args do not match formal args";FIXXXME.WN100916*)
   224       NONE))
   225   | mtc _ _ t = raise ERROR ("mtc: uncovered case with" ^ UnparseC.term t)
   226 
   227 (* match each pat of the model-pattern with an actual argument;
   228    precondition: copy-named vars are filtered out            *)
   229 fun matc _ [] _ oris = oris
   230   | matc _ pbt [] _ =
   231     (tracing (dashs 70);
   232      raise ERROR ("actual arg(s) missing for '" ^ Model_Pattern.to_string pbt ^ "' i.e. should be 'copy-named' by '*_._'"))
   233   | matc thy ((p as (_, (_, t))) :: pbt) (a :: ags) oris =
   234     (*del?..*)if (is_copy_named_idstr o TermC.free2str) t then oris
   235     else(*..del?*)
   236       let val opt = mtc thy p a
   237       in
   238         case opt of
   239           SOME ori => matc thy pbt ags (oris @ [ori])
   240 	      | NONE => [](*WN050903 skipped by exn handled in match_ags*)
   241 	 end
   242 
   243 (* generate a new variable "x_i" name from a related given one "x"
   244    by use of oris relating "v_v'i'" (is_copy_named!) to "v_v"
   245    e.g. (v_v, x) & (v_v'i', ?) --> (v_v'i', x_i),
   246    but leave is_copy_named_generating as is, e.t. ss''' *)
   247 fun cpy_nam pbt oris (p as (field, (dsc, t))) =
   248   (if is_copy_named_generating p
   249    then (*WN051014 kept strange old code ...*)
   250      let fun sel (_,_,d,ts) = Input_Descript.join'''' (d, ts) 
   251        val cy' = (implode o (drop_last_n 3) o Symbol.explode o TermC.free2str) t
   252        val ext = (last_elem o drop_last o Symbol.explode o TermC.free2str) t
   253        val vars' = map (Term.term_name o snd o snd) pbt (*cpy-nam filtered_out*)
   254        val vals = map sel oris
   255        val cy_ext = (Term.term_name o the) (assoc (vars' ~~ vals, cy')) ^ "_" ^ ext
   256      in ([1], field, dsc, [TermC.mk_free (type_of t) cy_ext]) end
   257    else ([1], field, dsc, [t])
   258 	) handle _ => raise ERROR ("cpy_nam: for "^ UnparseC.term t)
   259 
   260 (* ["BOOL (1+x=2)","REAL x"] --match_ags--> oris 
   261    --oris2fmz_vals--> ["equality (1+x=2)","boundVariable x","solutions L"] *)
   262 fun oris2fmz_vals oris =
   263   let fun ori2fmz_vals (_, _, _, dsc, ts) = 
   264 	  ((UnparseC.term o Input_Descript.join') (dsc, ts), last_elem ts) 
   265 	  handle _ => raise ERROR ("ori2fmz_env called with " ^ UnparseC.terms ts)
   266   in (split_list o (map ori2fmz_vals)) oris end
   267 
   268 (* match the actual arguments of a SubProblem with a model-pattern
   269    and create an ori list (in root-pbl created from formalization).
   270    expects ags:pats = 1:1, while copy-named are filtered out of pats;
   271    if no 1:1 then exn raised by matc/mtc and handled at call.
   272    copy-named pats are appended in order to get them into the model-items *)
   273 fun match_ags thy pbt ags =
   274   let
   275     fun flattup (i, (var, bool, str, itm_)) = (i, var, bool, str, itm_)
   276     val pbt' = filter_out is_copy_named pbt
   277     val cy = filter is_copy_named pbt  (* cy is NOT a (formal) argument, but the fun's result *)
   278     val oris' = matc thy pbt' ags []
   279     val cy' = map (cpy_nam pbt' oris') cy
   280     val ors = add_id (oris' @ cy') (*...appended in order to get into the model-items *)
   281   in (map flattup ors) end
   282 
   283 (* report part of the error-msg which is not available in match_args *)
   284 fun match_ags_msg pI stac ags =
   285   let
   286     val pats = (#ppc o Problem.from_store) pI
   287     val msg = (dots 70 ^ "\n"
   288        ^ "*** problem " ^ strs2str pI ^ " has the ...\n"
   289        ^ "*** model-pattern " ^ Model_Pattern.to_string pats ^ "\n"
   290        ^ "*** stac   '" ^ UnparseC.term stac ^ "' has the ...\n"
   291        ^ "*** arg-list " ^ UnparseC.terms ags ^ "\n"
   292        ^ dashs 70)
   293 	  (*WN100921 ^^^^ expect TYPE errormsg below; lost with Isa09*)
   294   in tracing msg end
   295 
   296 (* get the variables out of a pbl_; FIXME.WN.0311: is_copy_named ...obscure!!! *)
   297 fun vars_of_pbl_' pbl_ = 
   298   let
   299     fun var_of_pbl_ (_, (_, t)) = t: term
   300   in ((map var_of_pbl_)(* o (filter_out is_copy_named)*)) pbl_ end
   301 
   302 (**)end(**);