-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
A monad for programming with template-coq operations #37
base: coq-8.5
Are you sure you want to change the base?
Conversation
Just created a new vernac command "Make Inductive". As of now, it does nothing. Tested the dummy command in demo.v
The body is ignored for now. Tested this part in demo.v
The name and arity are obtained properly populated. However the resultant definition changes arity from Set to Prop.
Found the correct input by snooping on the paramcoq plugin (using coq/dev/top_printer.ml) Also, needed to recompile coq so that top_printer.ml gets included in coqtop/coqc: coq/dev$ echo "Top_printer" > printer.mllib then add dev/printer.cma to $CORECMA in coq/Makefile.common
However, it is not clear how to access the body of a definition.
The case when the name is an inductive declaration is not handled yet
Many fields are currently dummy and not properly quoted. Also, the quote operations fails on fixpoints
…ote) Suddently, quoting Nat.add works now, perhaps because now I use the Names.constant returned by Nametab.locate, instead of manually cooking up something.
Thus, we can now make definitions after quoting and hence achieve the functionality of "Quote (Recursively) Definition .. :="
In some programs, the strings may not be in normal form.
This fixes a previous bug where unqupoting constants in modules inside files failed. As a side benefit, because of Locate, the names in tConst need not be fully qualified
@aa755 What is the current status of this? Is it ready to review or are there more things that you are looking at? |
The quoting operation here is beginning to look a lot more involved than I thought that it would. There also seems to be a lot of overlap with MetaCoq in terms of implementation and operation (the reification plugin in MirrorCore also works in a similar way). I'm wondering if some of this functionality should be merged into that project. |
Thanks for those pointers. Indeed, now I notice that some operations overlap with MetaCoq. I thought MetaCoq's monad was mainly for ltac-style proof automation, whereas I am mainly interested in program transformations. I will sometime take a closer look at MetaCoq and MirrorCore. I currently don't plan to add any more operations to the monad in this PR. It seems that the current operations suffice for my project. The only thing that I am missing now is the ability to properly reify and reflect universes. |
(** A monad for programming with template-coq operations. | ||
Using this monad, it should be possible to write many plugins (e.g. paramcoq) | ||
in Gallina *) | ||
Inductive TemplateMonad : Type -> Type := |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems like it should go in a separate file.
To actually make the definition, use (tmMkDefinition false) *) | ||
| tmQuoteTerm : forall {A:Type}, A -> TemplateMonad term | ||
(** similar to Quote Recursively Definition ... := ...*) | ||
| tmQuoteTermRec : forall {A:Type}, A -> TemplateMonad program |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like we could implement tmQuoteTermRec
in terms of tmQuoteTerm
and maybe some sort of fixpoint combinator. That seems like it would be simpler to implement.
(** FIXME: strategy is currently ignored in the implementation -- it does all reductions.*) | ||
| tmReduce : reductionStrategy -> forall {A:Type}, A -> TemplateMonad A | ||
| tmMkDefinition : bool (* unquote? *) -> ident -> forall {A:Type}, A -> TemplateMonad unit (* bool indicating success? *) | ||
| tmMkInductive : mutual_inductive_entry -> TemplateMonad unit (* bool indicating success? *) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these generated as side-effects immediately or are the aggregated and then applied atomically at the end?
| tmPrint : forall {A:Type}, A -> TemplateMonad unit | ||
(** Quote the body of a definition or inductive. Its name need not be fully qualified -- | ||
the implementation uses Locate *) | ||
| tmQuote : ident -> bool (** bypass opacity?*)-> TemplateMonad (option (term+mutual_inductive_entry)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why quote identifiers and not terms? It seems like we could have two operations: quoteTerm
and getBody
/unfold
that performs delta
reduction. Those would provide for simpler primitives.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are going to use Locate
here, maybe we should export it? e.g.
tmLocate : ident -> TemplateMonad (option ident)
or maybe even separate the module name and return something like list ident * ident
(** A monad for programming with template-coq operations. | ||
Using this monad, it should be possible to write many plugins (e.g. paramcoq) | ||
in Gallina *) | ||
Inductive TemplateMonad : Type -> Type := |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Universes might become an issue with this. In MetaCoq (and MirrorCore) the monad is defined as a Prop
to avoid universe issues (though I'm not convinced that it works at all).
@@ -724,6 +911,58 @@ struct | |||
Command.declare_mutual_inductive_with_eliminations (mut_ind mr mf mp mi mpol mpr) [] [];() | |||
| _ -> raise (Failure "ill-typed mutual_inductive_entry") | |||
|
|||
let rec run_template_program_rec ((env,evm,pgm): Environ.env * Evd.evar_map * Term.constr) : Environ.env * Evd.evar_map * Term.constr = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be implemented in a separate file.
@@ -97,3 +97,37 @@ Record mutual_inductive_entry : Set := { | |||
(* mind_entry_universes : Univ.universe_context; *) | |||
mind_entry_private : option bool | |||
}. | |||
|
|||
Inductive reductionStrategy : Set := | |||
cbv | cbn | hnf | all. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not expose the flags?
if Term.eq_constr coConstr tmReturn then | ||
match args with | ||
| _::h::[] -> (env,evm,h) | ||
| _ -> raise (Failure "tmReturn must take 2 arguments. Please file a bug with Template-Coq.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to unify these error messages. Something like:
raise (BadCommand pgm)
where pgm
is the TemplateMonad
. At the toplevel, we can print it out.
| _(*reduction strategy*)::_(*type*)::trm::[] -> | ||
let (evm,trm) = reduce_all env (evm,trm) in (env, evm, trm) | ||
| _ -> raise (Failure "tmReduce must take 3 arguments. Please file a bug with Template-Coq.") | ||
else raise (Failure "Invalid argument or yot yet implemented. The argument must be a TemplateProgram") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like TemplateProgram
better than TemplateMonad
, but we should at least be consistent.
|
||
let run_template_program (env: Environ.env) (evm: Evd.evar_map) (body: Constrexpr.constr_expr) : unit = | ||
let (body,_) = Constrintern.interp_constr env evm body in | ||
let _ = run_template_program_rec (env,evm,body) in () |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should check the type here? That might produce a better error message than delaying it until we get into the interpreter.
where they where pushed to the environment in the correct order.
@aa755 Do you mind if I write a PR on top of this with a few cosmetic changes? |
Feel free to use the code here in any way you wish. I agree with all the changes you suggested -- thanks. However, I have been very busy lately because of some deadlines. It may take me a while to address all those changes. |
Completely understandable given the time of year. |
See Ast.TemplateMonad and some example programs in demo.v
There are 2 more enhancements/fixes:
Ast.tmQuote
) for quoting inductives (fixes It would be nice if inductives stored their types #17).denote_term
function unquotes constants and fixpoints as well.