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

Fix combined cartesian / flattened generators #263

Merged
merged 1 commit into from
May 2, 2023

Conversation

c42f
Copy link
Member

@c42f c42f commented May 1, 2023

The combined cartesian/flattened generator syntax is a very unusual use case found in only one or two packages in the general registry. It looks like this

((a,b,c,d) for a=as, b=bs for c=cs, d=ds)

Practically all such generators end up as a flat list (though ... should they?) but the ordering of tuples (a,b,c,d) in the list depends on which parts are cartesian (separated by commas) and which parts are flattened (separated by for's).

Here we fix the SyntaxNode representation of these, preferring a single generator head rather than combined flatten and generator, and instead grouping the sets of cartesian iterations into cartesian_iterator groups. This keeps the tree structure flat and closer to the source text while also faithfully representing these unusual forms. For example, the above parses as

(generator
  (tuple a b c d)
  (cartesian_iterator
    (= a as)
    (= b bs))
  (cartesian_iterator
    (= c cs)
    (= d ds)))

In addition, we also make use of the cartesian_iterator head in for loops, replacing the block which was used previously (but is not semantically or syntactically a block!). Thus for i=is, j=js body end now parses as

(for
  (cartesian_iterator
    (= i is)
    (= j js))
  body)

This also improves Expr conversion, removing some special cases which were necessary when processing block's in that situation.

Fixes perhaps the last important case in #134 🎉

@codecov
Copy link

codecov bot commented May 1, 2023

Codecov Report

Merging #263 (4714172) into main (d18dc3f) will increase coverage by 0.00%.
The diff coverage is 100.00%.

@@           Coverage Diff           @@
##             main     #263   +/-   ##
=======================================
  Coverage   96.41%   96.41%           
=======================================
  Files          15       15           
  Lines        3929     3931    +2     
=======================================
+ Hits         3788     3790    +2     
  Misses        141      141           
Impacted Files Coverage Δ
src/kinds.jl 79.10% <ø> (ø)
src/expr.jl 100.00% <100.00%> (ø)
src/parser.jl 98.25% <100.00%> (-0.01%) ⬇️

@c42f
Copy link
Member Author

c42f commented May 1, 2023

I'm pretty sure this is a good approach at this point, but as usual deciding on a satisfying naming is kind of tricky. I don't love K"cartesian_iterator" as a name for the new kind representing a cartesian product of iterators... but I guess that's what this is.

@timholy or @BenChung thoughts?

I find the use of block in for iteration specifications a bit awkwardly overloaded with other uses of block so I changed that as well, while I was fixing this.

@c42f
Copy link
Member Author

c42f commented May 1, 2023

Side note ... returning to tackle this issue has been psyching me out for months now, it's a relief to have finally done it :-)

The combined cartesian/flattened generator syntax is a very unusual use
case found in only one or two packages in the general registry. It looks
like this

    ((a,b,c,d) for a=as, b=bs for c=cs, d=ds)

Practically all such generators end up as a flat list (though ... should
they?) but the ordering of tuples (a,b,c,d) in the list depends on which
parts are cartesian (separated by commas) and which parts are flattened
(separated by for's).

Here we fix the `SyntaxNode` representation of these, preferring a single
`generator` head rather than combined `flatten` and `generator`, and
instead grouping the sets of cartesian iterations into
`cartesian_iterator` groups. This keeps the tree structure flat and
closer to the source text while also faithfully representing these
unusual forms.  For example, the above parses as

    (generator
      (tuple a b c d)
      (cartesian_iterator
        (= a as)
        (= b bs))
      (cartesian_iterator
        (= c cs)
        (= d ds)))

In addition, we also make use of the `cartesian_iterator` head in `for`
loops, replacing the `block` which was used previously (but is not
semantically or syntactically a block!). Thus `for i=is, j=js body end`
now parses as

    (for
      (cartesian_iterator
        (= i is)
        (= j js))
      body)

This also improves Expr conversion, removing some special cases which
were necessary when processing `block's` in that situation.
@c42f c42f force-pushed the c42f/generator-flatten-fixes branch from b7cd78c to 4714172 Compare May 2, 2023 05:56
@c42f
Copy link
Member Author

c42f commented May 2, 2023

I'll go ahead and merge this because I think it's generally correct and a good idea. Still interested in hearing feedback though!

@c42f c42f merged commit 8098cb0 into main May 2, 2023
@c42f c42f deleted the c42f/generator-flatten-fixes branch May 2, 2023 19:34
@BenChung
Copy link

BenChung commented May 2, 2023

Right - sorry, in the middle of moving (cities & jobs) so cycles are a bit wanting at the moment. Should be back to normal by next week.

I think that's this is a good change. Understanding the semantics of cartesian iterators was a big headache for SemanticAST and this'd make it a lot clearer what's happening. I'll need to rework my representation a little but that goes without saying.

@c42f
Copy link
Member Author

c42f commented May 3, 2023

Awesome, thanks for the feedback Ben, much appreciated ❤️

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.

2 participants