This topic has missing or partial documentation. Please help us improve it.
Once the parser has finished calling process_* methods an
abstract syntax tree is created. The syntax tree represents the
abstract syntactic structure of the parsed source code. Each node in
the tree denotes a construct in the source code. This tree is composed of instances
of classes defined in lib/compiler/ast/ directory.
Each of these classes inherits from Rubinius::AST::Node class.
The Node class defines a few methods that are utilized
by the subclasses (eg. pos(g) which records the line number for debugging purposes).
The AST classes usually define at least 3 methods:
process_* methods in the previous stageThe easiest way to see the AST that gets created is to call to_ast
on a string containing the code, eg:
irb(main):002:0> "a = 1".to_ast
=> #<Rubinius::AST::LocalVariableAssignment:0xf70
@value=#<Rubinius::AST::FixnumLiteral:0xf74 @value=1 @line=1>
@name=:a @variable=nil @line=1>
or compile the code and pass the -A option:
rbx compile -A -e "def hello;end"
Script
@name: __script__
@file: "(snippet)"
@body: \
Define
@name: hello
@line: 1
@arguments: \
FormalArguments
@defaults: nil
@names: \
@block_arg: nil
@optional: \
@splat: nil
@line: 1
@required: \
@body: \
Block
@line: 1
@array: \
NilLiteral
@line: 1
Similarily it’s possible to get a representation of the syntax tree as s-expressions:
irb(main):002:0> "a = 1".to_sexp
=> [:lasgn, :a, [:lit, 1]]
or pass the -S option to compile:
rbx compile -S -e "def hello;end"
[:script, [:defn, :hello, [:args], [:scope, [:block, [:nil]]]]]
The AST is a nested structure where nodes contain other nodes. For
example the hello method defined above is composed of a Script node
containing Define in its @body which in turns contains
FormalArguments in its @arguments and Block in its @body. The
Block node contains only the NilLiteral in its @array. The
NilLiteral node is a leaf node, it doesn’t contain other nodes.
Note that the following if expression:
rbx compile -S -e ":foo if :bar"
[:script, [:if, [:lit, :bar], [:lit, :foo], nil]]
and the same if expression but written differently
rbx compile -S -e "if :bar then :foo; end"
[:script, [:if, [:lit, :bar], [:lit, :foo], nil]]
produce exactly the same syntax tree. Because the tree doesn’t represent every detail that appears in the real syntax it is called “abstract”.
There are two ways to customize this stage of the compilation process. The easiest way to customize the creation of the AST is through AST Transforms.
You can also subclass the Melbourne processor and define your own
handlers for the process_ methods. This is an advanced topic that is
not yet documented.