-
Notifications
You must be signed in to change notification settings - Fork 12
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
Nonterminal blues #143
Nonterminal blues #143
Conversation
Put these in a dedicated module where they're usable both in the compiler itself as well as in tests.
This was formerly a utility in a single test module, but it's likely to be broadly useful in testing.
This adds a `test-compile` macro that accepts surface syntax, expands it, and applies the indicated optimization passes.
This uses on-demand invocation of the expander to generally avoid writing core language expressions by hand. There were also many tests that had the right descriptions but which were all identical. This fixes them to reflect the actual cases they meant to test.
This avoids the need to hand-write core language expressions, and avoids the need to manually attach the `nonterminal` syntax property. This also turns out to be more reliable since the hand-written input expressions may not actually be encountered in practice, whereas the ones produced by the expander from surface syntax are guaranteed to be.
This is necessary to get the tests to pass when executed using `racket -y`. They already pass when using just `racket`.
... when it was formerly mysteriously not working. I think that's one less mystery to worry about, but it might be two mysteries.
The problem occurs because of an interaction between the way that the tests are written and the fact that we made the When applying a syntax property with If a syntax property is really only needed temporarily for compilation, making it non-preserved can avoid increasing the size of compiled files. So as of right now we made the In the tests as written,
Expands to something like:
and then that runs at runtime. The problem is that because the I suggest instead running the entire compiler pipeline at expansion time, and only returning a boolean to runtime. This makes sure that the compiler runs in the same way it will in a real program---at phase 1, and without any step of serialization between expansion and compilation. Here's a test that works file with both
|
@michaelballantyne Ok, thanks for the explanation! That definitely helps to understand what's going on. I'll have to think about how to refactor the tests to do the checks in phase 1, and I think if I can get this test to pass, that should help reveal how to address the original problem with the |
This is a provisional fix for the multi-pass issue revealed by the `long-functional-pipeline` benchmark, where a nontrivial normalization was resulting in syntax that no longer had the `nonterminal` property, preventing deforestation from being applied.
I've fixed that specific test to run in phase 1, verified that it is capable of detecting the failure to propagate I'm assuming that:
Does that sound right? One general impression is that although the addition of the syntax property appeared a simple solution at first, it does make things a bit harder to reason about. We should revisit this at some point (after the release 😄) Now I need to push the remaining tests into phase 1, and I think the PR should be ready at that point. One "Interesting" thing @dzoep : |
Isn't find-and-map pretty crucial to the compiler or expander? I'm actually very shocked it needs to use datum->syntax this way, then, and think that suggests a possible [architectural? design? implementation?] flaw (because I would expect Racket macros and other compile-time code to not need that kind of low-level tool in most cases). I'll have to really study the code [again] to figure out why it's needed though, so I'm mostly saying this now as a way of "please publicly hold me accountable to investigate after the release." |
I'm also not seeing any changes to find-and-map in this PR; was that in a previous PR or am I missing something? |
Well, I think And yes, I should have clarified that this PR doesn't modify I'll gladly hold you accountable to implement the traversal if Syntax Spec doesn't get around to it quickly enough 😝 |
I think a generic syntax traversal using |
In case I happen to have time to pole around: does syntax-spec expose the grammar anywhere in a way that I can compute over it? Or where in its internals should I look? |
The `nonterminal` syntax property attached by Syntax Spec is "non-preserved," so the property would not be present at phase 0 if the code is compiled. We ensure that the compiler rules being tested are applied in phase 1.
It does not expose it, and currently the only thing it generates from the grammar is the macro expander so it also does not have a super clean internal representation of the grammar either. The syntax classes for matching the grammar declarations are here: And the generation of the expander from the grammar is here: |
Retain version 8.9 in the test matrix for both CS and BC, and 8.5 specifically for CS.
Yesterday we noticed that CI was failing, specifically on BC versions 8.5 through 8.8. We generally agreed that supporting BC is not a priority, so I've just updated the test matrix to reflect the actual current compatibility -- that is, BC/CS 8.9+, and CS all the way back to 8.5 (i.e. unchanged from before). These are the specific errors, for reference, in case anyone thinks they might be cause for concern: BC 8.5-8.7:
BC 8.8:
I think this PR is ready to go! Any review appreciated. I'll aim to merge it soon if there are no further comments. |
The first of those two errors seems like something we could potentially
fix; it’s complaining that you are embedding a srcloc structure value in
compiled code. We could probably avoid doing that easily.
The error message for the second suggests it’s a problem in the
rackunit-abbrevs dependency, so less straightforward for us to change.
…On Sat, Dec 30, 2023 at 2:33 PM Siddhartha Kasivajhula < ***@***.***> wrote:
Yesterday we noticed that CI was failing, specifically on BC versions 8.5
through 8.8. We generally agreed that supporting BC is not a priority, so
I've just updated the test matrix to reflect the actual current
compatibility -- that is, BC/CS 8.9+, and CS all the way back to 8.5 (i.e.
unchanged from before).
These are the specific errors, for reference, in case anyone thinks they
might be cause for concern:
BC 8.5-8.7:
write: cannot marshal value that is embedded in compiled code
value: (srcloc #<path:/home/runner/work/qi/qi/qi-lib/flow/core/normalize.rkt> 74 7 2297 22)
compilation context...:
/home/runner/work/qi/qi/qi-test/tests/qi.rkt
context...:
/usr/share/racket/collects/compiler/private/cm-minimal.rkt:808:8
BC 8.8:
mask-accessor: contract violation
raco setup: 1 making: <pkgs>/rackunit-abbrevs/scribblings
expected: mask?
given: #f
compilation context...:
/home/runner/.local/share/racket/8.8-bc/pkgs/rackunit-abbrevs/private/test-typed-rackunit-abbrevs.rkt
context...:
/usr/share/racket/pkgs/typed-racket-lib/typed-racket/types/overlap.rkt:48:0: overlap?
I think this PR is ready to go! Any review appreciated. I'll aim to merge
it soon if there are no further comments.
—
Reply to this email directly, view it on GitHub
<#143 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAK46U6EBUGMGXMQODFLL5TYMCCEJAVCNFSM6AAAAABBF6AQFWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNZSGYYTCMBYHA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Yeah, if it's an easy fix we might as well do it. From googling the error, it sounds like it might be a case of "3d syntax" which I gather is best avoided as it loses the separate compilation guarantee, which I've come to really appreciate as the codebase gets larger! |
I haven't looked into the srcloc issue yet, but so as not to hold up the other fixes in this PR, I've just modified the test workflow to run tests on BC 8.5 but not block other tests from running if it fails, so we see that the issue remains but it doesn't break CI. We can fix the remaining issue in a separate PR, so I'll merge this now! |
cad6c0e
into
drym-org:lets-write-a-qi-compiler
Summary of Changes
This began as an investigation of the
long-functional-pipeline
benchmark, which it turned out wasn't getting deforested. That seems to have something to do with the fact that that benchmark is rewritten by both of our current optimization passes, normalization and deforestation, and most likely, the latter doesn't see thenonterminal
syntax propertyfor reasons that are somewhat mysteriousbecause we weren't explicitly propagating it, and the syntax property being "nonpreserved" meant that our tests were not correctly handling this property across phases (see comments below).In the course of investigating I ended up refactoring a lot of tests, and they actually revealed a lot of other smaller issues that are mostly fixed.
But the main nonterminal property issue remains a mystery. Summary below:racket
, but fail when usingracket -y
. In the latter case, thenonterminal
property is not present after expansion.compiler/rules.rkt
that passes if we manually introduce thenonterminal
property between passes viatag-form-syntax
compiler.rkt
module itself, at the conclusion ofnormalize-pass
, does not make a difference to the test result. Adding the property at thefind-and-map/qi
level (after excluding non-syntax and expressions tagged#%host-expression
-- which it didn't like) doesn't make a difference to the test result either.Other changes:
nonterminal
propertyutil
module to (compiler)pass
. There are too many modules named "util" and obviously we should avoid such a generic name.Public Domain Dedication
(Why: The freely released, copyright-free work in this repository represents an investment in a better way of doing things called attribution-based economics. Attribution-based economics is based on the simple idea that we gain more by giving more, not by holding on to things that, truly, we could only create because we, in our turn, received from others. As it turns out, an economic system based on attribution -- where those who give more are more empowered -- is significantly more efficient than capitalism while also being stable and fair (unlike capitalism, on both counts), giving it transformative power to elevate the human condition and address the problems that face us today along with a host of others that have been intractable since the beginning. You can help make this a reality by releasing your work in the same way -- freely into the public domain in the simple hope of providing value. Learn more about attribution-based economics at drym.org, tell your friends, do your part.)