Skip to content
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

Open
wants to merge 51 commits into
base: coq-8.5
Choose a base branch
from

Conversation

aa755
Copy link

@aa755 aa755 commented Dec 24, 2016

See Ast.TemplateMonad and some example programs in demo.v
There are 2 more enhancements/fixes:

  1. This monad has a more informative quote function (Ast.tmQuote) for quoting inductives (fixes It would be nice if inductives stored their types #17).
  2. Now, the denote_term function unquotes constants and fixpoints as well.

aa755 added 30 commits November 14, 2016 23:33
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.
aa755 added 11 commits December 14, 2016 08:44
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 aa755 changed the title A monad for programming with template coq operations A monad for programming with template-coq operations Dec 24, 2016
@gmalecha
Copy link
Owner

gmalecha commented Jan 1, 2017

@aa755 What is the current status of this? Is it ready to review or are there more things that you are looking at?

@gmalecha
Copy link
Owner

gmalecha commented Jan 1, 2017

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.

@aa755
Copy link
Author

aa755 commented Jan 1, 2017

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 :=
Copy link
Owner

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
Copy link
Owner

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? *)
Copy link
Owner

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))
Copy link
Owner

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.

Copy link
Owner

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 :=
Copy link
Owner

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 =
Copy link
Owner

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.
Copy link
Owner

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.")
Copy link
Owner

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")
Copy link
Owner

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 ()
Copy link
Owner

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.

@gmalecha
Copy link
Owner

gmalecha commented Jan 4, 2017

@aa755 Do you mind if I write a PR on top of this with a few cosmetic changes?

@aa755
Copy link
Author

aa755 commented Jan 4, 2017

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.

@gmalecha
Copy link
Owner

gmalecha commented Jan 4, 2017

Completely understandable given the time of year.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants