Consider this source file:
def method
a, b = 4, 5
"str"
end
a, b = 4, 5
puts method
The corresponding AST would have two MultiAssign nodes, which should be expanded. Consider running this code through syntactic and semantic stages of the compiler:
require "compiler/crystal/**"
src = Crystal::Compiler::Source.new("filename", <<-CODE)
def method
a, b = 4, 5
"str"
end
a, b = 4, 5
puts method
CODE
compiler = Crystal::Compiler.new
compiler.no_codegen = true
compiler.no_cleanup = false
result = compiler.compile(src, "file_out")
puts result.node
It produces the following output:
<Stuff from prelude>
def method
a, b = 4, 5
"str"
end
__temp_305 = 4
__temp_306 = 5
a = __temp_305
b = __temp_306
puts(method)
I am sure method is called. Also, since I used Crystal::Compiler#compile and not Crystal::Compiler#top_level_semantic, I would expect all Visitors and Transformers to run on the whole code.
Am I missing something that only happens at codegen stage? Or am I somehow getting an untransformed ASTNode from Compiler#compile?
What’s really confusing is that if I didn’t set compiler.no_codegen to true, the next operation it’d do is the code generation. It uses Crystal::CodeGenVisitor, which has the following method:
def visit(node : ExpandableNode)
raise "BUG: #{node} at #{node.location} should have been expanded"
end
But this is not raised when compiling the initial source program normally. (MultiAssign is a subclass of ExpandableNode)