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

[do not merge] semantics-refactor #14

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

samuelgruetter
Copy link
Contributor

creating a PR, hoping that it will let me comment on several commits at a time...

Fixpoint eval_expr(st: state)(e: expr): option (word wXLEN) :=
Set Universe Polymorphism.
Unset Universe Minimization ToSet.
(* TODO: should we do this?
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do these two lines do, and why do you need it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-universe-polymorphic definitions are depraceted, we use polymorphic ones. Universe Minimization ToSet is a backwards compatability mode for that.
Primitive Projections means that you never need to destruct records to get something to typecheck.

| Some x => f
| None => None
end)
(right associativity, at level 60, x pattern).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this a local notation? Couldn't you put this into a library file?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could, but I don't want to have the readers of the semantics guessing what <- means in this particular context.

Local Notation interp_cont := Imp.(_interp_cont).

(* TODO: record ImpParametersOK *)
Context {mword_eq_dec : DecidableRel (@eq (Imp.varname p))}.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would you separate ImpParameters and ImpParametersOk?
Why don't you use DecidableEq?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separete to allow for parallel compilation of proofs (and in other use cases, reification of the code that doesn't have proofs in it).

end.

Context {set_varname: Type}.
Context {varset: set set_varname varname}.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these two go into ImpParameters too?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it is not necessary for defining the semantics of the language.

Record ImpParameters :=
{
mword : Type;
mword_nonzero : mword -> bool;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

abstracting over the word type to hide the dependent type is nice, I meant to do this for a while already

Local Inductive cont : Type :=
| CSuspended(_:T)
| CSeq(s1:cont) (s2: stmt)
| CStack(st: varmap)(c: cont)(binds rets: list varname).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the meaning of these 3 cases?
How much do we commit to by putting this into the semantics?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in the refactor PR by accident, let's discuss it separately from the actual refactor.


Section WithFunctions.
Context (lookupFunction : funname -> option (list varname * list varname * stmt)).
Local Fixpoint interp_stmt(f: nat)(st: varmap)(m: mem)(s: stmt): option (varmap*mem*option(cont ioact)) :=
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to instantiate ioact with something "empty" such that the existing proofs will still go through?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep.

_interp_stmt : forall (lookupFunction : funname -> option (list varname * list varname * stmt))(f: nat)(st: varmap)(m: mem)(s: stmt), option (varmap*mem*option(cont ioact));
_interp_cont : forall (lookupFunction : funname -> option (list varname * list varname * stmt))(f: nat)(st: varmap)(m: mem)(s: cont ioret), option (varmap*mem*option(cont ioact));
}.
Definition Imp : ImpType := Build_ImpType expr stmt cont interp_expr interp_stmt interp_cont.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yet another level of wrapping and indirection 😉 -- why is this needed?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No indirection here, just exporting. In Ocaml this would be in an mli file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, it is more than exporting. Not making a record of these definitions would mean that the parameters record would be duplicated for each definition in Imp. I think https://people.csail.mit.edu/jgross/personal-website/papers/category-coq-experience-itp-submission.pdf explains how that results in sadness and slowness.

Imp.varmap_operations := p.(varmap_operations);
|}.
Definition RISCVImp (p:RISCVImpParameters) : Imp.ImpType (ImpParameters_of_RISCVImpParameters p)
:= Imp.Imp (ImpParameters_of_RISCVImpParameters p).
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By making the right typeclass instances into available, you'd get this for free...

] in
fun bw varname funnname actname varmap varmap_operations =>
RISCVImp (Build_RISCVImpParameters bw varname funnname actname varmap varmap_operations).
*)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks suspicious, I guess you'll need it at some point... Will you have to do this to make sure "rewrite" finds matching terms? And is there a risk that the typechecker isn't happy unless you destruct a parameters record?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We won't need it, it was just a test. If record destruction would become an issue we could just turn on primitive projections for that record.

{ set_solver. }
{ set_solver. }
{ apply singleton_set_spec in H. auto. }
{ apply union_spec in H.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, why do you prefer { over bullets?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because brackets for one goal do not force the choice of delimiters for other goals. Here I can write 1,2: in the last case.

@andres-erbsen
Copy link
Contributor

I am not happy with the boilerplate either. But what else would we do? Using the module system would have less boilerplate but the boilerplate would be more arcane; using typeclasses breaks typechecking errors and this type-driven development in most cases where I have seen it used, and often tactics end up being sensitive to syntactic details of typeclass inference output (I had to change some tactics here because of that).

@andres-erbsen
Copy link
Contributor

Full version with desugaring of modules into records at source level: https://github.com/mit-plv/bedrock2/tree/refactor-even-more-boilerplate
Stuck attempt using the old module system: https://github.com/mit-plv/bedrock2/tree/modules-boilerplate

@andres-erbsen
Copy link
Contributor

andres-erbsen commented Jun 22, 2018

The remaining boilerplate could be removed using these two changes:

  1. removing ExprImpInterface gets rid of some boilerplate at the cost of not being able to pass around all Imp definitions as one unit and at the further cost of multiplicative blowup if for each additional parameter next to ImpParameters (as opposed to inside of it). Currently we don't do either anywhere.
  2. replacing ahead-of-time RecordImport (or after (1), manual specialization of individual functions) with time-of-use typeclass resolution gets rid of the python-generated RecordImport boilerplate, at the cost of less predictable typechecking (especially errors, see debugging typeclass resolution in semantics #9).

If both are applied, we get https://github.com/mit-plv/bedrock2/tree/typeclasses-without-functors

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

Successfully merging this pull request may close these issues.

None yet

2 participants