4

いくつかのステートメントと式を別の言語に翻訳する単純な Ruby DSL を作成したいと考えています。基本的な例は次のとおりです。

some_function {
    t + 2
}

ここで、t は Ruby 変数ではないため、ブロックは Ruby によって評価できません (また、評価してはなりません!)。したがって、私の最善の策は、解析出力 (または AST) を使用して自分で翻訳を行うことです。そのために、ParseTree と ruby​​2ruby を使用できます。ただし、使用したい他の構成要素があります。たとえば、次のようになります。

1.upto(10) {|x|
    some_function {
        t + x
    }
}

ここでは、ローカル変数があり、翻訳を行うためにその値を取得する必要があります。ただし、ブロック評価を行う関数では、呼び出しブロックのローカル変数にアクセスできません。それがグローバル変数 ($x) である場合、その名前が global_variables 配列に存在するかどうかを確認でき、最悪の場合は eval を使用できますが、可能であれば、ローカル変数に対してどのように行うことができますか?

アップデート:

物事を片付けるためだけに。最初に言ったように、ブロックに対応する AST (to_sexp を使用) を取得するために ruby​​2ruby (したがって ParseTree) を使用しています。しかし、ブロック内でローカル変数を使用すると、次のような問題が発生します。

[:dvar, :x]

したがって、変数の値をその名前から文字列/シンボルとして取得する必要があります。また、式全体を別の言語または構文 (RPN など) に翻訳したいので、method_missing または instance_eval を使用できません。

それでも、Ruby 1.9 では完全にサポートされていないため、ParseTree に基づかない別のソリューションを歓迎します。

4

3 に答える 3

1

変数値を取得するには、proc のバインディングを使用します。

def some_function(&block)
  b = block.binding
  p [b.eval("t"), b.eval("x")]
end

t = 1
1.upto(10) {|x|
  some_function {
    t + x
  }
}
于 2009-05-09T16:05:28.967 に答える
0

ここで、t は Ruby 変数ではないため、ブロックは Ruby によって評価できません (また、評価してはなりません!)。

「未評価」制限の理由は何ですか? method_missingは「欠落している」変数の評価をエレガントに処理するように見えtますが、Ruby はx変数を自動的に逆参照します。

于 2009-05-09T12:13:38.227 に答える
0

のオブジェクトに対して instance_eval を使用できますt

class Context
  attr_accessor :t

  def initialize(_t)
    @t = _t
  end
end

def some_function(&block)
  puts Context.new(1).instance_eval(&block)
end

1.upto(10) {|x|
  some_function {
    t + x
  }
}
于 2009-05-09T12:24:07.900 に答える