| Some term -> Some (k term)
and aux_capture_variable (term, typ_opt) = k term, aux_opt typ_opt
and aux_patterns patterns = List.map aux_pattern patterns
- and aux_pattern ((head, hrefs, vars), term) =
- ((head, hrefs, List.map aux_capture_variable vars), k term)
+ and aux_pattern =
+ function
+ Ast.Pattern (head, hrefs, vars), term ->
+ Ast.Pattern (head, hrefs, List.map aux_capture_variable vars), k term
+ | Ast.Wildcard, term -> Ast.Wildcard, k term
and aux_subst (name, term) = (name, k term)
and aux_substs substs = List.map aux_subst substs
in
and aux_branch (pattern, term) =
aux_pattern pattern ;
aux term
- and aux_pattern (head, _, vars) =
- List.iter aux_capture_var vars
+ and aux_pattern =
+ function
+ Ast.Pattern (head, _, vars) -> List.iter aux_capture_var vars
+ | Ast.Wildcard -> ()
and aux_definition (params, var, term, decrno) =
List.iter aux_capture_var params ;
aux_capture_var var ;
let cic_term = aux ~localize loc context term in
let cic_outtype = aux_option ~localize loc context None outtype in
let do_branch ((head, _, args), term) =
- let rec do_branch' context = function
- | [] -> aux ~localize loc context term
- | (name, typ) :: tl ->
- let cic_name = CicNotationUtil.cic_name_of_name name in
- let cic_body = do_branch' (cic_name :: context) tl in
- let typ =
- match typ with
- | None -> Cic.Implicit (Some `Type)
- | Some typ -> aux ~localize loc context typ
- in
- Cic.Lambda (cic_name, typ, cic_body)
- in
+ let rec do_branch' context = function
+ | [] -> aux ~localize loc context term
+ | (name, typ) :: tl ->
+ let cic_name = CicNotationUtil.cic_name_of_name name in
+ let cic_body = do_branch' (cic_name :: context) tl in
+ let typ =
+ match typ with
+ | None -> Cic.Implicit (Some `Type)
+ | Some typ -> aux ~localize loc context typ
+ in
+ Cic.Lambda (cic_name, typ, cic_body)
+ in
do_branch' context args
in
let indtype_uri, indtype_no =
| _ ->
raise (Invalid_choice (Some loc, lazy "The type of the term to be matched is not (co)inductive!")))
| None ->
- let fst_constructor =
- match branches with
- | ((head, _, _), _) :: _ -> head
- | [] -> raise (Invalid_choice (Some loc, lazy "The type of the term to be matched is an inductive type without constructors that cannot be determined"))
+ let rec fst_constructor =
+ function
+ (Ast.Pattern (head, _, _), _) :: _ -> head
+ | (Ast.Wildcard, _) :: tl -> fst_constructor tl
+ | [] -> raise (Invalid_choice (Some loc, lazy "The type of the term to be matched cannot be determined because it is an inductive type without constructors or because all patterns use wildcards"))
in
- (match resolve env (Id fst_constructor) () with
+ (match resolve env (Id (fst_constructor branches)) () with
| Cic.MutConstruct (indtype_uri, indtype_no, _, _) ->
(indtype_uri, indtype_no)
| Cic.Implicit _ ->
let rec sort branches cl =
match cl with
[] ->
- if branches = [] then []
- else
- raise (Invalid_choice
- (Some loc,
- lazy
- ("Unrecognized constructors: " ^
- String.concat " "
- (List.map (fun ((head,_,_),_) -> head) branches))))
+ let rec analyze unused unrecognized useless =
+ function
+ [] ->
+ if unrecognized != [] then
+ raise (Invalid_choice
+ (Some loc,
+ lazy
+ ("Unrecognized constructors: " ^
+ String.concat " " unrecognized)))
+ else if useless > 0 then
+ raise (Invalid_choice
+ (Some loc,
+ lazy
+ ("The last " ^ string_of_int useless ^
+ "case" ^ if useless > 1 then "s are" else " is" ^
+ " unused")))
+ else
+ []
+ | (Ast.Wildcard,_)::tl when not unused ->
+ analyze true unrecognized useless tl
+ | (Ast.Pattern (head,_,_),_)::tl when not unused ->
+ analyze unused (head::unrecognized) useless tl
+ | _::tl -> analyze unused unrecognized (useless + 1) tl
+ in
+ analyze false [] 0 branches
| (name,ty)::cltl ->
let rec find_and_remove =
function
raise
(Invalid_choice
(Some loc, lazy ("Missing case: " ^ name)))
- | ((name',_,_),_) as branch :: tl when name = name' ->
- branch,tl
+ | ((Ast.Wildcard, _) as branch :: _) as branches ->
+ branch, branches
+ | (Ast.Pattern (name',_,_),_) as branch :: tl
+ when name = name' ->
+ branch,tl
| branch::tl ->
let found,rest = find_and_remove tl in
found, branch::rest
in
let branch,tl = find_and_remove branches in
- let (_,_,args),_ = branch in
- if List.length args = count_prod ty - leftsno then
- branch::sort tl cltl
- else
- raise
- (Invalid_choice
- (Some loc,
- lazy ("Wrong number of arguments for " ^ name)))
+ match branch with
+ Ast.Pattern (name,y,args),term ->
+ if List.length args = count_prod ty - leftsno then
+ ((name,y,args),term)::sort tl cltl
+ else
+ raise
+ (Invalid_choice
+ (Some loc,
+ lazy ("Wrong number of arguments for " ^ name)))
+ | Ast.Wildcard,term ->
+ let rec mk_lambdas =
+ function
+ 0 -> term
+ | n ->
+ CicNotationPt.Binder
+ (`Lambda, (CicNotationPt.Ident ("_", None), None),
+ mk_lambdas (n - 1))
+ in
+ (("wildcard",None,[]),
+ mk_lambdas (count_prod ty - leftsno)) :: sort tl cltl
in
sort branches cl
| _ -> assert false
| Ast.Case (term, indty_ident, outtype, branches) ->
let term_dom = domain_of_term ~loc ~context term in
let outtype_dom = domain_of_term_option ~loc ~context outtype in
- let get_first_constructor = function
+ let rec get_first_constructor = function
| [] -> []
- | ((head, _, _), _) :: _ -> [ Node ([loc], Id head, []) ] in
- let do_branch ((head, _, args), term) =
- let (term_context, args_domain) =
- List.fold_left
- (fun (cont, dom) (name, typ) ->
- (CicNotationUtil.cic_name_of_name name :: cont,
- (match typ with
- | None -> dom
- | Some typ -> dom @ domain_of_term ~loc ~context:cont typ)))
- (context, []) args
- in
- domain_of_term ~loc ~context:term_context term @ args_domain
+ | (Ast.Pattern (head, _, _), _) :: _ -> [ Node ([loc], Id head, []) ]
+ | _ :: tl -> get_first_constructor tl in
+ let do_branch =
+ function
+ Ast.Pattern (head, _, args), term ->
+ let (term_context, args_domain) =
+ List.fold_left
+ (fun (cont, dom) (name, typ) ->
+ (CicNotationUtil.cic_name_of_name name :: cont,
+ (match typ with
+ | None -> dom
+ | Some typ -> dom @ domain_of_term ~loc ~context:cont typ)))
+ (context, []) args
+ in
+ domain_of_term ~loc ~context:term_context term @ args_domain
+ | Ast.Wildcard, term ->
+ domain_of_term ~loc ~context term
in
let branches_dom =
List.fold_left (fun dom branch -> dom @ do_branch branch) [] branches in
space
]
in
- let mk_case_pattern (head, href, vars) =
- hbox true false (ident_w_href href head :: List.map aux_var vars)
+ let mk_case_pattern =
+ function
+ Ast.Pattern (head, href, vars) ->
+ hbox true false (ident_w_href href head :: List.map aux_var vars)
+ | Ast.Wildcard -> builtin_symbol "_"
in
let patterns' =
List.map
and aux_capture_var env (name, ty_opt) = (aux env name, aux_opt env ty_opt)
and aux_branch env (pattern, term) =
(aux_pattern env pattern, aux env term)
- and aux_pattern env (head, hrefs, vars) =
- (head, hrefs, List.map (aux_capture_var env) vars)
+ and aux_pattern env =
+ function
+ Ast.Pattern (head, hrefs, vars) ->
+ Ast.Pattern (head, hrefs, List.map (aux_capture_var env) vars)
+ | Ast.Wildcard -> Ast.Wildcard
and aux_definition env (params, var, term, i) =
(List.map (aux_capture_var env) params, aux_capture_var env var, aux env term, i)
and aux_substs env substs =