class SyntaxTree::YARV::Compiler::RubyVisitor

This visitor is responsible for converting Syntax Tree nodes into their corresponding Ruby structures. This is used to convert the operands of some instructions like putobject that push a Ruby object directly onto the stack. It is only used when the entire structure can be represented at compile-time, as opposed to constructed at run-time.

Public Class Methods

compile(node) click to toggle source

This will attempt to compile the given node. If it’s possible, then it will return the compiled object. Otherwise it will return nil.

# File lib/syntax_tree/yarv/compiler.rb, line 122
def self.compile(node)
  node.accept(new)
rescue CompilationError
end

Public Instance Methods

visit_array(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 128
def visit_array(node)
  node.contents ? visit_all(node.contents.parts) : []
end
visit_bare_assoc_hash(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 132
def visit_bare_assoc_hash(node)
  node.assocs.to_h do |assoc|
    # We can only convert regular key-value pairs. A double splat **
    # operator means it has to be converted at run-time.
    raise CompilationError unless assoc.is_a?(Assoc)
    [visit(assoc.key), visit(assoc.value)]
  end
end
Also aliased as: visit_hash
visit_float(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 141
def visit_float(node)
  node.value.to_f
end
visit_hash(node)
visit_imaginary(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 147
def visit_imaginary(node)
  node.value.to_c
end
visit_int(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 151
def visit_int(node)
  case (value = node.value)
  when /^0b/
    value[2..].to_i(2)
  when /^0o/
    value[2..].to_i(8)
  when /^0d/
    value[2..].to_i
  when /^0x/
    value[2..].to_i(16)
  else
    value.to_i
  end
end
visit_label(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 166
def visit_label(node)
  node.value.chomp(":").to_sym
end
visit_mrhs(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 170
def visit_mrhs(node)
  visit_all(node.parts)
end
visit_qsymbols(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 174
def visit_qsymbols(node)
  node.elements.map { |element| visit(element).to_sym }
end
visit_qwords(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 178
def visit_qwords(node)
  visit_all(node.elements)
end
visit_range(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 182
def visit_range(node)
  left, right = [visit(node.left), visit(node.right)]
  node.operator.value === ".." ? left..right : left...right
end
visit_rational(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 187
def visit_rational(node)
  node.value.to_r
end
visit_regexp_literal(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 191
def visit_regexp_literal(node)
  if node.parts.length == 1 && node.parts.first.is_a?(TStringContent)
    Regexp.new(
      node.parts.first.value,
      visit_regexp_literal_flags(node)
    )
  else
    # Any interpolation of expressions or variables will result in the
    # regular expression being constructed at run-time.
    raise CompilationError
  end
end
visit_regexp_literal_flags(node) click to toggle source

This isn’t actually a visit method, though maybe it should be. It is responsible for converting the set of string options on a regular expression into its equivalent integer.

# File lib/syntax_tree/yarv/compiler.rb, line 249
def visit_regexp_literal_flags(node)
  node
    .options
    .chars
    .inject(0) do |accum, option|
      accum |
        case option
        when "i"
          Regexp::IGNORECASE
        when "x"
          Regexp::EXTENDED
        when "m"
          Regexp::MULTILINE
        else
          raise "Unknown regexp option: #{option}"
        end
    end
end
visit_symbol_literal(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 204
def visit_symbol_literal(node)
  node.value.value.to_sym
end
visit_symbols(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 208
def visit_symbols(node)
  node.elements.map { |element| visit(element).to_sym }
end
visit_tstring_content(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 212
def visit_tstring_content(node)
  node.value
end
visit_unsupported(_node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 268
def visit_unsupported(_node)
  raise CompilationError
end
visit_var_ref(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 216
def visit_var_ref(node)
  raise CompilationError unless node.value.is_a?(Kw)

  case node.value.value
  when "nil"
    nil
  when "true"
    true
  when "false"
    false
  else
    raise CompilationError
  end
end
visit_word(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 231
def visit_word(node)
  if node.parts.length == 1 && node.parts.first.is_a?(TStringContent)
    node.parts.first.value
  else
    # Any interpolation of expressions or variables will result in the
    # string being constructed at run-time.
    raise CompilationError
  end
end
visit_words(node) click to toggle source
# File lib/syntax_tree/yarv/compiler.rb, line 241
def visit_words(node)
  visit_all(node.elements)
end