doc/AST_FORMAT
AST and Source Location
Literals
Singletons
Format:
(true) "true" ~~~~ expression (false) "false" ~~~~~ expression (nil) "nil" ~~~ expression
Integer
Format:
(int 123) "123" ~~~ expression
Float
Format:
(float 1.0) "1.0" ~~~ expression
String
Plain
Format:
(str "foo") "'foo'" ^ begin ^ end ~~~~~ expresion
With interpolation
Format:
(dstr (str "foo") (lvar bar) (str "baz")) '"foo#{bar}baz"' ^ begin ^ end ~~~~~~~~~~~~~~ expression
Symbol
Plain
Format:
(sym :foo) ":foo" ~~~~ expresion ":'foo'" ^ begin ^ end ~~~~~~ expression
With interpolation
Format:
(dsym (str "foo") (lvar bar) (str "baz")) ':"foo#{bar}baz"' ^ begin ^ end ~~~~~~~~~~~~~~~ expression
Execute-string
Format:
(xstr (str "foo") (lvar bar)) "`foo#{bar}`" ^ begin ^ end ~~~~~~~~~~~ expression
Regexp
Options
Format:
(regopt :i :m) "im" ~~ expression
Regexp
Format:
(regexp (str "foo") (lvar :bar) (regopt :i)) "/foo#{bar}/i" ^ begin ^ end ~~~~~~~~~~~ expression
Array
Plain
Format:
(array (int 1) (int 2)) "[1, 2]" ~~~~~~ expression
Splat
Can also be used in argument lists: foo(bar, *baz)
Format:
(splat (lvar :foo)) "*foo" ^ operator ~~~~ expression
With interpolation
Format:
(array (int 1) (splat (lvar :foo)) (int 2)) "[1, *foo, 2]" ^ begin ^ end ~~~~~~~~~~~~ expression
Hash
Pair
With hashrocket
Format:
(pair (int 1) (int 2)) "1 => 2" ~~ operator ~~~~~~ expression
With label (1.9)
Format:
(pair (sym :answer) (int 42)) "answer: 42" ^ operator (pair) ~~~~~~ expression (sym) ~~~~~~~~~~ expression (pair)
Plain
Format:
(hash (pair (int 1) (int 2)) (pair (int 3) (int 4))) "{1 => 2, 3 => 4}" ^ begin ^ end ~~~~~~~~~~~~~~~~ expression
Keyword splat (2.0)
Can also be used in argument lists: foo(bar, **baz)
Format:
(kwsplat (lvar :foo)) "**foo" ~~ operator ~~~~~ expression
With interpolation (2.0)
Format:
(hash (pair (sym :foo) (int 2)) (kwsplat (lvar :bar))) "{ foo: 2, **bar }" ^ begin ^ end ~~~~~~~~~~~~~~~~~ expression
Range
Inclusive
Format:
(irange (int 1) (int 2)) "1..2" ~~ operator ~~~~ expression
Exclusive
Format:
(erange (int 1) (int 2)) "1...2" ~~~ operator ~~~~~ expression
Access
Self
Format:
(self) "self" ~~~~ expression
Local variable
Format:
(lvar :foo) "foo" ~~~ expression
Instance variable
Format:
(ivar :@foo) "@foo" ~~~~ expression
Class variable
Format:
(cvar :$foo) "$foo" ~~~~ expression
Global variable
Format:
(gvar :$foo) "$foo" ~~~~ expression
Constant
Top-level constant
Format:
(const (cbase) :Foo) "::Foo" ~~~ name ~~ double_colon ~~~~~ expression
Scoped constant
Format:
(const (lvar :a) :Foo) "a::Foo" ~~~ name ~~ double_colon ~~~~~~ expression
Unscoped constant
Format:
(const nil :Foo) "Foo" ~~~ name ~~~ expression
defined?
Format:
(defined? (lvar :a)) "defined? a" ~~~~~~~~ keyword ~~~~~~~~~~ expression "defined?(a)" ~~~~~~~~ keyword ^ begin ^ end ~~~~~~~~~~~ expression
Assignment
To local variable
Format:
(lvasgn :foo (lvar :bar)) "foo = bar" ^ operator ~~~~~~~~~ expression
To instance variable
Format:
(ivasgn :@foo (lvar :bar)) "@foo = bar" ^ operator ~~~~~~~~~~ expression
To class variable
Format:
(cvasgn :@@foo (lvar :bar)) "@@foo = bar" ^ operator ~~~~~~~~~~~ expression
To global variable
Format:
(gvasgn :$foo (lvar :bar)) "$foo = bar" ^ operator ~~~~~~~~~~ expression
To constant
Top-level constant
Format:
(casgn (cbase) :Foo (int 1)) "::Foo = 1" ~~~ name ~ operator ~~~~~~~ expression
Scoped constant
Format:
(casgn (lvar :a) :Foo (int 1)) "a::Foo = 1" ~~~ name ~ operator ~~~~~~~~ expression
Unscoped constant
Format:
(casgn nil :Foo (int 1)) "Foo = 1" ~~~ name ~ operator ~~~~~~~ expression
Multiple assignment
Multiple left hand side
Format:
(mlhs (lvasgn :a) (lvasgn :b)) "a, b" ~~~~ expression "(a, b)" ^ begin ^ end ~~~~~~ expression
Assignment
Rule of thumb: every node inside (mlhs)
is “incomplete”; to make
it “complete”, one could imagine that a corresponding node from the
mrhs is “appended” to the node in question. This applies both to
side-effect free assignments (lvasgn
, etc) and side-effectful
assignments (send
).
Format:
(masgn (mlhs (lvasgn :foo) (lvasgn :bar)) (array (int 1) (int 2))) "foo, bar = 1, 2" ^ operator ~~~~~~~~~~~~~~~ expression (masgn (mlhs (ivasgn :@a) (cvasgn :@@b)) (array (splat (lvar :c)))) "@a, @@b = *c" (masgn (mlhs (mlhs (lvasgn :a) (lvasgn :b)) (lvasgn :c)) (lvar :d)) "a, (b, c) = d" (masgn (mlhs (send (self) :a=) (send (self) :[]= (int 1))) (lvar :a)) "self.a, self[1] = a"
Binary operator-assignment
Binary operator-assignment features the same “incomplete assignments” and “incomplete calls” as multiple assignment.
Variable binary operator-assignment
Format:
(op-asgn (lvasgn :a) :+ (int 1)) "a += 1" ~~ operator ~~~~~~ expression (op-asgn (ivasgn :a) :+ (int 1)) "@a += 1"
Ruby_parser output for reference:
"a += 1" s(:lasgn, :a, s(:call, s(:lvar, :a), :+, s(:int, 1))) "@a += 1" s(:iasgn, :@a, s(:call, s(:ivar, :@a), :+, s(:int, 1)))
Method binary operator-assignment
Format:
(op-asgn (send (ivar :@a) :b) :+ (int 1)) "@a.b += 1" ~ selector (send) ~~~~ expression (send) ~~ operator (op-asgn) ~~~~~~~~~ expression (op-asgn) (op-asgn (send (ivar :@a) :[] (int 0) (int 1))) :+ (int 1)) "@a[0, 1] += 1" ~~~~~~ selector (send) ~~~~~~~~ expression (send) ~~ operator (op-asgn) ~~~~~~~~~~~~~ expression (op-asgn)
Ruby_parser output for reference:
"@a.b += 1" s(:op_asgn2, s(:ivar, :@a), :b=, :+, s(:int, 1)) "@a[0, 1] += 1" s(:op_asgn1, s(:ivar, :@a), s(:arglist, s(:int, 0), s(:int, 1)), :+, s(:int, 1))
Logical operator-assignment
Logical operator-assignment features the same “incomplete assignments” and “incomplete calls” as multiple assignment.
Variable logical operator-assignment
Format:
(or-asgn (iasgn :@a) (int 1)) "@a ||= 1" ~~~ operator ~~~~~~~~ expression (and-asgn (lasgn :a) (int 1)) "a &&= 1" ~~~ operator ~~~~~~~ expression
Ruby_parser output for reference:
"@a ||= 1" s(:op_asgn_or, s(:ivar, :@a), s(:iasgn, :@a, s(:int, 1))) "a &&= 1" s(:op_asgn_and, s(:lvar, :a), s(:lasgn, :a, s(:int, 1)))
Method logical operator-assignment
Format:
(or-asgn (send (ivar :@foo) :bar) (int 1)) "@foo.bar ||= 1" ~~~ selector (send) ~~~~~~~~ expr (send) ~~~ operator (or-asgn) ~~~~~~~~~~~~~~ expression (or-asgn) (and-asgn (send (lvar :@foo) :bar) (int 1)) "foo.bar &&= 1" ~~~ selector (send) ~~~~~~~ expr (send) ~~~ operator (and-asgn) ~~~~~~~~~~~~~ expression (and-asgn) (or-asgn (send (ivar :@foo) :[] (int 1) (int 2)) (int 1)) "@foo[1, 2] ||= 1" ~~~~~~ selector (send) ~~~~~~~~~~ expr (send) ~~~ operator (or-asgn) ~~~~~~~~~~~~~~~~ expression (or-asgn)
Ruby_parser output for reference:
"@foo.bar &&= 1" s(:op_asgn2, s(:ivar, :@foo), :bar=, :"&&", s(:int, 1)) "@foo[0] ||= 1" s(:op_asgn1, s(:ivar, :@foo), s(:arglist, s(:int, 0)), :"||", s(:int, 1))
Class and module definition
Module
Format:
(module (const nil :Foo) (nil)) "module Foo; end" ~~~~~~ keyword ~~~ end
Class
Format:
(class (const nil :Foo) (const nil :Bar) (nil)) "class Foo < Bar; end" ~~~~~ keyword ~~~ end ~ operator ~~~~~~~~~~~~~~~~~~~~ expression (class (const nil :Foo) nil (nil)) "class Foo; end" ~~~~~ keyword ~~~ end ~~~~~~~~~~~~~~ expression
Singleton class
Format:
(sclass (lvar :a) (nil)) "class << a; end" ~~~~~ keyword ~~ operator ~~~ end ~~~~~~~~~~~~~~~ expression
Method (un)definition
Instance methods
Format:
(def :foo (args) nil) "def foo; end" ~~~ keyword ~~~ name ~~~ end ~~~~~~~~~~~~ expression
Singleton methods
Format:
(defs (self) (args) nil) "def self.foo; end" ~~~ keyword ~~~ name ~~~ end ~~~~~~~~~~~~~~~~~ expression
Undefinition
Format:
(undef (sym :foo) (sym :bar) (dsym (str "foo") (int 1))) "undef foo :bar :"foo#{1}"" ~~~~~ keyword ~~~~~~~~~~~~~~~~~~~~~~~~~ expression
Aliasing
Method aliasing
Format:
(alias (sym :foo) (dsym (str "foo") (int 1))) "alias foo :"foo#{1}"" ~~~~~ keyword ~~~~~~~~~~~~~~~~~~~~ expression
Global variable aliasing
Format:
(alias (gvar :$foo) (gvar :$bar)) "alias $foo $bar" ~~~~~ keyword ~~~~~~~~~~~~~~~ expression (alias (gvar :$foo) (back-ref :$&)) "alias $foo $&" ~~~~~ keyword ~~~~~~~~~~~~~~~ expression
Formal arguments
Format:
(args (arg :foo)) "(foo)" ~~~~~ expression
Required argument
Format:
(arg :foo) "foo" ~~~ expression ~~~ name
Optional argument
Format:
(optarg :foo (int 1)) "foo = 1" ~~~~~~~ expression ^ operator ~~~ name
Named splat argument
Format:
(restarg :foo) "*foo" ~~~~ expression ~~~ name
Begin of the expression
points to *
.
Unnamed splat argument
Format:
(restarg) "*" ^ expression
Block argument
Format:
(blockarg :foo) "&foo" ~~~ name ~~~~ expression
Begin of the expression
points to &
.
Expression arguments
Ruby 1.8 allows to use arbitrary expressions as block arguments,
such as @var
or foo.bar
. Such expressions should be treated as
if they were on the lhs of a multiple assignment.
Format:
(args (arg_expr (ivasgn :@bar))) "|@bar|" (args (arg_expr (send (send nil :foo) :a=))) "|foo.a|" (args (restarg_expr (ivasgn :@bar))) "|*@bar|" (args (blockarg_expr (ivasgn :@bar))) "|&@bar|"
Block shadow arguments
Format:
(args (shadowarg :foo) (shadowarg :bar)) "|; foo, bar|"
Decomposition
Format:
(def :f (args (arg :a) (mlhs (arg :foo) (restarg :bar)))) "def f(a, (foo, *bar)); end" ^ begin ^ end ~~~~~~~~~~~ expression
Required keyword argument
Format:
(kwarg :foo (int 1)) "foo:" ~~~~ expression ~~~~ name
Optional keyword argument
Format:
(kwoptarg :foo (int 1)) "foo: 1" ~~~~~~ expression ~~~~ name
Named keyword splat argument
Format:
(kwrestarg :foo) "**foo" ~~~~~ expression ~~~ name
Unnamed keyword splat argument
Format:
(kwrestarg) "**" ~~ expression
Send
To self
Format:
(send nil :foo (lvar :bar)) "foo(bar)" ~~~ selector ^ begin ^ end ~~~~~~~~ expression
To receiver
Format:
(send (lvar :foo) :bar (int 1)) "foo.bar(1)" ~~~ selector ^ begin ^ end ~~~~~~~~~~ expression (send (lvar :foo) :+ (int 1)) "foo + 1" ^ selector ~~~~~~~ expression (send (lvar :foo) :-@) "-foo" ^ selector ~~~~ expression (send (lvar :foo) :a= (int 1)) "foo.a = 1" ~ selector ^ operator ~~~~~~~~~ expression (send (lvar :foo) :[] (int 1)) "foo[i]" ~~~ selector ~~~~~~ expression (send (lvar :bar) :[]= (int 1) (int 2) (lvar :baz)) "bar[1, 2] = baz" ~~~~~~ selector ^ operator ~~~~~~~~~~~~~~~ expression
To superclass
Format of super with arguments:
(super (lvar :a)) "super a" ~~~~~ keyword ~~~~~~~ expression (super) "super()" ^ begin ^ end ~~~~~ keyword ~~~~~~~ expression
Format of super without arguments (zero-arity):
(zsuper) "super" ~~~~~ keyword ~~~~~ expression
To block argument
Format:
(yield (lvar :foo)) "yield(foo)" ~~~~~ keyword ^ begin ^ end ~~~~~~~~~~ expression
Passing a literal block
(block (send nil :foo) (args (arg :bar)) (begin ...)) "foo do |bar|; end" ~~ begin ~~~ end ~~~~~~~~~~~~~ expression
Passing expression as block
Used when passing expression as block foo(&bar)
(send nil :foo (int 1) (block-pass (lvar :foo))) "foo(1, &foo)" ^ operator ~~~~ expression
Control flow
Logical operators
Binary (and or && ||)
Format:
(and (lvar :foo) (lvar :bar)) "foo and bar" ~~~ operator ~~~~~~~~~~~ expression
Unary (! not) (1.8)
Format:
(not (lvar :foo)) "!foo" ^ operator "not foo" ~~~ operator
Branching
Without else
Format:
(if (lvar :cond) (lvar :iftrue) nil) "if cond then iftrue; end" ~~ keyword ~~~~ begin ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~ expression "if cond; iftrue; end" ~~ keyword ~~~ end ~~~~~~~~~~~~~~~~~~~~ expression "iftrue if cond" ~~ keyword ~~~~~~~~~~~~~~ expression (if (lvar :cond) nil (lvar :iftrue)) "unless cond then iftrue; end" ~~~~~~ keyword ~~~~ begin ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression "unless cond; iftrue; end" ~~~~~~ keyword ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~ expression "iftrue unless cond" ~~~~~~ keyword ~~~~~~~~~~~~~~~~~~ expression
With else
Format:
(if (lvar :cond) (lvar :iftrue) (lvar :iffalse)) "if cond then iftrue; else; iffalse; end" ~~ keyword ~~~~ begin ~~~~ else ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression "if cond; iftrue; else; iffalse; end" ~~ keyword ~~~~ else ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression (if (lvar :cond) (lvar :iffalse) (lvar :iftrue)) "unless cond then iftrue; else; iffalse; end" ~~~~~~ keyword ~~~~ begin ~~~~ else ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression "unless cond; iftrue; else; iffalse; end" ~~~~~~ keyword ~~~~ else ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
With elsif
Format:
(if (lvar :cond1) (int 1) (if (lvar :cond2 (int 2) (int 3)))) "if cond1; 1; elsif cond2; 2; else 3; end" ~~ keyword (left) ~~~~~ else (left) ~~~ end (left) ~~~~~ keyword (right) ~~~~ else (right) ~~~ end (right)
Ternary
Format:
(if (lvar :cond) (lvar :iftrue) (lvar :iffalse)) "cond ? iftrue : iffalse" ^ question ^ colon ~~~~~~~~~~~~~~~~~~~~~~~ expression
Case matching
When clause
Format:
(when (regexp "foo" (regopt)) (begin (lvar :bar))) "when /foo/ then bar" ~~~~ keyword ~~~~ begin ~~~~~~~~~~~~~~~~~~~ expression (when (int 1) (int 2) (send nil :meth)) "when 1, 2; meth" (when (int 1) (splat (lvar :foo)) (send nil :meth)) "when 1, *foo; meth" (when (splat (lvar :foo)) (send nil :meth)) "when *foo; meth"
Case-expression clause
Without else
Format:
(case (lvar :foo) (when (str "bar") (lvar :bar)) nil) "case foo; when "bar"; bar; end" ~~~~ keyword ~~~ end
With else
Format:
(case (lvar :foo) (when (str "bar") (lvar :bar)) (lvar :baz)) "case foo; when "bar"; bar; else baz; end" ~~~~ keyword ~~~~ else ~~~ end
Case-conditions clause
Without else
Format:
(case nil (when (lvar :bar) (lvar :bar)) nil) "case; when bar; bar; end" ~~~~ keyword ~~~ end
With else
Format:
(case nil (when (lvar :bar) (lvar :bar)) (lvar :baz)) "case; when bar; bar; else baz; end" ~~~~ keyword ~~~~ else ~~~ end (case nil (lvar :baz)) "case; else baz; end" ~~~~ keyword ~~~~ else ~~~ end
Looping
With precondition
Format:
(while (lvar :condition) (send nil :foo)) "while condition do foo; end" ~~~~~ keyword ~~ begin ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression "while condition; foo; end" ~~~~~ keyword ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~ expression "foo while condition" ~~~~~ keyword ~~~~~~~~~~~~~~~~~~~ expression (until (lvar :condition) (send nil :foo)) "until condition do foo; end" ~~~~~ keyword ~~ begin ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression (until (lvar :condition) (send nil :foo)) "until condition; foo; end" ~~~~~ keyword ~~~ end ~~~~~~~~~~~~~~~~~~~~~~~~~~ expression "foo until condition" ~~~~~ keyword ~~~~~~~~~~~~~~~~~~~ expression
With postcondition
Format:
(while-post (lvar :condition) (begin (send nil :foo))) "begin; foo; end while condition" ~~~~~ begin (begin) ~~~ end (begin) ~~~~~ keyword (while-post) (until-post (lvar :condition) (begin (send nil :foo))) "begin; foo; end until condition" ~~~~~ begin (begin) ~~~ end (begin) ~~~~~ keyword (until-post)
For-in
Format:
(for (lasgn :a) (lvar :array) (send nil :p (lvar :a))) "for a in array do p a; end" ~~~ keyword ~~ in ~~ begin ~~~ end "for a in array; p a; end" ~~~ keyword ~~ in ~~~ end (for (mlhs (lasgn :a) (lasgn :b)) (lvar :array) (send nil :p (lvar :a) (lvar :b))) "for a, b in array; p a, b; end"
Break
Format:
(break (int 1)) "break 1" ~~~~~ keyword ~~~~~~~ expression
Next
Format:
(next (int 1)) "next 1" ~~~~ keyword ~~~~~~ expression
Redo
Format:
(redo) "redo" ~~~~ keyword ~~~~ expression
Return
Format:
(return (lvar :foo)) "return(foo)" ~~~~~~ keyword ~~~~~~~~~~~ expression
Exception handling
Rescue body
Format:
(resbody (array (const nil :Exception) (const nil :A)) (lvasgn :bar) (int 1)) "rescue Exception, A => bar; 1" ~~~~~~ keyword ~~ assoc ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression "rescue Exception, A => bar then 1" ~~~~~~ keyword ~~ assoc ~~~~ begin (resbody (array (const nil :Exception)) (ivasgn :bar) (int 1)) "rescue Exception => @bar; 1" ~~~~~~ keyword ~~ assoc (resbody nil (lvasgn :bar) (int 1)) "rescue => bar; 1" ~~~~~~ keyword ~~ assoc (resbody nil nil (int 1)) "rescue; 1" ~~~~~~ keyword
Rescue statement
Without else
Format:
(begin (rescue (send nil :foo) (resbody ...) (resbody ...) nil)) "begin; foo; rescue Exception; rescue; end" ~~~~~ begin ~~~ end ~~~~~~~~~~~~~~~~~ expression (rescue.resbody/1) ~~~~~~~ expression (rescue.resbody/2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression (rescue)
With else
Format:
(begin (rescue (send nil :foo) (resbody ...) (resbody ...) (true))) "begin; foo; rescue Exception; rescue; else true end" ~~~~~ begin ~~~~ else (rescue) ~~~ end
Ensure statement
Format:
(begin (ensure (send nil :foo) (send nil :bar)) "begin; foo; ensure; bar; end" ~~~~~ begin ~~~~~~ keyword (ensure) ~~~ end
Rescue with ensure
Format:
(begin (ensure (rescue (send nil :foo) (resbody ...) (int 1)) (send nil :bar)) "begin; foo; rescue; nil; else; 1; ensure; bar; end" ~~~~~ begin ~~~~ else (ensure.rescue) ~~~~~~~~~~~~~~~~~~~~~ expression (rescue) ~~~~~~ keyword (ensure) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression (ensure) ~~~ end
Retry
Format:
(retry) "retry" ~~~~~ keyword ~~~~~ expression
BEGIN and END
Format:
(preexe (send nil :puts (str "foo"))) "BEGIN { puts "foo" }" ~~~~~ keyword ^ begin ^ end ~~~~~~~~~~~~~~~~~~~~ expression (postexe (send nil :puts (str "bar"))) "END { puts "bar" }" ~~~ keyword ^ begin ^ end ~~~~~~~~~~~~~~~~~~ expression
Miscellanea
Flip-flops
Format:
(iflipflop (lvar :a) (lvar :b)) "if a..b; end" ~~ operator ~~~~ expression (eflipflop (lvar :a) (lvar :b)) "if a...b; end" ~~~ operator ~~~~~ expression
Implicit matches
Format:
(match-current-line (regexp (str "a") (regopt))) "if /a/; end"
Local variable injecting matches
Format:
(match-with-lvasgn (regexp (str "(?bar)") (regopt)) (lvar :baz)) "/(?bar)/ =~ baz" ~~ selector ~~~~~~~~~~~~~~~~~~~~~~ expression