consiliens edited this page Jul 20, 2011 · 2 revisions

Mirah supports macros for compile time code generation. Macros are functions that operate on nodes of the parsed Mirah AST at compile time and return a new node for the tree. In this way, they are much more similar (especially in expressivity) to macros in Lisp than those implemented by a C pre-processor (which simply operate on text strings).

Macros are defined by prefixing a function definition with "macro", and macro functions must return an instance of Node.


Ruby style attr_reader/attr_writer macros

class Foo                                   
  macro def attr_reader(name_node, type)
    name = name_node.string_value
    quote {
      def `name`

  macro def attr_writer(name_node, type)
    name = name_node.string_value
    quote do
      def `"#{name}_set"`(value:`type`)
        @`name` = value

class Bar < Foo
  attr_reader :size, :int
  attr_writer :size, :int

b =
b.size = 4
puts "b has size #{b.size}"

There are two basic mechanisms to notice in these examples: quote and the backtick unquote operators. quote takes a block and returns it's AST representation (a Node) while the backticks allow you to "unquote" expressions in the block so that they will be replaced with whatever was passed to the macro. So when the parser sees a macro call (e.g. attr_reader :size, :int) it replaces it with the quoted block to produce something like:

def size:int

This all happens at compile-time, meaning your code runs as fast as if you had written out the boilerplate yourself, (e.g. no startup penalty)

Another example--renaming methods so they have java friendlier names:

macro def foo?  
  quote { isFoo }  

class A
  def foo?
puts # outputs true
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.