Format:
(true)
"true"
~~~~ expression
(false)
"false"
~~~~~ expression
(nil)
"nil"
~~~ expression
Format:
(int 123)
"123"
~~~ expression
(int -123)
"-123"
^ operator
~~~ expression
(int 1)
"__LINE__"
~~~~~~~~ expression
Format:
(float 1.0)
"1.0"
~~~ expression
(float -1.0)
"-1.0"
^ operator
~~~~ expression
Format:
(complex (0+1i))
"1i"
~~ expression
(complex (0+(1/1)*i))
"1ri"
~~~ expression
Format:
(rational (2/1))
"2.0r"
~~~~ expression
Format:
(str "foo")
"'foo'"
^ begin
^ end
~~~~~ expresion
(string "foo.rb")
"__FILE__"
~~~~~~~~ expression
Format:
(dstr (str "foo") (begin (lvar bar)) (str "baz"))
'"foo#{bar}baz"'
^ begin ^ end
~~~~~~~~~~~~~~ expression
^^ begin (begin)
^ end (begin)
^^^^^^ expression (begin)
Format:
(str "foo\nbar\n")
'<<HERE␊foo␊bar␊HERE'
~~~~~~ expression
~~~~~~~~ heredoc_body
~~~~ heredoc_end
Format:
(sym :foo)
":foo"
~~~~ expresion
":'foo'"
^ begin
^ end
~~~~~~ expression
Format:
(dsym (str "foo") (lvar bar) (str "baz"))
':"foo#{bar}baz"'
^ begin ^ end
~~~~~~~~~~~~~~~ expression
Format:
(xstr (str "foo") (lvar bar))
"`foo#{bar}`"
^ begin ^ end
~~~~~~~~~~~ expression
Format:
(xstr (str "foo\nbar\n"))
"<<`HERE`␊foo␊bar␊HERE"
~~~~~~~~ expression
~~~~~~~~ heredoc_body
~~~~ heredoc_end
Format:
(regopt :i :m)
"im"
~~ expression
Format:
(regexp (str "foo") (lvar :bar) (regopt :i))
"/foo#{bar}/i"
^ begin ^ end
~~~~~~~~~~~ expression
Format:
(array (int 1) (int 2))
"[1, 2]"
^ begin
^ end
~~~~~~ expression
Can also be used in argument lists: foo(bar, *baz)
Format:
(splat (lvar :foo))
"*foo"
^ operator
~~~~ expression
Format:
(array (int 1) (splat (lvar :foo)) (int 2))
"[1, *foo, 2]"
^ begin ^ end
~~~~~~~~~~~~ expression
Format:
(pair (int 1) (int 2))
"1 => 2"
~~ operator
~~~~~~ expression
Format:
(pair (sym :answer) (int 42))
"answer: 42"
^ operator (pair)
~~~~~~ expression (sym)
~~~~~~~~~~ expression (pair)
Format:
(pair (sym :foo) (lvar :foo))
"{foo:}"
^ operator (pair)
~~~ expression (sym)
~~~ expression (lvar)
Format:
(pair (sym :foo) (const nil :foo))
"{FOO:}"
^ operator (pair)
~~~ expression (const)
~~~ expression (lvar)
Format:
(pair (sym :puts) (send nil :puts))
"{puts:}"
^ operator (pair)
~~~~ expression (sym)
~~~~ expression (send)
Format:
(hash (pair (int 1) (int 2)) (pair (int 3) (int 4)))
"{1 => 2, 3 => 4}"
^ begin ^ end
~~~~~~~~~~~~~~~~ expression
Starting from Ruby 2.7 only implicit hash literals (that are not wrapped into { .. }
) are passed as keyword arguments.
Explicit hash literals are passed as positional arguments.
This is reflected in AST as kwargs
node that is emitted only for implicit
hash literals and only if emit_kwargs
compatibility flag is enabled.
Note that it can be a part of send
, csend
, index
and yield
nodes.
Format:
(kwargs (pair (int 1) (int 2)) (kwsplat (lvar :bar)) (pair (sym :baz) (int 3)))
"foo(1 => 2, **bar, baz: 3)"
~~~~~~~~~~~~~~~~~~~~~ expression
Can also be used in argument lists: foo(bar, **baz)
Format:
(kwsplat (lvar :foo))
"**foo"
~~ operator
~~~~~ expression
Format:
(hash (pair (sym :foo) (int 2)) (kwsplat (lvar :bar)))
"{ foo: 2, **bar }"
^ begin ^ end
~~~~~~~~~~~~~~~~~ expression
Format:
(irange (int 1) (int 2))
"1..2"
~~ operator
~~~~ expression
Format:
(erange (int 1) (int 2))
"1...2"
~~~ operator
~~~~~ expression
Format:
(irange (int 1) nil)
"1.."
~~ operator
~~~ expression
(erange (int 1) nil)
"1..."
~~~ operator
~~~~ expression
Format:
(irange nil (int 1))
"..1"
~~ operator
~~~ expression
(erange nil (int 1))
"...1"
~~~ operator
~~~~ expression
Format:
(self)
"self"
~~~~ expression
Format:
(lvar :foo)
"foo"
~~~ expression
Format:
(ivar :@foo)
"@foo"
~~~~ expression
Format:
(cvar :@@foo)
"@@foo"
~~~~~ expression
Format:
(gvar :$foo)
"$foo"
~~~~ expression
Format:
(nth-ref 1)
"$1"
~~ expression
Format:
(back-ref :$&)
"$&"
~~ expression
(back-ref :$`)
"$`"
(back-ref :$')
"$'"
(back-ref :$+)
"$+"
Format:
(const (cbase) :Foo)
"::Foo"
~~~ name
~~ double_colon
~~~~~ expression
Format:
(const (lvar :a) :Foo)
"a::Foo"
~~~ name
~~ double_colon
~~~~~~ expression
Format:
(const nil :Foo)
"Foo"
~~~ name
~~~ expression
Format:
(defined? (lvar :a))
"defined? a"
~~~~~~~~ keyword
~~~~~~~~~~ expression
"defined?(a)"
~~~~~~~~ keyword
^ begin
^ end
~~~~~~~~~~~ expression
Format:
(lvasgn :foo (lvar :bar))
"foo = bar"
^ operator
~~~~~~~~~ expression
Format:
(ivasgn :@foo (lvar :bar))
"@foo = bar"
^ operator
~~~~~~~~~~ expression
Format:
(cvasgn :@@foo (lvar :bar))
"@@foo = bar"
^ operator
~~~~~~~~~~~ expression
Format:
(gvasgn :$foo (lvar :bar))
"$foo = bar"
^ operator
~~~~~~~~~~ expression
Format:
(casgn (cbase) :Foo (int 1))
"::Foo = 1"
~~~ name
~ operator
~~~~~~~ expression
Format:
(casgn (lvar :a) :Foo (int 1))
"a::Foo = 1"
~~~ name
~ operator
~~~~~~~~ expression
Format:
(casgn nil :Foo (int 1))
"Foo = 1"
~~~ name
~ operator
~~~~~~~ expression
Format:
(send (self) :foo= (int 1))
"self.foo = 1"
^ dot
~~~ selector
^ operator
~~~~~~~~~~~~ expression
Format:
(csend (self) :foo= (int 1))
"self&.foo = 1"
^^ dot
~~~ selector
^ operator
~~~~~~~~~~~~~ expression
Format:
(mlhs (lvasgn :a) (lvasgn :b))
"a, b"
~~~~ expression
"(a, b)"
^ begin
^ end
~~~~~~ expression
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 (lvasgn :a) (mlhs (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 features the same "incomplete assignments" and "incomplete calls" as multiple assignment.
Format:
(op-asgn (lvasgn :a) :+ (int 1))
"a += 1"
~~ operator
~~~~~~ expression
(op-asgn (ivasgn :a) :+ (int 1))
"@a += 1"
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)
Logical operator-assignment features the same "incomplete assignments" and "incomplete calls" as multiple assignment.
Format:
(or-asgn (ivasgn :@a) (int 1))
"@a ||= 1"
~~~ operator
~~~~~~~~ expression
(and-asgn (lvasgn :a) (int 1))
"a &&= 1"
~~~ operator
~~~~~~~ expression
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)
Format:
(lvasgn :a (int 1))
"1 => a"
~~~~~~ expression
~ name
~~ operator
Format:
(masgn (mlhs (lvasgn :a) (lvasgn :b)) (send (int 13) :divmod (int 5)))
"13.divmod(5) => a,b"
~~~~~~~~~~~~~~~~~~~ expression
^^ operator
Format:
(module (const nil :Foo) (nil))
"module Foo; end"
~~~~~~ keyword
~~~ end
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
Format:
(sclass (lvar :a) (nil))
"class << a; end"
~~~~~ keyword
~~ operator
~~~ end
~~~~~~~~~~~~~~~ expression
Format:
(def :foo (args) nil)
"def foo; end"
~~~ keyword
~~~ name
~~~ end
~~~~~~~~~~~~ expression
Format:
(defs (self) :foo (args) nil)
"def self.foo; end"
~~~ keyword
~~~ name
~~~ end
~~~~~~~~~~~~~~~~~ expression
Format:
(def :foo (args) (int 42))
"def foo() = 42"
~~~ keyword
~~~ name
^ assignment
~~~~~~~~~~~~~~ expression
Format:
(defs (self) :foo (args) (int 42))
"def self.foo() = 42"
~~~ keyword
~~~ name
^ assignment
~~~~~~~~~~~~~~~~~~~ expression
Format:
(undef (sym :foo) (sym :bar) (dsym (str "foo") (int 1)))
"undef foo :bar :"foo#{1}""
~~~~~ keyword
~~~~~~~~~~~~~~~~~~~~~~~~~ expression
Format:
(alias (sym :foo) (dsym (str "foo") (int 1)))
"alias foo :"foo#{1}""
~~~~~ keyword
~~~~~~~~~~~~~~~~~~~~ expression
Format:
(alias (gvar :$foo) (gvar :$bar))
"alias $foo $bar"
~~~~~ keyword
~~~~~~~~~~~~~~~ expression
(alias (gvar :$foo) (back-ref :$&))
"alias $foo $&"
~~~~~ keyword
~~~~~~~~~~~~~~~ expression
Format:
(args (arg :foo))
"(foo)"
~~~~~ expression
Format:
(arg :foo)
"foo"
~~~ expression
~~~ name
Format:
(optarg :foo (int 1))
"foo = 1"
~~~~~~~ expression
^ operator
~~~ name
Format:
(restarg :foo)
"*foo"
~~~~ expression
~~~ name
Begin of the expression
points to *
.
Format:
(restarg)
"*"
^ expression
Format:
(blockarg :foo)
"&foo"
~~~ name
~~~~ expression
Begin of the expression
points to &
.
Format:
(blockarg nil)
"&"
~ expression
In Ruby 1.9 and later, when a proc-like closure (i.e. a closure
created by capturing a block or with the proc
method, but not
with the ->{}
syntax or the lambda
method) has exactly one
argument, and it is called with more than one argument, the behavior
is as if the array of all arguments was instead passed as the sole
argument. This behavior can be prevented by adding a comma after
the sole argument (e.g. |foo,|
).
Format:
(procarg0 (arg :foo))
"|foo|"
~~~ expression
(procarg0 (arg :foo) (arg :bar))
"|(foo, bar)|"
~ begin
~ end
~~~~~~~~~~ expression
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|"
Format:
(args (shadowarg :foo) (shadowarg :bar))
"|; foo, bar|"
Format:
(def :f (args (arg :a) (mlhs (arg :foo) (restarg :bar))))
"def f(a, (foo, *bar)); end"
^ begin ^ end
~~~~~~~~~~~ expression
Format:
(kwarg :foo)
"foo:"
~~~~ expression
~~~~ name
Format:
(kwoptarg :foo (int 1))
"foo: 1"
~~~~~~ expression
~~~~ name
Format:
(kwrestarg :foo)
"**foo"
~~~~~ expression
~~~ name
Format:
(kwrestarg)
"**"
~~ expression
Format:
(kwnilarg)
"**nil"
~~~ name
~~~~~ expression
MacRuby includes a few more syntactic "arguments" whose name becomes the part of the Objective-C method name, despite looking like Ruby 2.0 keyword arguments, and are thus treated differently.
Format:
(objc-kwarg :a :b)
"a: b"
~ keyword
~ operator
~ argument
~~~~ expression
Format:
(objc-kwarg :a :b)
"a => b"
~ keyword
~~ operator
~ argument
~~~~~~ expression
Format:
(objc-restarg (objc-kwarg :foo))
"(*a: b)"
~ objc-kwarg.keyword
~ objc-kwarg.operator
~ objc-kwarg.argument
~ operator
~~~~~ expression
Note that these splat arguments will only be parsed inside parentheses, e.g. in the following code:
def f((*a: b)); end
However, the following code results in a parse error:
def f(*a: b); end
Ruby 2.7 introduced a feature called "numbered parameters". Numbered and ordinal parameters are mutually exclusive, so if the block has only numbered parameters it also has a different AST node.
Note that the second child represents a total number of numbered parameters.
Format:
s(:numblock,
s(:send, nil, :proc), 3,
s(:send,
s(:lvar, :_1), :+,
s(:lvar, :_3)))
"proc { _1 + _3 }"
~ begin ~ end
~~~~~~~~~~~~~~~~ expression
Ruby 2.7 introduced a feature called "arguments forwarding".
When a method takes any arguments for forwarding them in the future
the whole args
node gets replaced with forward-args
node.
Format if emit_forward_arg
compatibility flag is disabled:
(def :foo
(forward-args) nil)
"def foo(...); end"
~ end
~ begin
~~~~~ expression
However, Ruby 3.0 added support for leading arguments before ...
, and so
it can't be used as a replacement of the (args)
node anymore. To solve it
emit_forward_arg
should be enabled.
Format if emit_forward_arg
compatibility flag is enabled:
(def :foo
(args
(forward-arg)) nil)
"def foo(...); end"
~ begin (args)
~ end (args)
~~~~~ expression (args)
~~~ expression (forward_arg)
Note that the node is called forward_arg
when emitted separately.
Format:
(send nil :foo
(forwarded-args))
"foo(...)"
~~~ expression
Format:
(send nil :foo
(forwarded-restarg))
"foo(*)"
~ expression
Format:
(send nil :foo
(forwarded-kwrestarg))
"foo(**)"
~~ expression
Format:
(send nil :foo (lvar :bar))
"foo(bar)"
~~~ selector
^ begin
^ end
~~~~~~~~ expression
Format:
(send (lvar :foo) :bar (int 1))
"foo.bar(1)"
^ dot
~~~ 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
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
Format:
(yield (lvar :foo))
"yield(foo)"
~~~~~ keyword
^ begin
^ end
~~~~~~~~~~ expression
Format:
(index (lvar :foo) (int 1))
"foo[1]"
^ begin
^ end
~~~~~~ expression
(indexasgn (lvar :bar) (int 1) (int 2) (lvar :baz))
"bar[1, 2] = baz"
^ begin
^ end
^ operator
~~~~~~~~~~~~~~~ expression
(block (send nil :foo) (args (arg :bar)) (begin ...))
"foo do |bar|; end"
~~ begin
~~~ end
~~~~~~~~~~~~~ expression
Used when passing expression as block foo(&bar)
(send nil :foo (int 1) (block-pass (lvar :foo)))
"foo(1, &foo)"
^ operator
~~~~ expression
(send nil :foo (int 1) (block-pass nil))
"foo(1, &)"
^ operator
~ expression
(block (lambda) (args) nil)
"-> {}"
~~ lambda.expression
(csend (send nil :foo) :bar)
"foo&.bar"
~~ dot
MacRuby allows to pass a variadic amount of arguments via the last
keyword "argument". Semantically, these, together with the pair value
of the last pair in the hash implicitly passed as the last argument,
form an array, which replaces the pair value. Despite that, the node
is called objc-varargs
to distinguish it from a literal array passed
as a value.
(send nil :foo (int 1) (hash (pair (sym :bar) (objc-varargs (int 1) (int 2) (nil)))))
"foo(1, bar: 2, 3, nil)"
~~~~~~~~~ expression (array)
Format:
(and (lvar :foo) (lvar :bar))
"foo and bar"
~~~ operator
~~~~~~~~~~~ expression
(or (lvar :foo) (lvar :bar))
"foo or bar"
~~ operator
~~~~~~~~~~ expression
Format:
(not (lvar :foo))
"!foo"
^ operator
"not foo"
~~~ operator
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
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
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)
Format:
(if (lvar :cond) (lvar :iftrue) (lvar :iffalse))
"cond ? iftrue : iffalse"
^ question
^ colon
~~~~~~~~~~~~~~~~~~~~~~~ expression
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"
Format:
(case (lvar :foo) (when (str "bar") (lvar :bar)) nil)
"case foo; when "bar"; bar; end"
~~~~ keyword ~~~ end
Format:
(case (lvar :foo) (when (str "bar") (lvar :bar)) (lvar :baz))
"case foo; when "bar"; bar; else baz; end"
~~~~ keyword ~~~~ else ~~~ end
Format:
(case nil (when (lvar :bar) (lvar :bar)) nil)
"case; when bar; bar; end"
~~~~ keyword ~~~ end
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
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
Format:
(while-post (lvar :condition) (kwbegin (send nil :foo)))
"begin; foo; end while condition"
~~~~~ begin (begin)
~~~ end (begin)
~~~~~ keyword (while-post)
(until-post (lvar :condition) (kwbegin (send nil :foo)))
"begin; foo; end until condition"
~~~~~ begin (begin)
~~~ end (begin)
~~~~~ keyword (until-post)
Format:
(for (lvasgn :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 (lvasgn :a) (lvasgn :b)) (lvar :array)
(send nil :p (lvar :a) (lvar :b)))
"for a, b in array; p a, b; end"
Format:
(break (int 1))
"break 1"
~~~~~ keyword
~~~~~~~ expression
Format:
(next (int 1))
"next 1"
~~~~ keyword
~~~~~~ expression
Format:
(redo)
"redo"
~~~~ keyword
~~~~ expression
Format:
(return (lvar :foo))
"return(foo)"
~~~~~~ keyword
~~~~~~~~~~~ expression
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
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)
Format:
(begin
(rescue (send nil :foo) (resbody ...) (resbody ...) (true)))
"begin; foo; rescue Exception; rescue; else true end"
~~~~~ begin ~~~~ else (rescue)
~~~ end
Format:
(begin
(ensure (send nil :foo) (send nil :bar))
"begin; foo; ensure; bar; end"
~~~~~ begin ~~~~~~ keyword (ensure)
~~~ end
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
Format:
(retry)
"retry"
~~~~~ keyword
~~~~~ expression
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
Format:
(iflipflop (lvar :a) (lvar :b))
"if a..b; end"
~~ operator
~~~~ expression
(eflipflop (lvar :a) (lvar :b))
"if a...b; end"
~~~ operator
~~~~~ expression
Format:
(match-current-line (regexp (str "a") (regopt)))
"if /a/; end"
~~~ expression
Format:
(match-with-lvasgn (regexp (str "(?<match>bar)") (regopt)) (lvar :baz))
"/(?<match>bar)/ =~ baz"
~~ selector
~~~~~~~~~~~~~~~~~~~~~~ expression
Format:
(__FILE__)
"__FILE__"
~~~~~~~~ expression
Format:
(__LINE__)
"__LINE__"
~~~~~~~~ expression
Format:
(__ENCODING__)
"__ENCODING__"
~~~~~~~~~~~~ expression
Ruby 2.7 throws a NoMatchingPatternError
for foo in bar
if given value doesn't match pattern.
Format when emit_match_pattern
compatibility attribute is disabled (the default):
(in-match
(int 1)
(match-var :a))
"1 in a"
~~ operator
~~~~~~ expression
Format when emit_match_pattern
is enabled:
(match-pattern
(int 1)
(match-var :a))
"1 in a"
~~ operator
~~~~~~ expression
Starting from 3.0 Ruby returns true
/false
for the same code construction.
Ruby 3.0 format (compatibility attribute has no effect):
(match-pattern-p
(int 1)
(match-var :a))
"1 in a"
~~ operator
~~~~~~ expression
This node appears in AST only starting from Ruby 3.0.
Format:
(match-pattern
(int 1)
(match-var :a))
"1 => a"
~~ operator
~~~~~~ expression
Format:
(case-match
(str "str")
(in-pattern
(match-var :foo)
(lvar :bar)) nil)
"case "str"; in foo; bar; end"
~~~~ keyword ~~~ end
~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
Format:
(case-match,
(str "str")
(in-pattern
(match-var :foo)
(lvar :bar))
(lvar :baz))
"case "str"; in foo; bar; else; baz; end"
~~~~ keyword ~~~~ else ~~~ end
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
Empty else
differs from the missing (or implicit) else
for pattern matching, since
the latter one raises a NoMatchingPattern
exception. Thus, we need a way to distinguish this
two cases in the resulting AST.
Format:
(case-match,
(str "str")
(in-pattern
(match-var :foo)
(lvar :bar))
(empty-else))
"case "str"; in foo; bar; else; end"
~~~~ keyword ~~~~ else
~~~ end
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
Format:
(in-pattern
(match-var :foo)
(lvar :bar))
"in foo then bar"
~~ keyword
~~~~ begin
~~~~~~~~~~~~~~~ expression
This guard runs after matching, so it's not an if
modifier.
Format:
(in-pattern
(match-var :foo)
(if-guard
(lvar :bar)) nil)
"in foo if bar"
~~ keyword
~~~~~~ expression
This guard runs after matching, so it's not an unless
modifier.
Format:
(in-pattern
(match-var :foo)
(unless-guard
(lvar :bar)) nil)
"in foo unless bar"
~~~~~~ keyword
~~~~~~~~~~ expression
Format:
(match-var :foo)
"in foo"
~~~ name
~~~ expression
Format:
(match-rest
(match-var :foo))
"in *foo"
~ operator
~~~~ expression
Format:
(match-rest)
"in *"
~ operator
~ expression
Format:
(pin
(lvar :foo))
"in ^foo"
~ selector
~~~~ expression
Format:
(pin
(begin
(send
(int 2) :+
(int 2))))
"in ^(2 + 2)"
~ selector
~~~~~~~~ expression
~ begin (begin)
~ end (begin)
~~~~~~~ expression (begin)
Format:
(match-alt
(pin
(lvar :foo))
(int 1))
"in ^foo | 1"
~ operator
~~~~~~~~ expression
Format:
(match-as
(int 1)
(match-var :foo))
"in 1 => foo"
~~ operator
~~~~~~~~ expression
Format:
(array-pattern
(pin
(lvar :foo))
(match-var :bar))
"in [^foo, bar]"
~ begin ~ end
~~~~~~~~~~~ expression
Adding a trailing comma in the end works as , *
Format:
(array-pattern-with-tail
(pin
(lvar :foo))
(match-var :bar))
"in [^foo, bar,]"
~ begin ~ end
~~~~~~~~~~~~ expression
Format:
(array-pattern
(pin
(lvar :foo))
(match-var :bar))
"in ^foo, bar"
~~~~~~~~~ expression
Format:
Adding a trailing comma in the end works as , *
,
so a single item match with comma gets interpreted as an array.
(array-pattern-with-tail
(match-var :foo))
"in foo,"
~~~~ expression
Format:
(hash-pattern
(pair
(sym :a)
(int 10)))
"in { a: 10 }"
~ begin ~ end
~~~~~~~~~ expression
Format:
(hash-pattern
(pair
(sym :a)
(int 10)))
"in a: 10"
~~~~~ expression
Format:
(hash-pattern
(match-var :a))
"in a:"
~ name (match-var)
~~ expression (match-var)
Format:
(hash-pattern
(match-nil-pattern))
"in **nil"
~~~~~ expression (match-nil-pattern)
~~~ name (match-nil-pattern)
Format:
(find-pattern
(match-rest
(match-var :a))
(int 42)
(match-rest))
"in [*, 42, *]"
~ begin
~ end
~~~~~~~~~~ expression
Note that it can be used as a top-level pattern only when used in a case
statement. In that case begin
and end
are empty.
Format:
(const-pattern
(const nil :X)
(array-pattern
(pin
(lvar :foo))
(match-var :bar)))
"in X[^foo bar]"
~ begin (const-pattern)
~ end (const-pattern)
~~~~~~~~~~~~ expression (const-pattern)
~ name (const-pattern.const)
~ expression (const-pattern.const)
Format:
(const-pattern
(const nil :X)
(hash-pattern
(match-var :foo)
(match-var :bar)))
"in X[foo:, bar:]"
~ begin (const-pattern)
~ end (const-pattern)
~~~~~~~~~~~~~ expression (const-pattern)
~ name (const-pattern.const)
~ expression (const-pattern.const)
Format:
(const-pattern
(const nil :X)
(array-pattern))
"in X[]"
~ begin (const-pattern)
~ end (const-pattern)
~~~ expression (const-pattern)
~ name (const-pattern.const)
~ expression (const-pattern.const)
~~ expression (const-pattern.array_pattern)
Format:
(const-pattern
(const nil :X)
(find-pattern
(match-rest)
(int 42)
(match-rest)))
"in X[*, 42, *]"
~ begin
~ end
~~~~~~~~~~~ expression