Closed anshumanmohan closed 4 months ago
I'm kinda down to the wire with this comment before we meet synchronously, but I just wanted to write that this is exactly right! That is, the "normal" way to do this (and the clearly correct one, IMO) is to have assignments be a "top-level" construct that cannot appear in more deeply nested expressions.
@anshumanmohan's proposal is:
type program = Prog of declare * statement
Which is 100% cool. But another way to flatten it out is:
type program = Prog of declare * (statement list) * return
That is, eliminating the Seq
constructor in favor of a flat list, and making sure that there is exactly one return
(it does not make sense for there to be more than one). But this is a small difference and either can work.
Our DSL is coming along nicely (see #25) but I have requested @csziklai to drop the assignment operator from there. I think it's a little subtle, so here's a little discussion of how it may need to be done.
The Issue
The existing attempt is:
And I presume the grand finale will be
This looks close, but I think assignments cannot be a policy-constructor in quite that way. Here's the issue. We want the user to be able to write:
but I think the AST above will force the user to write:
or something like that. This is because assignments are trying to hang around as policies, and simply stating a variable's name (like we'd need to do, to get
return RR(p, C)
to work) is not currently a legal policy.The Fix
I actually think that
policy
needs a constructor that is just a variable, like so:and we need a separate type for assignments:
Now we need a slightly higher-order thing that lets these two things intermix. I define a statement to be either an assignment, or a sequence, or a return. The
return
constructor will return a policy.Note, putting sequences and returns into
policy
will again pose an issue I think! I think those need to operate on statements so that they can intermix policies and assignments.And finally a program is:
Usage
Now the user needs to use this AST correctly. If they have:
then we should give up because
q
is undefined.But I think this is no different than other forms of checking that the user behaved correctly. For instance, we also need to give up in case the user did not end with a return statement.