Class: Otaku::Handler::MagicProc

Inherits:
Object
  • Object
show all
Defined in:
lib/otaku/handler.rb

Constant Summary collapse

RUBY_PARSER =
RubyParser.new
RUBY_2_RUBY =
Ruby2Ruby.new

Instance Method Summary collapse

Constructor Details

#initialize(block) ⇒ MagicProc

Returns a new instance of MagicProc.



31
32
33
# File 'lib/otaku/handler.rb', line 31

def initialize(block)
  @block = block
end

Instance Method Details

#code_fragmentsObject



48
49
50
51
52
53
54
55
# File 'lib/otaku/handler.rb', line 48

def code_fragments
  ignore, start_marker, arg =
    [:ignore, :start_marker, :arg].map{|key| code_match_args[key] }
  [
    "proc #{start_marker} |#{arg}| ",
    source_code.sub(ignore, '')
  ]
end

#code_match_argsObject



79
80
81
82
83
84
85
86
87
88
# File 'lib/otaku/handler.rb', line 79

def code_match_args
  @code_match_args ||= (
    args = source_code.match(code_regexp)
    {
      :ignore => args[1],
      :start_marker => args[3],
      :arg => args[4]
    }
  )
end

#code_regexpObject



74
75
76
77
# File 'lib/otaku/handler.rb', line 74

def code_regexp
  @code_regexp ||=
    /^(.*?(Otaku\.start.*?|lambda|proc|Proc\.new)\s*(do|\{)\s*\|(\w+)\|\s*)/m
end

#frag_regexpObject



67
68
69
70
71
72
# File 'lib/otaku/handler.rb', line 67

def frag_regexp
  @frag_regexp ||= (
    end_marker = {'do' => 'end', '{' => '\}'}[code_match_args[:start_marker]]
    /^(.*?\W#{end_marker})/m
  )
end

#sexp_regexpObject



57
58
59
60
61
62
63
64
65
# File 'lib/otaku/handler.rb', line 57

def sexp_regexp
  @sexp_regexp ||= (
    Regexp.new([
      Regexp.quote("s(:iter, s(:call, nil, :"),
      "(proc|lambda)",
      Regexp.quote(", s(:arglist)), s(:lasgn, :#{code_match_args[:arg]}), s("),
    ].join)
  )
end

#source_codeObject



90
91
92
93
94
95
96
# File 'lib/otaku/handler.rb', line 90

def source_code
  @source_code ||= (
    @file, line_no = /^#<Proc:0x[0-9A-Fa-f]+@(.+):(\d+).*?>$/.match(@block.inspect)[1..2]
    @line_no = line_no.to_i
    File.readlines(@file)[@line_no.pred .. -1].join
  )
end

#to_codeObject



35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/otaku/handler.rb', line 35

def to_code
  code, remaining = code_fragments

  while frag = remaining[frag_regexp,1]
    begin
      sexp = RUBY_PARSER.parse(code += frag, File.expand_path(@file))
      return RUBY_2_RUBY.process(sexp) if sexp.inspect =~ sexp_regexp
    rescue SyntaxError, Racc::ParseError, NoMethodError
      remaining.sub!(frag,'')
    end
  end
end