21 fun opt_parens s = if s = "" then "" else enclose "(" ")" s; |
21 fun opt_parens s = if s = "" then "" else enclose "(" ")" s; |
22 |
22 |
23 (* ----------------------------------------------------------------------- *) |
23 (* ----------------------------------------------------------------------- *) |
24 (* Derivation of the primrec combinator application from the equations *) |
24 (* Derivation of the primrec combinator application from the equations *) |
25 |
25 |
26 (* subst. applications fname(ls,xk,rs) by yk(ls,rs) for xk in rargs *) |
26 (* substitute fname(ls,xk,rs) by yk(ls,rs) in t for (xk,yk) in pairs *) |
27 |
27 |
28 fun subst_apps (_,_) [] t = t |
28 fun subst_apps (_,_) [] t = t |
29 | subst_apps (fname,cpos) pairs t = |
29 | subst_apps (fname,rpos) pairs t = |
30 let |
30 let |
31 fun subst (Abs(a,T,t)) = Abs(a,T,subst t) |
31 fun subst (Abs(a,T,t)) = Abs(a,T,subst t) |
32 | subst (funct $ body) = |
32 | subst (funct $ body) = |
33 let val (f,b) = strip_comb (funct$body) |
33 let val (f,b) = strip_comb (funct$body) |
34 in |
34 in |
35 if is_Const f andalso fst(dest_Const f) = fname |
35 if is_Const f andalso fst(dest_Const f) = fname |
36 then |
36 then |
37 let val (ls,rest) = (take(cpos,b), drop (cpos,b)); |
37 let val (ls,rest) = (take(rpos,b), drop(rpos,b)); |
38 val (xk,rs) = (hd rest,tl rest) |
38 val (xk,rs) = (hd rest,tl rest) |
39 handle LIST _ => raise RecError "not enough arguments \ |
39 handle LIST _ => raise RecError "not enough arguments \ |
40 \ in recursive application on rhs" |
40 \ in recursive application on rhs" |
41 in |
41 in |
42 (case assoc (pairs,xk) of |
42 (case assoc (pairs,xk) of |
43 None => raise RecError |
43 None => raise RecError |
44 ("illegal occurence of " ^ fname ^ " on rhs") |
44 ("illegal occurence of " ^ fname ^ " on rhs") |
45 | Some(U) => list_comb(U,ls @ rs)) |
45 | Some(U) => list_comb(U,map subst (ls @ rs))) |
46 end |
46 end |
47 else list_comb(f, map subst b) |
47 else list_comb(f, map subst b) |
48 end |
48 end |
49 | subst(t) = t |
49 | subst(t) = t |
50 in subst t end; |
50 in subst t end; |
51 |
51 |
52 (* abstract rhs *) |
52 (* abstract rhs *) |
53 |
53 |
54 fun abst_rec (fname,cpos,tc,ls,cargs,rs,rhs) = |
54 fun abst_rec (fname,rpos,tc,ls,cargs,rs,rhs) = |
55 let val rargs = (map fst o |
55 let val rargs = (map fst o |
56 (filter (fn (a,T) => is_dtRek T))) (cargs ~~ tc); |
56 (filter (fn (a,T) => is_dtRek T))) (cargs ~~ tc); |
57 val subs = map (fn (s,T) => (s,dummyT)) |
57 val subs = map (fn (s,T) => (s,dummyT)) |
58 (rev(rename_wrt_term rhs rargs)); |
58 (rev(rename_wrt_term rhs rargs)); |
59 val subst_rhs = subst_apps (fname,cpos) |
59 val subst_rhs = subst_apps (fname,rpos) |
60 (map Free rargs ~~ map Free subs) rhs; |
60 (map Free rargs ~~ map Free subs) rhs; |
61 val res = list_abs_free (cargs @ subs @ ls @ rs, subst_rhs); |
61 in |
62 in |
62 list_abs_free (cargs @ subs @ ls @ rs, subst_rhs) |
63 if fname mem add_term_names (res,[]) |
|
64 then raise RecError ("illegal occurence of " ^ fname ^ " on rhs") |
|
65 else res |
|
66 end; |
63 end; |
67 |
64 |
68 (* parsing the prim rec equations *) |
65 (* parsing the prim rec equations *) |
69 |
66 |
70 fun dest_eq ( Const("Trueprop",_) $ (Const ("op =",_) $ lhs $ rhs)) |
67 fun dest_eq ( Const("Trueprop",_) $ (Const ("op =",_) $ lhs $ rhs)) |
74 fun dest_rec eq = |
71 fun dest_rec eq = |
75 let val (lhs,rhs) = dest_eq eq; |
72 let val (lhs,rhs) = dest_eq eq; |
76 val (name,args) = strip_comb lhs; |
73 val (name,args) = strip_comb lhs; |
77 val (ls',rest) = take_prefix is_Free args; |
74 val (ls',rest) = take_prefix is_Free args; |
78 val (middle,rs') = take_suffix is_Free rest; |
75 val (middle,rs') = take_suffix is_Free rest; |
79 val cpos = length ls'; |
76 val rpos = length ls'; |
80 val (c,cargs') = strip_comb (hd middle) |
77 val (c,cargs') = strip_comb (hd middle) |
81 handle LIST "hd" => raise RecError "constructor missing"; |
78 handle LIST "hd" => raise RecError "constructor missing"; |
82 val (ls,cargs,rs) = (map dest_Free ls', map dest_Free cargs' |
79 val (ls,cargs,rs) = (map dest_Free ls', map dest_Free cargs' |
83 , map dest_Free rs') |
80 , map dest_Free rs') |
84 handle TERM ("dest_Free",_) => |
81 handle TERM ("dest_Free",_) => |
88 raise RecError "more than one non-variable in pattern" |
85 raise RecError "more than one non-variable in pattern" |
89 else if not(null(findrep (map fst (ls @ rs @ cargs)))) then |
86 else if not(null(findrep (map fst (ls @ rs @ cargs)))) then |
90 raise RecError "repeated variable name in pattern" |
87 raise RecError "repeated variable name in pattern" |
91 else (fst(dest_Const name) handle TERM _ => |
88 else (fst(dest_Const name) handle TERM _ => |
92 raise RecError "function is not declared as constant in theory" |
89 raise RecError "function is not declared as constant in theory" |
93 ,cpos,ls,fst( dest_Const c),cargs,rs,rhs) |
90 ,rpos,ls,fst( dest_Const c),cargs,rs,rhs) |
94 end; |
91 end; |
95 |
92 |
96 (* check function specified for all constructors and sort function terms *) |
93 (* check function specified for all constructors and sort function terms *) |
97 |
94 |
98 fun check_and_sort (n,its) = |
95 fun check_and_sort (n,its) = |
104 (* translate rec equations into function arguments suitable for rec comb *) |
101 (* translate rec equations into function arguments suitable for rec comb *) |
105 (* theory parameter needed for printing error messages *) |
102 (* theory parameter needed for printing error messages *) |
106 |
103 |
107 fun trans_recs _ _ [] = error("No primrec equations.") |
104 fun trans_recs _ _ [] = error("No primrec equations.") |
108 | trans_recs thy cs' (eq1::eqs) = |
105 | trans_recs thy cs' (eq1::eqs) = |
109 let val (name1,cpos1,ls1,_,_,_,_) = dest_rec eq1 |
106 let val (name1,rpos1,ls1,_,_,_,_) = dest_rec eq1 |
110 handle RecError s => |
107 handle RecError s => |
111 error("Primrec definition error: " ^ s ^ ":\n" |
108 error("Primrec definition error: " ^ s ^ ":\n" |
112 ^ " " ^ Sign.string_of_term (sign_of thy) eq1); |
109 ^ " " ^ Sign.string_of_term (sign_of thy) eq1); |
113 val tcs = map (fn (_,c,T,_) => (c,T)) cs'; |
110 val tcs = map (fn (_,c,T,_) => (c,T)) cs'; |
114 val cs = map fst tcs; |
111 val cs = map fst tcs; |
115 fun trans_recs' _ [] = [] |
112 fun trans_recs' _ [] = [] |
116 | trans_recs' cis (eq::eqs) = |
113 | trans_recs' cis (eq::eqs) = |
117 let val (name,cpos,ls,c,cargs,rs,rhs) = dest_rec eq; |
114 let val (name,rpos,ls,c,cargs,rs,rhs) = dest_rec eq; |
118 val tc = assoc(tcs,c); |
115 val tc = assoc(tcs,c); |
119 val i = (1 + find (c,cs)) handle LIST "find" => 0; |
116 val i = (1 + find (c,cs)) handle LIST "find" => 0; |
120 in |
117 in |
121 if name <> name1 then |
118 if name <> name1 then |
122 raise RecError "function names inconsistent" |
119 raise RecError "function names inconsistent" |
123 else if cpos <> cpos1 then |
120 else if rpos <> rpos1 then |
124 raise RecError "position of rec. argument inconsistent" |
121 raise RecError "position of rec. argument inconsistent" |
125 else if i = 0 then |
122 else if i = 0 then |
126 raise RecError "illegal argument in pattern" |
123 raise RecError "illegal argument in pattern" |
127 else if i mem cis then |
124 else if i mem cis then |
128 raise RecError "constructor already occured as pattern " |
125 raise RecError "constructor already occured as pattern " |
129 else (i,abst_rec (name,cpos,the tc,ls,cargs,rs,rhs)) |
126 else (i,abst_rec (name,rpos,the tc,ls,cargs,rs,rhs)) |
130 :: trans_recs' (i::cis) eqs |
127 :: trans_recs' (i::cis) eqs |
131 end |
128 end |
132 handle RecError s => |
129 handle RecError s => |
133 error("Primrec definition error\n" ^ s ^ "\n" |
130 error("Primrec definition error\n" ^ s ^ "\n" |
134 ^ " " ^ Sign.string_of_term (sign_of thy) eq); |
131 ^ " " ^ Sign.string_of_term (sign_of thy) eq); |
442 |> add_consts consts |
439 |> add_consts consts |
443 |> add_trrules xrules |
440 |> add_trrules xrules |
444 |> add_axioms rules,add_primrec) |
441 |> add_axioms rules,add_primrec) |
445 end |
442 end |
446 end |
443 end |
|
444 |
|
445 (* |
|
446 Informal description of functions used in datatype.ML for the Isabelle/HOL |
|
447 implementation of prim. rec. function definitions. (N. Voelker, Feb. 1995) |
|
448 |
|
449 * subst_apps (fname,rpos) pairs t: |
|
450 substitute the term |
|
451 fname(ls,xk,rs) |
|
452 by |
|
453 yk(ls,rs) |
|
454 in t for (xk,yk) in pairs, where rpos = length ls. |
|
455 Applied with : |
|
456 fname = function name |
|
457 rpos = position of recursive argument |
|
458 pairs = list of pairs (xk,yk), where |
|
459 xk are the rec. arguments of the constructor in the pattern, |
|
460 yk is a variable with name derived from xk |
|
461 t = rhs of equation |
|
462 |
|
463 * abst_rec (fname,rpos,tc,ls,cargs,rs,rhs) |
|
464 - filter recursive arguments from constructor arguments cargs, |
|
465 - perform substitutions on rhs, |
|
466 - derive list subs of new variable names yk for use in subst_apps, |
|
467 - abstract rhs with respect to cargs, subs, ls and rs. |
|
468 |
|
469 * dest_eq t |
|
470 destruct a term denoting an equation into lhs and rhs. |
|
471 |
|
472 * dest_req eq |
|
473 destruct an equation of the form |
|
474 name (vl1..vlrpos, Ci(vi1..vin), vr1..vrn) = rhs |
|
475 into |
|
476 - function name (name) |
|
477 - position of the first non-variable parameter (rpos) |
|
478 - the list of first rpos parameters (ls = [vl1..vlrpos]) |
|
479 - the constructor (fst( dest_Const c) = Ci) |
|
480 - the arguments of the constructor (cargs = [vi1..vin]) |
|
481 - the rest of the variables in the pattern (rs = [vr1..vrn]) |
|
482 - the right hand side of the equation (rhs). |
|
483 |
|
484 * check_and_sort (n,its) |
|
485 check that n = length its holds, and sort elements of its by |
|
486 first component. |
|
487 |
|
488 * trans_recs thy cs' (eq1::eqs) |
|
489 destruct eq1 into name1, rpos1, ls1, etc.. |
|
490 get constructor list with and without type (tcs resp. cs) from cs', |
|
491 for every equation: |
|
492 destruct it into (name,rpos,ls,c,cargs,rs,rhs) |
|
493 get typed constructor tc from c and tcs |
|
494 determine the index i of the constructor |
|
495 check function name and position of rec. argument by comparison |
|
496 with first equation |
|
497 check for repeated variable names in pattern |
|
498 derive function term f_i which is used as argument of the rec. combinator |
|
499 sort the terms f_i according to i and return them together |
|
500 with the function name and the parameter of the definition (ls). |
|
501 |
|
502 * Application: |
|
503 |
|
504 The rec. combinator is applied to the function terms resulting from |
|
505 trans_rec. This results in a function which takes the recursive arg. |
|
506 as first parameter and then the arguments corresponding to ls. The |
|
507 order of parameters is corrected by setting the rhs equal to |
|
508 |
|
509 list_abs_free |
|
510 (ls @ [(tname,dummyT)] |
|
511 ,list_comb(rec_comb |
|
512 , fns @ map Bound (0 ::(length ls downto 1)))); |
|
513 |
|
514 Note the de-Bruijn indices counting the number of lambdas between the |
|
515 variable and its binding. |
|
516 *) |