Skip to content
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

Expand macro expressions arguments before macro calls. Fixes #2388 #2392

Merged
merged 1 commit into from
Apr 1, 2016

Conversation

asterite
Copy link
Member

This change makes this code:

call({{argument}})

to first expand {{argument}}. If it's a Path denoting a type, a TypeNode is passed to the macro. If it denotes a constant, the constant's value is passed to the macro. Otherwise the regular expansion is passed to it.

This makes it possible to extract a repeated macro argument into a constant:

require "json"
require "yaml"

class Point
  MAPPING = {
    x: Int32,
    y: Int32,
  }

  JSON.mapping({{MAPPING}})
  YAML.mapping({{MAPPING}})
end

Or, following @BlaXpirit 's example you can include the constants of a type inside another type:

macro include_constants(t)
  {% for c in t.constants %}
    {{c}} = {{t}}::{{c}}
  {% end %}
end

enum E
  A, B, C
end

class T1
  include_constants({{E}})
end

p T1::A # works
p T1::B # works
p T1::C # works

In fact in the above case it can also be simplified for the macro caller by using a second macro, because the expected argument is always expected to be a type:

macro include_constants(t)
  include_constants_for_real(\{{ {{t}} }})
end

macro include_constants_for_real(t)
  {% for c in t.constants %}
    {{c}} = {{t}}::{{c}}
  {% end %}
end

enum E
  A, B, C
end

class T1
  include_constants(E)
end

p T1::A # works
p T1::B # works
p T1::C # works

For this last case we might also want to make it simpler by maybe putting a TypeNode type restriction in the macro, so the compiler will always try to convert a Path argument to a TypeNode so there's no need to surround it in curly braces. But this won't solve the JSON/YAML Mapping reuse, so it's still worth introducing this feature.

@asterite asterite force-pushed the feature/macro_args_expansion branch from 97ff565 to 956d5a1 Compare March 31, 2016 19:16
@asterite asterite merged commit cc9488d into master Apr 1, 2016
@asterite asterite deleted the feature/macro_args_expansion branch April 1, 2016 15:30
@jhass
Copy link
Member

jhass commented Apr 6, 2016

Do we want to support expansion inside literals passed to macros too?

ID_TYPE = {type: Int32, converter: ObscureApi}
class Foo
  JSON.mapping({
    id: {{ID_TYPE}}
    other: Stuff
   })
end

class Bar
  JSON.mapping({
    id: {{ID_TYPE}}
    different: Stuff
  })
end

@asterite
Copy link
Member Author

asterite commented Apr 6, 2016

@jhass Probably yes. When I implemented it I noticed it's not checked inside other expressions, but didn't come up with a good use case. The above use case is good enough :-)

@asterite
Copy link
Member Author

asterite commented Apr 6, 2016

@jhass Could you open a separate issue for this? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants