-
Notifications
You must be signed in to change notification settings - Fork 9
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
Add renamer phase and a simala backend for natural4 #609
Conversation
Start documentation for the overall pipeline.
This was an attempt to use Tries for lexical scope checking. However, after talking a little bit more about this, we decided to change this a simpler implementation.
Scan the clauses of rules for variables they may have introduced. Rename in a separate step.
Adds Renamer results to `Interpreted` record.
0f0b1f9
to
d6b0b54
Compare
Some quick feedback: Renamer.hsHigh level things
Specific things
In case the above came off as being negative: Again, I think that this PR has been a truly heroic amount of work. |
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.
Looks good to me! Most of my comments are just minor remarks ("a comment rather than a question"). I thought the code was well documented, but of course, true test comes at the point when one starts trying to work with the code, not just passively look at it.
-- TODO: error handling, would we accept an enum such as `a IS ONE OF 1, 2, 3`? | ||
-- Only if we treat them as text, which might be confusing, as user might infer | ||
-- this to be some kind of type checked number 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.
I guess this could be used for things like number of children (e.g. < 100) or birth year (e.g. > 1900). Even in such cases, the validation would be given as a range rather than an enum. Probably the most practical question is, what kind of error messages we'd like to give if a user claims to be born in 1700: is it a type error, or just a runtime result "you're too old for insurance"?
(There's also the TYPICALLY keyword, but I don't know of its status in any of the various transpilers or previous case studies.)
renameLocalRules :: Tracer Log -> [Rule] -> Renamer [RnRule] | ||
renameLocalRules = renameRules |
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.
Is this meant to be replaced with something else later?
I'm asking, because earlier you wrote that GIVETH
s are global, GIVEN
s are local and DECIDE head term
in "IS" clauses is global. Is that the case in WHERE clauses as well? (Or am I mistaken about what renameRules
does?)
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.
So, in lexical scoping, we have a hierarchy of scopes. GIVETH
and DECIDE
are not "global", but their definitions may be used one level up the hierarchy. This generalises nicely, as rules in WHERE
can be used by DECIDE
and other rules in the WHERE
clause, but not outside the rule that defines the WHERE
clause.
For a practical example with nested clauses:
GIVEN x
DECIDE f x IS y
WHERE
y IS g x
GIVEN d DECIDE g d IS y WHERE y IS SUM(d, d)
- Then the rules
y IS g x
andGIVEN d DECIDE g d IS y WHERE y IS SUM(d, d)
is local to the rule and the functiong
may be used in bothWHERE
andDECIDE
blocks. y IS SUM(d,d)
is local to the ruleg
, and can not be referenced by the top-levelWHERE
orDECIDE
.y IS SUM(d,d)
name shadows the outery
.
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 see, thanks for the explanation!
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 is another tangential syntax thing, but it's not clear to me that we really should allow users the flexibility to write arbitrary declarations in a WHERE
block (as opposed to just things of the form y IS g x
. There's probably no easy way to answer this question right now, and it's definitely not high-priority, but I'd be curious to see what you all think.
-- TODO: this could be an expression such as "2+2" (for whatever reason), so perhaps | ||
-- we need to parse this further. Allegedly, we also want to support | ||
-- expressions nested into one csv-cell, for example: | ||
-- | ||
-- >>> MT "f x y" | ||
-- | ||
-- where 'f' is a function. | ||
-- We ignore this for now, though. |
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.
The question of what to support has always been a bit vague. If I remember correctly, arbitrary expressions in a single cell became an explicit thing around last spring, with these 4 test cases for (Generic)MathLang.
Simultaneously, we have been saying for many years "we can totally make NaturaL4 stricter and require the user to not just type in whatever". Maybe this could be a natural spot to make some decisions. 😛 @mengwong , any comments/opinions?
lib/haskell/natural4/src/LS/XPile/MathLang/GenericMathLang/TranslateL4.hs
Show resolved
Hide resolved
-- TODO: handle multiple GIVETH's. | ||
-- Actually, handle GIVETHs at 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.
Does this comment mean that you plan to do so eventually (but it wasn't a prio for the first version), or that you are unsure how GIVETHs should be handled?
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 suppose both, I want to focus on something that works with documented limitations, so that we can iteratively improve this version.
However, it is also unclear what a GIVETH really is, and how it would work in a function context, for example.
Failed transpilation: | ||
Unsupported RelationalPredicate: RPis |
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.
Is this the excpected result?
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.
Yes! This is intended as documenting the current capabilties of the transpilation.
I struggled to identify all possible meanings of predicates. In this case,
"Loss or Damage" IS ANY ( "caused by rodents"
, "caused by insects"
, "caused by vermin"
, "caused by birds"
)
Is a weird RelationalPredicate in my opinion. ANY
feels overloaded. It may mean OR
, but IS ANY
suddenly means ELEM
, and there is actually a RPelem
RelationalPredicate
which we don't use here.
So, I didn't even try to support this example, but rather we should talk about, which composite operators we want to support, or whether we rather want to use some ELEM
operator.
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.
Good point! I pretty much have forgotten that RPelem existed 😁
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.
Yeah in general I think we shouldn't be afraid to try to make the syntax more regimented and understandable (not least because there is a non-trivial chance we'll actually have to try to help other people learn and use this!)
8843b98
to
f1efe65
Compare
I tried to address some of the feedback, moved some code around that makes it hopefully a bit more clear what we are trying to do and added a documentation block that will hopefully evolve to a specification of the scoping rules in naturalL4. A lot of good questions were raised regarding supported syntax and the type system, which we should write down and discuss. I also fixed some glaring issues with the Simala Transpiler. However, I expect there are many issues left in the code, which we will hopefully weed out over time. |
ea50df1
to
4e6208e
Compare
After adding a test case, I realised the name shadowing did not work as anticipated. We fix this now, move some code around and extend the transpiler to work correctly for many more naturalL4 constructs and fragments.
4e6208e
to
0c59ebd
Compare
505ff61
to
664fb86
Compare
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.
Thanks for adding more docs / explanations!
This PR introduces two new things:
Rule
sRule
to a SimalaDecl
.The renamer implements lexical scope checking for
Hornlike
andTypeDecl
rules.It resolves all names, replacing occurrences of each name with its renamed equivalent.
This is supposed to lay the groundwork for a principled transpilation pipeline, avoiding redoing work for each transpiler, such as resolving names, making sure variables are in scope, etc...
In the future, we want to implement a type checker on top of a
RnRule
. However, that's currently only a dream and there are no attempts of doing any kind of typechecking at the moment.The simala transpiler solely operates on the renamed rules. This simplifies the implementation a lot, demonstrating how other transpilers may also benefit from the rename phase.
The simala backend can currently only handle
Hornlike
rules and ignores any kind ofTypeDecl
rules, as simala is dynamically typed and typechecking should occur in a dedicated rule phase, not ad-hoc in the transpiler.Both components are somewhat experimental and are expected to have bugs and missing features.
Todos:
String
s)