2013-04-17 2 views
3

첨부 된 블록에서 약간의 마법을 사용해야하는 방법이 있습니다. 이러한 블록의 샘플블록에서 def를 가로 채기

myMethod do 

    somemethod x 
    someother y 
    def name(a,b) 
    a+b 
    end 
end 

처음 두 메소드 호출 (somemethod xsomeother y)는 단지 정상으로 실행되어야 할 것이다. 그러나 실제로 새 메서드를 정의하지 않고 메서드 정의 (S- 식)를 가로 채 싶습니다. 전체 블록을 S 식으로 변환 한 다음 AST를 검색하면이 작업을 수행 할 수 있습니다. 그러나 방법을 호출하는 방법을 알아 내야합니다. 둘 중 하나에 대한 해결책이 될 것입니다. 즉, S-식 (Ruby2Ruby 이해할 수있는)

  • 는 S-표현으로 변환 블록 및 메쏘드 호출을 발견하고 이들
  • 편집을 실행하기 위해, 변환의 정의를 인터셉트하거나

    • 인 내가 understa 경우 내가 찾는 AST는

      [:defn, 
      :name, 
      [:args,:a,:b], 
      [:call, 
          [lvar,:a], 
          :+ 
          [lvar,:b]]] 
      
    +0

    요구 사항에 대해 더 자세히 말할 수 있습니까? '이름'으로 원하는게 뭐야? –

    +0

    @RubyLovely 샘플로 업데이트했습니다 –

    +0

    ['Module # method_added'] (http://www.ruby-doc.org/core-2.0/Module.html#method-i-method_added) 콜백으로 인해 당신은 당신이 원하는 것을합니다. – dbenhur

    답변

    0

    비슷한입니다 올바르게, 당신은 다른 메소드에 전달 된 코드 블록 내에서 메소드를 정의 할 수 있기를 원하지만, 실제로 정의되지는 않지만 대신 S- 표현식으로 변환되도록 내부 메소드 정의를 인터셉트 할 수 있습니까? 따라서 주석 처리 된 것처럼 거의 동작하고 일부 외부 프로세스가 소스 코드를 통해 들어 와서 구현을 S- 표현으로 구문 분석 한 것처럼 작동하게할까요? 같은

    뭔가 :

    myMethod do 
    
        somemethod x 
        someother y 
        # def name(a,b) 
        # a+b 
        # end 
    end 
    

    경우 somemethodsomeother 여전히 실행은 name의 구현이 정의되어 있지만 루비 인터프리터에서 무시됩니다. 그런 다음 어떻게 든이 구현을 S- 표현식으로 포착하려고합니다. 그것은 분명히 이런 식으로 해설하지 않을 것입니다. 해설을 해두면 좋지만, 그 행동을 묘사하는 좋은 방법입니다.

    글쎄, RubyParser gem이 원하는대로 할 수 있습니다. 그것은이 예에서와 같이, 방법에 문자열로 '여기 서'를 전달하는 능력을 활용 :

    require 'ruby_parser' 
    require 'pp' 
    
    pp RubyParser.new.parse(<<-EOF) 
    def plus(x,y) 
        x+y 
    end 
    EOF 
    # => s(:defn, :name, s(:args, :a, :b), s(:call, s(:lvar, :a), :+, s(:lvar, :b))) 
    
    : RubyParser를 사용

    def x (str) 
        str 
    end 
    
    x(<<-EOF) 
    this is 
        a here 
    document 
    EOF 
    
    # => "this is\n a here\ndocument\n" 
    

    , 당신은 다음과 같이 뭔가를 할 수

    그것은과 같이, 원하는 코드로 병합하고, 사소한 문제 일 것입니다 : 당신이 볼 수 있듯이

    require 'ruby_parser' 
    
    def myMethod 
        x = yield 
    end 
    
    def somemethod(x) 
        puts x 
    end 
    
    def someother(y) 
        puts y 
    end 
    
    x = 'magic' 
    y = 'output' 
    
    sexp = myMethod do 
        somemethod x 
        someother y 
        RubyParser.new.parse(<<-EOF) 
        def name(a,b) 
        a+b 
        end 
        EOF 
    end 
    
    pp sexp 
    name(1,2) 
    # magic 
    # output 
    # s(:defn, :name, s(:args, :a, :b), s(:call, s(:lvar, :a), :+, s(:lvar, :b))) 
    # NoMethodError: undefined local variable or method 'name' for main:Object 
    

    는, 메소드 정의는 본질적으로 문자열이며, 같은 조작 할 수 있습니다.

    +0

    제안 해 주셔서 감사합니다. 그러나 이미 귀하의 코드와 같은 문자열을 처리 할 수있는 솔루션이 있습니다. –