Skip to content

Commit

Permalink
Expand macro expressions arguments before macro calls. Fixes #2388
Browse files Browse the repository at this point in the history
  • Loading branch information
asterite committed Mar 31, 2016
1 parent ddd9105 commit 97ff565
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 3 deletions.
22 changes: 22 additions & 0 deletions spec/compiler/codegen/macro_spec.cr
Expand Up @@ -1257,4 +1257,26 @@ describe "Code gen: macro" do
x.foo
)).to_i.should eq(1)
end

it "solves macro expression arguments before macro expansion (type)" do
run(%(
macro name(x)
{{x.name.stringify}}
end
name({{String}})
)).to_string.should eq("String")
end

it "solves macro expression arguments before macro expansion (constant)" do
run(%(
CONST = 1
macro id(x)
{{x}}
end
id({{CONST}})
)).to_i.should eq(1)
end
end
41 changes: 38 additions & 3 deletions src/compiler/crystal/semantic/base_type_visitor.cr
Expand Up @@ -496,12 +496,18 @@ module Crystal
node.raise "macro '#{node.name}' must be defined before this point but is defined later"
end

@exp_nest -= 1
expansion_scope = (macro_scope || @scope || current_type)

args = expand_macro_arguments(node, expansion_scope)

@exp_nest -= 1
generated_nodes = expand_macro(the_macro, node) do
@mod.expand_macro the_macro, node, (macro_scope || @scope || current_type)
old_args = node.args
node.args = args
expanded = @mod.expand_macro the_macro, node, expansion_scope
node.args = old_args
expanded
end

@exp_nest += 1

node.expanded = generated_nodes
Expand Down Expand Up @@ -531,6 +537,35 @@ module Crystal
generated_nodes
end

def expand_macro_arguments(node, expansion_scope)
# If any argument is a MacroExpression, solve it first and
# replace Path with Const/TypeNode if it denotes such thing
args = node.args
if args.any? &.is_a?(MacroExpression)
@exp_nest -= 1
args = args.map do |arg|
if arg.is_a?(MacroExpression)
arg.accept self
expanded = arg.expanded.not_nil!
if expanded.is_a?(Path)
expanded_type = expansion_scope.lookup_type(expanded)
case expanded_type
when Const
expanded = expanded_type.value
when Type
expanded = TypeNode.new(expanded_type)
end
end
expanded
else
arg
end
end
@exp_nest += 1
end
args
end

def visit(node : MacroExpression)
expand_inline_macro node
end
Expand Down

0 comments on commit 97ff565

Please sign in to comment.