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

[PERF] Result dropping can duplicate needlessly for constant returns. #247

Open
j-mie6 opened this issue Jan 3, 2025 · 0 comments
Open
Labels
quirk Something that's not quite a bug, but could be improved

Comments

@j-mie6
Copy link
Owner

j-mie6 commented Jan 3, 2025

Consider the following parser:

lazy val top: Parsley[Unit] = p.void
lazy val p: Parsley[Unit] = char('a').void | ~q
lazy val q: Parsley[Unit] = sepBy1(r, char(',')).void
lazy val r: Parsley[Unit] = many(p).void

If you look at the instructions for top, you'll see there are less instructions than there are for p:

 0 [4dfbc197]: Call(3);
 1 [523186c5]: Push(());
 2 [568e0b2f]: Halt;
 3 [7736e526]: PushHandlerAndClearHints(6);
 4 [64d2752e]: Chr(a);
 5 [3a8bc0df]: JumpAndPopCheck(13);
 6 [1c7a73d2]: Catch(18);
 7 [5c25aaae]: Call(14);
 8 [2b29cf01]: PushHandler(11);
 9 [4f406f83]: Chr(,);
10 [00eb615a]: Call(14);
11 [716acb33]: SkipMany(9);
12 [14de43d8]: ErrorToHints;
13 [58ae0ab7]: Return;
14 [03145149]: PushHandler(16);
15 [2480314b]: Call(3);
16 [42a66680]: SkipMany(15);
17 [58ae0ab7]: Return;
18 [2e08d237]: MergeErrorsAndFail

vs

 0 [301bc3d3]: Call(2);
 1 [43e341e1]: Halt;
 2 [2b8f133c]: PushHandlerAndClearHints(5);
 3 [7604f3df]: Chr(a);
 4 [186fb397]: JumpAndPopCheck(12);
 5 [41da0532]: Catch(29);
 6 [121ff8c6]: Call(14);
 7 [43546b51]: PushHandler(10);
 8 [26428ba7]: Chr(,);
 9 [37a0e9c8]: Call(14);
10 [5a94fe32]: SkipMany(8);
11 [3afa08d2]: ErrorToHints;
12 [08d7b399]: Push(());
13 [3809e5e2]: Return;
14 [4511f9bf]: PushHandler(16);
15 [2fc7c557]: Call(18);
16 [1ab9e04d]: SkipMany(15);
17 [3809e5e2]: Return;
18 [6d68200d]: PushHandlerAndClearHints(21);
19 [27fef01e]: Chr(a);
20 [368264cb]: JumpAndPopCheck(28);
21 [636c41de]: Catch(29);
22 [4f287df6]: Call(14);
23 [1f861a0d]: PushHandler(26);
24 [3a87810a]: Chr(,);
25 [3b644535]: Call(14);
26 [372f4862]: SkipMany(24);
27 [3afa08d2]: ErrorToHints;
28 [3809e5e2]: Return;
29 [1f6e10db]: MergeErrorsAndFail

This is because the code generation determines that there are two version of p in the second case: one which produces (), and the other that produces no result. In the former case, top will drop the result of p and return its own (), which means across the whole parser p only exists in a result-dropping state.

While this could reasonably be considered a mere "quirk", it might be possible to avoid this by recognising that p has a constant output. In this case, result-demanding locations for p can be translated to p.as(c), and result-dropping locations use p directly. This would eliminate the duplication here. This transformation is done manually above via top, which serves as p.as(()). This may or may not be possible to do...

@j-mie6 j-mie6 added bug Something isn't working low priority This bug is mainly cosmetic or easy to avoid quirk Something that's not quite a bug, but could be improved and removed bug Something isn't working low priority This bug is mainly cosmetic or easy to avoid labels Jan 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
quirk Something that's not quite a bug, but could be improved
Projects
None yet
Development

No branches or pull requests

1 participant