File Manager
Viewing File: AST_FORMAT.md
AST and Source Location
=======================
## Literals
### Singletons
Format:
~~~
(true)
"true"
~~~~ expression
(false)
"false"
~~~~~ expression
(nil)
"nil"
~~~ expression
~~~
### Integer
Format:
~~~
(int 123)
"123"
~~~ expression
(int -123)
"-123"
^ operator
~~~ expression
(int 1)
"__LINE__"
~~~~~~~~ expression
~~~
### Float
Format:
~~~
(float 1.0)
"1.0"
~~~ expression
(float -1.0)
"-1.0"
^ operator
~~~~ expression
~~~
### Complex
Format:
~~~
(complex (0+1i))
"1i"
~~ expression
(complex (0+(1/1)*i))
"1ri"
~~~ expression
~~~
### Rational
Format:
~~~
(rational (2/1))
"2.0r"
~~~~ expression
~~~
### String
#### Plain
Format:
~~~
(str "foo")
"'foo'"
^ begin
^ end
~~~~~ expresion
(string "foo.rb")
"__FILE__"
~~~~~~~~ expression
~~~
#### With interpolation
Format:
~~~
(dstr (str "foo") (lvar bar) (str "baz"))
'"foo#{bar}baz"'
^ begin ^ end
~~~~~~~~~~~~~~ expression
~~~
#### Here document
Format:
~~~
(str "foo\nbar\n")
'<<HERE␊foo␊bar␊HERE'
~~~~~~ expression
~~~~~~~~ heredoc_body
~~~~ heredoc_end
~~~
### 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
#### Plain
Format:
~~~
(xstr (str "foo") (lvar bar))
"`foo#{bar}`"
^ begin ^ end
~~~~~~~~~~~ expression
~~~
#### Here document
Format:
~~~
(xstr (str "foo\nbar\n"))
"<<`HERE`␊foo␊bar␊HERE"
~~~~~~~~ expression
~~~~~~~~ heredoc_body
~~~~ heredoc_end
~~~
### 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]"
^ begin
^ end
~~~~~~ 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
#### Regular global variable
Format:
~~~
(gvar :$foo)
"$foo"
~~~~ expression
~~~
#### Regular expression capture groups
Format:
~~~
(nth-ref 1)
"$1"
~~ expression
~~~
#### Regular expression back-references
Format:
~~~
(back-ref :$&)
"$&"
~~ expression
(back-ref :$`)
"$`"
(back-ref :$')
"$'"
(back-ref :$+)
"$+"
~~~
### 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
~~~
### To attribute
Format:
~~~
(send (self) :foo= (int 1))
"self.foo = 1"
^ dot
~~~ selector
^ operator
~~~~~~~~~~~~ expression
~~~
### To attribute, using "safe navigation operator"
Format:
~~~
(csend (self) :foo= (int 1))
"self&.foo = 1"
^^ dot
~~~ selector
^ 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](#assignment-1).
#### 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](#assignment-1).
#### Variable logical operator-assignment
Format:
~~~
(or-asgn (ivasgn :@a) (int 1))
"@a ||= 1"
~~~ operator
~~~~~~~~ expression
(and-asgn (lvasgn :a) (int 1))
"a &&= 1"
~~~ operator
~~~~~~~ expression
~~~
Ruby_parser output for reference:
~~~
"@a ||= 1"
s(:op_asgn_or, s(:ivar, :@a), s(:ivasgn, :@a, s(:int, 1)))
"a &&= 1"
s(:op_asgn_and, s(:lvar, :a), s(:lvasgn, :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) :foo (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 `&`.
### Auto-expanding proc argument (1.9)
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 :foo)
"|foo|"
~~~ expression
~~~ name
~~~
### 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)
"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
~~~
### Objective-C arguments
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.
#### Objective-C label-like keyword argument
Format:
~~~
(objc-kwarg :a :b)
"a: b"
~ keyword
~ operator
~ argument
~~~~ expression
~~~
#### Objective-C pair-like keyword argument
Format:
~~~
(objc-kwarg :a :b)
"a => b"
~ keyword
~~ operator
~ argument
~~~~~~ expression
~~~
#### Objective-C keyword splat argument
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
~~~
## 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)"
^ 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
(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 (**z**ero-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
~~~
### "Stabby lambda"
~~~
(block (lambda) (args) nil)
"-> {}"
~~ lambda.expression
~~~
### "Safe navigation operator"
~~~
(csend (send nil :foo) :bar)
"foo&.bar"
~~ dot
~~~
### Objective-C variadic send
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)
~~~
## Control flow
### Logical operators
#### Binary (and or && ||)
Format:
~~~
(and (lvar :foo) (lvar :bar))
"foo and bar"
~~~ operator
~~~~~~~~~~~ expression
~~~
~~~
(or (lvar :foo) (lvar :bar))
"foo or 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) (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)
~~~
#### For-in
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"
~~~
#### 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"
~~~ expression
~~~
### Local variable injecting matches
Format:
~~~
(match-with-lvasgn (regexp (str "(?<match>bar)") (regopt)) (lvar :baz))
"/(?<match>bar)/ =~ baz"
~~ selector
~~~~~~~~~~~~~~~~~~~~~~ expression
~~~