-
Notifications
You must be signed in to change notification settings - Fork 92
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
Structural ADTs: first step #1770
Merged
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This commit is a very first step toward adding structural Algebraic Data Types to Nickel. This commit adds a new node in the AST for an enum tag with an argument (a variant), and fill the blanks/compiler errors from there. A temporary syntax, choosen mostly to be obscure, ugly, easy to add and to not conflict with existing syntax has been added for further testing and experimentation: 'SomeTag..(argument).
This commit extend enum row types to accept a variant, that is to handle types such as `[| 'Foo Number, 'Bar {foo : String} |]`, which are basically structural ADTs. The bulk of the work consist to extend most function operating on enum rows to now take into account the fact that enum rows can have types inside, much as record rows. That is, the code handling enum rows and record rows is much more similar than before; the main difference being that for now, enum rows have an optional type argument (the variant, which can be there or not), while a record row always have a type assignment. At this point, no elimination forms for ADTs have been introduced yet (that is, you can't match on/unwrap ADTs). This part is intentionally on the side for the time being.
yannham
force-pushed
the
feat/adt-first-step
branch
from
January 25, 2024 12:09
5635149
to
b99ee1e
Compare
Add missing surface syntax to write enum rows with a variant (an argument). Fix some pretty printing shortcomings as well.
Extend various typechecker internal error types with new cases for augmented (with variants) enum rows
yannham
force-pushed
the
feat/adt-first-step
branch
from
January 25, 2024 12:34
9762351
to
8b0412f
Compare
yannham
commented
Jan 25, 2024
yannham
commented
Jan 25, 2024
yannham
commented
Jan 25, 2024
yannham
commented
Jan 25, 2024
jneem
approved these changes
Jan 26, 2024
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.
Exciting! I'd vote for a single ast node with a unit type, especially if that would make it easier to deduplicate the rrows/erows stuff.
Co-authored-by: jneem <[email protected]>
This was referenced Jan 29, 2024
vkleen
reviewed
Jan 30, 2024
Co-authored-by: Viktor Kleen <[email protected]>
This was referenced Feb 6, 2024
This was referenced Feb 14, 2024
Closed
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
MVP for adding structural ADTs to Nickel (see #1448), see what works and what breaks, and iterate from there.
Content
This PR adds some preliminary elements of structural algebraic data types, although some functionalities are still missing. The goal is to produce a reviewable chunk of work, that doesn't impact the normal usage of the language, and doesn't commit permanently when bikshedding needs to be involved. More specifically, this PR:
EnumVariant(Ident, RichTerm)
node to the AST, which represent an applied enum tag (ie an ADT with one argument). Extend the existing code to support it/fix compiler errors.'Foo...(arg)
(yes, it's a literal ellipsis, not the expression of some kind of repetition)EnumRow { id, typ: None}
, and an applied tag corresponds toEnumRow {id, typ: Some(ty_arg)
[| 'Foo, 'Bar Number, 'Baz {foo : String}, 'Motto (Dyn -> Dyn) |]
is a valid type.I've also expanded/reworded some of the existing in-code documentation: going through our own comments a few month later is a good exercise to see what is useful, and what is missing, when the technical aspects aren't so fresh anymore 🙂
The bulk of this PR, beside adding new definitions and fixing compiler errors, is to extend row types and adapt the typechecker to handle the corresponding new cases. In particular, a lot of cases were previously simpler for enum rows (as compared to record rows) because those couldn't contain any other type inside, beside an enum row unification variable in tail position. Now, as with record rows, enum rows might contain normal types inside, which thus must be walked/folded over/variable-level updated, etc. It actually makes the handling of
Missing features
The following important aspects are missing for the moment, and will be covered in follow-up PRs:
==
: currently'Foo..(1) == 'Foo(1)
is false...( )
. Distinguishing between zero-ary enum tags and 1-ary enum tags would be done at parsing time alone.Maintainability shortcomings
In order to keep the diff reasonable, some visible shortcomings aren't addressed right now but should be explored nonetheless:
Unit
. Ie,[| 'Foo |]
would be surface syntax for[| 'Foo Unit |]
and'Foo
alone would be surface syntax for'Foo ()
. The typeUnit
doesn't exist currently, but could be added even only internally, as a special value, if we don't want to create confusion around two different ways of writing the same thing ('Foo == 'Foo ()
). This might make some of the special casing because of the optional type argument of enum rows go away, and we could use the exact same definition for record rows and enum rows.() : Unit
for unapplied enum tags. Another solution, if we don't go the unit route, is to have one AST node with an optional argument. It's hard to say currently if that would be a win or not.