Class: Oga::Ruby::Node

Inherits:
BasicObject
Defined in:
lib/oga/ruby/node.rb

Overview

Class representing a single node in a Ruby AST.

The setup of this class is roughly based on the “ast” Gem. The “ast” Gem is not used for this class as it provides too many methods that might conflict with this class’ #method_missing.

ASTs can be built by creating a node and then chaining various method calls together. For example, the following could be used to build an “if” statement:

number1 = Node.new(:lit, %w{10})
number2 = Node.new(:lit, %w{20})

(number2 > number1).if_true do
  Node.new(:lit, %w{30})
end

When serialized to Ruby this would roughly lead to the following code:

if 20 > 10
  30
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(type, children = []) ⇒ Node

Returns a new instance of Node

Parameters:

  • type (Symbol)
  • children (Array) (defaults to: [])


35
36
37
38
# File 'lib/oga/ruby/node.rb', line 35

def initialize(type, children = [])
  @type     = type.to_sym
  @children = children
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args) ⇒ Oga::Ruby::Node

Returns a node for a method call.

Parameters:

  • name (Symbol)

    The name of the method to call.

  • args (Array)

    Any arguments (as Node instances) to pass to the method.

Returns:



179
180
181
# File 'lib/oga/ruby/node.rb', line 179

def method_missing(name, *args)
  Node.new(:send, [self, name.to_s, *args])
end

Instance Attribute Details

#typeSymbol (readonly)

Returns:

  • (Symbol)


31
32
33
# File 'lib/oga/ruby/node.rb', line 31

def type
  @type
end

Instance Method Details

#add_block(*args) ⇒ Oga::Ruby::Node

Wraps the current node in a block.

Parameters:

  • args (Array)

    Arguments (as Node instances) to pass to the block.

Returns:



114
115
116
# File 'lib/oga/ruby/node.rb', line 114

def add_block(*args)
  Node.new(:block, [self, args, yield])
end

#and(other) ⇒ Oga::Ruby::Node

Returns a boolean “and” node.

Parameters:

Returns:



81
82
83
# File 'lib/oga/ruby/node.rb', line 81

def and(other)
  Node.new(:and, [self, other])
end

#assign(other) ⇒ Oga::Ruby::Node

Returns an assignment node.

This method wraps assigned values in a begin/end block to ensure that multiple lines of code result in the proper value being assigned.

Parameters:

Returns:



61
62
63
64
65
66
67
# File 'lib/oga/ruby/node.rb', line 61

def assign(other)
  if other.type == :followed_by
    other = other.wrap
  end

  Node.new(:assign, [self, other])
end

#elseOga::Ruby::Node

Adds an “else” statement to the current node.

This method assumes it’s being called only on “if” nodes.

Returns:



157
158
159
# File 'lib/oga/ruby/node.rb', line 157

def else
  Node.new(:if, @children + [yield])
end

#eq(other) ⇒ Oga::Ruby::Node

Returns an equality expression node.

Parameters:

Returns:



73
74
75
# File 'lib/oga/ruby/node.rb', line 73

def eq(other)
  Node.new(:eq, [self, other])
end

#followed_by(other = nil) ⇒ Oga::Ruby::Node

Chains two nodes together.

Parameters:

Returns:



165
166
167
168
169
# File 'lib/oga/ruby/node.rb', line 165

def followed_by(other = nil)
  other = yield if ::Kernel.block_given?

  Node.new(:followed_by, [self, other])
end

#if_falseObject

Wraps the current node in an if !... statement.

See Also:

  • Oga::Ruby::Node.[[#if_true]


138
139
140
# File 'lib/oga/ruby/node.rb', line 138

def if_false
  self.not.if_true { yield }
end

#if_trueOga::Ruby::Node

Wraps the current node in an if statement node.

The body of this statement is set to the return value of the supplied block.

Returns:



131
132
133
# File 'lib/oga/ruby/node.rb', line 131

def if_true
  Node.new(:if, [self, yield])
end

#inspectString

Returns:

  • (String)


184
185
186
# File 'lib/oga/ruby/node.rb', line 184

def inspect
  "(#{type} #{@children.map(&:inspect).join(' ')})"
end

#is_a?(klass) ⇒ Oga::Ruby::Node

Returns a node for Ruby’s “is_a?” method.

Parameters:

  • klass (Class)

Returns:



106
107
108
# File 'lib/oga/ruby/node.rb', line 106

def is_a?(klass)
  Node.new(:send, [self, 'is_a?', Node.new(:lit, [klass.to_s])])
end

#notOga::Ruby::Node

Returns a node that evaluates to its inverse.

For example, a variable foo would be turned into !foo.

Returns:



98
99
100
# File 'lib/oga/ruby/node.rb', line 98

def not
  !self
end

#or(other) ⇒ Oga::Ruby::Node

Returns a boolean “or” node.

Parameters:

Returns:



89
90
91
# File 'lib/oga/ruby/node.rb', line 89

def or(other)
  Node.new(:or, [self, other])
end

#to_aArray Also known as: to_ary

Returns:

  • (Array)


41
42
43
# File 'lib/oga/ruby/node.rb', line 41

def to_a
  @children
end

#to_arrayOga::Ruby::Node

Returns a “to_a” call node.

Returns:



50
51
52
# File 'lib/oga/ruby/node.rb', line 50

def to_array
  Node.new(:send, [self, :to_a])
end

#while_trueOga::Ruby::Node

Wraps the current node in a while statement.

The body of this statement is set to the return value of the supplied block.

Returns:



148
149
150
# File 'lib/oga/ruby/node.rb', line 148

def while_true
  Node.new(:while, [self, yield])
end

#wrapOga::Ruby::Node

Wraps the current node in a begin node.

Returns:



121
122
123
# File 'lib/oga/ruby/node.rb', line 121

def wrap
  Node.new(:begin, [self])
end