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
Reset location after block yielding in macro expansion #3751
Reset location after block yielding in macro expansion #3751
Conversation
Introduce #<loc:save> and #<loc:reset> new pragma comment, #<loc:save> saves current location and #<loc:reset> resets it. They are useful to keep original location when block yielding in macro expansion. For example, this code makes broken error message: macro foo a = {{ yield }} a.ok end foo { 1 } It cannot be compiled and error message is: in foo.cr:7: undefined method 'ok' for Int32 Error message points line 7 of foo.cr, but this code consists only 6 lines. This bug comes from a location is not reset after block yielding in macro expansion. For instance, `foo { 1 }` expands to: a = begin #<loc:"foo.cr",6,7>1 end a.ok So, the parser reports `a.ok` is on line 7 of foo.cr. This commit fixes it by wrapping #<loc:save> and #<loc:reeset> to yielding expanded code, such a like: a = #<loc:save>begin #<loc:"foo.cr",6,7>1 end#<loc:reset> a.ok
Super interesting! I actually had this idea too and eventually was going to implement it, though I imagined something more like a stack (push/pop). What do you think if we change it to |
@asterite I'll try to implement |
Hmm... then I misunderstood something. I thought |
For example, when given block is multiple lines: macro foo
a = {{ yield }}
a.ok
end
foo do
:foo
:bar
end It is expands to: a = #<loc:save>begin #<loc:"foo.cr",7,3>:foo
#<loc:"foo.cr",8,3>:bar
end#<loc:reset>
a.ok If |
Oooh... I understand now. Yes, the lexer needs to continue incrementing lines for the old line number. I think like you implemented it it's fine :-) |
Thanks. I already implemented |
@makenowjust Great! Though now I'm not sure there's a use case for push/pop. I thought it was going to be useful to implement/fix this, but I'm not sure anymore. Can you think of a use case? |
@asterite No, so I didn't implement location stack at first. However, I think |
@makenowjust Thank you! And thank you for extracting a method for incrementing line numbers. I was actually going to ask if you wanted to do that, so it seems you somehow read my mind... :-P |
It is fixed in crystal-lang#3751. Yeah, we need no hack for it! This reverts commit 1d26d45.
It is fixed in crystal-lang#3751. Yeah, we need no hack for it! This reverts commit 1d26d45.
This pull request introduces
#<loc:save>
and#<loc:reset>
new pragma comment,#<loc:save>
saves current location and#<loc:reset>
resets it. They are useful to keep original location when block yielding in macro expansion.For example, this code makes broken error message:
It cannot be compiled and error message is:
Error message points line 7 of foo.cr, but this code consists only 6 lines.
This bug comes from a location is not reset after block yielding in macro expansion. In fact,
foo { 1 }
expands to:So, the parser reports
a.ok
is on line 7 of foo.cr.This pull request also fixes it by wrapping
#<loc:save>
and#<loc:reeset>
to yielding expanded code, such a like:It works well.