-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
macros: Keep the location (file/line/column) of AST nodes #6125
Comments
I did a simple implementation: diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr
index 724d27aaf..1b3ee42fd 100644
--- a/src/compiler/crystal/macros/methods.cr
+++ b/src/compiler/crystal/macros/methods.cr
@@ -319,6 +319,12 @@ module Crystal
column_number = end_location.try &.original_location.try &.column_number
column_number ? NumberLiteral.new(column_number) : NilLiteral.new
end
+ when "with_location"
+ interpret_argless_method("with_location", args) do
+ MacroId.new(String.build do |str|
+ to_s(str, emit_loc_pragma: true)
+ end)
+ end
when "=="
interpret_one_arg_method(method, args) do |arg|
BoolLiteral.new(self == arg) It seems to work well for the tests I did. I can start a WIP PR with this diff if you want |
You explained what you want to do, but not why. |
Oh, I see the reason now. I don't think pushing the responsibility of showing nice error messages to the user is a good idea. We should think of how to improve that long error message. Maybe not show the whole macro source, and only show it when |
I agree the macro source is a bit too much, 'hiding' it under But then what do you want to show the user when If we want the nice error message as I showed, without the user telling us where the token is coming from, I fear this is impossible: The macro language as a 'templating'-like language makes token tracing impossible, or I have no idea how.. |
Any other opinions? |
I opened a couple issues around this because macros made it hard to tell what was happening. They were closed I think because I didn't explain myself clearly and because of a misunderstanding in how macros were expanded: #4700 and #4699 Here's my attempt to clarify:
Here is what I imagine the code you wrote would look like with what I'm proposing: https://gist.github.com/paulcsmith/52bad9e5862c92bf535edeee97dfbc66
I don't know how difficult this would be, but I think it'd be a huge step in the right direction. Even just making macro code condensed would make it much easier to navigate compile errors |
A good example of the macro create_class(name, file = __FILE__, line = __LINE__, &block)
class {{name.id}}
{{block.body}}
end
end
macro create_method(name, file = __FILE__, line = __LINE__, &block)
def {{name.id}}
puts "{{file.id}}:{{line.id}}"
{{block.body}}
end
end
create_class Hello do
# Blank lines
# to help
# demonstrate
# this example.
create_method say do
"Hello"
end
create_method yell do
"HELLO"
end
end
Hello.new.say # test.cr:14
Hello.new.yell # test.cr:14 We see at the end that the reported lines in With macro create_class(name, &block)
class {{name.with_location.id}}
{{block.body.with_location}}
end
end
macro create_method(name, file = __FILE__, line = __LINE__, &block)
def {{name.with_location.id}}
puts "{{file.id}}:{{line.id}}"
{{block.body.with_location}}
end
end
create_class Hello do
# Blank lines
# to help
# demonstrate
# this example.
create_method say do
"Hello"
end
create_method yell do
"HELLO"
end
end
Hello.new.say # test.cr:19
Hello.new.yell # test.cr:23 And the |
Note: here is another example, that doesn't work yet even when adding some macro raise_on(node)
{% node.raise "node '#{node}' is here!" %}
end
macro will_raise_soon(node)
# this is a helper macro
raise_on {{node}}
end
macro will_raise(node)
# this is a helper macro
will_raise_soon {{node}}
end
will_raise :this I think this should report the error |
@asterite does that mean that you think that the user should not have to put If yes, I've been thinking about it, and I think we could try to ALWAYS keep the ast nodes locations (unless the node doesn't come from the outside, e.g it could have been created inside the macro). |
ASTNode#with_location
Thanks @makenowjust (and the approvers!!) 😃 I'll extract the macro raise example as it's a separate issue, than I think I can close this issue |
I currently can't compile master (on arch, LLVM 7, etc..), so I can't verify that #6125 (comment) works now (the top example), can someone do this check? Thx! |
@bew install |
To get proper location in case of bad usage of macros we can use location pragma around a specific AST node, but it's very repetitive to do it each time, and so nobody does that (and also it's not really documented either).
Here is an example:
This gives the proper error on
BadConst
:I think it's a good candidate for a macro method that does that when writing:
For stdlib usage I think this could make JSON.mapping error more clean when a type doesn't exist (instead of the huuuuge error https://carc.in/#/r/44p0 for example)
WDYT?
The text was updated successfully, but these errors were encountered: