Crystalのマクロでメタプロする

## <i class="fa fa-flask" style="font-size:1em;"></i> Sample
上下左右を出力するメソッドを好きな名前で定義できるクラスマクロをつくります。
マクロは `macro` で利用できます。
詳細は公式ドキュメント参照。

* <i class="fa fa-external-link" style="font-size:1em;"></i> [Macros - Docs - Crystal](http://crystal-lang.org/docs/syntax_and_semantics/macros.html)

* <i class="fa fa-external-link" style="font-size:1em;"></i> [Macros - Docs - Crystal(日本語版)](http://ja.crystal-lang.org/docs/syntax_and_semantics/macros.html)

`{{ some_macro_argument }}` でASTノードを貼り付け・埋め込みできます。
`{{ some_macro_argument }}` をマクロ展開と呼びます。

分岐、ループなどを行いたい場合は `{% if condition %} ... {% end %} ` のように `{% %}` を使います。

### <i class="fa fa-code" style="font-size:1em;"></i> コード
* ./src/direction_dsl.cr

```crystal
module Direction
  module Dsl
    macro move(key, direction)
      def {{key.id}}
        {% if direction == :↑ %} print "上"
        {% elsif direction == :↓ %} print "下"
        {% elsif direction == :→ %} print "右"
        {% elsif direction == :← %} print "左"
        {% end %}
        self
      end
    end
  end
end
```

* ./src/direction_mover.cr

```crystal
require "./direction_mover/*"
require "./direction_dsl"

module Vim
  class Mover
    include Direction::Dsl
    move :k, :↑
    move :j, :↓
    move :l, :→
    move :h, :←
  end
end

puts "==Vim=="
Vim::Mover.new.k.k.j.j.l.r.l.r

module Japanese
  class Mover
    include Direction::Dsl
    move :上, :↑
    move :下, :↓
    move :右, :→
    move :左, :←
  end
end

puts
puts "==Japanese=="
Japanese::Mover.new.上.上.下.下.左.右.左.右

module Emoji
  class Mover
    include Direction::Dsl
    move :🔼, :↑
    move :🔽, :↓
    move :⏩, :→
    move :⏪, :←
  end
end

puts
puts "==Emoji=="
Emoji::Mover.new.🔼.🔼.🔽.🔽.⏪.⏩.⏪.⏩
```

## <i class="fa fa-play-circle" style="font-size:1em;"></i> 実行結果
```
$ crystal ./src/direction_mover.cr
==Vim==
上上下下左右左右
==Japanese==
上上下下左右左右
==Emoji==
上上下下左右左右
```

## <i class="fa fa-bug" style="font-size:1em;"></i> Debug
`{{ debug() }}` でマクロの内容をデバッグ出力できます。

### <i class="fa fa-code" style="font-size:1em;"></i> コード

```crystal
module Direction
  module Dsl
    macro move(key, direction)
      def {{key.id}}
        {% if direction == :↑ %} print "上"
        {% elsif direction == :↓ %} print "下"
        {% elsif direction == :→ %} print "右"
        {% elsif direction == :← %} print "左"
        {% end %}
        self
      end
      {{ debug() }}
    end
  end
end
```

### <i class="fa fa-calculator" style="font-size:1em;"></i> 出力

```crystal
      def k
         print "上"
        
        self
      end
      
      def j
         print "下"
        
        self
      end
      
      def l
         print "右"
        
        self
      end
      
      def h
         print "左"
        
        self
      end
      
      def 上
         print "上"
        
        self
      end
      
      def 下
         print "下"
        
        self
      end
      
      def 右
         print "右"
        
        self
      end
      
      def 左
         print "左"
        
        self
      end
      
      def 🔼
         print "上"
        
        self
      end
      
      def 🔽
         print "下"
        
        self
      end
      
      def ⏩
         print "右"
        
        self
      end
      
      def ⏪
         print "左"
        
        self
      end
```

のように出力されます

## <i class="fa fa-cube" style="font-size:1em;"></i> 継承先の型情報
`@type` で継承先の型情報を参照できます。

### <i class="fa fa-code" style="font-size:1em;"></i> コード

```crystal
module Direction
  module Dsl
    macro move(key, direction)
      {% puts @type %}
      def {{key.id}}
        {% if direction == :↑ %} print "上"
        {% elsif direction == :↓ %} print "下"
        {% elsif direction == :→ %} print "右"
        {% elsif direction == :← %} print "左"
        {% end %}
        self
      end
    end
  end
end
```

### <i class="fa fa-calculator" style="font-size:1em;"></i> 出力

```
Vim::Mover
Vim::Mover
Vim::Mover
Vim::Mover
Japanese::Mover
Japanese::Mover
Japanese::Mover
Japanese::Mover
Emoji::Mover
Emoji::Mover
Emoji::Mover
Emoji::Mover
```

## <i class="fa fa-book" style="font-size:1em;"></i> 外部資料
* <i class="fa fa-external-link" style="font-size:1em;"></i> [コンパイル時評価でもメタプロしたい - Crystal - HKDnet - Qiita](http://qiita.com/HKDnet/items/0aeaa2b31f7321fc43ed)
* <i class="fa fa-external-link" style="font-size:1em;"></i> [Macros - Docs - Crystal](http://crystal-lang.org/docs/syntax_and_semantics/macros.html)