uehaj's blog

Grな日々 - GroovyとかGrailsとかElmとかRustとかHaskellとかReactとかFregeとかJavaとか -

RubyライクにGroovyを書く

誰得なエントリ、かつ「これはひどい」ネタ。

まず、以下のようなコンパイラ設定ファイルを書いておき、例えば~/.groovy/config.groovyなどに保存しておきます。

import org.codehaus.groovy.control.*
import org.codehaus.groovy.antlr.*
import org.codehaus.groovy.syntax.*

class Rubylizer extends ParserPluginFactory {
  ParserPlugin createParserPlugin() {
    new AntlrParserPlugin() {
      Reduction parseCST(SourceUnit sourceUnit, Reader reader) {
        def s = reader.text
        s = s.replaceAll(/(?m)^([^(= \t]+[ \t][^(=]+\([^)]*\))/, '$1 {')
        s = s.replaceAll(/(class.*)</, '$1 implements ')
        s = s.replaceAll(/(\bclass[ \t]+.*)/, '$1 {')
        s = s.replaceAll(/\bend\b/, '}')
        s = s.replaceAll(/#(.*)/, '// $1')
        super.parseCST(sourceUnit, new StringReader(s))
      }
    }
  }
} 

withConfig(configuration) {
  source(extension:'grb') {
    configuration.pluginFactory = new Rubylizer()
    ast(Newify)
  }
}

すると、こんな謎のコード(test.grbとでも保存しておく。拡張子重要。)

def foo(arg,n) # comment
   println arg*n
end

class Person < Comparable
  def name
  int compareTo(rhs)
    println "compareTo"
    this.name <=> rhs.name
  end

  def foo()
    @Newify p1 = Person.new(name:"abc")
    @Newify p2 = Person.new(name:"def")
    println p1<=>p2
  end
end

foo("hello!", 3)
@Newify p = Person.new(name:"abc")
p.foo()

が以下のようにGroovyコマンドで実行できます。

% groovy -configscript ~/.groovy/config.groovy test.grb
hello!hello!hello!
compareTo
-1

ちなみにgroovyコマンドに対する-configscriptオプションは、2.1.0-rc-2以降じゃないと使えません。

# configでast(Newify)してるのに@Newifyしないとうまく作用しないのは原因不明です。