class RbPlusPlus::Builders::Base

Base class for all code generation nodes

A Node is simply a handler for one complete statement or block of C++ code.

The code generation system for Rb++ is a two step process. We first, starting with an ExtensionNode, build up an internal representation of the resulting code, setting up all the code nodes required for proper wrapping of the library.

Once that’s in place, then we run through the tree, actually generating the C++ wrapper code.

Attributes

code[RW]

Link to the underlying rbgccxml node this node is writing code for

declarations[RW]

List of declaration nodes for this node

global_nodes[RW]

List of children nodes that generate code that the entire extension needs to be able to read. Code that fits here includes any auto-generated to_/from_ruby and any Allocation Strategies

includes[RW]

List of includes for this node

nodes[RW]

List of children nodes

parent[RW]

Link to the parent node of this node

registrations[RW]

List of registeration nodes for this node

rice_variable[RW]

The Rice variable name for this node

rice_variable_type[RW]

The type of the #rice_variable

Public Class Methods

new(code, parent = nil) click to toggle source
# File lib/rbplusplus/builders/base.rb, line 46
def initialize(code, parent = nil)
  @code = code
  @parent = parent
  @includes = []
  @declarations = []
  @registrations = []
  @nodes = []
  @global_nodes = []
end

Public Instance Methods

build() click to toggle source

Trigger the construction of the internal representation of a given node. All nodes must implement this.

# File lib/rbplusplus/builders/base.rb, line 63
def build
  raise "Nodes must implement #build"
end
has_children?() click to toggle source

Does this builder node have child nodes?

# File lib/rbplusplus/builders/base.rb, line 57
def has_children?
  @nodes && !@nodes.empty?
end
qualified_name() click to toggle source

Proxy method for writers

# File lib/rbplusplus/builders/base.rb, line 97
def qualified_name
  self.code.qualified_name
end
sort() click to toggle source

Once building is done, the resulting node tree needs to be sorted according to subclass / superclass definitions. Like anything with C++, Rice needs to know about base classes before it can build sub classes. We go through each node’s children, sorting them according to this.

# File lib/rbplusplus/builders/base.rb, line 77
def sort
  @nodes.each { |n| n.sort }

  # sort_by lets us build an array of numbers that Ruby then uses
  # to sort the list. Our method here is to simply specify the
  # depth a given class is in a heirarchy, as bigger numbers end
  # up sorted farther down the list
  @nodes =
    @nodes.sort_by do |a|
      if a.is_a?(ClassNode)
        superclass_count(a.code)
      elsif a.is_a?(ImplicitCasterNode) # Hmm, hack
        1_000_000
      else
        0
      end
    end
end
write() click to toggle source

After build has run, this then triggers the actual generation of the C++ code All nodes must implement this.

# File lib/rbplusplus/builders/base.rb, line 69
def write
  raise "Nodes must implement #write"
end

Protected Instance Methods

add_child(node) click to toggle source

Given a new node, build it and add it to our nodes list

# File lib/rbplusplus/builders/base.rb, line 124
def add_child(node)
  node.build
  nodes << node
end
add_global_child(node) click to toggle source

Add a node to the “globals” list. See the declaration of #global_nodes

# File lib/rbplusplus/builders/base.rb, line 130
def add_global_child(node)
  node.build
  global_nodes << node
end
do_not_wrap?(node) click to toggle source

Should this node be wrapped as it is or has the user specified something else for this node?

# File lib/rbplusplus/builders/base.rb, line 115
def do_not_wrap?(node)
  node.ignored? ||
    (node.moved_to && node.moved_to != self.code) ||
    !node.public? ||
    (node.is_a?(RbGCCXML::Struct) && node.incomplete?) ||
    node.is_a?(RbGCCXML::FundamentalType)
end
find_typedef(node = self.code) click to toggle source

Any node can also have a typedef. There are cases where it’s much better to use a typedef instead of the original fully qualified name, for example deep template definitions (say, any STL structures). This method will look for the best Typedef to use for this node. This lookup can be disabled on a per-node basis by calling node.disable_typedef_lookup, as there are cases where the typedef search works against the parsed code.

@returns the typedef node found or the node passed in (self.code by default)

# File lib/rbplusplus/builders/base.rb, line 143
def find_typedef(node = self.code)
  return node if node.is_a?(RbGCCXML::FundamentalType)

  found = last_found = node

  if !node._disable_typedef_lookup?
    while found
      last_found = found
      typedef = RbGCCXML::NodeCache.all("Typedef").select {|t| t.attributes["type"] == found.attributes["id"]}.first

      # Some typedefs have the access attribute, some don't. We want those without the attribute
      # and those with the access="public". For this reason, we can't put :access => "public" in the
      # query above.
      found = (typedef && typedef.public?) ? typedef : nil
    end
  end

  if node == self.code && last_found != node
    Logger.debug "Found Typedef #{last_found.qualified_name} for #{node.qualified_name}"
  end

  last_found
end
Also aliased as: find_typedef_for
find_typedef_for(node = self.code) click to toggle source
Alias for: find_typedef
superclass_count(node) click to toggle source

Count the heirarchy depth of a given class node

# File lib/rbplusplus/builders/base.rb, line 104
def superclass_count(node)
  count = 0
  n = node
  while n = n.superclass
    count += 1
  end
  count
end