123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331(************************************************************************)(* coq-layout-engine *)(* Copyright 2021 Inria *)(* Written by Emilio J. Gallego Arias *)(************************************************************************)(* Status: Very Experimental *)(************************************************************************)(* typrinter *)(* introduce an unparsing monad *)openCAstopenConstrexpr(** notes with the discussion with Hugo:
- there are two kinds of information that the printer can know:
+ parsing-level: this includes notations, implicit arities, etc...
+ semantic-level: only after typchecking has run! For example coertions!
- how to remember for example the type of a sub-expression:
The expression goes from Ast.t to Term.t, then goes back to Ast.t for
printing.
+ doing it for all types, it is too expensive + doing it for some, requires
a way to specify which
+ an interesting idea is to attach all the possible requests over the
structure of a term in the term itself once it has been recosntructed from
the typing phase
- continuation maybe a meeting with Clement and Shachar? *)moduleBM=BoxModelletxxxstr=BoxModel.Constant("FIXME: "^str)letly_prim_tokenptok=matchptokwith|Numbere->BM.Constant(NumTok.Signed.sprinte)|Stringa->BM.Constantaletly_sort_name_expr(s:sort_name_expr)=matchswith|CSProp->"SProp"|CProp->"Prop"|CSet->"Set"|CType_qid->"Type"|CRawType_ulvl->"Type"(* FIXME: _i *)letly_named_sort((s,_i):sort_name_expr*int)=ly_sort_name_exprsletly_sort(s:sort_expr)=let_qv_expr,s=sinmatchswith|Glob_term.UAnonymous{rigid}->(* XXX: What's going on here *)ifrigid==UnivRigidthenBM.Sort["Type"]elseBM.Sort["Type"]|Glob_term.UNamedsl->BM.Sort(List.maply_named_sortsl)type_cast_kind=|VMcast|NATIVEcast|DEFAULTcastletly_cast_kind(s:Constr.cast_kind)=matchswith|VMcast->xxx"VMcast"|NATIVEcast->xxx"NATIVEcast"|DEFAULTcast->xxx"DEFAULTcast"letly_qualid{Coq_util.Id.relative;absolute;typ}=letrelative=Libnames.string_of_qualidrelativeinletabsolute=Option.mapLibnames.string_of_pathabsoluteinBoxModel.Identifier{relative;absolute;typ}letly_fixexpr_=BoxModel.Constant"TODO"letly_cofixexpr_=BoxModel.Constant"TODO"(* instance_expr = univ_level_expr list *)letly_instance_expr(_e:instance_expr)=[][@@@ocaml.warning"-26-27"]letabs_kind_of(t:constr_expr)=matcht.CAst.vwith|CProdN_->BoxModel.Prod|CLambdaN_->BoxModel.Lam|_->BoxModel.Lam(* XXX *)let_debug=reffalseletenv=refEnviron.empty_envletsigma=refEvd.emptyletrecly_hunksunpargsbl=letopenPpextendinmatchunpwith|[]->[]|UnpMetaVar_::l->letla=List.hdargsinletlr=ly_hunksl(List.tlargs)blinla::lr|UnpTerminals::l->BM.Constants::ly_hunkslargsbl|UnpBox(_,l1)::l->letl1=List.map(fun(_,l)->l)l1inly_hunks(l1@l)argsbl|(UnpCut_asunp)::l->ly_hunkslargsbl|UnpBinderMetaVar(ntn_entry_r_lvl,_pquote_style)::l->letkind=BM.Laminlet{notation_subentry;_}=ntn_entry_r_lvlinletb,bl=(List.hdbl,List.tlbl)inletname=Ppconstr.pr_cases_pattern_expr(fstb)|>Pp.string_of_ppcmdsinlettyp=Noneinletb_var=BM.Variable{name;typ}inb_var::ly_hunkslargsbl(* We'd like to introduce a binder here, kind of...? Maybe it is better to
support that in the notation box natively *)(* [ Abs { kind; binderl; v } ] *)|UnpListMetaVar(_ntn_entry_r_lvl,_upl)::l->[xxx"UnpListMetaVar"]|UnpBinderListMetaVar(_open_binder,_quote_print,_upl)::l->[xxx"UnpListMetaVar"](* | _ -> [ xxx "not_printer" ] *)letlname_to_string=CAst.with_val(function|Names.Anonymous->"_"|Names.Nameid->Names.Id.to_stringid)letly_notationkeyargs=let{Ppextend.notation_printing_unparsing;notation_printing_level}=Ppextend.find_notation_printing_ruleNonekeyinly_hunksnotation_printing_unparsingargsletrecly_qidqid=letid_info=Coq_util.Id.makeqidinletid_info=Coq_util.Id.map_typ~f:layoutid_infoinly_qualidid_infoandly_idid=ly_qid(Libnames.qualid_of_identid)andly_lid(lid:Names.lident)=ly_idlid.vandly_lname(lid:Names.lname)=matchlid.vwith|Names.Anonymous->xxx"name.anonymous"|Names.Nameid->ly_ididandly_binder_expr(b:local_binder_expr)=matchbwith|CLocalAssum(namel,_relevance_info,kind,pat)->letnamel=List.maplname_to_stringnamelin{BM.Binder.namel;typ=layoutpat}|CLocalDef(name,_relevance_info,pat,pat_tyo)->{BM.Binder.namel=["XXX localdef"];typ=layoutpat}|CLocalPatternpat->{BM.Binder.namel=["XXX localpat"];typ=xxx"local pat"}andlayoutt=if!_debugthenFeedback.msg_warningPp.(str"ly [->]: "++Ppconstr.pr_constr_expr!env!sigmat);letres=matcht.CAst.vwith(* | CRef of qualid * instance_expr option *)|CRef(qid,iexp)->let_=Option.maply_instance_expriexpinly_qidqid(* | CFix of lident * fix_expr list *)|CFix(lid,fixexpr)->BoxModel.Fixpoint(ly_lidlid,ly_fixexprfixexpr)(* | CCoFix of lident * cofix_expr list *)|CCoFix(lid,cofixexpr)->BoxModel.Fixpoint(ly_lidlid,ly_cofixexprcofixexpr)(* | CProdN of local_binder_expr list * constr_expr *)(* | CLambdaN of local_binder_expr list * constr_expr *)|CProdN(bds,inner)|CLambdaN(bds,inner)->letkind=abs_kind_oftinletbinderl=List.maply_binder_exprbdsinBoxModel.Abs{kind;binderl;v=layoutinner}(* | CLetIn of lname * constr_expr * constr_expr option * constr_expr *)|CLetIn(name,e,tyo,ty)->letlhs=ly_lnamenameinletrhs=layouteinlettyp=Option.maplayouttyoinBoxModel.Let{lhs;rhs;typ;v=layoutty}(* | CAppExpl of (proj_flag * qualid * instance_expr option) * constr_expr
list *)|CAppExpl((fn,ioexp),argl)->letimpl=[]inletargl=List.maplayoutarglinletfn=ly_qidfninBoxModel.App{fn;impl;argl}(* | CApp of (proj_flag * constr_expr) *
* (constr_expr * explicitation CAst.t option) list *)|CApp(fn,argl)->letimpl=[]inletargl=List.map(fun(e,_)->layoute)arglinBoxModel.App{fn=layoutfn;impl;argl}|CProj_->xxx"proj"(* | CRecord of (qualid * constr_expr) list *)|CRecordfl->xxx"record"(* representation of the "let" and "match" constructs *)(* | CCases of Constr.case_style (\* determines whether this value represents "let" or "match" construct *\)
* * constr_expr option (\* return-clause *\)
* * case_expr list
* * branch_expr list (\* branches *\) *)|CCases(sty,rtyo,brl,el)->xxx"cases"(* | CLetTuple of lname list * (lname option * constr_expr option) *
* constr_expr * constr_expr *)|CLetTuple(nl,(no,eo),e1,e2)->xxx"lettuple"(* | CIf of constr_expr * (lname option * constr_expr option)
* * constr_expr * constr_expr *)|CIf(cond,_,et,ef)->xxx"if"(* | CHole of Evar_kinds.glob_evar_kind option *)|CHole_->xxx"hole"(* | CPatVar of Pattern.patvar *)|CPatVarpat->xxx"patvar"(* | CEvar of Glob_term.existential_name CAst.t * (lident * constr_expr)
list *)|CEvar(ename,ctx)->xxx"evar"(* | CSort of sort_expr *)|CSorts->ly_sorts(* | CCast of constr_expr * Constr.cast_kind * constr_expr *)|CCast(e,cast_kind,cast)->letp_c=Option.maply_cast_kindcast_kindinletp_e=layouteinCast(p_c,p_e)(* | CNotation of notation_with_optional_scope option * notation *
constr_notation_substitution *)|CNotation(oscope,ntn,ntn_subst)->letntn_entry,key=ntninletargs,_,bl,_bll=ntn_substinletargs=List.maplayoutargsinletpretty=ly_notation(ntn_entry,key)argsblinletraw=Coq_util.notation_raw!env!sigmat|>Option.catalayout(xxx"raw notation failed [binders usually]")inNotation{key;args;pretty;raw}(* ntn_subst is:
constr_expr list * (* for constr subterms *)
constr_expr list list * (* for recursive notations *)
kinded_cases_pattern_expr list * (* for binders *)
local_binder_expr list list (* for binder lists (recursive notations) *)
*)(* Unparsing for "_ + _":
(UnpBox
(PpHOVB 0)
((() (UnpMetaVar (LevelLe 50) (Left)))
(() (UnpTerminal " +"))
(() (UnpCut (PpBrk 1 0)))
(() (UnpMetaVar (LevelLt 50) (Right))))))
Unparsing for "_ = _":
(UnpBox
(PpHOVB 0)
((() (UnpMetaVar (LevelLt 70) (Left)))
(() (UnpTerminal " ="))
(() (UnpCut (PpBrk 1 0)))
(() (UnpMetaVar (LevelLt 70) (Right)))))
Unparsing for "_ -> _":
(UnpBox
(PpHOVB 0)
((() (UnpMetaVar (LevelLt 99) (Left)))
(() (UnpTerminal " ->"))
(() (UnpCut (PpBrk 1 0)))
(() (UnpMetaVar (LevelLe 200) ()))))
(Query () (Unparsing "exists2 _ : _ , _ & _"))
(UnpBox
(PpHOVB 0)
((() (UnpTerminal "exists2"))
(() (UnpCut (PpBrk 1 2)))
(() (UnpBinderMetaVar LevelSome NotQuotedPattern))
(() (UnpTerminal " "))
(() (UnpTerminal ":"))
(() (UnpTerminal " "))
(() (UnpMetaVar (LevelLe 200) ()))
(() (UnpTerminal ","))
(() (UnpCut (PpBrk 1 2)))
(()
(UnpBox
(PpHOVB 0)
((() (UnpMetaVar (LevelLe 200) ()))
(() (UnpTerminal " "))
(() (UnpTerminal "&"))
(() (UnpCut (PpBrk 1 0)))
(() (UnpMetaVar (LevelLe 200) (Right))))))))
*)[@ocamlformat"disable"](* | CGeneralization of Glob_term.binding_kind * abstraction_kind option *
constr_expr *)|CGeneralization_->xxx"generalization"(* | CPrim of prim_token *)|CPrimptok->ly_prim_tokenptok(* | CDelimiters of delimiter_depth * string * constr_expr *)|CDelimiters(_depth,delim,e)->xxx"delimiters"(* | CArray of instance_expr option * constr_expr array * constr_expr *
constr_expr *)|CArray(univs,el,eu,ea)->xxx"array"|CGenarg_->xxx"genarg"|CGenargGlob_->xxx"genargglob"inif!_debugthenFeedback.msg_warningPp.(str"ly [<-]: "++Ppconstr.pr_constr_expr!env!sigmat);resletlayout?(debug=false)est=_debug:=debug;env:=e;sigma:=s;layoutt