diff options
| author | bertot | 2001-04-04 12:44:55 +0000 |
|---|---|---|
| committer | bertot | 2001-04-04 12:44:55 +0000 |
| commit | e16efa883ae0cf5c82a2ee60bf05304fb9c69b51 (patch) | |
| tree | c34994a4b24950cde4af71d65baa4ac29fb51d00 /contrib/interface/xlate.ml | |
| parent | e1d0e117652115b05faec1c276b9f14c5bf70d1f (diff) | |
Files that handle the dialogue with the graphical user-interface pcoq.
git-svn-id: svn+ssh://scm.gforge.inria.fr/svn/coq/trunk@1531 85f007b7-540e-0410-9357-904b9bb8a0f7
Diffstat (limited to 'contrib/interface/xlate.ml')
| -rw-r--r-- | contrib/interface/xlate.ml | 2026 |
1 files changed, 2026 insertions, 0 deletions
diff --git a/contrib/interface/xlate.ml b/contrib/interface/xlate.ml new file mode 100644 index 0000000000..8d4d952b5f --- /dev/null +++ b/contrib/interface/xlate.ml @@ -0,0 +1,2026 @@ + +(** Translation from coq abstract syntax trees to centaur vernac + *) +open String;; +open Char;; +open Util;; +open Ast;; +open Names;; +open Ascent;; +open Coqast;; + +let in_coq_ref = ref false;; + +let xlate_mut_stuff = ref ((fun _ -> + Nvar((0,0), "function xlate_mut_stuff should not be used here")): + Coqast.t -> Coqast.t);; + +let set_xlate_mut_stuff v = xlate_mut_stuff := v;; + +let declare_in_coq () = in_coq_ref:=true;; + +let in_coq () = !in_coq_ref;; + +(* // Verify whether this is dead code, as of coq version 7 *) +(* The following three sentences have been added to cope with a change +of strategy from the Coq team in the way rules construct ast's. The +problem is that now grammar rules will refer to identifiers by giving +their absolute name, using the mutconstruct when needed. Unfortunately, +when you have a mutconstruct structure, you don't have a way to guess +the corresponding identifier without an environment, and the parser +does not have an environment. We add one, only for the constructs +that are always loaded. *) +let type_table = ((Hashtbl.create 17) : + (string, ((string array) array)) Hashtbl.t);; + +Hashtbl.add type_table "Coq.Init.Logic.and" + [|[|"dummy";"conj"|]|];; + +Hashtbl.add type_table "Coq.Init.Datatypes.prod" + [|[|"dummy";"pair"|]|];; + +(*The following two codes are added to cope with the distinction + between ocaml and caml-light syntax while using ctcaml to + manipulate the program *) +let code_plus = code (get "+" 0);; + +let code_minus = code (get "-" 0);; + +let coercion_description_holder = ref (function _ -> None : t -> int option);; + +let coercion_description t = !coercion_description_holder t;; + +let set_coercion_description f = + coercion_description_holder:=f; ();; + +let string_of_node_loc the_node = + match loc the_node with + (a,b) -> "(" ^ (string_of_int a) ^ ", " ^ (string_of_int b) ^ ")";; + +let xlate_error s = error ("Translation error: " ^ s);; + +type astrecurse = Rbinder of ct_ID_OPT * astrecurse + | Rform of ct_FORMULA + | Rform_list of ct_FORMULA list;; + +let ctf_STRING_OPT_NONE = CT_coerce_NONE_to_STRING_OPT CT_none;; + +let ctf_STRING_OPT_SOME s = CT_coerce_STRING_to_STRING_OPT s;; + +let ctv_ID_OPT_NONE = CT_coerce_NONE_to_ID_OPT CT_none;; + +let ctf_ID_OPT_SOME s = CT_coerce_ID_to_ID_OPT s;; + +let ctv_ID_OPT_OR_ALL_NONE = + CT_coerce_ID_OPT_to_ID_OPT_OR_ALL (CT_coerce_NONE_to_ID_OPT CT_none);; + +let ctv_FORMULA_OPT_NONE = + CT_coerce_ID_OPT_to_FORMULA_OPT(CT_coerce_NONE_to_ID_OPT CT_none);; + +let ctf_ID_OPT_OR_ALL_SOME s = + CT_coerce_ID_OPT_to_ID_OPT_OR_ALL (ctf_ID_OPT_SOME s);; + +let ctv_ID_OPT_OR_ALL_ALL = CT_all;; + +let ctv_SPEC_OPT_NONE = CT_coerce_NONE_to_SPEC_OPT CT_none;; + +let castc x = CT_coerce_TYPED_FORMULA_to_FORMULA x;; + +let varc x = CT_coerce_ID_to_FORMULA x;; + +let ident_tac s = CT_user_tac (CT_ident s, CT_targ_list []);; + +let ident_vernac s = CT_user_vernac (CT_ident s, CT_varg_list []);; + +type iTARG = Targ_command of ct_FORMULA + | Targ_intropatt of ct_INTRO_PATT_LIST + | Targ_id_list of ct_ID_LIST + | Targ_spec_list of ct_SPEC_LIST + | Targ_binding_com of ct_FORMULA + | Targ_ident of ct_ID + | Targ_int of ct_INT + | Targ_binding of ct_BINDING + | Targ_pattern of ct_PATTERN + | Targ_unfold of ct_UNFOLD + | Targ_unfold_ne_list of ct_UNFOLD_NE_LIST + | Targ_string of ct_STRING + | Targ_fixtac of ct_FIXTAC + | Targ_cofixtac of ct_COFIXTAC + | Targ_tacexp of ct_TACTIC_COM + | Targ_redexp of ct_RED_COM;; + +type iVARG = Varg_binder of ct_BINDER + | Varg_binderlist of ct_BINDER_LIST + | Varg_bindernelist of ct_BINDER_NE_LIST + | Varg_call of ct_ID * iVARG list + | Varg_constr of ct_FORMULA + | Varg_sorttype of ct_SORT_TYPE + | Varg_constrlist of ct_FORMULA list + | Varg_ident of ct_ID + | Varg_int of ct_INT + | Varg_intlist of ct_INT_LIST + | Varg_none + | Varg_string of ct_STRING + | Varg_tactic of ct_TACTIC_COM + | Varg_ast of ct_AST + | Varg_astlist of ct_AST_LIST + | Varg_tactic_arg of iTARG + | Varg_varglist of iVARG list;; + +let coerce_iTARG_to_TARG = + function + | Targ_intropatt x -> xlate_error "coerce_iTARG_to_TARG (3)" + | Targ_command x -> CT_coerce_FORMULA_to_TARG x + | Targ_id_list x -> xlate_error "coerce_iTARG_to_TARG" + | Targ_spec_list x -> CT_coerce_SPEC_LIST_to_TARG x + | Targ_binding_com x -> CT_coerce_FORMULA_to_TARG x + | Targ_ident x -> CT_coerce_ID_OR_INT_to_TARG (CT_coerce_ID_to_ID_OR_INT x) + | Targ_int x -> CT_coerce_ID_OR_INT_to_TARG (CT_coerce_INT_to_ID_OR_INT x) + | Targ_binding x -> CT_coerce_BINDING_to_TARG x + | Targ_pattern x -> CT_coerce_PATTERN_to_TARG x + | Targ_unfold_ne_list x -> CT_coerce_UNFOLD_NE_LIST_to_TARG x + | Targ_unfold x -> CT_coerce_UNFOLD_to_TARG x + | Targ_string x -> + CT_coerce_ID_OR_STRING_to_TARG (CT_coerce_STRING_to_ID_OR_STRING x) + | Targ_fixtac x -> CT_coerce_FIXTAC_to_TARG x + | Targ_cofixtac x -> CT_coerce_COFIXTAC_to_TARG x + | Targ_tacexp x -> CT_coerce_TACTIC_COM_to_TARG x + | Targ_redexp x -> xlate_error "coerce_iTarg_to_TARG(2)";; + +let rec coerce_iVARG_to_VARG = + function + | Varg_binder x -> CT_coerce_BINDER_to_VARG x + | Varg_binderlist x -> CT_coerce_BINDER_LIST_to_VARG x + | Varg_bindernelist x -> CT_coerce_BINDER_NE_LIST_to_VARG x + | Varg_call (id, l) -> xlate_error "coerce_iVARG_to_VARG: CALL as varg" + | Varg_constr x -> + CT_coerce_FORMULA_OPT_to_VARG (CT_coerce_FORMULA_to_FORMULA_OPT x) + | Varg_sorttype x -> + CT_coerce_FORMULA_OPT_to_VARG + (CT_coerce_FORMULA_to_FORMULA_OPT (CT_coerce_SORT_TYPE_to_FORMULA x)) + | Varg_constrlist x -> CT_coerce_FORMULA_LIST_to_VARG (CT_formula_list x) + | Varg_ident x -> + CT_coerce_ID_OPT_OR_ALL_to_VARG + (CT_coerce_ID_OPT_to_ID_OPT_OR_ALL (CT_coerce_ID_to_ID_OPT x)) + | Varg_int x -> CT_coerce_INT_OPT_to_VARG (CT_coerce_INT_to_INT_OPT x) + | Varg_intlist x -> CT_coerce_INT_LIST_to_VARG x + | Varg_none -> CT_coerce_FORMULA_OPT_to_VARG ctv_FORMULA_OPT_NONE + | Varg_string x -> + CT_coerce_STRING_OPT_to_VARG (CT_coerce_STRING_to_STRING_OPT x) + | Varg_tactic x -> + CT_coerce_TACTIC_OPT_to_VARG (CT_coerce_TACTIC_COM_to_TACTIC_OPT x) + | Varg_astlist x -> CT_coerce_AST_LIST_to_VARG x + | Varg_ast x -> CT_coerce_AST_to_VARG x + | Varg_varglist x -> + CT_coerce_VARG_LIST_to_VARG + (CT_varg_list (List.map coerce_iVARG_to_VARG x)) + | _ -> xlate_error "coerce_iVARG_to_VARG: leftover case";; + +let coerce_iVARG_to_FORMULA = + function + | Varg_constr x -> x + | Varg_sorttype x -> CT_coerce_SORT_TYPE_to_FORMULA x + | _ -> xlate_error "coerce_iVARG_to_FORMULA: unexpected argument";; + +let coerce_iVARG_to_ID = + function Varg_ident id -> id + | _ -> xlate_error "coerce_iVARG_to_ID";; + +let coerce_VARG_to_ID = + function + | CT_coerce_ID_OPT_OR_ALL_to_VARG (CT_coerce_ID_OPT_to_ID_OPT_OR_ALL (CT_coerce_ID_to_ID_OPT x)) -> + x + | _ -> xlate_error "coerce_VARG_to_ID";; + +let xlate_id = + function + | Nvar (_, id) -> + (match id with + | "_" -> xlate_error "xlate_id: '_' is ident option" + | s -> CT_ident s) + | Id (_, id) -> + (match id with + | "_" -> xlate_error "xlate_id: '_' is ident option" + | s -> CT_ident s) + | _ -> xlate_error "xlate_id: not an identifier";; + +let xlate_id_unit = function + Node(_, "VOID", []) -> CT_unit + | x -> CT_coerce_ID_to_ID_UNIT (xlate_id x);; + +let xlate_id_opt = + function + | Nvar (_, id) -> + (match id with + | "_" -> ctv_ID_OPT_NONE + | s -> ctf_ID_OPT_SOME (CT_ident s)) + | _ -> xlate_error "xlate_id: not an identifier";; + +let xlate_int = + function + | Num (_, n) -> CT_int n + | _ -> xlate_error "xlate_int: not an int";; + +let xlate_string = + function + | Str (_, s) -> CT_string s + | _ -> xlate_error "xlate_string: not a string";; + +(** Formulae + *) +let strip_Rform = + function + | Rform body -> body + | _ -> xlate_error "strip_Rform: binder expression as formula";; + +let make_lambdac dom boundcod = + let rec gather = + function + | Rbinder (x, body) -> + let l, body' = gather body in + x::l, body' + | Rform body -> [], body + | _ -> xlate_error "make_lambdac : not Rbinder or Rform" in + let varlist, cod = gather boundcod in + match varlist with + | [] -> xlate_error "make_lamdac: empty binder list" + | id :: l -> CT_lambdac (CT_binder (CT_id_opt_ne_list (id, l), dom), cod);; + +let rec make_prodc dom = + let rec gather = + function + | Rbinder (id_opt, body) -> + let l, body' = gather body in + id_opt::l, body' + | Rform body -> [], body + | _ -> xlate_error "gather for make_prodc : not Rbinder or Rform" in + function + | Rform body -> xlate_error "make_prodc: empty binder list in make_binder" + | boundrange -> + let varlist, range = gather boundrange in + (match varlist with + | [] -> range + | id :: l -> CT_prodc (CT_binder (CT_id_opt_ne_list (id, l), dom), range));; + +let make_appln = + function + | [] -> xlate_error "make_appln: empty application list" + | (Rform m) :: [] -> m + | (Rform m) :: ((Rform n) :: l) -> + CT_appc (m, CT_formula_ne_list (n, List.map strip_Rform l)) + | _ -> xlate_error "make_appln: binder expression in application";; + +let make_casec casety = + function + | [] -> xlate_error "bad case expression" + | x :: [] -> xlate_error "bad case expression" + | (Rform a) :: ((Rform m) :: l) -> + CT_elimc (CT_case casety, a, m, CT_formula_list (List.map strip_Rform l)) + | _ -> xlate_error "make_casec: binder expression as formula";; + +let qualid_to_ct_ID = + function + Nvar(_, s) -> Some(CT_ident s) + | Node(_, ("QUALID"|"QUALIDARG"), l) -> + (* // to be modified when qualified identifiers are introducted. *) + let rec f = + function + [] -> xlate_error "empty list in qualified identifier" + | [Nvar(_,a)] -> a + | (Nvar(_,s))::l -> s ^ "." ^ (f l) + | _ -> assert false in + Some(CT_ident (f l)) + | _ -> None;; + + +let special_case_qualid cont_function astnode = + match qualid_to_ct_ID astnode with + Some(id) -> Some(Rform(CT_coerce_ID_to_FORMULA id)) + | None -> None;; + +let xlate_op the_node opn a b = + match opn with + | "META" -> + (match a, b with + | ((Num (_, n)) :: []), [] -> CT_metac (CT_int n) + | _, _ -> xlate_error "xlate_op : META ") + | "ISEVAR" -> CT_existvarc + | "FORCEIF" -> + (match a,b with + | [], l -> + make_casec "Case" l + | _,_ -> xlate_error "xlate_op : FORCEIF") + | "PROP" -> + (match a, b with + | [], [] -> + CT_coerce_SORT_TYPE_to_FORMULA (CT_sortc "Prop") + | _, _ -> xlate_error "xlate_op : PROP ") + | "SET" -> + (match a, b with + | [], [] -> + CT_coerce_SORT_TYPE_to_FORMULA (CT_sortc "Set") + | _, _ -> xlate_error "xlate_op : PROP ") + | (*The number of elements in the argument list is left unspecified: this list + varies when the object is type-checked <Yves Bertot 21/3/95> *) + "TYPE" -> + (match a, b with + | _, _ -> CT_coerce_SORT_TYPE_to_FORMULA (CT_sortc "Type")) + | "CAST" -> + (match a, b with + | [], ((Rform c1) :: ((Rform c2) :: [])) -> castc (CT_typed_formula (c1, c2)) + | _, _ -> xlate_error "xlate_op : CAST ") + | "PROD" -> + (match a, b with + | [], + ((Rform c1) :: + ((Rbinder ((CT_coerce_NONE_to_ID_OPT CT_none), (Rform c2))) :: [])) -> + CT_arrowc (c1, c2) + | [], + ((Rform c1) :: ((Rbinder ((CT_coerce_ID_to_ID_OPT id), (Rform c2))) :: [])) -> + CT_prodc + (CT_binder (CT_id_opt_ne_list (CT_coerce_ID_to_ID_OPT id, []), c1), c2) + | _, _ -> xlate_error "xlate_op : PROD") + | "LAMBDA" -> + (match a, b with + | [], [Rform c1;Rbinder (b, (Rform c2))] -> + CT_lambdac (CT_binder (CT_id_opt_ne_list (b, []), c1), c2) + | _, _ -> xlate_error "xlate_op : LAMBDA") + | "PRODLIST" -> + (match a, b with + | [], ((Rform c1) :: (c2 :: [])) -> make_prodc c1 c2 + | _, _ -> xlate_error "xlate_op : PRODLIST") + | "LAMBDALIST" -> + (match a, b with + | [], ((Rform c1) :: (c2 :: [])) -> make_lambdac c1 c2 + | _, _ -> xlate_error "xlate_op : LAMBDALIST") + | "APPLIST" -> + (match a, b with + | [], tl -> make_appln tl + | _, _ -> xlate_error "xlate_op : APPLIST") + | (** string_of_path needs to be investigated. + *) + "CONST" -> + (match a, b with + | ((Path (_, sl, kind)) :: []), [] -> + CT_coerce_ID_to_FORMULA(CT_ident + (Names.string_of_id (Names.basename (Ast.section_path sl kind)))) + | ((Path (_, sl, kind)) :: []), tl -> + CT_coerce_ID_to_FORMULA(CT_ident + (Names.string_of_id(Names.basename (Ast.section_path sl kind)))) + | _, _ -> xlate_error "xlate_op : CONST") + | (** string_of_path needs to be investigated. + *) + "MUTIND" -> + (match a, b with + | [Path(_, sl, kind); Num(_, tyi)], [] -> + if !in_coq_ref then + match special_case_qualid () + (!xlate_mut_stuff (Node((0,0),"MUTIND", a))) with + Some (Rform x) -> x + | _ -> assert false + else + CT_coerce_ID_to_FORMULA( + CT_ident(Names.string_of_id + (Names.basename + (Ast.section_path sl kind)))) + | _, _ -> xlate_error "xlate_op : MUTIND") + | "MUTCASE" + | "CASE" -> + let compute_flag s = + match s with "REC" -> "Match" | "NOREC" -> "Case" | _ -> assert false in + (match a, b with + | [Str(_,v)], tl -> make_casec (compute_flag v) tl + | [Str(_,v); Str(_,"SYNTH")], tl -> + make_casec (compute_flag v) (Rform CT_existvarc::tl) + | _, _ -> xlate_error "xlate_op : MUTCASE") + | (** string_of_path needs to be investigated. + *) + "MUTCONSTRUCT" -> + (match a, b with + | [Path(_, sl, kind);Num(_, tyi);Num(_, n)], cl -> + if !in_coq_ref then + match + special_case_qualid () + (!xlate_mut_stuff (Node((0,0),"MUTCONSTRUCT",a))) with + | Some(Rform x) -> x + | _ -> assert false + else + let name = Names.string_of_path (Ast.section_path sl kind) in + (* This is rather a patch to cope with the fact that identifier + names have disappeared from the vo files for grammar rules *) + let type_desc = (try Some (Hashtbl.find type_table name) with + Not_found -> None) in + (match type_desc with + None -> + xlate_error + ("MUTCONSTRUCT:" ^ + " can't describe a constructor without its name " ^ + name) + | Some type_desc' -> + let type_desc'' = type_desc'.(tyi) in + let ident = type_desc''.(n) in + CT_coerce_ID_to_FORMULA(CT_ident ident)) + | _, _ -> xlate_error "xlate_op : MUTCONSTRUCT") + + | opn -> xlate_error ("xlate_op : " ^ opn ^ " doesn't exist (" ^ + (string_of_node_loc the_node) ^ ")");; + +let split_params = + let rec sprec acc = + function + | (Id _ as p) :: l -> sprec (p::acc) l + | (Str _ as p) :: l -> sprec (p::acc) l + | (Num _ as p) :: l -> sprec (p::acc) l + | (Path _ as p) :: l -> sprec (p::acc) l + | l -> List.rev acc, l in + sprec [];; + +let id_to_pattern_var ctid = + match ctid with + | CT_ident "_" -> + CT_coerce_ID_OPT_to_MATCH_PATTERN (CT_coerce_NONE_to_ID_OPT CT_none) + | CT_ident id_string -> + CT_coerce_ID_OPT_to_MATCH_PATTERN + (CT_coerce_ID_to_ID_OPT (CT_ident id_string));; + +let rec xlate_cases_pattern cont_function = + function + | Nvar(_, s) -> id_to_pattern_var (CT_ident s) + | Node (_, "QUALID", l) as it -> + (match qualid_to_ct_ID it with + Some x -> id_to_pattern_var x + | None -> assert false) + | Node (_, "PATTCONSTRUCT", (f1 :: (arg1 :: args))) -> + CT_pattern_app + (xlate_cases_pattern cont_function f1, + CT_match_pattern_ne_list + (xlate_cases_pattern cont_function arg1, + List.map (xlate_cases_pattern cont_function) args)) + | Node (_, "PATTAS", [Nvar (_, id); pattern]) -> + CT_pattern_as + (xlate_cases_pattern + cont_function pattern, CT_coerce_ID_to_ID_OPT (CT_ident id)) + | Node (_, "PATTCONSTRUCT", [f]) -> xlate_cases_pattern cont_function f + | Node (_, ("MUTCONSTRUCT" as s), args) as it -> + let pl, tl = split_params args in + (match xlate_op it s pl (List.map cont_function tl) with + | CT_coerce_ID_to_FORMULA id -> id_to_pattern_var id + | _ -> assert false) + | Node(_, s, _) -> xlate_error ("error for a pattern " ^ s) + | _ -> xlate_error "Unexpected data while translating a pattern";; + +(*This function recognizes and translates let constructs + // I think this code should be adapted to build a real let construct *) +let special_case_let_construct cont_function = + function + | Node (_, "LETIN", [val_arg;Slam(_, (Some b), body)]) -> + Some + (Rform + (CT_letin(CT_ident b, strip_Rform (cont_function val_arg), + strip_Rform (cont_function body)))) + | _ -> None;; + +(*This function recognizes and translates the integers introduced by P.Cregut. + However, it relies on the patterns given in our our version of integer_gram *) +let compile_decomposed_number cont_function ast = + (*cdn_rec returns a list of strings that represent the bits in a + binary representation of the number. 1 is represented by "xI" and 0 by "xO" *) + let rec cdn_rec = + function + | Node (_, "APPLIST", ((Nvar (_, s)) :: args)) as t -> + (match s with + | "xI" | "xO" -> + (match args with + | arg :: [] -> + let digit_list, head = cdn_rec arg in + s::digit_list, head + | _ -> xlate_error "bad number of arguments for xI or XO") + | it -> [], Some t) + | Nvar (_, s) as t -> + (match s with + | "xH" -> ["xI"], None + | _ -> [], Some t) + | t -> [], Some t in + (*when the number will appear as a binary number, we fake it by using base + 10 when reconstructing the number (A binary number looks like a decimal number + written only with ones and zeros). Otherwise, we use base 2, respecting + the true meaning of each bit. *) + let rec convert_to_number base = + function + | [] -> 0 + | "xI" :: tail -> 1 + base * convert_to_number base tail + | "xO" :: tail -> base * convert_to_number base tail + | _ -> xlate_error "compile_decomposed_number" in + match cdn_rec ast with + | (*binary representation is only used when constructing an incomplete number *) + digit_list, (Some formula) -> + CT_incomplete_binary + (strip_Rform (cont_function formula), + CT_binary (convert_to_number 10 digit_list)) + | digit_list, None -> + CT_int_encapsulator (CT_int (convert_to_number 2 digit_list));; + +let special_case_omega_integer cont_function = + function + | Node (_, "XTRA", + ((Str (_, "omega_integer_for_ctcoq")) :: ((Num (_, n)) :: []))) -> + Some (Rform (CT_int_encapsulator (CT_int n))) + | Node (_, "XTRA", + ((Str (_, "omega_binary_for_ctcoq")) :: ((Num (_, n)) :: []))) -> + Some (Rform (CT_coerce_BINARY_to_FORMULA (CT_binary n))) + | Node (_, "XTRA", + ((Str (_, "omega_variable_binary_for_ctcoq")) :: + (formula :: ((Num (_, n)) :: [])))) -> + Some + (Rform + (CT_incomplete_binary (strip_Rform (cont_function formula), CT_binary n))) + | Node (_, "APPLIST", + ((Nvar (_, pos_or_neg_string)) :: + ((Node (_, "APPLIST", ((Nvar (_, id)) :: (_ :: []))) as number) + :: []))) -> + (match pos_or_neg_string with + | "POS" -> + (match id with + | "xI" | "xO" | "xH" -> + Some (Rform (compile_decomposed_number cont_function number)) + | _ -> None) + | "NEG" -> + (match id with + | "xI" | "xO" | "xH" -> + Some + (Rform + (CT_appc + (CT_coerce_ID_to_FORMULA (CT_ident "NEG"), + CT_formula_ne_list (compile_decomposed_number cont_function number, [])))) + | _ -> None) + | _ -> None) + | _ -> None;; + +let cvt_binder cont_function = + function + | Node (_,"BINDER", (c :: idl)) -> + (match idl with + | [] -> xlate_error "cvt_binder empty identifier list" + | id :: l -> + CT_binder + (CT_id_opt_ne_list (xlate_id_opt id, + List.map xlate_id_opt l), + cont_function c)) + | _ -> failwith "cvt_binder";; + +let cvt_binders cont_function = + function + | Node(_,name, args) when name = "BINDERLIST" or name = "BINDERS" -> + CT_binder_list(List.map (cvt_binder cont_function) args) + | _ -> failwith "cvt_binders";; + + +(*This function recognizes and translates the Fix construct *) +let special_case_fix cont_function = + function + | Node (_, "FIX", ((Nvar (_, iddef)) :: (l :: ldecl))) -> + let xlate_fixbinder = + function + | Node (_, "NUMFDECL", + ((Nvar (_, fi)) :: + ((Num (_, ni)) :: (v_Type :: (v_Value :: []))))) -> + let v_Type' = strip_Rform (cont_function v_Type) in + let v_Value' = strip_Rform (cont_function v_Value) in + CT_fix_binder (CT_ident fi, CT_int ni, v_Type', v_Value') + | Node (_, "FDECL", + ((Nvar (_, fi)) :: + (binder :: (v_Type :: (v_Value :: []))))) -> + let v_Type' = strip_Rform (cont_function v_Type) in + let v_Value' = strip_Rform (cont_function v_Value) in + (match cvt_binders (compose strip_Rform cont_function) binder with + | CT_binder_list(a::tl) -> + CT_coerce_FIX_REC_to_FIX_BINDER + (CT_fix_rec (CT_ident fi, CT_binder_ne_list(a,tl), + v_Type', v_Value')) + | _ -> xlate_error ("special_case_fix : " ^ + "empty list of binders")) + | _ -> + xlate_error + ("special_case_fix : " ^ "FIX, unexpected form in xlate_fixbinder") + in + Some + (Rform + (CT_fixc + (CT_ident iddef, + CT_fix_binder_list (xlate_fixbinder l, List.map xlate_fixbinder ldecl)))) + | _ -> None;; + +(*This function recognizes and translates cofix constructs *) +let special_case_cofix cont_function = + function + | Node (_, "COFIX", ((Nvar (_, iddef)) :: (l :: ldecl))) -> + let xlate_cofixbinder = + function + | Node (_, "CFDECL", ((Nvar (_, fi)) :: (v_Type :: (v_Value :: [])))) -> + let v_Type' = strip_Rform (cont_function v_Type) in + let v_Value' = strip_Rform (cont_function v_Value) in + CT_cofix_rec (CT_ident fi, v_Type', v_Value') + | _ -> + xlate_error + ("special_case_cofix : " ^ + "COFIX, unexpected form in xlate_fixbinder") in + Some + (Rform + (CT_cofixc + (CT_ident iddef, + CT_cofix_rec_list (xlate_cofixbinder l, List.map xlate_cofixbinder ldecl)))) + | _ -> None;; + + + +let rec list_last = function + | [a] -> a + | a::l -> list_last l + | [] -> failwith "list_last called on an empty list";; + +let rec slam_body = function + | Slam(_, _, b) -> slam_body b + | c -> c;; + +let translate_one_equation cont_function = function + | Node (_, "EQN", body::first_pattern::patterns) -> + let translated_patterns = List.map + (xlate_cases_pattern cont_function) + patterns in + CT_eqn + (CT_match_pattern_ne_list + (xlate_cases_pattern + cont_function first_pattern, translated_patterns), + strip_Rform (cont_function body)) + | _ -> + xlate_error "Unexpected equation shape while translating a Cases" + +(*this function recognizes and translates Cases constructs *) +let special_case_cases cont_function = + function + | Node(_, s, + type_returned::matched_arg::equations) when + (s = "CASES") or (s = "FORCELET") or (s = "FORCEIF") -> + let simple_type_returned = + match type_returned with + | (Str (_, "SYNTH")) -> ctv_FORMULA_OPT_NONE + | _ -> + CT_coerce_FORMULA_to_FORMULA_OPT + (strip_Rform (cont_function type_returned)) in + let extract_equation = (function + | Node(_, "EQN", l) as it -> it + | _ -> xlate_error "equation is not an EQN") in + let translated_equations = + List.map + (fun x -> translate_one_equation cont_function (extract_equation x)) + equations in + let first_value, translated_matched_values = + match matched_arg with + | Node (_, "TOMATCH", matched_values) -> + (match + List.map (function x -> strip_Rform (cont_function x)) matched_values + with + | a :: b -> a, b + | _ -> xlate_error "Empty list of match values while translating a Cases") + | one_matched_value -> strip_Rform (cont_function one_matched_value), [] + in + Some + (Rform + (CT_cases + (simple_type_returned, + CT_formula_ne_list (first_value, translated_matched_values), + CT_eqn_list translated_equations))) + | _ -> None;; + +(*These functions are auxiliary to the function that translate annotated + formulas for the natural language presentation of proofs *) +let xlate_ID = + function + | Node (_, "ident", ((Str (_, str)) :: [])) -> CT_ident str + | Node (_, str, l) -> + xlate_error ("xlate_ID:" ^ str ^ ":" ^ string_of_int (List.length l)) + | _ -> xlate_error "xlate_ID";; + +let xlate_STRING = + function + | Str (_, str) -> CT_string str + | Node (_, str, l) -> + xlate_error ("xlate_STRING:" ^ str ^ ":" ^ string_of_int (List.length l)) + | _ -> xlate_error "xlate_STRING";; + +let rec strip_bang cont_function = + function + | [] -> [], false + | a :: tl -> + (match a with + | Node (_, "XTRA", ((Str (_, "!")) :: ((Num (_, n)) :: (f :: [])))) -> + if in_coq () then + strip_bang cont_function tl + else + begin + let l, b = strip_bang cont_function tl in + strip_Rform (cont_function f)::l, b + end + | Node (_, "EXPL", [Num(_, n); f]) -> + let l, _ = strip_bang cont_function tl in + strip_Rform (cont_function f)::l, true + | _ -> + let l, b = strip_bang cont_function tl in + strip_Rform (cont_function a)::l, b);; + +let special_case_bang cont_function = + function + | Node (_, "APPLISTEXPL", f::tl) -> + let l, b = strip_bang cont_function tl in + let compiled_f = strip_Rform (cont_function f) in + let + real_function = + if in_coq () then + (if b then CT_bang (CT_coerce_NONE_to_INT_OPT CT_none, compiled_f) + else compiled_f) + else CT_bang (CT_coerce_NONE_to_INT_OPT CT_none, compiled_f) in + (match l with + | [] -> xlate_error "special_case_bang: empty argument list?" + | elnt :: l' -> + Some (Rform (CT_appc (real_function, CT_formula_ne_list (elnt, l'))))) + | _ -> None;; + +exception Not_natural;; + +let rec nat_to_number = + function + | Node (_, "APPLIST", ((Nvar (_, "S")) :: (v :: []) as v0)) -> + 1 + nat_to_number v + | Nvar (_, "O") -> 0 + | _ -> raise Not_natural;; + +let g_nat_syntax_flag = ref false;; + +let set_flags = ref (function () -> ());; + +let special_case_S cont_function ast = + if !g_nat_syntax_flag then (match ast with + | Node (_, "APPLIST", ((Nvar (_, "S")) :: (v :: []))) as v0 -> begin + try Some (Rform (CT_int_encapsulator (CT_int (nat_to_number v0)))) + with + | Not_natural -> None + end + | Nvar (_, "O") -> Some (Rform (CT_int_encapsulator (CT_int 0))) + | _ -> None) + else None;; + +let xlate_formula_special_cases = + [special_case_qualid; + special_case_let_construct; + special_case_omega_integer; + special_case_fix; + special_case_cofix; + special_case_cases; + special_case_bang; special_case_S];; + +let xlate_special_cases cont_function arg = + let rec xlate_rec = + function + | f :: tl -> + (match f cont_function arg with + | Some _ as it -> it + | None -> xlate_rec tl) + | [] -> None in + xlate_rec xlate_formula_special_cases;; + +let xlate_formula a = + !set_flags (); + let rec ctrec = + function + | Nvar (_, id) -> Rform (varc (CT_ident id)) + | Slam (_, na, t) -> + let id = + match na with + | None -> ctv_ID_OPT_NONE + | Some id -> if id = "_" then ctv_ID_OPT_NONE + else ctf_ID_OPT_SOME (CT_ident id) in + let body = ctrec t in + Rbinder (id, body) + | Node (_, opn, tl) as it -> + (match xlate_special_cases ctrec it with + | Some result -> result + | None -> + let pl, tl' = split_params tl in + Rform (xlate_op it opn pl (List.map ctrec tl'))) + | _ -> xlate_error "xlate_formula" in + strip_Rform (ctrec a);; + +let xlate_formula_opt = + function + | Node (_, "None", []) -> ctv_FORMULA_OPT_NONE + | e -> CT_coerce_FORMULA_to_FORMULA_OPT (xlate_formula e);; + +(** Tactics + *) +let strip_targ_spec_list = + function + | Targ_spec_list x -> x + | _ -> xlate_error "strip tactic: non binding-list argument";; + +let strip_targ_binding = + function + | Targ_binding x -> x + | _ -> xlate_error "strip tactic: non-binding argument";; + +let strip_targ_command = + function + | Targ_command x -> x + | Targ_binding_com x -> x + | _ -> xlate_error "strip tactic: non-command argument";; + +let strip_targ_ident = + function + | Targ_ident x -> x + | _ -> xlate_error "strip tactic: non-ident argument";; + +let strip_targ_int = + function + | Targ_int x -> x + | _ -> xlate_error "strip tactic: non-int argument";; + +let strip_targ_pattern = + function + | Targ_pattern x -> x + | _ -> xlate_error "strip tactic: non-pattern argument";; + +let strip_targ_unfold = + function + | Targ_unfold x -> x + | _ -> xlate_error "strip tactic: non-unfold argument";; + +let strip_targ_fixtac = + function + | Targ_fixtac x -> x + | _ -> xlate_error "strip tactic: non-fixtac argument";; + +let strip_targ_cofixtac = + function + | Targ_cofixtac x -> x + | _ -> xlate_error "strip tactic: non-cofixtac argument";; + +(*Need to transform formula to id for "Prolog" tactic problem *) +let make_ID_from_FORMULA = + function + | CT_coerce_ID_to_FORMULA id -> id + | _ -> xlate_error "make_ID_from_FORMULA: non-formula argument";; + +let make_ID_from_iTARG_FORMULA x = make_ID_from_FORMULA (strip_targ_command x);; + +let filter_binding_or_command_list bl = + match bl with + | (Targ_binding_com cmd) :: bl' -> + CT_coerce_FORMULA_LIST_to_SPEC_LIST + (CT_formula_list (List.map strip_targ_command bl)) + | (Targ_binding b) :: bl' -> + CT_coerce_BINDING_LIST_to_SPEC_LIST + (CT_binding_list (List.map strip_targ_binding bl)) + | [] -> CT_coerce_FORMULA_LIST_to_SPEC_LIST (CT_formula_list []) + | _ -> xlate_error "filter_binding_or_command_list";; + +let strip_targ_spec_list = + function + | Targ_spec_list x -> x + | _ -> xlate_error "strip_tar_spec_list";; + +let strip_targ_intropatt = + function + | Targ_intropatt x -> x + | _ -> xlate_error "strip_targ_intropatt";; + + +let rec get_flag_rec = + function + | n1 :: tail -> + let conv_flags, red_ids = get_flag_rec tail in + (match n1 with + | Node (_, "Beta", []) -> CT_beta::conv_flags, red_ids + | Node (_, "Delta", []) -> CT_delta::conv_flags, red_ids + | Node (_, "Iota", []) -> CT_iota::conv_flags, red_ids + | Node (_, "Unf", l) -> + (match red_ids with + | CT_unf [] -> conv_flags, CT_unf (List.map xlate_id l) + | _ -> error "Cannot specify identifiers to unfold twice") + | Node (_, "UnfBut", l) -> + (match red_ids with + | CT_unf [] -> conv_flags, CT_unfbut (List.map xlate_id l) + | _ -> error "Cannot specify identifiers to unfold twice") + | Node (_, a, _) -> error ("get_flag_rec : unexpected flag " ^ a) + | _ -> error "get_flag_rec : unexpected flag") + | [] -> [], CT_unf [];; + +let rec xlate_intro_pattern = + function + | Node(_,"CONJPATTERN",[Node(_, "LISTPATTERN", l)]) -> + CT_conj_pattern(CT_intro_patt_list (List.map xlate_intro_pattern l)) + | Node(_, "DISJPATTERN", [Node(_,"LISTPATTERN",l)]) -> + CT_disj_pattern(CT_intro_patt_list (List.map xlate_intro_pattern l)) + | Node(_, "IDENTIFIER", [Nvar(_,c)]) -> + CT_coerce_ID_to_INTRO_PATT(CT_ident c) + | Node(_, a, _) -> failwith ("xlate_intro_pattern on node " ^ a) + | _ -> failwith "xlate_intro_pattern";; + +let compute_INV_TYPE_from_string = function + "InversionClear" -> CT_inv_clear + | "HalfInversion" -> CT_inv_simple + | "Inversion" -> CT_inv_regular + | _ -> failwith "unexpected Inversion type";; + +let is_tactic_special_case = function + "AutoRewrite" -> true + | _ -> false;; + +let tactic_special_case cont_function cvt_arg = function + "AutoRewrite", (tac::v::bl) -> + CT_autorewrite + (CT_id_ne_list(xlate_id v, List.map xlate_id bl), + CT_coerce_TACTIC_COM_to_TACTIC_OPT(cont_function tac)) + | "AutoRewrite", (v::bl) -> + CT_autorewrite + (CT_id_ne_list(xlate_id v, List.map xlate_id bl), + CT_coerce_NONE_to_TACTIC_OPT CT_none) + | _ -> assert false;; + +let xlate_context_pattern = function + Node(_,"TERM", [Node(_, "COMMAND", [v])]) -> + CT_coerce_FORMULA_to_CONTEXT_PATTERN (xlate_formula v) + | Node(_,"SUBTERM", [Nvar(_, s); Node(_, "COMMAND", [v])]) -> + CT_context(ctf_ID_OPT_SOME (CT_ident s), xlate_formula v) + | _ -> assert false;; + +let xlate_match_context_hyps = function + [b] -> CT_premise_pattern(ctv_ID_OPT_NONE, xlate_context_pattern b) + | [Nvar(_,s);b] -> CT_premise_pattern(ctf_ID_OPT_SOME (CT_ident s), + xlate_context_pattern b) + | _ -> assert false;; + + +let xlate_largs_to_id_unit largs = + match List.map xlate_id_unit largs with + fst::rest -> fst, rest + | _ -> assert false;; + +let rec cvt_arg = + function + | Nvar (_, id) -> Targ_ident (CT_ident id) + | Str (_, s) -> Targ_string (CT_string s) + | Num (_, n) -> Targ_int (CT_int n) + | Node (_, "LETPATTERNS", fst::l) -> + let mk_unfold_occ = function + Node(_, "HYPPATTERN", Nvar(_, name)::ints) -> + CT_unfold_occ( + CT_int_list (List.map xlate_int ints), CT_ident name) + | Node(_, "CCLPATTERN", ints) -> + CT_unfold_occ( + CT_int_list (List.map xlate_int ints), CT_ident "Goal") + | _ -> xlate_error "unexpected argument in mk_unfold_occ" in + Targ_unfold_ne_list( + CT_unfold_ne_list(mk_unfold_occ fst, List.map mk_unfold_occ l)) + | Node (_, "COMMAND", (c :: [])) -> Targ_command (xlate_formula c) + | Node (_, "CASTEDCOMMAND", (c :: [])) -> Targ_command (xlate_formula c) + | Node (_, "BINDINGS", bl) -> + Targ_spec_list (filter_binding_or_command_list (List.map cvt_arg bl)) + | Node (_, "BINDING", ((Node (_, "COMMAND", (c :: []))) :: [])) -> + Targ_binding_com (xlate_formula c) + | Node (_, "BINDING", + ((Num (_, n)) :: ((Node (_, "COMMAND", (c :: []))) :: []))) -> + Targ_binding + (CT_binding (CT_coerce_INT_to_ID_OR_INT (CT_int n), xlate_formula c)) + | Node (_, "BINDING", + ((Nvar (_, id)) :: ((Node (_, "COMMAND", (c :: []))) :: []))) -> + Targ_binding + (CT_binding (CT_coerce_ID_to_ID_OR_INT (CT_ident id), xlate_formula c)) + | Node (_, "TACTIC", (t :: [])) -> Targ_tacexp (xlate_tactic t) + | Node (_, "FIXEXP", + ((Nvar (_, id)) :: + ((Num (_, n)) :: ((Node (_, "COMMAND", (c :: []))) :: [])))) -> + Targ_fixtac (CT_fixtac (CT_ident id, CT_int n, xlate_formula c)) + | Node (_, "COFIXEXP", + ((Nvar (_, id)) :: ((Node (_, "COMMAND", (c :: []))) :: []))) -> + Targ_cofixtac (CT_cofixtac (CT_ident id, xlate_formula c)) + | Node (_, "CLAUSE", l) -> Targ_id_list (CT_id_list (List.map (function + | Nvar (_, x) -> CT_ident x + | _ -> + xlate_error + "expected identifiers in a CLAUSE") l)) + | Node (_, "REDEXP", (tac :: [])) -> Targ_redexp (xlate_red_tactic tac) + | Node (_, "INTROPATTERN", + [Node(_,"LISTPATTERN", l)]) -> + Targ_intropatt (CT_intro_patt_list(List.map xlate_intro_pattern l)) + | Node(_, "Str", [x]) -> cvt_arg x + | Node (_, a, _) -> failwith ("cvt_arg on node " ^ a) + | _ -> failwith "cvt_arg" +and xlate_red_tactic = + function + | Node (loc, s, []) -> + (match s with + | "Red" -> CT_red + | "Hnf" -> CT_hnf + | "Simpl" -> CT_simpl + | "Fold" -> CT_fold(CT_formula_list[]) + | _ -> xlate_error ("xlate_red_tactic, unexpected singleton " ^ s)) + | Node (_, "Unfold", unf_list) -> + let ct_unf_list = List.map (function + | Node (_, "UNFOLD", qid::nums) -> + (match qualid_to_ct_ID qid with + Some x -> + CT_unfold_occ (CT_int_list (List.map xlate_int nums), x) + | _ -> assert false) + | n -> + xlate_error ("xlate_red_tactic, expected unfold occurrence at " ^ + (string_of_node_loc n))) + unf_list in + (match ct_unf_list with + | first :: others -> CT_unfold (CT_unfold_ne_list (first, others)) + | [] -> error "there should be at least one thing to unfold") + | Node (_, "Cbv", flag_list) -> + let conv_flags, red_ids = get_flag_rec flag_list in + CT_cbv (CT_conversion_flag_list conv_flags, red_ids) + | Node (_, "Lazy", flag_list) -> + let conv_flags, red_ids = get_flag_rec flag_list in + CT_lazy (CT_conversion_flag_list conv_flags, red_ids) + | Node (_, "Pattern", l) -> + let pat_list = List.map (function + | Node (_, "PATTERN", ((Node (_, "COMMAND", (c :: []))) :: nums)) -> + CT_pattern_occ + (CT_int_list (List.map xlate_int nums), xlate_formula c) + | _ -> error "Expecting patterns in a Pattern command") l in + (match pat_list with + | first :: others -> CT_pattern (CT_pattern_ne_list (first, others)) + | [] -> error "Expecting at least one pattern in a Pattern command") + | Node (_, "Fold", formula_list) -> + CT_fold(CT_formula_list(List.map + (function Node(_,"COMMAND", [c]) -> xlate_formula c + | _ -> error("xlate_red_tactic expected a COMMAND")) + formula_list)) + | Node (_, a, _) -> error ("xlate_red_tactic: unexpected argument " ^ a) + | _ -> error "xlate_red_tactic : unexpected argument" +and xlate_tactic = + function + | Node (_, s, l) -> + (match s, l with + | "FUN", [Node(_, "FUNVAR", largs); t] -> + let fst, rest = xlate_largs_to_id_unit largs in + CT_tactic_fun + (CT_id_unit_list(fst, rest), xlate_tactic t) + | "TACTICLIST", (t :: tl) -> + (match List.map xlate_tactic (t::tl) with + | [] -> xlate_error "xlate_tactic: internal xlate_error" + | xt :: [] -> xt + | CT_then(xt,xtl1) :: xtl -> CT_then (xt, xtl1@xtl) + | xt :: xtl -> CT_then (xt, xtl)) + | "TACTICLIST", _ -> + xlate_error "xlate_tactic: malformed tactic-expression TACTICLIST" + | "TACLIST", (t :: tl) -> + (match List.map xlate_tactic (t::tl) with + | [] -> xlate_error "xlate_tactic: internal xlate_error" + | xt :: [] -> xt + | xt :: xtl -> CT_parallel (xt, xtl)) + | "FIRST", (a::l) -> + CT_first(xlate_tactic a,List.map xlate_tactic l) + | "TCLSOLVE", (a::l) -> + CT_tacsolve(xlate_tactic a, List.map xlate_tactic l) + | "DO", ((Num (_, n)) :: (t :: [])) -> CT_do (CT_int n, xlate_tactic t) + | "DO", _ -> xlate_error "xlate_tactic: malformed tactic-expression DO" + | "TRY", (t :: []) -> CT_try (xlate_tactic t) + | "TRY", _ -> xlate_error "xlate_tactic: malformed tactic-expression TRY" + | "REPEAT", (t :: []) -> CT_repeat (xlate_tactic t) + | "ABSTRACT", (Node(_,_,[t]) :: []) -> CT_abstract(ctv_ID_OPT_NONE, (xlate_tactic t)) + | "ABSTRACT", (Nvar(_, id)::(Node(_,"TACTIC",[t]) :: [])) -> + CT_abstract(ctf_ID_OPT_SOME (CT_ident id), (xlate_tactic t)) + | "INFO", (t :: []) -> CT_info (xlate_tactic t) + | "REPEAT", _ -> + xlate_error "xlate_tactic: malformed tactic-expression REPEAT" + | "ORELSE", (t1 :: (t2 :: [])) -> + CT_orelse (xlate_tactic t1, xlate_tactic t2) + | "ORELSE", _ -> + xlate_error "xlate_tactic: malformed tactic-expression ORELSE" + | ((s, l) as it) when (is_tactic_special_case s) -> + tactic_special_case xlate_tactic cvt_arg it + | "APP", (Nvar(_,s))::l -> + let f = fun x -> CT_coerce_FORMULA_to_TACTIC_ARG x in + let args = + List.map (function + Node(_, "COMMAND", [x]) -> f (xlate_formula x) + | x -> f (xlate_formula x)) l in + let fst,args2 = + match args with + fst::args2 -> fst, args2 + | _ -> assert false in + CT_simple_user_tac(CT_ident s, CT_tactic_arg_list(fst, args2)) + | "MATCHCONTEXT", rule1::rules -> + CT_match_context(xlate_context_rule rule1, + List.map xlate_context_rule rules) + | s, l -> xlate_tac (s, List.map cvt_arg l)) + | Nvar(_, s) -> ident_tac s + | the_node -> xlate_error ("xlate_tactic at " ^ + (string_of_node_loc the_node) ) + +and xlate_tac = + function + | "Absurd", ((Targ_command c) :: []) -> CT_absurd c + | "Change", [Targ_command f; Targ_id_list b] -> CT_change(f,b) + | "Contradiction", [] -> CT_contradiction + | "DoubleInd", ((Targ_int n1) :: ((Targ_int n2) :: [])) -> + CT_tac_double (n1, n2) + | "Discr", [] -> CT_discriminate_eq ctv_ID_OPT_NONE + | "DiscrHyp", ((Targ_ident id) :: []) -> + CT_discriminate_eq (ctf_ID_OPT_SOME id) + | "DEqConcl", [] -> CT_simplify_eq ctv_ID_OPT_NONE + | "DEqHyp", ((Targ_ident id) :: []) -> CT_simplify_eq (ctf_ID_OPT_SOME id) + | "Inj", [] -> CT_injection_eq ctv_ID_OPT_NONE + | "InjHyp", ((Targ_ident id) :: []) -> CT_injection_eq (ctf_ID_OPT_SOME id) + | "Fix", ((Targ_int n) :: []) -> + CT_fixtactic (ctv_ID_OPT_NONE, n, CT_fix_tac_list []) + | "Fix", ((Targ_ident id) :: ((Targ_int n) :: fixtac_list)) -> + CT_fixtactic + (ctf_ID_OPT_SOME id, n, + CT_fix_tac_list (List.map strip_targ_fixtac fixtac_list)) + | "Cofix", [] -> CT_cofixtactic (ctv_ID_OPT_NONE, CT_cofix_tac_list []) + | "Cofix", ((Targ_ident id) :: cofixtac_list) -> + CT_cofixtactic + (CT_coerce_ID_to_ID_OPT id, + CT_cofix_tac_list (List.map strip_targ_cofixtac cofixtac_list)) + | "IntrosUntil", ((Targ_ident id) :: []) -> CT_intros_until id + | "IntroMove", [Targ_ident id1;Targ_ident id2] -> + CT_intro_after(CT_coerce_ID_to_ID_OPT id1, id2) + | "IntroMove", [Targ_ident id2] -> + CT_intro_after(CT_coerce_NONE_to_ID_OPT CT_none, id2) + | "MoveDep", [Targ_ident id1;Targ_ident id2] -> + CT_move_after(id1, id2) + | "Intros", [] -> CT_intros (CT_intro_patt_list []) + | "Intros", [patt_list] -> + CT_intros (strip_targ_intropatt patt_list) + | "Intro", [Targ_ident (CT_ident id)] -> + CT_intros (CT_intro_patt_list [CT_coerce_ID_to_INTRO_PATT(CT_ident id)]) + | "Left", (bindl :: []) -> CT_left (strip_targ_spec_list bindl) + | "Right", (bindl :: []) -> CT_right (strip_targ_spec_list bindl) + | "Split", (bindl :: []) -> CT_split (strip_targ_spec_list bindl) + | "Replace", ((Targ_command c1) :: ((Targ_command c2) :: [])) -> + CT_replace_with (c1, c2) + | (*Changes to Equality.v some more rewrite possibilities *) + "RewriteLR", [(Targ_command c); bindl] -> + CT_rewrite_lr (c, strip_targ_spec_list bindl, ctv_ID_OPT_NONE) + | "RewriteLRin", ((Targ_ident id) :: ((Targ_command c) :: (bindl::[]))) -> + CT_rewrite_lr (c, strip_targ_spec_list bindl, ctf_ID_OPT_SOME id) + | "RewriteRL", [Targ_command c; bindl] -> + CT_rewrite_rl (c, strip_targ_spec_list bindl, ctv_ID_OPT_NONE) + | "RewriteRLin", [Targ_ident id; Targ_command c; bindl] -> + CT_rewrite_rl (c, strip_targ_spec_list bindl, ctf_ID_OPT_SOME id) + | "CondRewriteLR", [Targ_tacexp t; Targ_command c; bindl] -> + CT_condrewrite_lr (t, c, strip_targ_spec_list bindl, ctv_ID_OPT_NONE) + | "CondRewriteRL", [Targ_tacexp t; Targ_command c; bindl] -> + CT_condrewrite_rl (t, c, strip_targ_spec_list bindl, ctv_ID_OPT_NONE) + | "CondRewriteLRin", [Targ_tacexp t; Targ_ident id; Targ_command c; bindl] -> + CT_condrewrite_lr (t, c, strip_targ_spec_list bindl, ctf_ID_OPT_SOME id) + | "CondRewriteRLin", [Targ_tacexp t; Targ_ident id; Targ_command c; bindl] -> + CT_condrewrite_rl (t, c, strip_targ_spec_list bindl, ctf_ID_OPT_SOME id) + | "SubstConcl_LR", ((Targ_command c) :: []) -> + CT_cutrewrite_lr (c, ctv_ID_OPT_NONE) + | "SubstHyp_LR", ((Targ_command c) :: ((Targ_ident id) :: [])) -> + CT_cutrewrite_lr (c, ctf_ID_OPT_SOME id) + | "SubstConcl_RL", ((Targ_command c) :: []) -> + CT_cutrewrite_rl (c, ctv_ID_OPT_NONE) + | "SubstHyp_RL", ((Targ_command c) :: ((Targ_ident id) :: [])) -> + CT_cutrewrite_rl (c, ctf_ID_OPT_SOME id) + | "SubstHypInConcl_LR", ((Targ_ident id) :: []) -> CT_deprewrite_lr id + | "SubstHypInConcl_RL", ((Targ_ident id) :: []) -> CT_deprewrite_rl id + | "Reflexivity", [] -> CT_reflexivity + | "Symmetry", [] -> CT_symmetry + | "Transitivity", ((Targ_command c) :: []) -> CT_transitivity c + | "Assumption", [] -> CT_assumption + | "FAIL", [] -> CT_fail + | "IDTAC", [] -> CT_idtac + | "Exact", ((Targ_command c) :: []) -> CT_exact c + | "DHyp", [Targ_ident id] -> CT_dhyp id + | "CDHyp", [Targ_ident id] -> CT_cdhyp id + | "DConcl", [] -> CT_dconcl + | "SuperAuto", [a1;a2;a3;a4] -> + CT_superauto( + (match a1 with + | Targ_int n -> (CT_coerce_INT_to_INT_OPT n) + | _ -> (CT_coerce_NONE_to_INT_OPT CT_none)), + (match a2 with + | Targ_id_list l -> l + | _ -> xlate_error + "SuperAuto expects a list of identifiers as second argument"), + (match a3 with + | Targ_string (CT_string "Destructing") -> CT_destructing + | _ -> (CT_coerce_NONE_to_DESTRUCTING CT_none)), + (match a4 with + | Targ_string (CT_string "UsingTDB") -> CT_usingtdb + | _ -> (CT_coerce_NONE_to_USINGTDB CT_none))) + + + | "AutoTDB", [Targ_int n] -> CT_autotdb (CT_coerce_INT_to_INT_OPT n) + | "AutoTDB", [] -> CT_autotdb (CT_coerce_NONE_to_INT_OPT CT_none) + | "Auto", ((Targ_int n) :: []) -> CT_auto (CT_coerce_INT_to_INT_OPT n) + | "Auto", ((Targ_string (CT_string "*"))::[]) + -> CT_auto_with((CT_coerce_NONE_to_INT_OPT CT_none), CT_star) + | "Auto", [] -> CT_auto (CT_coerce_NONE_to_INT_OPT CT_none) + | "Auto", ((Targ_int n) :: ((Targ_ident id1) :: idl)) -> + CT_auto_with ((CT_coerce_INT_to_INT_OPT n), + CT_coerce_ID_NE_LIST_to_ID_NE_LIST_OR_STAR( + CT_id_ne_list(id1, List.map (function Targ_ident(x) -> x + | _ -> xlate_error + "Auto expects identifiers") + idl))) + | "Auto", ((Targ_ident id1) :: idl) -> + CT_auto_with ((CT_coerce_NONE_to_INT_OPT CT_none), + CT_coerce_ID_NE_LIST_to_ID_NE_LIST_OR_STAR( + CT_id_ne_list(id1, List.map (function Targ_ident(x) -> x + | _ -> xlate_error + "Auto expects identifiers") + idl))) + | "Auto", ((Targ_int n) :: ((Targ_string (CT_string "*")) :: [])) -> + CT_auto_with ((CT_coerce_INT_to_INT_OPT n), CT_star) + | "EAuto", ((Targ_int n) :: []) -> CT_eauto (CT_coerce_INT_to_INT_OPT n) + | "EAuto", [] -> CT_eauto (CT_coerce_NONE_to_INT_OPT CT_none) + | "EAuto", ((Targ_int n) :: ((Targ_ident id1) :: idl)) -> + CT_eauto_with ((CT_coerce_INT_to_INT_OPT n), + CT_coerce_ID_NE_LIST_to_ID_NE_LIST_OR_STAR( + CT_id_ne_list(id1, List.map (function Targ_ident(x) -> x + | _ -> xlate_error + "Auto expects identifiers") + idl))) + | "EAuto", ((Targ_ident id1) :: idl) -> + CT_eauto_with ((CT_coerce_NONE_to_INT_OPT CT_none), + CT_coerce_ID_NE_LIST_to_ID_NE_LIST_OR_STAR( + CT_id_ne_list(id1, List.map (function Targ_ident(x) -> x + | _ -> xlate_error + "Auto expects identifiers") + idl))) + | "EAuto", ((Targ_int n) :: ((Targ_string (CT_string "*")) :: [])) -> + CT_eauto_with ((CT_coerce_INT_to_INT_OPT n), CT_star) + | "EAuto", ((Targ_string (CT_string "*"))::[]) + -> CT_eauto_with((CT_coerce_NONE_to_INT_OPT CT_none), CT_star) + | "Prolog", ((Targ_int n) :: idlist) -> + (*according to coqdev the code is right, they want formula *) + CT_prolog (CT_formula_list (List.map strip_targ_command idlist), n) + | (**) + "EApplyWithBindings", ((Targ_command c) :: (bindl :: [])) -> + CT_eapply (c, strip_targ_spec_list bindl) + | "Trivial", [] -> CT_trivial + | "Trivial", ((Targ_string (CT_string "*"))::[]) -> + CT_trivial_with(CT_star) + | "Trivial", ((Targ_ident id1):: idl) -> + CT_trivial_with(CT_coerce_ID_NE_LIST_to_ID_NE_LIST_OR_STAR( + (CT_id_ne_list(id1, + List.map (function Targ_ident x -> x + | _ -> xlate_error "Trivial expects identifiers") + idl)))) + | "Reduce", ((Targ_redexp id) :: ((Targ_id_list l) :: [])) -> + CT_reduce (id, l) + | "Apply", ((Targ_command c) :: (bindl :: [])) -> + CT_apply (c, strip_targ_spec_list bindl) + | "Constructor", ((Targ_int n) :: bindl) -> + CT_constructor (n, filter_binding_or_command_list bindl) + | "Specialize", + ((Targ_int n) :: ((Targ_command c) :: ((Targ_spec_list sl) :: []))) -> + CT_specialize (CT_coerce_INT_to_INT_OPT n, c, sl) + | "Specialize", ((Targ_command c) :: ((Targ_spec_list sl) :: [])) -> + CT_specialize (CT_coerce_NONE_to_INT_OPT CT_none, c, sl) + | "Generalize", (first :: cl) -> + CT_generalize + (CT_formula_ne_list + (strip_targ_command first, List.map strip_targ_command cl)) + | "GeneralizeDep", [Targ_command c] -> + CT_generalize_dependent c + | "ElimType", ((Targ_command c) :: []) -> CT_elim_type c + | "CaseType", ((Targ_command c) :: []) -> CT_case_type c + | "Elim", ((Targ_command c1) :: ((Targ_spec_list sl) :: [])) -> + CT_elim (c1, sl, CT_coerce_NONE_to_USING CT_none) + | "Elim", + ((Targ_command c1) :: + ((Targ_spec_list sl) :: + ((Targ_command c2) :: ((Targ_spec_list sl2) :: [])))) -> + CT_elim (c1, sl, CT_using (c2, sl2)) + | "Case", ((Targ_command c1) :: ((Targ_spec_list sl) :: [])) -> + CT_casetac (c1, sl) + | "Induction", ((Targ_ident id) :: []) -> + CT_induction (CT_coerce_ID_to_ID_OR_INT id) + | "Induction", ((Targ_int n) :: []) -> + CT_induction (CT_coerce_INT_to_ID_OR_INT n) + | "Destruct", ((Targ_ident id) :: []) -> + CT_destruct (CT_coerce_ID_to_ID_OR_INT id) + | "Destruct", ((Targ_int n) :: []) -> + CT_destruct (CT_coerce_INT_to_ID_OR_INT n) + | "Cut", ((Targ_command c) :: []) -> CT_cut c + | "CutAndApply", ((Targ_command c) :: []) -> CT_use c + | "DecomposeThese", ((Targ_id_list l) :: ((Targ_command c) :: [])) -> + (match l with + CT_id_list (id :: l') -> + CT_decompose_list( + CT_id_ne_list(id,l'),c) + | _ -> xlate_error "DecomposeThese : empty list of identifiers?") + | "Clear", [id_list] -> + (match id_list with + Targ_id_list(CT_id_list(id::idl)) -> + CT_clear (CT_id_ne_list (id, idl)) + | _ -> xlate_error "Clear expects a non empty list of identifiers") + | (*For translating tactics/Inv.v *) + "Inv", [Targ_ident (CT_ident s); Targ_ident id] -> + CT_inversion (compute_INV_TYPE_from_string s, id, CT_id_list []) + | "InvIn", ((Targ_ident (CT_ident s))::((Targ_ident id) :: idlist)) -> + CT_inversion + (compute_INV_TYPE_from_string s, id, + CT_id_list (List.map strip_targ_ident idlist)) + | "DInv", ((Targ_ident (CT_ident s))::((Targ_ident id) :: [])) -> + CT_depinversion + (compute_INV_TYPE_from_string s, id, ctv_FORMULA_OPT_NONE) + | "DInvWith", ((Targ_ident (CT_ident s)):: + ((Targ_ident id) :: ((Targ_command c) :: []))) -> + CT_depinversion + (compute_INV_TYPE_from_string s, id, CT_coerce_FORMULA_to_FORMULA_OPT c) + | "UseInversionLemma", ((Targ_ident id) :: ((Targ_command c) :: [])) -> + CT_use_inversion (id, c, CT_id_list []) + | "UseInversionLemmaIn", ((Targ_ident id) :: ((Targ_command c) :: idlist)) -> + CT_use_inversion (id, c, CT_id_list (List.map strip_targ_ident idlist)) + | "Omega", [] -> CT_omega + | "APP", (Targ_ident id)::l -> + CT_user_tac (id, CT_targ_list (List.map coerce_iTARG_to_TARG l)) + | s, l -> + CT_user_tac (CT_ident s, CT_targ_list (List.map coerce_iTARG_to_TARG l)) +and (xlate_context_rule: Coqast.t -> ct_CONTEXT_RULE) = + function + | Node(_, "MATCHCONTEXTRULE", parts) -> + let rec xlate_ctxt_rule_aux = function + [concl_pat; tac] -> + [], xlate_context_pattern concl_pat, xlate_tactic tac + | Node(_,"MATCHCONTEXTHYPS", hyp_parts)::b -> + let hyps, cpat, tactic = xlate_ctxt_rule_aux b in + (xlate_match_context_hyps hyp_parts)::hyps, cpat, tactic + | _ -> assert false in + let hyps, cpat, tactic = xlate_ctxt_rule_aux parts in + CT_context_rule(CT_context_hyp_list hyps, cpat, tactic) + | _ -> assert false;; + +let strip_varg_int = + function + | Varg_int n -> n + | _ -> xlate_error "strip vernac: non-integer argument";; + +let strip_varg_string = + function + | Varg_string str -> str + | _ -> xlate_error "strip vernac: non-string argument";; + +let strip_varg_ident = + function + | Varg_ident id -> id + | _ -> xlate_error "strip vernac: non-ident argument";; + +let strip_varg_binder = + function + | Varg_binder n -> n + | _ -> xlate_error "strip vernac: non-binder argument";; + +let xlate_thm x = CT_thm (match x with + | "THEOREM" -> "Theorem" + | "REMARK" -> "Remark" + | "LEMMA" -> "Lemma" + | "FACT" -> "Fact" + | _ -> xlate_error "xlate_thm");; + +let xlate_defn x = CT_defn (match x with + | "DEFINITION" -> "Definition" + | "LOCAL" -> "Local" + | "OBJECT" -> "@Definition" + | "LOBJECT" -> "@Local" + | "OBJCOERCION" -> "@Coercion" + | "LOBJCOERCION" -> "LOBJCOERCION" + | "SUBCLASS" -> "SubClass" + | "LSUBCLASS" -> "LSUBCLASS" + | "COERCION" -> "Coercion" + | "LCOERCION" -> "LCOERCION" + | _ -> xlate_error "xlate_defn");; + +let xlate_defn_or_thm s = + try CT_coerce_THM_to_DEFN_OR_THM (xlate_thm s) + with + | _ -> CT_coerce_DEFN_to_DEFN_OR_THM (xlate_defn s);; + +let xlate_var x = CT_var (match x with + | "HYPOTHESES" -> "Hypothesis" + | "HYPOTHESIS" -> "Hypothesis" + | "VARIABLE" -> "Variable" + | "VARIABLES" -> "Variable" + | "AXIOM" -> "Axiom" + | "PARAMETER" -> "Parameter" + | "PARAMETERS" -> "Parameter" + | (*backwards compatible with 14a leave for now *) + "Axiom" as s -> s + | "Parameter" as s -> s + | _ -> xlate_error "xlate_var");; + +let xlate_dep = + function + | "DEP" -> CT_dep "Induction for" + | "NODEP" -> CT_dep "Minimality for" + | _ -> xlate_error "xlate_dep";; + +let xlate_locn = + function + | Varg_int n -> CT_coerce_INT_to_INT_OR_LOCN n + | Varg_string (CT_string "top") -> + CT_coerce_LOCN_to_INT_OR_LOCN (CT_locn "top") + | Varg_string (CT_string "prev") -> + CT_coerce_LOCN_to_INT_OR_LOCN (CT_locn "prev") + | Varg_string (CT_string "next") -> + CT_coerce_LOCN_to_INT_OR_LOCN (CT_locn "next") + | _ -> xlate_error "xlate_locn";; + +let xlate_check = + function + | "CHECK" -> "Check" + | "PRINTTYPE" -> "Type" + | _ -> xlate_error "xlate_check";; + +let build_constructors l = + let strip_coerce = + function + | CT_coerce_ID_to_ID_OPT id -> id + | _ -> xlate_error "build_constructors" in + let rec rebind = + function + | [] -> [] + | (CT_binder ((CT_id_opt_ne_list (id, ids)), c)) :: l -> + (List.map (function id_opt -> CT_constr (strip_coerce id_opt, c)) + (id::ids)) @ rebind l in + CT_constr_list (rebind l);; + +let build_record_field_list l = + let build_record_field = + function + | Varg_varglist ((Varg_string (CT_string "")) :: + ((Varg_ident id) :: (c :: []))) -> + CT_coerce_CONSTR_to_RECCONSTR (CT_constr (id, coerce_iVARG_to_FORMULA c)) + | Varg_varglist ((Varg_string (CT_string "COERCION")) :: + ((Varg_ident id) :: (c :: []))) -> + CT_constr_coercion (id, coerce_iVARG_to_FORMULA c) + | _ -> xlate_error "unexpected field in build_record_field_list" in + CT_recconstr_list (List.map build_record_field l);; + +let xlate_ast = + let rec xlate_ast_aux = + function + | Node (_, s, tl) -> + CT_astnode (CT_ident s, CT_ast_list (List.map xlate_ast_aux tl)) + | Nvar (_, s) -> + CT_coerce_ID_OR_STRING_to_AST + (CT_coerce_STRING_to_ID_OR_STRING (CT_string s)) + | Slam (_, (Some s), t) -> + CT_astslam (CT_coerce_ID_to_ID_OPT (CT_ident s), xlate_ast_aux t) + | Slam (_, None, t) -> CT_astslam (ctv_ID_OPT_NONE, xlate_ast_aux t) + | Num (_, i) -> failwith "Numbers not treated in xlate_ast" + | Id (_, s) -> + CT_coerce_ID_OR_STRING_to_AST + (CT_coerce_STRING_to_ID_OR_STRING (CT_string s)) + | Str (_, s) -> + CT_coerce_ID_OR_STRING_to_AST + (CT_coerce_STRING_to_ID_OR_STRING (CT_string s)) + | Dynamic(_,_) -> failwith "Dynamics not treated in xlate_ast" + | Path (_, sl, s) -> + CT_astpath + (CT_id_list (List.map (function s -> CT_ident s) sl), CT_ident s) in + xlate_ast_aux;; + +let get_require_flags impexp spec = + let ct_impexp = + match impexp with + | CT_string "IMPORT" -> CT_import + | CT_string "EXPORT" -> CT_export + | CT_string s -> xlate_error ("unexpected Require import flag " ^ s) in + let ct_spec = + match spec with + | CT_string "UNSPECIFIED" -> ctv_SPEC_OPT_NONE + | CT_string "SPECIFICATION" -> CT_spec + | CT_string "IMPLEMENTATION" -> ctv_SPEC_OPT_NONE + | CT_string s -> xlate_error ("unexpected Require specification flag " ^ s) in + ct_impexp, ct_spec;; + +let cvt_optional_eval_for_definition c1 optional_eval = + match optional_eval with + None -> CT_coerce_FORMULA_to_DEF_BODY c1 + | Some (Targ_redexp red_com) -> + CT_coerce_EVAL_CMD_to_DEF_BODY( + CT_eval(CT_coerce_NONE_to_INT_OPT CT_none, + red_com, + c1)) + | _ -> xlate_error + "bad extra argument (tactic?) for Definition";; + +let rec cvt_varg = + function + | Node (_, "VERNACARGLIST", l) -> Varg_varglist (List.map cvt_varg l) + | Node (_, "VERNACCALL", ((Str (_, na)) :: l)) -> + Varg_call (CT_ident na, List.map cvt_varg l) + | Node (_, "VERNACCALL", ((Id (_, na)) :: l)) -> + Varg_call (CT_ident na, List.map cvt_varg l) + | Node (_, "QUALIDARG", _) as it -> + (match qualid_to_ct_ID it with + Some x -> Varg_ident x + | None -> assert false) + | Nvar (_, id) -> Varg_ident (CT_ident id) + | Str (_, s) -> Varg_string (CT_string s) + | Num (_, n) -> Varg_int (CT_int n) + | Node (_, "NONE", []) -> Varg_none + | Node (_, "CONSTR", ((Node (_, "PROP", ((Id (_, c)) :: []))) :: [])) -> + (match c with + | "Pos" -> Varg_sorttype (CT_sortc "Set") + | "Null" -> Varg_sorttype (CT_sortc "Prop") + | _ -> xlate_error "cvt_varg : PROP : Failed match ") + | Node (_, "CONSTR", ((Node (_, "TYPE", [])) :: [])) -> + Varg_sorttype (CT_sortc "Type") + | Node (_, "CONSTR", [c]) -> Varg_constr (xlate_formula c) + | Node (_, "CONSTRLIST", cs) -> Varg_constrlist (List.map xlate_formula cs) + | Node (_, "TACTIC", [c]) -> Varg_tactic (xlate_tactic c) + | Node (_, "BINDER", args) as arg -> + Varg_binder(cvt_binder xlate_formula arg) + | Node (_, "BINDERLIST", l) as arg -> + Varg_binderlist(cvt_binders xlate_formula arg) + | Node (_, "BINDERS", l) as arg -> + Varg_binderlist(cvt_binders xlate_formula arg) + | Node (_, "NUMBERLIST", ln) -> + Varg_intlist (CT_int_list (List.map xlate_int ln)) + | Node (_, "AST", [Node(_, "ASTACT", [ + Node(_, "ASTLIST", [Node(_, "TACTICLIST", _) as it])])]) -> + Varg_tactic(xlate_tactic it) + | Node (_, "AST", (a :: [])) -> Varg_ast (xlate_ast a) + | Node (_, "ASTLIST", al) -> + Varg_astlist (CT_ast_list (List.map xlate_ast al)) + | Node (_, "TACTIC_ARG", (targ :: [])) -> Varg_tactic_arg (cvt_arg targ) + | Node (_, s, _) as it -> failwith ("cvt_varg : " ^ s ^ " at location " ^ + (string_of_node_loc it)) + | the_node -> failwith ("cvt_varg : " ^ (string_of_node_loc the_node)) +and xlate_vernac = + function + | Node(_, "TACDEF", [Nvar(_,id); + Node(_,"AST", + [Node(_,"FUN", + [Node(_,"FUNVAR", + largs); + tac])])]) -> + CT_tactic_definition(CT_ident id, + CT_id_list(List.map xlate_id largs), + xlate_tactic tac) + | Node(_, "TACDEF", Nvar(_, id):: + ((Node(_, "AST",[Node(_, "REC", [vc])])::tl) as the_list)) -> + let x_rec_tacs = + List.fold_right + (fun e res -> match e with + Node(_,"AST", + [Node(_,"REC", + [Node(_,"RECCLAUSE", [Nvar(_,x); + Node(_, "FUNVAR", argl); + tac])])]) -> + let fst, rest = xlate_largs_to_id_unit argl in + CT_rec_tactic_fun(CT_ident x, + CT_id_unit_list(fst, rest), + xlate_tactic tac)::res + | _ -> res) the_list [] in + let fst, others = match x_rec_tacs with + fst::others -> fst, others + | _ -> assert false in + CT_rec_tactic_definition(CT_rec_tactic_fun_list(fst, others)) + | Node(_, "TACDEF", [Nvar(_,id);Node(_,"AST",[tac])]) -> + CT_tactic_definition(CT_ident id, CT_id_list[], xlate_tactic tac) + | Node (_, s, l) -> + (match s, List.map cvt_varg l with + | "LoadFile", ((Varg_string verbose) :: ((Varg_string s) :: [])) -> + CT_load ( + (match verbose with + | CT_string "" -> CT_coerce_NONE_to_VERBOSE_OPT CT_none + | CT_string "Verbose" as it -> CT_verbose + | CT_string s -> + xlate_error ("expecting the keyword Verbose only :" ^ s)), + CT_coerce_STRING_to_ID_OR_STRING s) + | "Eval", + ((Varg_tactic_arg (Targ_redexp tac)) :: ((Varg_constr f) :: tail)) -> + let numopt = + match tail with + | (Varg_int i) :: [] -> CT_coerce_INT_to_INT_OPT i + | [] -> CT_coerce_NONE_to_INT_OPT CT_none + | _ -> xlate_error "Eval expects an optional integer" in + CT_coerce_EVAL_CMD_to_COMMAND(CT_eval (numopt, tac, f)) + | "PWD", [] -> CT_pwd + | "CD", ((Varg_string str) :: []) -> CT_cd (ctf_STRING_OPT_SOME str) + | "CD", [] -> CT_cd ctf_STRING_OPT_NONE + | "ADDPATH", ((Varg_string str) :: []) -> CT_addpath str + | "RECADDPATH", ((Varg_string str) :: []) -> CT_recaddpath str + | "DELPATH", ((Varg_string str) :: []) -> CT_delpath str + | "PrintPath", [] -> CT_print_loadpath + | "QUIT", [] -> CT_quit + | (*ML commands *) + "AddMLPath", ((Varg_string str) :: []) -> CT_ml_add_path str + | "RecAddMLPath", ((Varg_string str) :: []) -> CT_rec_ml_add_path str + | "PrintMLPath", [] -> CT_ml_print_path + | "PrintMLModules", [] -> CT_ml_print_modules + | "DeclareMLModule", (str :: l) -> + CT_ml_declare_modules + (CT_string_ne_list (strip_varg_string str, List.map strip_varg_string l)) + | "GOAL", [] -> CT_proof_no_op + | "GOAL", (c :: []) -> CT_coerce_THEOREM_GOAL_to_COMMAND (CT_goal (coerce_iVARG_to_FORMULA c)) + | (*My attempt at getting all variants of Abort to use abort node *) + "ABORT", ((Varg_ident id) :: []) -> CT_abort (ctf_ID_OPT_OR_ALL_SOME id) + | "ABORT", [] -> CT_abort ctv_ID_OPT_OR_ALL_NONE + | "ABORTALL", [] -> CT_abort ctv_ID_OPT_OR_ALL_ALL + | (*formerly | ("ABORTALL", []) -> ident_vernac "Abort All" *) + "RESTART", [] -> CT_restart + | "PROOF", (c :: []) -> CT_proof (coerce_iVARG_to_FORMULA c) + | "SOLVE", ((Varg_int n) :: ((Varg_tactic tcom) :: [])) -> + CT_solve (n, tcom) + | "FOCUS", [] -> CT_focus (CT_coerce_NONE_to_INT_OPT CT_none) + | "FOCUS", [Varg_int n] -> CT_focus (CT_coerce_INT_to_INT_OPT n) + | "UNFOCUS", [] -> CT_unfocus + | "HintRewrite", [orient; formula_list; Varg_ident base; Varg_tactic t] -> + let ct_orient = match orient with + | Varg_string (CT_string "LR") -> CT_lr + | Varg_string (CT_string "Rl") -> CT_rl + | _ -> assert false in + let f_ne_list = match formula_list with + Varg_constrlist (fst::rest) -> CT_formula_ne_list(fst,rest) + | _ -> assert false in + CT_hintrewrite(ct_orient, f_ne_list, base, t) + | "HintResolve", + ((Varg_ident id_name) :: + ((Varg_varglist dbnames) :: ((Varg_constr c)::[]))) -> + CT_hint(id_name, + CT_id_list(List.map coerce_iVARG_to_ID + dbnames), CT_resolve(c)) + | "HintUnfold", + ((Varg_ident id_name) :: + ((Varg_varglist dbnames) :: ((Varg_ident c)::[]))) -> + CT_hint(id_name, + CT_id_list(List.map coerce_iVARG_to_ID + dbnames), CT_unfold_hint(c)) + | "HintConstructors", + ((Varg_ident id_name) :: + ((Varg_varglist dbnames) :: ((Varg_ident c)::[]))) -> + CT_hint(id_name, + CT_id_list(List.map coerce_iVARG_to_ID + dbnames), CT_constructors(c)) + | "HintImmediate", + ((Varg_ident id_name) :: + ((Varg_varglist dbnames) :: ((Varg_constr c)::[]))) -> + CT_hint(id_name, + CT_id_list(List.map coerce_iVARG_to_ID + dbnames), CT_immediate(c)) + | "HintExtern", + [Varg_ident id_name; + Varg_varglist dbnames; + Varg_int n; + Varg_constr c; + Varg_tactic t] -> + CT_hint(id_name, CT_id_list (List.map coerce_iVARG_to_ID dbnames), + CT_extern(n, c, t)) + | "HintsResolve", + (Varg_varglist(dbnames)::(Varg_ident n1) :: names) -> + CT_hints(CT_ident "Resolve", + CT_id_ne_list(n1, List.map coerce_iVARG_to_ID names), + CT_id_list(List.map coerce_iVARG_to_ID dbnames)) + | "HintsImmediate", + (Varg_varglist(dbnames)::(Varg_ident n1) :: names) -> + CT_hints(CT_ident "Immediate", + CT_id_ne_list(n1, List.map coerce_iVARG_to_ID names), + CT_id_list(List.map coerce_iVARG_to_ID dbnames)) + | "HintsUnfold", + (Varg_varglist(dbnames)::(Varg_ident n1) :: names) -> + CT_hints(CT_ident "Unfold", + CT_id_ne_list(n1, List.map coerce_iVARG_to_ID names), + CT_id_list(List.map coerce_iVARG_to_ID dbnames)) + | "BY", ((Varg_tactic tcom) :: []) -> xlate_error "BY not implemented" + | (*My attempt to get all variants of Save to use the same node *) + "SaveNamed", [] -> + CT_save (CT_coerce_THM_to_THM_OPT (CT_thm "Theorem"), ctv_ID_OPT_NONE) + | "DefinedNamed", [] -> + CT_save (CT_coerce_THM_to_THM_OPT (CT_thm "Definition"), ctv_ID_OPT_NONE) + | "SaveAnonymousThm", ((Varg_ident s) :: []) -> + CT_save (CT_coerce_THM_to_THM_OPT (CT_thm "Theorem"), ctf_ID_OPT_SOME s) + | "SaveAnonymousRmk", ((Varg_ident s) :: []) -> + CT_save (CT_coerce_THM_to_THM_OPT (CT_thm "Remark"), ctf_ID_OPT_SOME s) + | "TRANSPARENT", (id :: idl) -> + CT_transparent(CT_id_ne_list(strip_varg_ident id, + List.map strip_varg_ident idl)) + | "OPAQUE", (id :: idl) + -> CT_opaque (CT_id_ne_list(strip_varg_ident id, + List.map strip_varg_ident idl)) + | "WriteModule", ((Varg_ident id) :: []) -> + CT_write_module (id, CT_coerce_NONE_to_STRING_OPT CT_none) + | "UNDO", ((Varg_int n) :: []) -> CT_undo (CT_coerce_INT_to_INT_OPT n) + | "SHOW", [] -> CT_show_goal (CT_coerce_NONE_to_INT_OPT CT_none) + | "SHOW", ((Varg_int n) :: []) -> CT_show_goal (CT_coerce_INT_to_INT_OPT n) + | "ShowNode", [] -> CT_show_node + | "ShowProof", [] -> CT_show_proof + | "ShowTree", [] -> CT_show_tree + | "ShowScript", [] -> CT_show_script + | "ShowProofs", [] -> CT_show_proofs + | "SHOWIMPL", [] -> CT_show_implicits + | "Go", (arg :: []) -> CT_go (xlate_locn arg) + | "ExplainProof", l -> + CT_explain_proof (CT_int_list (List.map strip_varg_int l)) + | "ExplainProofTree", l -> + CT_explain_prooftree (CT_int_list (List.map strip_varg_int l)) + | "PrintHint", [] -> CT_print_hint (CT_coerce_NONE_to_ID_OPT CT_none) + | "PrintHintDb", [Varg_ident id] -> CT_print_hintdb id + | "CheckGuard", [] -> CT_guarded + | "PrintHintId", ((Varg_ident id) :: []) -> + CT_print_hint (CT_coerce_ID_to_ID_OPT id) + | "PrintAll", [] -> CT_print_all + | "PrintId", ((Varg_ident id) :: []) -> CT_print_id id + | "PrintOpaqueId", ((Varg_ident id) :: []) -> CT_print_opaqueid id + | "PrintSec", ((Varg_ident id) :: []) -> CT_print_section id + | "PrintStates", [] -> CT_print_states + | "PrintModules", [] -> CT_print_modules + | "PrintGrammar", ((Varg_ident phylum) :: ((Varg_ident name) :: [])) -> + CT_print_grammar CT_grammar_none + | "BeginModule", ((Varg_ident id) :: []) -> CT_module id + | "BeginSection", ((Varg_ident id) :: []) -> + CT_coerce_SECTION_BEGIN_to_COMMAND (CT_section id) + | "EndSection", ((Varg_ident id) :: []) -> CT_section_end id + | "StartProof", + ((Varg_string (CT_string kind)) :: ((Varg_ident s) :: (c :: []))) -> + CT_coerce_THEOREM_GOAL_to_COMMAND( + CT_theorem_goal (xlate_defn_or_thm kind, s, coerce_iVARG_to_FORMULA c)) + | (*My attempt: suspend and resume as separate nodes *) + "SUSPEND", [] -> CT_suspend + | "RESUME", ((Varg_ident id) :: []) -> CT_resume (ctf_ID_OPT_SOME id) + | "RESUME", [] -> CT_resume ctv_ID_OPT_NONE + | (*formerly | ("SUSPEND", []) -> suspend(CT_true) + | ("RESUME", []) -> suspend(CT_false) + *) + "DEFINITION", + (* reference : toplevel/vernacentries.ml *) + (Varg_string (CT_string kind):: Varg_ident s :: Varg_constr c :: rest) -> + let typ_opt, red_option = match rest with + | [] -> ctv_FORMULA_OPT_NONE, None + | [Varg_constr b] -> CT_coerce_FORMULA_to_FORMULA_OPT b, None + | [Varg_tactic_arg r] -> ctv_FORMULA_OPT_NONE, Some r + | [Varg_constr b; Varg_tactic_arg r] -> + CT_coerce_FORMULA_to_FORMULA_OPT b, Some r + | _ -> assert false in + CT_definition + (xlate_defn kind, s, + cvt_optional_eval_for_definition c red_option, typ_opt) + | "VARIABLE", + ((Varg_string (CT_string kind)) :: ((Varg_binderlist b) :: [])) -> + CT_variable (xlate_var kind, b) + | "PARAMETER", + ((Varg_string (CT_string kind)) :: ((Varg_binderlist b) :: [])) -> + CT_variable (xlate_var kind, b) + | "Check", ((Varg_string (CT_string kind)) :: (c :: [])) -> + CT_check (coerce_iVARG_to_FORMULA c) + | "SEARCH", (Varg_ident id):: l -> + (match l with + | [] -> CT_search(id, CT_coerce_NONE_to_IN_OR_OUT_MODULES CT_none) + | (Varg_string (CT_string x))::(Varg_ident m1)::l1 -> + let l2 = CT_id_ne_list(m1, List.map coerce_iVARG_to_ID l1) in + let modifier = + (match x with + | "inside" -> CT_in_modules l2 + | "outside" -> CT_out_modules l2 + | _ -> xlate_error "bad extra argument for Search") in + CT_search(id, modifier) + | _ -> xlate_error "bad argument list for Search") + | "INSPECT", ((Varg_int n) :: []) -> CT_inspect n + | (*Record from tactics/Record.v *) + "RECORD", + ((Varg_string coercion_or_not) :: ((Varg_ident s) :: + ((Varg_binderlist binders) :: + ((Varg_sorttype c) :: + ((Varg_varglist rec_constructor_or_none) :: + ((Varg_varglist field_list) :: [])))))) -> + let record_constructor = + match rec_constructor_or_none with + | [] -> CT_coerce_NONE_to_ID_OPT CT_none + | (Varg_ident id) :: [] -> CT_coerce_ID_to_ID_OPT id + | _ -> xlate_error "unexpected record constructor" in + CT_record + ((match coercion_or_not with CT_string "" -> + CT_coerce_NONE_to_COERCION_OPT(CT_none) + | _ -> CT_coercion_atm), + s, binders, c, record_constructor, + build_record_field_list field_list) + | (*Inversions from tactics/Inv.v *) + "MakeSemiInversionLemmaFromHyp", + ((Varg_int n) :: ((Varg_ident id1) :: ((Varg_ident id2) :: []))) -> + CT_derive_inversion + (CT_inv_regular, CT_coerce_INT_to_INT_OPT n, id1, id2) + | "MakeInversionLemmaFromHyp", + ((Varg_int n) :: ((Varg_ident id1) :: ((Varg_ident id2) :: []))) -> + CT_derive_inversion + (CT_inv_clear, + CT_coerce_INT_to_INT_OPT n, id1, id2) + | "MakeSemiInversionLemma", + ((Varg_ident id) :: (c :: ((Varg_sorttype sort) :: []))) -> + CT_derive_inversion_with + (CT_inv_regular, id, coerce_iVARG_to_FORMULA c, sort) + | "MakeInversionLemma", + ((Varg_ident id) :: (c :: ((Varg_sorttype sort) :: []))) -> + CT_derive_inversion_with + (CT_inv_clear, id, + coerce_iVARG_to_FORMULA c, sort) + | "MakeDependentSemiInversionLemma", + ((Varg_ident id) :: (c :: ((Varg_sorttype sort) :: []))) -> + CT_derive_depinversion + (CT_inv_regular, id, coerce_iVARG_to_FORMULA c, sort) + | "MakeDependentInversionLemma", + ((Varg_ident id) :: (c :: ((Varg_sorttype sort) :: []))) -> + CT_derive_depinversion + (CT_inv_clear, id, coerce_iVARG_to_FORMULA c, sort) + | + "ONEINDUCTIVE", + ((Varg_string (CT_string f)) :: + ((Varg_ident s) :: + (c :: + ((Varg_binderlist binders) :: + ((Varg_binderlist (CT_binder_list constructors)) :: []))))) -> + CT_mind_decl + (CT_co_ind f, + CT_ind_spec_list( + [CT_ind_spec(s,binders, coerce_iVARG_to_FORMULA c, + build_constructors constructors)])) + | "OLDMUTUALINDUCTIVE", + [Varg_binderlist binders; Varg_string(CT_string f); + Varg_varglist lmi] -> + let strip_mutind = + function + | Varg_varglist([Varg_ident s;c; + Varg_binderlist (CT_binder_list constructors)]) -> + CT_ind_spec(s, binders, coerce_iVARG_to_FORMULA c, + build_constructors constructors) + | _ -> xlate_error "mutual inductive, old style" in + CT_mind_decl(CT_co_ind f, CT_ind_spec_list(List.map strip_mutind lmi)) + | "MUTUALINDUCTIVE", + ((Varg_string (CT_string co_or_ind)) :: + ((Varg_varglist lmi) ::[])) -> + let strip_mutind = + function + | Varg_varglist ((Varg_ident s) :: + (c :: + ((Varg_binderlist parameters) :: + ((Varg_binderlist (CT_binder_list constructors)) + :: [])))) -> + CT_ind_spec + (s, parameters, coerce_iVARG_to_FORMULA c, + build_constructors constructors) + | _ -> xlate_error "mutual inductive" in + CT_mind_decl + (CT_co_ind co_or_ind, CT_ind_spec_list (List.map strip_mutind lmi)) + | "MUTUALRECURSIVE", ((Varg_varglist (lm :: lmi)) :: []) -> + let strip_mutrec = + function + | Varg_varglist ((Varg_ident fid) :: + ((Varg_binderlist (CT_binder_list (b :: bl))) :: + (arf :: (ardef :: [])))) -> + CT_fix_rec + (fid, CT_binder_ne_list (b, bl), coerce_iVARG_to_FORMULA arf, + coerce_iVARG_to_FORMULA ardef) + | _ -> xlate_error "mutual recursive" in + CT_fix_decl + (CT_fix_rec_list (strip_mutrec lm, List.map strip_mutrec lmi)) + | "MUTUALCORECURSIVE", ((Varg_varglist (lm :: lmi)) :: []) -> + let strip_mutcorec = + function + | Varg_varglist ((Varg_ident fid) :: (arf :: (ardef :: []))) -> + CT_cofix_rec + (fid, coerce_iVARG_to_FORMULA arf, coerce_iVARG_to_FORMULA ardef) + | _ -> xlate_error "mutual corecursive" in + CT_cofix_decl + (CT_cofix_rec_list (strip_mutcorec lm, List.map strip_mutcorec lmi)) + | "INDUCTIONSCHEME", ((Varg_varglist (lm :: lmi)) :: []) -> + let strip_ind = + function + | Varg_varglist ((Varg_ident fid) :: + ((Varg_string (CT_string depstr)) :: + (inde :: ((Varg_sorttype sort) :: [])))) -> + CT_scheme_spec + (fid, xlate_dep depstr, coerce_iVARG_to_FORMULA inde, sort) + | _ -> xlate_error "induction scheme" in + CT_ind_scheme + (CT_scheme_spec_list (strip_ind lm, List.map strip_ind lmi)) + | + "SyntaxMacro", ((Varg_ident id) :: (c :: [])) -> + CT_syntax_macro + (id, coerce_iVARG_to_FORMULA c, CT_coerce_NONE_to_INT_OPT CT_none) + | "SyntaxMacro", ((Varg_ident id) :: (c :: ((Varg_int n) :: []))) -> + CT_syntax_macro + (id, coerce_iVARG_to_FORMULA c, CT_coerce_INT_to_INT_OPT n) + | "ABSTRACTION", ((Varg_ident id) :: (c :: l)) -> + CT_abstraction + (id, coerce_iVARG_to_FORMULA c, CT_int_list (List.map strip_varg_int l)) + | "Require", + ((Varg_string impexp) :: + ((Varg_string spec) :: ((Varg_ident id) :: []))) -> + let ct_impexp, ct_spec = get_require_flags impexp spec in + CT_require (ct_impexp, ct_spec, id, CT_coerce_NONE_to_STRING_OPT CT_none) + | "RequireFrom", + ((Varg_string impexp) :: + ((Varg_string spec) :: + ((Varg_ident id) :: ((Varg_string filename) :: [])))) -> + let ct_impexp, ct_spec = get_require_flags impexp spec in + CT_require + (ct_impexp, ct_spec, id, CT_coerce_STRING_to_STRING_OPT filename) + | "SYNTAX", ((Varg_ident phylum) :: ((Varg_ident s) :: (x :: (y :: l)))) -> + xlate_error "SYNTAX not implemented" + | (*Two versions of the syntax node with and without the binder list. *) + (*Need to update the metal file and ascent.mli first! + | ("SYNTAX", [Varg_ident phy; Varg_ident s; spatarg; unparg; blist]) -> + (syntaxop phy s spatarg unparg blist) + | ("SYNTAX", [Varg_ident phy; Varg_ident s; spatarg; unparg]) -> + (syntaxop phy s spatarg unparg + coerce_ID_OPT_to_FORMULA_OPT(CT_coerce_NONE_to_ID_OPT(CT_none)))*) + "TOKEN", ((Varg_string str) :: []) -> CT_token str + | "INFIX", + ((Varg_ast (CT_coerce_ID_OR_STRING_to_AST + (CT_coerce_STRING_to_ID_OR_STRING + (CT_string str_assoc)))) :: + ((Varg_int n) :: ((Varg_string str) :: ((Varg_ident id) :: [])))) -> + CT_infix ( + (match str_assoc with + | "LEFTA" -> CT_lefta + | "RIGHTA" -> CT_righta + | "NONA" -> CT_nona + | "NONE" -> CT_coerce_NONE_to_ASSOC CT_none + | _ -> xlate_error "infix1"), n, str, id) + | "GRAMMAR", (ge :: []) -> xlate_error "GRAMMAR not implemented" + | "SETUNDO", ((Varg_int n) :: []) -> CT_setundo n + | "UNSETUNDO", [] -> CT_unsetundo + | "SETHYPSLIMIT", ((Varg_int n) :: []) -> CT_sethyp n + | "UNSETHYPSLIMIT", [] -> CT_unsethyp + | "COERCION", + ((Varg_string s) :: + ((Varg_string (CT_string str)) :: + ((Varg_ident id1) :: ((Varg_ident id2) :: ((Varg_ident id3) :: []))))) -> + let id_opt = + match str with + | "IDENTITY" -> CT_identity + | "" -> CT_coerce_NONE_to_IDENTITY_OPT CT_none + | _ -> xlate_error "unknown flag for a coercion" in + let local_opt = + match str with + | "LOCAL" -> CT_local + | "" -> CT_coerce_NONE_to_LOCAL_OPT CT_none + | _ -> xlate_error "unknown flag for a coercion" in + CT_coercion (local_opt, id_opt, id1, id2, id3) + | "CLASS", (_ :: ((Varg_ident id1) :: [])) -> CT_class id1 + | "PrintGRAPH", [] -> CT_print_graph + | "PrintCLASSES", [] -> CT_print_classes + | "PrintCOERCIONS", [] -> CT_print_coercions + | "PrintPATH", ((Varg_ident id1) :: ((Varg_ident id2) :: [])) -> + CT_print_path (id1, id2) + | "SelectLanguageText", ((Varg_ident id) :: []) -> CT_set_natural id + | "PrintText", ((Varg_ident id) :: []) -> CT_print_natural id + | "AddTextParamOmit", ((Varg_ident id) :: []) -> + CT_add_natural_feature (CT_implicit, id) + | "MemTextParamOmit", ((Varg_ident id) :: []) -> + CT_test_natural_feature (CT_implicit, id) + | "RemoveTextParamOmit", ((Varg_ident id) :: []) -> + CT_remove_natural_feature (CT_implicit, id) + | "PrintTextParamOmit", [] -> CT_print_natural_feature CT_implicit + | "AddTextParamRecSub", ((Varg_ident id) :: []) -> + CT_add_natural_feature (CT_contractible, id) + | "MemTextParamRecSub", ((Varg_ident id) :: []) -> + CT_test_natural_feature (CT_contractible, id) + | "RemoveTextParamRecSub", ((Varg_ident id) :: []) -> + CT_remove_natural_feature (CT_contractible, id) + | "PrintTextParamRecSub", [] -> CT_print_natural_feature CT_contractible + | "AddTextParamImmediate", ((Varg_ident id) :: []) -> + CT_add_natural_feature (CT_nat_transparent, id) + | "MemTextParamImmediate", ((Varg_ident id) :: []) -> + CT_test_natural_feature (CT_nat_transparent, id) + | "RemoveTextParamImmediate", ((Varg_ident id) :: []) -> + CT_remove_natural_feature (CT_nat_transparent, id) + | "PrintTextParamImmediate", [] -> + CT_print_natural_feature CT_nat_transparent + | "ResetName", ((Varg_ident id) :: []) -> CT_reset id + | "ResetSection", ((Varg_ident id) :: []) -> CT_reset_section id + | "ResetInitial", [] -> CT_restore_state (CT_ident "Initial") + | "OmegaFlag", ((Varg_string (CT_string s)) :: []) -> + let fst_code = code (get s 0) in + let + set_or_unset, tail = + if fst_code = code_plus then (CT_set, sub s 1 (length s - 1)) + else if fst_code = code_minus then (CT_unset, sub s 1 (length s - 1)) + else (CT_switch, s) in + (match tail with + | "time" -> CT_omega_flag (set_or_unset, CT_flag_time) + | "action" -> CT_omega_flag (set_or_unset, CT_flag_action) + | "system" -> CT_omega_flag (set_or_unset, CT_flag_system) + | _ -> + CT_omega_flag + (set_or_unset, CT_coerce_STRING_to_OMEGA_FEATURE (CT_string s))) + | s, l -> + CT_user_vernac + (CT_ident s, CT_varg_list (List.map coerce_iVARG_to_VARG l))) + | _ -> xlate_error "xlate_vernac";; + +let xlate_vernac_list = + function + | Node (_, "vernac_list", (v :: l)) -> + CT_command_list (xlate_vernac v, List.map xlate_vernac l) + | _ -> xlate_error "xlate_command_list";; |
