Brian (@bcardiff) wrote a blog post about a handy way to reveal the type of an expression. You’ll learn not only a neat tool, but also a bit of macro magic
7 Likes
Following solution can be a supplement to above solution.
1. Add a BlackHole
type for a universal type for any unknown type.
class BlackHole
macro method_missing(call)
raise "BUG: must implement {{call.name}}"
end
end
2. for any places compiler complain “can not infer current type”, just use BlackHole as type.
3. compile again, compiler will tell you, “should be a String, not BlackHole”, then, you known, the correct type should be String
.
I use this hack all the days when i porting Ruby gems into Crystal, this solution come from asterite by this reply
BTW, the code in blog conclusion not works on my laptop 1.7.2
# 1.cr
def reveal_type_helper(t : T, l) : T forall T
{% puts " : #{T}" %}
t
end
macro reveal_type(t)
{% loc = "#{t.filename.id}:#{t.line_number}:#{t.column_number}" %}
{% puts "Revealed type #{loc.id}" %}
{% puts " #{t.id}" %}
reveal_type_helper({{t}}, { {{loc.tr("/:.", "___").id}}: 1 })
end
x = "hello"
reveal_type x
Revealed type /home/zw963/1.cr:15:13
x
There was a problem expanding macro 'reveal_type'
Code in src/1.cr:15:1
15 | reveal_type x
^
Called macro defined in src/1.cr:6:1
6 | macro reveal_type(t)
Which expanded to:
2 |
3 |
> 4 | reveal_type_helper(x, { _home_zw963_Crystal_crystal-china_ferrum_src_1_cr_15_13: 1 })
^
Warning: space required before colon in type declaration (run `crystal tool format` to fix this)
A total of 1 warnings were found.
There was a problem expanding macro 'reveal_type'
Code in src/1.cr:15:1
15 | reveal_type x
^
Called macro defined in src/1.cr:6:1
6 | macro reveal_type(t)
Which expanded to:
> 2 |
> 3 |
> 4 | reveal_type_helper(x, { _home_zw963_Crystal_crystal-china_ferrum_src_1_cr_15_13: 1 })
^
Error: unexpected token: "1"
The error happens because your path contains a dash (-
) and the example code does not escape that.
It needs more complete sanitizing to produce only valid symbol names.
This particular issue can be fixed with using loc.tr("/:.-", "____")
. But that’s just a minor improvement and it’s still susceptible to other problems.
Wrapping the name in quotes (and escaping "
) would probably be a good idea.