summaryrefslogtreecommitdiff
path: root/doc/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'doc/syntax')
-rw-r--r--doc/syntax/assignment.rdoc485
-rw-r--r--doc/syntax/calling_methods.rdoc500
-rw-r--r--doc/syntax/comments.rdoc253
-rw-r--r--doc/syntax/control_expressions.rdoc639
-rw-r--r--doc/syntax/exceptions.rdoc106
-rw-r--r--doc/syntax/keywords.rdoc162
-rw-r--r--doc/syntax/layout.rdoc118
-rw-r--r--doc/syntax/literals.rdoc625
-rw-r--r--doc/syntax/methods.rdoc653
-rw-r--r--doc/syntax/miscellaneous.rdoc136
-rw-r--r--doc/syntax/modules_and_classes.rdoc398
-rw-r--r--doc/syntax/operators.rdoc75
-rw-r--r--doc/syntax/pattern_matching.rdoc528
-rw-r--r--doc/syntax/precedence.rdoc64
-rw-r--r--doc/syntax/refinements.rdoc281
15 files changed, 5023 insertions, 0 deletions
diff --git a/doc/syntax/assignment.rdoc b/doc/syntax/assignment.rdoc
new file mode 100644
index 0000000000..3988f82e5f
--- /dev/null
+++ b/doc/syntax/assignment.rdoc
@@ -0,0 +1,485 @@
+= Assignment
+
+In Ruby, assignment uses the <code>=</code> (equals sign) character. This
+example assigns the number five to the local variable +v+:
+
+ v = 5
+
+Assignment creates a local variable if the variable was not previously
+referenced.
+
+An assignment expression result is always the assigned value, including
+{assignment methods}[rdoc-ref:@Assignment+Methods].
+
+== Local Variable Names
+
+A local variable name must start with a lowercase US-ASCII letter or a
+character with the eight bit set. Typically local variables are US-ASCII
+compatible since the keys to type them exist on all keyboards.
+
+(Ruby programs must be written in a US-ASCII-compatible character set. In
+such character sets if the eight bit is set it indicates an extended
+character. Ruby allows local variables to contain such characters.)
+
+A local variable name may contain letters, numbers, an <code>_</code>
+(underscore or low line) or a character with the eighth bit set.
+
+== Local Variable Scope
+
+Once a local variable name has been assigned-to all uses of the name for the
+rest of the scope are considered local variables.
+
+Here is an example:
+
+ 1.times do
+ a = 1
+ puts "local variables in the block: #{local_variables.join ", "}"
+ end
+
+ puts "no local variables outside the block" if local_variables.empty?
+
+This prints:
+
+ local variables in the block: a
+ no local variables outside the block
+
+Since the block creates a new scope, any local variables created inside it do
+not leak to the surrounding scope.
+
+Variables defined in an outer scope appear inner scope:
+
+ a = 0
+
+ 1.times do
+ puts "local variables: #{local_variables.join ", "}"
+ end
+
+This prints:
+
+ local variables: a
+
+You may isolate variables in a block from the outer scope by listing them
+following a <code>;</code> in the block's arguments. See the documentation
+for block local variables in the {calling
+methods}[rdoc-ref:syntax/calling_methods.rdoc] documentation for an example.
+
+See also Kernel#local_variables, but note that a +for+ loop does not create a
+new scope like a block does.
+
+== Local Variables and Methods
+
+In Ruby local variable names and method names are nearly identical. If you
+have not assigned to one of these ambiguous names ruby will assume you wish to
+call a method. Once you have assigned to the name ruby will assume you wish
+to reference a local variable.
+
+The local variable is created when the parser encounters the assignment, not
+when the assignment occurs:
+
+ a = 0 if false # does not assign to a
+
+ p local_variables # prints [:a]
+
+ p a # prints nil
+
+The similarity between method and local variable names can lead to confusing
+code, for example:
+
+ def big_calculation
+ 42 # pretend this takes a long time
+ end
+
+ big_calculation = big_calculation()
+
+Now any reference to +big_calculation+ is considered a local variable and will
+be cached. To call the method, use <code>self.big_calculation</code>.
+
+You can force a method call by using empty argument parentheses as shown above
+or by using an explicit receiver like <code>self</code>. Using an explicit
+receiver may raise a NameError if the method's visibility is not public or the
+receiver is the literal <code>self</code>.
+
+Another commonly confusing case is when using a modifier +if+:
+
+ p a if a = 0.zero?
+
+Rather than printing "true" you receive a NameError, "undefined local variable
+or method `a'". Since ruby parses the bare +a+ left of the +if+ first and has
+not yet seen an assignment to +a+ it assumes you wish to call a method. Ruby
+then sees the assignment to +a+ and will assume you are referencing a local
+variable.
+
+The confusion comes from the out-of-order execution of the expression. First
+the local variable is assigned-to then you attempt to call a nonexistent
+method.
+
+== Local Variables and eval
+
+Using +eval+ to evaluate Ruby code will allow access to local variables defined
+in the same scope, even if the local variables are not defined until after the
+call to +eval+. However, local variables defined inside the call to +eval+
+will not be reflected in the surrounding scope. Inside the call to +eval+,
+local variables defined in the surrounding scope and local variables defined
+inside the call to +eval+ will be accessible. However, you will not be able
+to access local variables defined in previous or subsequent calls to +eval+ in
+the same scope. Consider each +eval+ call a separate nested scope. Example:
+
+ def m
+ eval "bar = 1"
+ lvs = eval "baz = 2; ary = [local_variables, foo, baz]; x = 2; ary"
+ eval "quux = 3"
+ foo = 1
+ lvs << local_variables
+ end
+
+ m
+ # => [[:baz, :ary, :x, :lvs, :foo], nil, 2, [:lvs, :foo]]
+
+== Instance Variables
+
+Instance variables are shared across all methods for the same object.
+
+An instance variable must start with a <code>@</code> ("at" sign or
+commercial at). Otherwise instance variable names follow the rules as local
+variable names. Since the instance variable starts with an <code>@</code> the
+second character may be an upper-case letter.
+
+Here is an example of instance variable usage:
+
+ class C
+ def initialize(value)
+ @instance_variable = value
+ end
+
+ def value
+ @instance_variable
+ end
+ end
+
+ object1 = C.new "some value"
+ object2 = C.new "other value"
+
+ p object1.value # prints "some value"
+ p object2.value # prints "other value"
+
+An uninitialized instance variable has a value of +nil+.
+
+The +value+ method has access to the value set by the +initialize+ method, but
+only for the same object.
+
+== Class Variables
+
+Class variables are shared between a class, its subclasses and its instances.
+
+A class variable must start with a <code>@@</code> (two "at" signs). The rest
+of the name follows the same rules as instance variables.
+
+Here is an example:
+
+ class A
+ @@class_variable = 0
+
+ def value
+ @@class_variable
+ end
+
+ def update
+ @@class_variable = @@class_variable + 1
+ end
+ end
+
+ class B < A
+ def update
+ @@class_variable = @@class_variable + 2
+ end
+ end
+
+ a = A.new
+ b = B.new
+
+ puts "A value: #{a.value}"
+ puts "B value: #{b.value}"
+
+This prints:
+
+ A value: 0
+ B value: 0
+
+Continuing with the same example, we can update using objects from either
+class and the value is shared:
+
+ puts "update A"
+ a.update
+
+ puts "A value: #{a.value}"
+ puts "B value: #{b.value}"
+
+ puts "update B"
+ b.update
+
+ puts "A value: #{a.value}"
+ puts "B value: #{b.value}"
+
+ puts "update A"
+ a.update
+
+ puts "A value: #{a.value}"
+ puts "B value: #{b.value}"
+
+This prints:
+
+ update A
+ A value: 1
+ B value: 1
+ update B
+ A value: 3
+ B value: 3
+ update A
+ A value: 4
+ B value: 4
+
+Accessing an uninitialized class variable will raise a NameError exception.
+
+Note that classes have instance variables because classes are objects, so
+try not to confuse class and instance variables.
+
+== Global Variables
+
+Global variables are accessible everywhere.
+
+Global variables start with a <code>$</code> (dollar sign). The rest of the
+name follows the same rules as instance variables.
+
+Here is an example:
+
+ $global = 0
+
+ class C
+ puts "in a class: #{$global}"
+
+ def my_method
+ puts "in a method: #{$global}"
+
+ $global = $global + 1
+ $other_global = 3
+ end
+ end
+
+ C.new.my_method
+
+ puts "at top-level, $global: #{$global}, $other_global: #{$other_global}"
+
+This prints:
+
+ in a class: 0
+ in a method: 0
+ at top-level, $global: 1, $other_global: 3
+
+An uninitialized global variable has a value of +nil+.
+
+Ruby has some special globals that behave differently depending on context
+such as the regular expression match variables or that have a side-effect when
+assigned to. See the {global variables documentation}[rdoc-ref:language/globals.md]
+for details.
+
+== Assignment Methods
+
+You can define methods that will behave like assignment, for example:
+
+ class C
+ def value=(value)
+ @value = value
+ end
+ end
+
+ c = C.new
+ c.value = 42
+
+Using assignment methods allows your programs to look nicer. When assigning
+to an instance variable most people use Module#attr_accessor:
+
+ class C
+ attr_accessor :value
+ end
+
+When using method assignment you must always have a receiver. If you do not
+have a receiver, Ruby assumes you are assigning to a local variable:
+
+ class C
+ attr_accessor :value
+
+ def my_method
+ value = 42
+
+ puts "local_variables: #{local_variables.join ", "}"
+ puts "@value: #{@value.inspect}"
+ end
+ end
+
+ C.new.my_method
+
+This prints:
+
+ local_variables: value
+ @value: nil
+
+To use the assignment method you must set the receiver:
+
+ class C
+ attr_accessor :value
+
+ def my_method
+ self.value = 42
+
+ puts "local_variables: #{local_variables.join ", "}"
+ puts "@value: #{@value.inspect}"
+ end
+ end
+
+ C.new.my_method
+
+This prints:
+
+ local_variables:
+ @value: 42
+
+Note that the value returned by an assignment method is ignored whatever,
+since an assignment expression result is always the assignment value.
+
+== Abbreviated Assignment
+
+You can mix several of the operators and assignment. To add 1 to an object
+you can write:
+
+ a = 1
+
+ a += 2
+
+ p a # prints 3
+
+This is equivalent to:
+
+ a = 1
+
+ a = a + 2
+
+ p a # prints 3
+
+You can use the following operators this way: <code>+</code>, <code>-</code>,
+<code>*</code>, <code>/</code>, <code>%</code>, <code>**</code>,
+<code>&</code>, <code>|</code>, <code>^</code>, <code><<</code>,
+<code>>></code>
+
+There are also <code>||=</code> and <code>&&=</code>. The former makes an
+assignment if the value was +nil+ or +false+ while the latter makes an
+assignment if the value was not +nil+ or +false+.
+
+Here is an example:
+
+ a ||= 0
+ a &&= 1
+
+ p a # prints 1
+
+Note that these two operators behave more like <code>a || a = 0</code> than
+<code>a = a || 0</code>.
+
+== Implicit Array Assignment
+
+You can implicitly create an array by listing multiple values when assigning:
+
+ a = 1, 2, 3
+
+ p a # prints [1, 2, 3]
+
+This implicitly creates an Array.
+
+You can use <code>*</code> or the "splat" operator or unpack an Array when
+assigning. This is similar to multiple assignment:
+
+ a = *[1, 2, 3]
+
+ p a # prints [1, 2, 3]
+
+ b = *1
+
+ p b # prints [1]
+
+You can splat anywhere in the right-hand side of the assignment:
+
+ a = 1, *[2, 3]
+
+ p a # prints [1, 2, 3]
+
+== Multiple Assignment
+
+You can assign multiple values on the right-hand side to multiple variables:
+
+ a, b = 1, 2
+
+ p a: a, b: b # prints {:a=>1, :b=>2}
+
+In the following sections any place "variable" is used an assignment method,
+instance, class or global will also work:
+
+ def value=(value)
+ p assigned: value
+ end
+
+ self.value, $global = 1, 2 # prints {:assigned=>1}
+
+ p $global # prints 2
+
+You can use multiple assignment to swap two values in-place:
+
+ old_value = 1
+
+ new_value, old_value = old_value, 2
+
+ p new_value: new_value, old_value: old_value
+ # prints {:new_value=>1, :old_value=>2}
+
+If you have more values on the right hand side of the assignment than variables
+on the left hand side, the extra values are ignored:
+
+ a, b = 1, 2, 3
+
+ p a: a, b: b # prints {:a=>1, :b=>2}
+
+You can use <code>*</code> to gather extra values on the right-hand side of
+the assignment.
+
+ a, *b = 1, 2, 3
+
+ p a: a, b: b # prints {:a=>1, :b=>[2, 3]}
+
+The <code>*</code> can appear anywhere on the left-hand side:
+
+ *a, b = 1, 2, 3
+
+ p a: a, b: b # prints {:a=>[1, 2], :b=>3}
+
+But you may only use one <code>*</code> in an assignment.
+
+== Array Decomposition
+
+Like Array decomposition in {method arguments}[rdoc-ref:syntax/methods.rdoc]
+you can decompose an Array during assignment using parenthesis:
+
+ (a, b) = [1, 2]
+
+ p a: a, b: b # prints {:a=>1, :b=>2}
+
+You can decompose an Array as part of a larger multiple assignment:
+
+ a, (b, c) = 1, [2, 3]
+
+ p a: a, b: b, c: c # prints {:a=>1, :b=>2, :c=>3}
+
+Since each decomposition is considered its own multiple assignment you can use
+<code>*</code> to gather arguments in the decomposition:
+
+ a, (b, *c), *d = 1, [2, 3, 4], 5, 6
+
+ p a: a, b: b, c: c, d: d
+ # prints {:a=>1, :b=>2, :c=>[3, 4], :d=>[5, 6]}
diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc
new file mode 100644
index 0000000000..76babcc3dc
--- /dev/null
+++ b/doc/syntax/calling_methods.rdoc
@@ -0,0 +1,500 @@
+= Calling Methods
+
+Calling a method sends a message to an object so it can perform some work.
+
+In ruby you send a message to an object like this:
+
+ my_method()
+
+Note that the parenthesis are optional:
+
+ my_method
+
+Except when there is difference between using and omitting parentheses, this
+document uses parenthesis when arguments are present to avoid confusion.
+
+This section only covers calling methods. See also the {syntax documentation
+on defining methods}[rdoc-ref:syntax/methods.rdoc].
+
+== Receiver
+
++self+ is the default receiver. If you don't specify any receiver +self+ will
+be used. To specify a receiver use <code>.</code>:
+
+ my_object.my_method
+
+This sends the +my_method+ message to +my_object+. Any object can be a
+receiver but depending on the method's visibility sending a message may raise a
+NoMethodError.
+
+You may also use <code>::</code> to designate a receiver, but this is rarely
+used due to the potential for confusion with <code>::</code> for namespaces.
+
+=== Chaining Method Calls
+
+You can "chain" method calls by immediately following one method call with another.
+
+This example chains methods Array#append and Array#compact:
+
+ a = [:foo, 'bar', 2]
+ a1 = [:baz, nil, :bam, nil]
+ a2 = a.append(*a1).compact
+ a2 # => [:foo, "bar", 2, :baz, :bam]
+
+Details:
+
+- First method <tt>merge</tt> creates a copy of <tt>a</tt>,
+ appends (separately) each element of <tt>a1</tt> to the copy, and returns
+ [:foo, "bar", 2, :baz, nil, :bam, nil]
+- Chained method <tt>compact</tt> creates a copy of that return value,
+ removes its <tt>nil</tt>-valued entries, and returns
+ [:foo, "bar", 2, :baz, :bam]
+
+You can chain methods that are in different classes.
+This example chains methods Hash#to_a and Array#reverse:
+
+ h = {foo: 0, bar: 1, baz: 2}
+ h.to_a.reverse # => [[:baz, 2], [:bar, 1], [:foo, 0]]
+
+Details:
+
+- First method Hash#to_a converts <tt>a</tt> to an \Array, and returns
+ [[:foo, 0], [:bar, 1], [:baz, 2]]
+- Chained method Array#reverse creates copy of that return value,
+ reverses it, and returns
+ [[:baz, 2], [:bar, 1], [:foo, 0]]
+
+=== Safe Navigation Operator
+
+<code>&.</code>, called "safe navigation operator", allows to skip method call
+when receiver is +nil+. It returns +nil+ and doesn't evaluate method's arguments
+if the call is skipped.
+
+ REGEX = /(ruby) is (\w+)/i
+ "Ruby is awesome!".match(REGEX).values_at(1, 2)
+ # => ["Ruby", "awesome"]
+ "Python is fascinating!".match(REGEX).values_at(1, 2)
+ # NoMethodError: undefined method `values_at' for nil:NilClass
+ "Python is fascinating!".match(REGEX)&.values_at(1, 2)
+ # => nil
+
+This allows to easily chain methods which could return empty value. Note that
+<code>&.</code> skips only one next call, so for a longer chain it is necessary
+to add operator on each level:
+
+ "Python is fascinating!".match(REGEX)&.values_at(1, 2).join(' - ')
+ # NoMethodError: undefined method `join' for nil:NilClass
+ "Python is fascinating!".match(REGEX)&.values_at(1, 2)&.join(' - ')
+ # => nil
+
+== Arguments
+
+There are three types of arguments when sending a message, the positional
+arguments, keyword (or named) arguments and the block argument. Each message
+sent may use one, two or all types of arguments, but the arguments must be
+supplied in this order.
+
+All arguments in ruby are passed by reference and are not lazily evaluated.
+
+Each argument is separated by a <code>,</code>:
+
+ my_method(1, '2', :three)
+
+Arguments may be an expression, a hash argument:
+
+ 'key' => value
+
+or a keyword argument:
+
+ key: value
+
+Hash and keyword arguments must be contiguous and must appear after all
+positional arguments, but may be mixed:
+
+ my_method('a' => 1, b: 2, 'c' => 3)
+
+=== Positional Arguments
+
+The positional arguments for the message follow the method name:
+
+ my_method(argument1, argument2)
+
+In many cases, parenthesis are not necessary when sending a message:
+
+ my_method argument1, argument2
+
+However, parenthesis are necessary to avoid ambiguity. This will raise a
+SyntaxError because ruby does not know which method argument3 should be sent
+to:
+
+ method_one argument1, method_two argument2, argument3
+
+If the method definition has a <code>*argument</code> extra positional
+arguments will be assigned to +argument+ in the method as an Array.
+
+If the method definition doesn't include keyword arguments, the keyword or
+hash-type arguments are assigned as a single hash to the last argument:
+
+ def my_method(options)
+ p options
+ end
+
+ my_method('a' => 1, b: 2) # prints: {'a'=>1, :b=>2}
+
+If too many positional arguments are given, an ArgumentError is raised.
+
+=== Default Positional Arguments
+
+When the method defines default arguments you do not need to supply all the
+arguments to the method. Ruby will fill in the missing arguments in-order.
+
+First we'll cover the simple case where the default arguments appear on the
+right. Consider this method:
+
+ def my_method(a, b, c = 3, d = 4)
+ p [a, b, c, d]
+ end
+
+Here +c+ and +d+ have default values which ruby will apply for you. If you
+send only two arguments to this method:
+
+ my_method(1, 2)
+
+You will see ruby print <code>[1, 2, 3, 4]</code>.
+
+If you send three arguments:
+
+ my_method(1, 2, 5)
+
+You will see ruby print <code>[1, 2, 5, 4]</code>
+
+Ruby fills in the missing arguments from left to right.
+
+Ruby allows default values to appear in the middle of positional arguments.
+Consider this more complicated method:
+
+ def my_method(a, b = 2, c = 3, d)
+ p [a, b, c, d]
+ end
+
+Here +b+ and +c+ have default values. If you send only two arguments to this
+method:
+
+ my_method(1, 4)
+
+You will see ruby print <code>[1, 2, 3, 4]</code>.
+
+If you send three arguments:
+
+ my_method(1, 5, 6)
+
+You will see ruby print <code>[1, 5, 3, 6]</code>.
+
+Describing this in words gets complicated and confusing. I'll describe it
+in variables and values instead.
+
+First <code>1</code> is assigned to +a+, then <code>6</code> is assigned to
++d+. This leaves only the arguments with default values. Since
+<code>5</code> has not been assigned to a value yet, it is given to +b+ and
++c+ uses its default value of <code>3</code>.
+
+=== Keyword Arguments
+
+Keyword arguments follow any positional arguments and are separated by commas
+like positional arguments:
+
+ my_method(positional1, keyword1: value1, keyword2: value2)
+
+Any keyword arguments not given will use the default value from the method
+definition. If a keyword argument is given that the method did not list,
+and the method definition does not accept arbitrary keyword arguments, an
+ArgumentError will be raised.
+
+Keyword argument value can be omitted, meaning the value will be fetched
+from the context by the name of the key
+
+ keyword1 = 'some value'
+ my_method(positional1, keyword1:)
+ # ...is the same as
+ my_method(positional1, keyword1: keyword1)
+
+Be aware that when method parenthesis are omitted, too, the parsing order might
+be unexpected:
+
+ my_method positional1, keyword1:
+
+ some_other_expression
+
+ # ...is actually parsed as
+ my_method(positional1, keyword1: some_other_expression)
+
+=== Block Argument
+
+The block argument sends a closure from the calling scope to the method.
+
+The block argument is always last when sending a message to a method. A block
+is sent to a method using <code>do ... end</code> or <code>{ ... }</code>:
+
+ my_method do
+ # ...
+ end
+
+or:
+
+ my_method {
+ # ...
+ }
+
+<code>do end</code> has lower precedence than <code>{ }</code> so:
+
+ method_1 method_2 {
+ # ...
+ }
+
+Sends the block to +method_2+ while:
+
+ method_1 method_2 do
+ # ...
+ end
+
+Sends the block to +method_1+. Note that in the first case if parentheses are
+used the block is sent to +method_1+.
+
+A block will accept arguments from the method it was sent to. Arguments are
+defined similar to the way a method defines arguments. The block's arguments
+go in <code>| ... |</code> following the opening <code>do</code> or
+<code>{</code>:
+
+ my_method do |argument1, argument2|
+ # ...
+ end
+
+==== Block Local Arguments
+
+You may also declare block-local arguments to a block using <code>;</code> in
+the block arguments list. Assigning to a block-local argument will not
+override local arguments outside the block in the caller's scope:
+
+ def my_method
+ yield self
+ end
+
+ place = "world"
+
+ my_method do |obj; place|
+ place = "block"
+ puts "hello #{obj} this is #{place}"
+ end
+
+ puts "place is: #{place}"
+
+This prints:
+
+ hello main this is block
+ place is: world
+
+So the +place+ variable in the block is not the same +place+ variable as
+outside the block. Removing <code>; place</code> from the block arguments
+gives this result:
+
+ hello main this is block
+ place is: block
+
+=== Unpacking Positional Arguments
+
+Given the following method:
+
+ def my_method(argument1, argument2, argument3)
+ end
+
+You can turn an Array into an argument list with <code>*</code> (or splat)
+operator:
+
+ arguments = [1, 2, 3]
+ my_method(*arguments)
+
+or:
+
+ arguments = [2, 3]
+ my_method(1, *arguments)
+
+Both are equivalent to:
+
+ my_method(1, 2, 3)
+
+The <code>*</code> unpacking operator can be applied to any object, not only
+arrays. If the object responds to a <code>#to_a</code> method, this method
+is called, and is expected to return an Array, and elements of this array are passed
+as separate positional arguments:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+
+ def to_a = @name.split(' ')
+ end
+
+ name = Name.new('Jane Doe')
+ p(*name)
+ # prints separate values:
+ # Jane
+ # Doe
+
+If the object doesn't have a <code>#to_a</code> method, the object itself is passed
+as one argument:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+ end
+
+ name = Name.new('Jane Doe')
+ p(*name)
+ # Prints the object itself:
+ # #<Name:0x00007f9d07bca650 @name="Jane Doe">
+
+This allows to handle one or many arguments polymorphically. Note also that <tt>*nil</tt>
+is unpacked to an empty list of arguments, so conditional unpacking is possible:
+
+ my_method(*(some_arguments if some_condition?))
+
+If <code>#to_a</code> method exists and does not return an Array, it would be an
+error on unpacking:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+
+ def to_a = @name
+ end
+
+ name = Name.new('Jane Doe')
+ p(*name)
+ # can't convert Name to Array (Name#to_a gives String) (TypeError)
+
+You may also use the <code>**</code> (described next) to convert a Hash into
+keyword arguments.
+
+If the number of objects in the Array do not match the number of arguments for
+the method, an ArgumentError will be raised.
+
+If the splat operator comes first in the call, parentheses must be used to
+avoid an ambiguity of interpretation as an unpacking operator or multiplication
+operator. In this case, Ruby issues a warning in verbose mode:
+
+ my_method *arguments # warning: '*' interpreted as argument prefix
+ my_method(*arguments) # no warning
+
+=== Unpacking Keyword Arguments
+
+Given the following method:
+
+ def my_method(first: 1, second: 2, third: 3)
+ end
+
+You can turn a Hash into keyword arguments with the <code>**</code>
+(keyword splat) operator:
+
+ arguments = { first: 3, second: 4, third: 5 }
+ my_method(**arguments)
+
+or:
+
+ arguments = { first: 3, second: 4 }
+ my_method(third: 5, **arguments)
+
+Both are equivalent to:
+
+ my_method(first: 3, second: 4, third: 5)
+
+The <code>**</code> unpacking operator can be applied to any object, not only
+hashes. If the object responds to a <code>#to_hash</code> method, this method
+is called, and is expected to return an Hash, and elements of this hash are passed
+as keyword arguments:
+
+ class Name
+ def initialize(name)
+ @name = name
+ end
+
+ def to_hash = {first: @name.split(' ').first, last: @name.split(' ').last}
+ end
+
+ name = Name.new('Jane Doe')
+ p(**name)
+ # Prints: {name: "Jane", last: "Doe"}
+
+Unlike <code>*</code> operator, <code>**</code> raises an error when used on an
+object that doesn't respond to <code>#to_hash</code>. The one exception is
++nil+, which doesn't explicitly define this method, but is still allowed to
+be used in <code>**</code> unpacking, not adding any keyword arguments.
+
+Again, this allows for conditional unpacking:
+
+ my_method(some: params, **(some_extra_params if pass_extra_params?))
+
+Like <code>*</code> operator, <code>**</code> raises an error when the object responds
+to <code>#to_hash</code>, but it doesn't return a Hash.
+
+If the method definition uses the keyword splat operator to
+gather arbitrary keyword arguments, they will not be gathered
+by <code>*</code>:
+
+ def my_method(*a, **kw)
+ p arguments: a, keywords: kw
+ end
+
+ my_method(1, 2, '3' => 4, five: 6)
+
+Prints:
+
+ {:arguments=>[1, 2], :keywords=>{'3'=>4, :five=>6}}
+
+=== Proc to Block Conversion
+
+Given a method that use a block:
+
+ def my_method
+ yield self
+ end
+
+You can convert a proc or lambda to a block argument with the <code>&</code>
+(block conversion) operator:
+
+ argument = proc { |a| puts "#{a.inspect} was yielded" }
+
+ my_method(&argument)
+
+If the block conversion operator comes first in the call, parenthesis must be
+used to avoid a warning:
+
+ my_method &argument # warning
+ my_method(&argument) # no warning
+
+== Method Lookup
+
+When you send a message, Ruby looks up the method that matches the name of the
+message for the receiver. Methods are stored in classes and modules so method
+lookup walks these, not the objects themselves.
+
+Here is the order of method lookup for the receiver's class or module +R+:
+
+* The prepended modules of +R+ in reverse order
+* For a matching method in +R+
+* The included modules of +R+ in reverse order
+
+If +R+ is a class with a superclass, this is repeated with +R+'s superclass
+until a method is found.
+
+Once a match is found method lookup stops.
+
+If no match is found this repeats from the beginning, but looking for
++method_missing+. The default +method_missing+ is BasicObject#method_missing
+which raises a NameError when invoked.
+
+If refinements (an experimental feature) are active, the method lookup changes.
+See the {refinements documentation}[rdoc-ref:syntax/refinements.rdoc] for
+details.
diff --git a/doc/syntax/comments.rdoc b/doc/syntax/comments.rdoc
new file mode 100644
index 0000000000..cb6829a984
--- /dev/null
+++ b/doc/syntax/comments.rdoc
@@ -0,0 +1,253 @@
+= Code Comments
+
+Ruby has two types of comments: inline and block.
+
+Inline comments start with the <code>#</code> character and continue until the
+end of the line:
+
+ # On a separate line
+ class Foo # or at the end of the line
+ # can be indented
+ def bar
+ end
+ end
+
+Block comments start with <code>=begin</code> and end with <code>=end</code>.
+Each should start on a separate line.
+
+ =begin
+ This is
+ commented out
+ =end
+
+ class Foo
+ end
+
+ =begin some_tag
+ this works, too
+ =end
+
+<code>=begin</code> and <code>=end</code> can not be indented, so this is a
+syntax error:
+
+ class Foo
+ =begin
+ Will not work
+ =end
+ end
+
+== Magic Comments
+
+While comments are typically ignored by Ruby, special "magic comments" contain
+directives that affect how the code is interpreted.
+
+Top-level magic comments must appear in the first comment section of a file.
+
+NOTE: Magic comments affect only the file in which they appear;
+other files are unaffected.
+
+ # frozen_string_literal: true
+
+ var = 'hello'
+ var.frozen? # => true
+
+=== Alternative syntax
+
+Magic comments may consist of a single directive (as in the example above).
+Alternatively, multiple directives may appear on the same line if separated by ";"
+and wrapped between "-*-" (see Emacs' {file variables}[https://www.gnu.org/software/emacs/manual/html_node/emacs/Specifying-File-Variables.html]).
+
+ # emacs-compatible; -*- coding: big5; mode: ruby; frozen_string_literal: true -*-
+
+ p 'hello'.frozen? # => true
+ p 'hello'.encoding # => #<Encoding:Big5>
+
+=== +encoding+ Directive
+
+Indicates which string encoding should be used for string literals,
+regexp literals and <code>__ENCODING__</code>:
+
+ # encoding: big5
+
+ ''.encoding # => #<Encoding:Big5>
+
+Default encoding is UTF-8.
+
+Top-level magic comments must start on the first line, or on the second line if
+the first line looks like <tt>#! shebang line</tt>.
+
+The word "coding" may be used instead of "encoding".
+
+=== +frozen_string_literal+ Directive
+
+Indicates that string literals should be allocated once at parse time and frozen.
+
+ # frozen_string_literal: true
+
+ 3.times do
+ p 'hello'.object_id # => prints same number
+ end
+ p 'world'.frozen? # => true
+
+The default is false; this can be changed with <code>--enable=frozen-string-literal</code>.
+Without the directive, or with <code># frozen_string_literal: false</code>,
+the example above would print 3 different numbers and "false".
+
+Starting in Ruby 3.0, string literals that are dynamic are not frozen nor reused:
+
+ # frozen_string_literal: true
+
+ p "Addition: #{2 + 2}".frozen? # => false
+
+It must appear in the first comment section of a file.
+
+=== +warn_indent+ Directive
+
+This directive can turn on detection of bad indentation for statements that follow it:
+
+ def foo
+ end # => no warning
+
+ # warn_indent: true
+ def bar
+ end # => warning: mismatched indentations at 'end' with 'def' at 6
+
+Another way to get these warnings to show is by running Ruby with warnings (<code>ruby -w</code>). Using a directive to set this false will prevent these warnings to show.
+
+=== +shareable_constant_value+ Directive
+
+Note: This directive is experimental in Ruby 3.0 and may change in future releases.
+
+This special directive helps to create constants that hold only immutable objects, or {Ractor-shareable}[rdoc-ref:Ractor@Shareable+and+unshareable+objects] constants.
+
+The directive can specify special treatment for values assigned to constants:
+
+* +none+: (default)
+* +literal+: literals are implicitly frozen, others must be Ractor-shareable
+* +experimental_everything+: all made shareable
+* +experimental_copy+: copy deeply and make it shareable
+
+==== Mode +none+ (default)
+
+No special treatment in this mode (as in Ruby 2.x): no automatic freezing and no checks.
+
+It has always been a good idea to deep-freeze constants; Ractor makes this
+an even better idea as only the main ractor can access non-shareable constants:
+
+ # shareable_constant_value: none
+ A = {foo: []}
+ A.frozen? # => false
+ Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.
+
+==== Mode +literal+
+
+In "literal" mode, constants assigned to literals will be deeply-frozen:
+
+ # shareable_constant_value: literal
+ X = [{foo: []}] # => same as [{foo: [].freeze}.freeze].freeze
+
+Other values must be shareable:
+
+ # shareable_constant_value: literal
+ X = Object.new # => cannot assign unshareable object to X
+
+Note that only literals directly assigned to constants, or recursively held in such literals will be frozen:
+
+ # shareable_constant_value: literal
+ var = [{foo: []}]
+ var.frozen? # => false (assignment was made to local variable)
+ X = var # => cannot assign unshareable object to X
+
+ X = Set[1, 2, {foo: []}].freeze # => cannot assign unshareable object to X
+ # (`Set[...]` is not a literal and
+ # `{foo: []}` is an argument to `Set.[]`)
+
+The method Module#const_set is not affected.
+
+==== Mode +experimental_everything+
+
+In this mode, all values assigned to constants are made shareable.
+
+ # shareable_constant_value: experimental_everything
+ FOO = Set[1, 2, {foo: []}]
+ # same as FOO = Ractor.make_shareable(...)
+ # OR same as `FOO = Set[1, 2, {foo: [].freeze}.freeze].freeze`
+
+ var = [{foo: []}]
+ var.frozen? # => false (assignment was made to local variable)
+ X = var # => calls `Ractor.make_shareable(var)`
+ var.frozen? # => true
+
+This mode is "experimental", because it might be error prone, for
+example by deep-freezing the constants of an external resource which
+could cause errors:
+
+ # shareable_constant_value: experimental_everything
+ FOO = SomeGem::Something::FOO
+ # => deep freezes the gem's constant!
+
+This will be revisited before Ruby 3.1 to either allow `everything`
+or to instead remove this mode.
+
+The method Module#const_set is not affected.
+
+==== Mode +experimental_copy+
+
+In this mode, all values assigned to constants are deeply copied and
+made shareable. It is safer mode than +experimental_everything+.
+
+ # shareable_constant_value: experimental_copy
+ var = [{foo: []}]
+ var.frozen? # => false (assignment was made to local variable)
+ X = var # => calls `Ractor.make_shareable(var, copy: true)`
+ var.frozen? # => false
+ Ractor.shareable?(X) #=> true
+ var.object_id == X.object_id #=> false
+
+This mode is "experimental" and has not been discussed thoroughly.
+This will be revisited before Ruby 3.1 to either allow `copy`
+or to instead remove this mode.
+
+The method Module#const_set is not affected.
+
+==== Scope
+
+This directive can be used multiple times in the same file:
+
+ # shareable_constant_value: none
+ A = {foo: []}
+ A.frozen? # => false
+ Ractor.new { puts A } # => can not access non-shareable objects by non-main Ractor.
+
+ # shareable_constant_value: literal
+ B = {foo: []}
+ B.frozen? # => true
+ B[:foo].frozen? # => true
+
+ C = [Object.new] # => cannot assign unshareable object to C (Ractor::IsolationError)
+
+ D = [Object.new.freeze]
+ D.frozen? # => true
+
+ # shareable_constant_value: experimental_everything
+ E = Set[1, 2, Object.new]
+ E.frozen? # => true
+ E.all(&:frozen?) # => true
+
+The directive affects only subsequent constants and only for the current scope:
+
+ module Mod
+ # shareable_constant_value: literal
+ A = [1, 2, 3]
+ module Sub
+ B = [4, 5]
+ end
+ end
+
+ C = [4, 5]
+
+ module Mod
+ D = [6]
+ end
+ p Mod::A.frozen?, Mod::Sub::B.frozen? # => true, true
+ p C.frozen?, Mod::D.frozen? # => false, false
diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc
new file mode 100644
index 0000000000..3de6cd293f
--- /dev/null
+++ b/doc/syntax/control_expressions.rdoc
@@ -0,0 +1,639 @@
+= Control Expressions
+
+Ruby has a variety of ways to control execution. All the expressions described
+here return a value.
+
+For the tests in these control expressions, +nil+ and +false+ are false-values
+and +true+ and any other object are true-values. In this document "true" will
+mean "true-value" and "false" will mean "false-value".
+
+== +if+ Expression
+
+The simplest +if+ expression has two parts, a "test" expression and a "then"
+expression. If the "test" expression evaluates to a true then the "then"
+expression is evaluated.
+
+Here is a simple if statement:
+
+ if true then
+ puts "the test resulted in a true-value"
+ end
+
+This will print "the test resulted in a true-value".
+
+The +then+ is optional:
+
+ if true
+ puts "the test resulted in a true-value"
+ end
+
+This document will omit the optional +then+ for all expressions as that is the
+most common usage of +if+.
+
+You may also add an +else+ expression. If the test does not evaluate to true
+the +else+ expression will be executed:
+
+ if false
+ puts "the test resulted in a true-value"
+ else
+ puts "the test resulted in a false-value"
+ end
+
+This will print "the test resulted in a false-value".
+
+You may add an arbitrary number of extra tests to an if expression using
++elsif+. An +elsif+ executes when all tests above the +elsif+ are false.
+
+ a = 1
+
+ if a == 0
+ puts "a is zero"
+ elsif a == 1
+ puts "a is one"
+ else
+ puts "a is some other value"
+ end
+
+This will print "a is one" as <code>1</code> is not equal to <code>0</code>.
+Since +else+ is only executed when there are no matching conditions.
+
+Once a condition matches, either the +if+ condition or any +elsif+ condition,
+the +if+ expression is complete and no further tests will be performed.
+
+Like an +if+, an +elsif+ condition may be followed by a +then+.
+
+In this example only "a is one" is printed:
+
+ a = 1
+
+ if a == 0
+ puts "a is zero"
+ elsif a == 1
+ puts "a is one"
+ elsif a >= 1
+ puts "a is greater than or equal to one"
+ else
+ puts "a is some other value"
+ end
+
+The tests for +if+ and +elsif+ may have side-effects. The most common use of
+side-effect is to cache a value into a local variable:
+
+ if a = object.some_value
+ # do something to a
+ end
+
+The result value of an +if+ expression is the last value executed in the
+expression.
+
+== Ternary if
+
+You may also write a if-then-else expression using <code>?</code> and
+<code>:</code>. This ternary if:
+
+ input_type = gets =~ /hello/i ? "greeting" : "other"
+
+Is the same as this +if+ expression:
+
+ input_type =
+ if gets =~ /hello/i
+ "greeting"
+ else
+ "other"
+ end
+
+While the ternary if is much shorter to write than the more verbose form, for
+readability it is recommended that the ternary if is only used for simple
+conditionals. Also, avoid using multiple ternary conditions in the same
+expression as this can be confusing.
+
+== +unless+ Expression
+
+The +unless+ expression is the opposite of the +if+ expression. If the value
+is false, the "then" expression is executed:
+
+ unless true
+ puts "the value is a false-value"
+ end
+
+This prints nothing as true is not a false-value.
+
+You may use an optional +then+ with +unless+ just like +if+.
+
+Note that the above +unless+ expression is the same as:
+
+ if not true
+ puts "the value is a false-value"
+ end
+
+Like an +if+ expression you may use an +else+ condition with +unless+:
+
+ unless true
+ puts "the value is false"
+ else
+ puts "the value is true"
+ end
+
+This prints "the value is true" from the +else+ condition.
+
+You may not use +elsif+ with an +unless+ expression.
+
+The result value of an +unless+ expression is the last value executed in the
+expression.
+
+== Modifier +if+ and +unless+
+
++if+ and +unless+ can also be used to modify an expression. When used as a
+modifier the left-hand side is the "then" statement and the right-hand side
+is the "test" expression:
+
+ a = 0
+
+ a += 1 if a.zero?
+
+ p a
+
+This will print 1.
+
+ a = 0
+
+ a += 1 unless a.zero?
+
+ p a
+
+This will print 0.
+
+While the modifier and standard versions have both a "test" expression and a
+"then" statement, they are not exact transformations of each other due to
+parse order. Here is an example that shows the difference:
+
+ p a if a = 0.zero?
+
+This raises the NameError "undefined local variable or method `a'".
+
+When ruby parses this expression it first encounters +a+ as a method call in
+the "then" expression, then later it sees the assignment to +a+ in the "test"
+expression and marks +a+ as a local variable.
+
+When running this line it first executes the "test" expression, <code>a =
+0.zero?</code>.
+
+Since the test is true it executes the "then" expression, <code>p a</code>.
+Since the +a+ in the body was recorded as a method which does not exist the
+NameError is raised.
+
+The same is true for +unless+.
+
+== +case+ Expression
+
+The +case+ expression can be used in two ways.
+
+The most common way is to compare an object against multiple patterns. The
+patterns are matched using the <tt>===</tt> method which is aliased to <tt>==</tt> on
+Object. Other classes must override it to give meaningful behavior. See
+Module#=== and Regexp#=== for examples.
+
+Here is an example of using +case+ to compare a String against a pattern:
+
+ case "12345"
+ when /^1/
+ puts "the string starts with one"
+ else
+ puts "I don't know what the string starts with"
+ end
+
+Here the string <code>"12345"</code> is compared with <code>/^1/</code> by
+calling <code>/^1/ === "12345"</code> which returns +true+. Like the +if+
+expression, the first +when+ that matches is executed and all other matches are
+ignored.
+
+If no matches are found, the +else+ is executed.
+
+The +else+ and +then+ are optional, this +case+ expression gives the same
+result as the one above:
+
+ case "12345"
+ when /^1/
+ puts "the string starts with one"
+ end
+
+You may place multiple conditions on the same +when+:
+
+ case "2"
+ when /^1/, "2"
+ puts "the string starts with one or is '2'"
+ end
+
+Ruby will try each condition in turn, so first <code>/^1/ === "2"</code>
+returns +false+, then <code>"2" === "2"</code> returns +true+, so "the string
+starts with one or is '2'" is printed.
+
+You may use +then+ after the +when+ condition. This is most frequently used
+to place the body of the +when+ on a single line.
+
+ case a
+ when 1, 2 then puts "a is one or two"
+ when 3 then puts "a is three"
+ else puts "I don't know what a is"
+ end
+
+The other way to use a +case+ expression is like an if-elsif expression:
+
+ a = 2
+
+ case
+ when a == 1, a == 2
+ puts "a is one or two"
+ when a == 3
+ puts "a is three"
+ else
+ puts "I don't know what a is"
+ end
+
+Again, the +then+ and +else+ are optional.
+
+The result value of a +case+ expression is the last value executed in the
+expression.
+
+Since Ruby 2.7, +case+ expressions also provide a more powerful
+pattern matching feature via the +in+ keyword:
+
+ case {a: 1, b: 2, c: 3}
+ in a: Integer => m
+ "matched: #{m}"
+ else
+ "not matched"
+ end
+ # => "matched: 1"
+
+The pattern matching syntax is described on
+{its own page}[rdoc-ref:syntax/pattern_matching.rdoc].
+
+== +while+ Loop
+
+The +while+ loop executes while a condition is true:
+
+ a = 0
+
+ while a < 10 do
+ p a
+ a += 1
+ end
+
+ p a
+
+Prints the numbers 0 through 10. The condition <code>a < 10</code> is checked
+before the loop is entered, then the body executes, then the condition is
+checked again. When the condition results in false the loop is terminated.
+
+The +do+ keyword is optional. The following loop is equivalent to the loop
+above:
+
+ while a < 10
+ p a
+ a += 1
+ end
+
+The result of a +while+ loop is +nil+ unless +break+ is used to supply a
+value.
+
+== +until+ Loop
+
+The +until+ loop executes while a condition is false:
+
+ a = 0
+
+ until a > 10 do
+ p a
+ a += 1
+ end
+
+ p a
+
+This prints the numbers 0 through 11. Like a while loop the condition <code>a
+> 10</code> is checked when entering the loop and each time the loop body
+executes. If the condition is false the loop will continue to execute.
+
+Like a +while+ loop, the +do+ is optional.
+
+Like a +while+ loop, the result of an +until+ loop is nil unless +break+ is
+used.
+
+== +for+ Loop
+
+The +for+ loop consists of +for+ followed by a variable to contain the
+iteration argument followed by +in+ and the value to iterate over using #each.
+The +do+ is optional:
+
+ for value in [1, 2, 3] do
+ puts value
+ end
+
+Prints 1, 2 and 3.
+
+Like +while+ and +until+, the +do+ is optional.
+
+The +for+ loop is similar to using #each, but does not create a new variable
+scope.
+
+The result value of a +for+ loop is the value iterated over unless +break+ is
+used.
+
+The +for+ loop is rarely used in modern ruby programs.
+
+== Modifier +while+ and +until+
+
+Like +if+ and +unless+, +while+ and +until+ can be used as modifiers:
+
+ a = 0
+
+ a += 1 while a < 10
+
+ p a # prints 10
+
++until+ used as a modifier:
+
+ a = 0
+
+ a += 1 until a > 10
+
+ p a # prints 11
+
+You can use +begin+ and +end+ to create a +while+ loop that runs the body once
+before the condition:
+
+ a = 0
+
+ begin
+ a += 1
+ end while a < 10
+
+ p a # prints 10
+
+If you don't use +rescue+ or +ensure+, Ruby optimizes away any exception
+handling overhead.
+
+== +break+ Statement
+
+Use +break+ to leave a block early. This will stop iterating over the items in +values+ if one of them is even:
+
+ values.each do |value|
+ break if value.even?
+
+ # ...
+ end
+
+You can also terminate from a +while+ loop using +break+:
+
+ a = 0
+
+ while true do
+ p a
+ a += 1
+
+ break if a < 10
+ end
+
+ p a
+
+This prints the numbers 0 and 1.
+
++break+ accepts a value that supplies the result of the expression it is
+"breaking" out of:
+
+ result = [1, 2, 3].each do |value|
+ break value * 2 if value.even?
+ end
+
+ p result # prints 4
+
+== +next+ Statement
+
+Use +next+ to skip the rest of the current iteration:
+
+ result = [1, 2, 3].map do |value|
+ next if value.even?
+
+ value * 2
+ end
+
+ p result # prints [2, nil, 6]
+
++next+ accepts an argument that can be used as the result of the current
+block iteration:
+
+ result = [1, 2, 3].map do |value|
+ next value if value.even?
+
+ value * 2
+ end
+
+ p result # prints [2, 2, 6]
+
+== +redo+ Statement
+
+Use +redo+ to redo the current iteration:
+
+ result = []
+
+ while result.length < 10 do
+ result << result.length
+
+ redo if result.last.even?
+
+ result << result.length + 1
+ end
+
+ p result
+
+This prints [0, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11]
+
+In Ruby 1.8, you could also use +retry+ where you used +redo+. This is no
+longer true, now you will receive a SyntaxError when you use +retry+ outside
+of a +rescue+ block. See {Exceptions}[rdoc-ref:syntax/exceptions.rdoc]
+for proper usage of +retry+.
+
+== Modifier Statements
+
+Ruby's grammar differentiates between statements and expressions. All
+expressions are statements (an expression is a type of statement), but
+not all statements are expressions. Some parts of the grammar accept
+expressions and not other types of statements, which causes code that
+looks similar to be parsed differently.
+
+For example, when not used as a modifier, +if+, +else+, +while+, +until+,
+and +begin+ are expressions (and also statements). However, when
+used as a modifier, +if+, +else+, +while+, +until+ and +rescue+
+are statements but not expressions.
+
+ if true; 1 end # expression (and therefore statement)
+ 1 if true # statement (not expression)
+
+Statements that are not expressions cannot be used in contexts where an
+expression is expected, such as method arguments.
+
+ puts( 1 if true ) #=> SyntaxError
+
+You can wrap a statement in parentheses to create an expression.
+
+ puts((1 if true)) #=> 1
+
+If you put a space between the method name and opening parenthesis, you
+do not need two sets of parentheses.
+
+ puts (1 if true) #=> 1, because of optional parentheses for method
+
+This is because this is parsed similar to a method call without
+parentheses. It is equivalent to the following code, without the creation
+of a local variable:
+
+ x = (1 if true)
+ p x
+
+In a modifier statement, the left-hand side must be a statement and the
+right-hand side must be an expression.
+
+So in <code>a if b rescue c</code>, because <code>b rescue c</code> is a
+statement that is not an expression, and therefore is not allowed as the
+right-hand side of the +if+ modifier statement, the code is necessarily
+parsed as <code>(a if b) rescue c</code>.
+
+This interacts with operator precedence in such a way that:
+
+ stmt if v = expr rescue x
+ stmt if v = expr unless x
+
+are parsed as:
+
+ stmt if v = (expr rescue x)
+ (stmt if v = expr) unless x
+
+This is because modifier +rescue+ has higher precedence than <code>=</code>,
+and modifier +if+ has lower precedence than <code>=</code>.
+
+== Flip-Flop
+
+The flip-flop is a slightly special conditional expression. One of its
+typical uses is processing text from ruby one-line programs used with
+<code>ruby -n</code> or <code>ruby -p</code>.
+
+The form of the flip-flop is an expression that indicates when the
+flip-flop turns on, <code>..</code> (or <code>...</code>), then an expression
+that indicates when the flip-flop will turn off. While the flip-flop is on it
+will continue to evaluate to +true+, and +false+ when off.
+
+Here is an example:
+
+ selected = []
+
+ 0.upto 10 do |value|
+ selected << value if value==2..value==8
+ end
+
+ p selected # prints [2, 3, 4, 5, 6, 7, 8]
+
+In the above example, the `on' condition is <code>n==2</code>. The flip-flop
+is initially `off' (false) for 0 and 1, but becomes `on' (true) for 2 and
+remains `on' through 8. After 8 it turns off and remains `off' for 9 and 10.
+
+The flip-flop must be used inside a conditional such as <code>!</code>,
+<code>? :</code>, +not+, +if+, +while+, +unless+, +until+ etc. including the
+modifier forms.
+
+When you use an inclusive range (<code>..</code>), the `off' condition is
+evaluated when the `on' condition changes:
+
+ selected = []
+
+ 0.upto 5 do |value|
+ selected << value if value==2..value==2
+ end
+
+ p selected # prints [2]
+
+Here, both sides of the flip-flop are evaluated so the flip-flop turns on and
+off only when +value+ equals 2. Since the flip-flop turned on in the
+iteration it returns true.
+
+When you use an exclusive range (<code>...</code>), the `off' condition is
+evaluated on the following iteration:
+
+ selected = []
+
+ 0.upto 5 do |value|
+ selected << value if value==2...value==2
+ end
+
+ p selected # prints [2, 3, 4, 5]
+
+Here, the flip-flop turns on when +value+ equals 2, but doesn't turn off on the
+same iteration. The `off' condition isn't evaluated until the following
+iteration and +value+ will never be two again.
+
+== throw/catch
+
++throw+ and +catch+ are used to implement non-local control flow in Ruby. They
+operate similarly to exceptions, allowing control to pass directly from the
+place where +throw+ is called to the place where the matching +catch+ is
+called. The main difference between +throw+/+catch+ and the use of exceptions
+is that +throw+/+catch+ are designed for expected non-local control flow,
+while exceptions are designed for exceptional control flow situations, such
+as handling unexpected errors.
+
+When using +throw+, you provide 1-2 arguments. The first argument is the
+value for the matching +catch+. The second argument is optional (defaults to
++nil+), and will be the value that +catch+ returns if there is a matching
++throw+ inside the +catch+ block. If no matching +throw+ method is called
+inside a +catch+ block, the +catch+ method returns the return value of the
+block passed to it.
+
+ def a(n)
+ throw :d, :a if n == 0
+ b(n)
+ end
+
+ def b(n)
+ throw :d, :b if n == 1
+ c(n)
+ end
+
+ def c(n)
+ throw :d if n == 2
+ end
+
+ 4.times.map do |i|
+ catch(:d) do
+ a(i)
+ :default
+ end
+ end
+ # => [:a, :b, nil, :default]
+
+If the first argument you pass to +throw+ is not handled by a matching
++catch+, an UncaughtThrowError exception will be raised. This is because
++throw+/+catch+ should only be used for expected control flow changes, so
+using a value that is not already expected is an error.
+
++throw+/+catch+ are implemented as Kernel methods (Kernel#throw and
+Kernel#catch), not as keywords. So they are not usable directly if you are
+in a BasicObject context. You can use Kernel.throw and Kernel.catch in
+this case:
+
+ BasicObject.new.instance_exec do
+ def a
+ b
+ end
+
+ def b
+ c
+ end
+
+ def c
+ ::Kernel.throw :d, :e
+ end
+
+ result = ::Kernel.catch(:d) do
+ a
+ end
+ result # => :e
+ end
diff --git a/doc/syntax/exceptions.rdoc b/doc/syntax/exceptions.rdoc
new file mode 100644
index 0000000000..cdf9d367a7
--- /dev/null
+++ b/doc/syntax/exceptions.rdoc
@@ -0,0 +1,106 @@
+= Exception Handling
+
+Exceptions are rescued in a +begin+/+end+ block:
+
+ begin
+ # code that might raise
+ rescue
+ # handle exception
+ end
+
+If you are inside a method, you do not need to use +begin+ or +end+ unless you
+wish to limit the scope of rescued exceptions:
+
+ def my_method
+ # ...
+ rescue
+ # ...
+ end
+
+The same is true for a +class+, +module+, and +block+:
+
+ [0, 1, 2].map do |i|
+ 10 / i
+ rescue ZeroDivisionError
+ nil
+ end
+ #=> [nil, 10, 5]
+
+You can assign the exception to a local variable by using <tt>=>
+variable_name</tt> at the end of the +rescue+ line:
+
+ begin
+ # ...
+ rescue => exception
+ warn exception.message
+ raise # re-raise the current exception
+ end
+
+By default, StandardError and its subclasses are rescued. You can rescue a
+specific set of exception classes (and their subclasses) by listing them after
++rescue+:
+
+ begin
+ # ...
+ rescue ArgumentError, NameError
+ # handle ArgumentError or NameError
+ end
+
+You may rescue different types of exceptions in different ways:
+
+ begin
+ # ...
+ rescue ArgumentError
+ # handle ArgumentError
+ rescue NameError
+ # handle NameError
+ rescue
+ # handle any StandardError
+ end
+
+The exception is matched to the rescue section starting at the top, and matches
+only once. If an ArgumentError is raised in the begin section, it will not be
+handled in the StandardError section.
+
+You may retry rescued exceptions:
+
+ begin
+ # ...
+ rescue
+ # do something that may change the result of the begin block
+ retry
+ end
+
+Execution will resume at the start of the begin block, so be careful not to
+create an infinite loop.
+
+Inside a rescue block is the only valid location for +retry+, all other uses
+will raise a SyntaxError. If you wish to retry a block iteration use +redo+.
+See {Control Expressions}[rdoc-ref:syntax/control_expressions.rdoc] for
+details.
+
+To always run some code whether an exception was raised or not, use +ensure+:
+
+ begin
+ # ...
+ rescue
+ # ...
+ ensure
+ # this always runs BUT does not implicitly return the last evaluated statement.
+ end
+
+You may also run some code when an exception is not raised:
+
+ begin
+ # ...
+ rescue
+ # ...
+ else
+ # this runs only when no exception was raised AND return the last evaluated statement
+ ensure
+ # this always runs.
+ # It is evaluated after the evaluation of either the `rescue` or the `else` block.
+ # It will not return implicitly.
+ end
+
+NB : Without explicit +return+ in the +ensure+ block, +begin+/+end+ block will return the last evaluated statement before entering in the +ensure+ block.
diff --git a/doc/syntax/keywords.rdoc b/doc/syntax/keywords.rdoc
new file mode 100644
index 0000000000..7c368205ef
--- /dev/null
+++ b/doc/syntax/keywords.rdoc
@@ -0,0 +1,162 @@
+= Keywords
+
+The following keywords are used by Ruby.
+
+__ENCODING__::
+ The script encoding of the current file. See Encoding.
+
+__LINE__::
+ The line number of this keyword in the current file.
+
+__FILE__::
+ The path to the current file.
+
+BEGIN::
+ Runs before any other code in the current file. See {miscellaneous
+ syntax}[rdoc-ref:syntax/miscellaneous.rdoc]
+
+END::
+ Runs after any other code in the current file. See {miscellaneous
+ syntax}[rdoc-ref:syntax/miscellaneous.rdoc]
+
+alias::
+ Creates an alias between two methods (and other things). See {modules and
+ classes syntax}[rdoc-ref:syntax/modules_and_classes.rdoc]
+
+and::
+ Short-circuit Boolean and with lower precedence than <code>&&</code>
+
+begin::
+ Starts an exception handling block. See {exceptions
+ syntax}[rdoc-ref:syntax/exceptions.rdoc]
+
+break::
+ Leaves a block early. See {control expressions
+ syntax}[rdoc-ref:syntax/control_expressions.rdoc]
+
+case::
+ Starts a +case+ expression. See {control expressions
+ syntax}[rdoc-ref:syntax/control_expressions.rdoc]
+
+class::
+ Creates or opens a class. See {modules and classes
+ syntax}[rdoc-ref:syntax/modules_and_classes.rdoc]
+
+def::
+ Defines a method. See {methods syntax}[rdoc-ref:syntax/methods.rdoc]
+
+defined?::
+ Returns a string describing its argument. See {miscellaneous
+ syntax}[rdoc-ref:syntax/miscellaneous.rdoc]
+
+do::
+ Starts a block.
+
+else::
+ The unhandled condition in +case+, +if+ and +unless+ expressions. See
+ {control expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+elsif::
+ An alternate condition for an +if+ expression. See {control
+ expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+end::
+ The end of a syntax block. Used by classes, modules, methods, exception
+ handling and control expressions.
+
+ensure::
+ Starts a section of code that is always run when an exception is raised.
+ See {exception handling}[rdoc-ref:syntax/exceptions.rdoc]
+
+false::
+ Boolean false. See {literals}[rdoc-ref:syntax/literals.rdoc]
+
+for::
+ A loop that is similar to using the +each+ method. See {control
+ expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+if::
+ Used for +if+ and modifier +if+ statements. See {control
+ expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+in::
+ Used to separate the iterable object and iterator variable in a +for+ loop.
+ See {control expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+ It also serves as a pattern in a +case+ expression.
+ See {pattern matching}[rdoc-ref:syntax/pattern_matching.rdoc]
+
+module::
+ Creates or opens a module. See {modules and classes
+ syntax}[rdoc-ref:syntax/modules_and_classes.rdoc]
+
+next::
+ Skips the rest of the block. See {control
+ expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+nil::
+ A false value usually indicating "no value" or "unknown". See
+ {literals}[rdoc-ref:syntax/literals.rdoc]
+
+not::
+ Inverts the following boolean expression. Has a lower precedence than
+ <code>!</code>
+
+or::
+ Boolean or with lower precedence than <code>||</code>
+
+redo::
+ Restarts execution in the current block. See {control
+ expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+rescue::
+ Starts an exception section of code in a +begin+ block. See {exception
+ handling}[rdoc-ref:syntax/exceptions.rdoc]
+
+retry::
+ Retries an exception block. See {exception
+ handling}[rdoc-ref:syntax/exceptions.rdoc]
+
+return::
+ Exits a method. See {methods}[rdoc-ref:syntax/methods.rdoc].
+ If met in top-level scope, immediately stops interpretation of
+ the current file.
+
+self::
+ The object the current method is attached to. See
+ {methods}[rdoc-ref:syntax/methods.rdoc]
+
+super::
+ Calls the current method in a superclass. See
+ {methods}[rdoc-ref:syntax/methods.rdoc]
+
+then::
+ Indicates the end of conditional blocks in control structures. See
+ {control expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+true::
+ Boolean true. See {literals}[rdoc-ref:syntax/literals.rdoc]
+
+undef::
+ Prevents a class or module from responding to a method call.
+ See {modules and classes}[rdoc-ref:syntax/modules_and_classes.rdoc]
+
+unless::
+ Used for +unless+ and modifier +unless+ statements. See {control
+ expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+until::
+ Creates a loop that executes until the condition is true. See
+ {control expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+when::
+ A condition in a +case+ expression. See
+ {control expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+while::
+ Creates a loop that executes while the condition is true. See
+ {control expressions}[rdoc-ref:syntax/control_expressions.rdoc]
+
+yield::
+ Starts execution of the block sent to the current method. See
+ {methods}[rdoc-ref:syntax/methods.rdoc]
+
diff --git a/doc/syntax/layout.rdoc b/doc/syntax/layout.rdoc
new file mode 100644
index 0000000000..f07447587b
--- /dev/null
+++ b/doc/syntax/layout.rdoc
@@ -0,0 +1,118 @@
+= Code Layout
+
+Expressions in Ruby are separated by line breaks:
+
+ x = 1
+ y = 2
+ z = x + y
+
+Line breaks also used as logical separators of the headers of some of control structures from their bodies:
+
+ if z > 3 # line break ends the condition and starts the body
+ puts "more"
+ end
+
+ while x < 3 # line break ends the condition and starts the body
+ x += 1
+ end
+
+<tt>;</tt> can be used as an expressions separator instead of a line break:
+
+ x = 1; y = 2; z = x + y
+ if z > 3; puts "more"; end
+
+Traditionally, expressions separated by <tt>;</tt> is used only in short scripts and experiments.
+
+In some control structures, there is an optional keyword that can be used instead of a line break to separate their elements:
+
+ # if, elsif, until and case ... when: 'then' is an optional separator:
+
+ if z > 3 then puts "more" end
+
+ case x
+ when Numeric then "number"
+ when String then "string"
+ else "object"
+ end
+
+ # while and until: 'do' is an optional separator
+ while x < 3 do x +=1 end
+
+Also, line breaks can be skipped in some places where it doesn't create any ambiguity. Note in the example above: no line break needed before +end+, just as no line break needed after +else+.
+
+== Breaking expressions in lines
+
+One expression might be split into several lines when each line can be unambiguously identified as "incomplete" without the next one.
+
+These works:
+
+ x = # incomplete without something after =
+ 1 + # incomplete without something after +
+ 2
+
+ File.read "test.txt", # incomplete without something after ,
+ enconding: "utf-8"
+
+These would not:
+
+ # unintended interpretation:
+ x = 1 # already complete expression
+ + 2 # interpreted as a separate +2
+
+ # syntax error:
+ File.read "test.txt" # already complete expression
+ , encoding: "utf-8" # attempt to parse as a new expression, SyntaxError
+
+The exceptions to the rule are lines starting with <tt>.</tt> ("leading dot" style of method calls) or logical operators <tt>&&</tt>/<tt>||</tt> and <tt>and</tt>/<tt>or</tt>:
+
+ # OK, interpreted as a chain of calls
+ File.read('test.txt')
+ .strip("\n")
+ .split("\t")
+ .sort
+
+ # OK, interpreted as a chain of logical operators:
+ File.empty?('test.txt')
+ || File.size('test.txt') < 10
+ || File.read('test.txt').strip.empty?
+
+If the expressions is broken into multiple lines in any of the ways described above, comments between separate lines are allowed:
+
+ sum = base_salary +
+ # see "yearly bonuses section"
+ yearly_bonus(year) +
+ # per-employee coefficient is described
+ # in another module
+ personal_coeff(employee)
+
+ # We want to short-circuit on empty files
+ File.empty?('test.txt')
+ # Or almost empty ones
+ || File.size('test.txt') < 10
+ # Otherwise we check if it is full of spaces
+ || File.read('test.txt').strip.empty?
+
+Finally, the code can explicitly tell Ruby that the expression is continued on the next line with <tt>\\</tt>:
+
+ # Unusual, but works
+ File.read "test.txt" \
+ , encoding: "utf-8"
+
+ # More regular usage (joins the strings on parsing instead
+ # of concatenating them in runtime, as + would do):
+ TEXT = "One pretty long line" \
+ "one more long line" \
+ "one other line of the text"
+
+The <tt>\\</tt> works as a parse time line break escape, so with it, comments can not be inserted between the lines:
+
+ TEXT = "line 1" \
+ # here would be line 2:
+ "line 2"
+
+ # This is interpreted as if there was no line break where \ is,
+ # i.e. the same as
+ TEXT = "line 1" # here would be line 2:
+ "line 2"
+
+ puts TEXT #=> "line 1"
diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc
new file mode 100644
index 0000000000..87a891bf2d
--- /dev/null
+++ b/doc/syntax/literals.rdoc
@@ -0,0 +1,625 @@
+= Literals
+
+Literals create objects you can use in your program. Literals include:
+
+* {Boolean and Nil Literals}[#label-Boolean+and+Nil+Literals]
+* {Numeric Literals}[#label-Numeric+Literals]
+
+ * {Integer Literals}[#label-Integer+Literals]
+ * {Float Literals}[#label-Float+Literals]
+ * {Rational Literals}[#label-Rational+Literals]
+ * {Complex Literals}[#label-Complex+Literals]
+
+* {String Literals}[#label-String+Literals]
+* {Here Document Literals}[#label-Here+Document+Literals]
+* {Symbol Literals}[#label-Symbol+Literals]
+* {Array Literals}[#label-Array+Literals]
+* {Hash Literals}[#label-Hash+Literals]
+* {Range Literals}[#label-Range+Literals]
+* {Regexp Literals}[#label-Regexp+Literals]
+* {Lambda Proc Literals}[#label-Lambda+Proc+Literals]
+* {Percent Literals}[#label-Percent+Literals]
+
+ * {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
+ * {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
+ * {%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals]
+ * {%i and %I: Symbol-Array Literals}[#label-25i+and+-25I-3A+Symbol-Array+Literals]
+ * {%r: Regexp Literals}[#label-25r-3A+Regexp+Literals]
+ * {%s: Symbol Literals}[#label-25s-3A+Symbol+Literals]
+ * {%x: Backtick Literals}[#label-25x-3A+Backtick+Literals]
+
+== Boolean and Nil Literals
+
++nil+ and +false+ are both false values. +nil+ is sometimes used to indicate
+"no value" or "unknown" but evaluates to +false+ in conditional expressions.
+
++true+ is a true value. All objects except +nil+ and +false+ evaluate to a
+true value in conditional expressions.
+
+== \Numeric Literals
+
+=== \Integer Literals
+
+You can write integers of any size as follows:
+
+ 1234
+ 1_234
+
+These numbers have the same value, 1,234. The underscore may be used to
+enhance readability for humans. You may place an underscore anywhere in the
+number.
+
+You can use a special prefix to write numbers in decimal, hexadecimal, octal
+or binary formats. For decimal numbers use a prefix of <tt>0d</tt>, for
+hexadecimal numbers use a prefix of <tt>0x</tt>, for octal numbers use a
+prefix of <tt>0</tt> or <tt>0o</tt>, for binary numbers use a prefix of
+<tt>0b</tt>. The alphabetic component of the number is not case-sensitive.
+
+Examples:
+
+ 0d170
+ 0D170
+
+ 0xaa
+ 0xAa
+ 0xAA
+ 0Xaa
+ 0XAa
+ 0XaA
+
+ 0252
+ 0o252
+ 0O252
+
+ 0b10101010
+ 0B10101010
+
+All these numbers have the same decimal value, 170. Like integers and floats
+you may use an underscore for readability.
+
+=== \Float Literals
+
+Floating-point numbers may be written as follows:
+
+ 12.34
+ 1234e-2
+ 1.234E1
+
+These numbers have the same value, 12.34. You may use underscores in floating
+point numbers as well.
+
+=== \Rational Literals
+
+You can write a Rational literal using a special suffix, <tt>'r'</tt>.
+
+Examples:
+
+ 1r # => (1/1)
+ 2/3r # => (2/3) # With denominator.
+ -1r # => (-1/1) # With signs.
+ -2/3r # => (-2/3)
+ 2/-3r # => (-2/3)
+ -2/-3r # => (2/3)
+ +1/+3r # => (1/3)
+ 1.2r # => (6/5) # With fractional part.
+ 1_1/2_1r # => (11/21) # With embedded underscores.
+ 2/4r # => (1/2) # Automatically reduced.
+
+Syntax:
+
+ <rational-literal> = <numerator> [ '/' <denominator> ] 'r'
+ <numerator> = [ <sign> ] <digits> [ <fractional-part> ]
+ <fractional-part> = '.' <digits>
+ <denominator> = [ sign ] <digits>
+ <sign> = '-' | '+'
+ <digits> = <digit> { <digit> | '_' <digit> }
+ <digit> = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+
+Note this, which is parsed as \Float numerator <tt>1.2</tt>
+divided by \Rational denominator <tt>3r</tt>,
+resulting in a \Float:
+
+ 1.2/3r # => 0.39999999999999997
+
+=== \Complex Literals
+
+You can write a Complex number as follows (suffixed +i+):
+
+ 1i #=> (0+1i)
+ 1i * 1i #=> (-1+0i)
+
+Also \Rational numbers may be imaginary numbers.
+
+ 12.3ri #=> (0+(123/10)*i)
+
++i+ must be placed after +r+; the opposite is not allowed.
+
+ 12.3ir #=> Syntax error
+
+== \String Literals
+
+=== Double-Quoted \String Literals
+
+The most common way of writing strings is using <tt>"</tt>:
+
+ "This is a string."
+
+The string may be many lines long.
+
+Any internal <tt>"</tt> must be escaped:
+
+ "This string has a quote: \". As you can see, it is escaped"
+
+Double-quoted strings allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+
+In a double-quoted string,
+any other character following a backslash is interpreted as the
+character itself.
+
+Double-quoted strings allow interpolation of other values using
+<tt>#{...}</tt>:
+
+ "One plus one is two: #{1 + 1}"
+
+Any expression may be placed inside the interpolated section, but it's best to
+keep the expression small for readability.
+
+You can also use <tt>#@foo</tt>, <tt>#@@foo</tt> and <tt>#$foo</tt> as a
+shorthand for, respectively, <tt>#{ @foo }</tt>, <tt>#{ @@foo }</tt> and
+<tt>#{ $foo }</tt>.
+
+See also:
+
+* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals]
+
+=== Single-Quoted \String Literals
+
+Interpolation may be disabled by escaping the "#" character or using
+single-quoted strings:
+
+ '#{1 + 1}' #=> "\#{1 + 1}"
+
+In addition to disabling interpolation, single-quoted strings also disable all
+escape sequences except for the single-quote (<tt>\'</tt>) and backslash
+(<tt>\\\\</tt>).
+
+In a single-quoted string,
+any other character following a backslash is interpreted as is:
+a backslash and the character itself.
+
+See also:
+
+* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals]
+
+=== Literal String Concatenation
+
+Adjacent string literals are automatically concatenated by the interpreter:
+
+ "con" "cat" "en" "at" "ion" #=> "concatenation"
+ "This string contains "\
+ "no newlines." #=> "This string contains no newlines."
+
+Any combination of adjacent single-quote, double-quote, percent strings will
+be concatenated as long as a percent-string is not last.
+
+ %q{a} 'b' "c" #=> "abc"
+ "a" 'b' %q{c} #=> NoMethodError: undefined method 'q' for main
+
+=== Character Literal
+
+There is also a character literal notation to represent single
+character strings, which syntax is a question mark (<tt>?</tt>)
+followed by a single character or escape sequence (except continuation line)
+that corresponds to a single codepoint in the script encoding:
+
+ ?a #=> "a"
+ ?abc #=> SyntaxError
+ ?\n #=> "\n"
+ ?\s #=> " "
+ ?\\ #=> "\\"
+ ?\u{41} #=> "A"
+ ?\C-a #=> "\x01"
+ ?\M-a #=> "\xE1"
+ ?\M-\C-a #=> "\x81"
+ ?\C-\M-a #=> "\x81", same as above
+ ?あ #=> "あ"
+
+=== Escape Sequences
+
+Some characters can be represented as escape sequences in
+double-quoted strings,
+character literals,
+here document literals (non-quoted, double-quoted, and with backticks),
+double-quoted symbols,
+double-quoted symbol keys in Hash literals,
+Regexp literals, and
+several percent literals (<tt>%</tt>, <tt>%Q</tt>, <tt>%W</tt>, <tt>%I</tt>, <tt>%r</tt>, <tt>%x</tt>).
+
+They allow escape sequences such as <tt>\n</tt> for
+newline, <tt>\t</tt> for tab, etc. The full list of supported escape
+sequences are as follows:
+
+ \a bell, ASCII 07h (BEL)
+ \b backspace, ASCII 08h (BS)
+ \t horizontal tab, ASCII 09h (TAB)
+ \n newline (line feed), ASCII 0Ah (LF)
+ \v vertical tab, ASCII 0Bh (VT)
+ \f form feed, ASCII 0Ch (FF)
+ \r carriage return, ASCII 0Dh (CR)
+ \e escape, ASCII 1Bh (ESC)
+ \s space, ASCII 20h (SPC)
+ \\ backslash, \
+ \nnn octal bit pattern, where nnn is 1-3 octal digits ([0-7])
+ \xnn hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F])
+ \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F])
+ \u{nnnn ...} Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F])
+ \cx or \C-x control character, where x is an ASCII printable character
+ \M-x meta character, where x is an ASCII printable character
+ \M-\C-x meta control character, where x is an ASCII printable character
+ \M-\cx same as above
+ \c\M-x same as above
+ \c? or \C-? delete, ASCII 7Fh (DEL)
+ \<newline> continuation line (empty string)
+
+The last one, <tt>\<newline></tt>, represents an empty string instead of a character.
+It is used to fold a line in a string.
+
+=== Here Document Literals
+
+If you are writing a large block of text you may use a "here document" or
+"heredoc":
+
+ expected_result = <<HEREDOC
+ This would contain specially formatted text.
+
+ That might span many lines
+ HEREDOC
+
+The heredoc starts on the line following <tt><<HEREDOC</tt> and ends with the
+next line that starts with <tt>HEREDOC</tt>. The result includes the ending
+newline.
+
+You may use any identifier with a heredoc, but all-uppercase identifiers are
+typically used.
+
+You may indent the ending identifier if you place a "-" after <tt><<</tt>:
+
+ expected_result = <<-INDENTED_HEREDOC
+ This would contain specially formatted text.
+
+ That might span many lines
+ INDENTED_HEREDOC
+
+Note that while the closing identifier may be indented, the content is
+always treated as if it is flush left. If you indent the content those spaces
+will appear in the output.
+
+To have indented content as well as an indented closing identifier, you can use
+a "squiggly" heredoc, which uses a "~" instead of a "-" after <tt><<</tt>:
+
+ expected_result = <<~SQUIGGLY_HEREDOC
+ This would contain specially formatted text.
+
+ That might span many lines
+ SQUIGGLY_HEREDOC
+
+The indentation of the least-indented line will be removed from each line of
+the content. Note that empty lines and lines consisting solely of literal tabs
+and spaces will be ignored for the purposes of determining indentation, but
+escaped tabs and spaces are considered non-indentation characters.
+
+For the purpose of measuring an indentation, a horizontal tab is regarded as a
+sequence of one to eight spaces such that the column position corresponding to
+its end is a multiple of eight. The amount to be removed is counted in terms
+of the number of spaces. If the boundary appears in the middle of a tab, that
+tab is not removed.
+
+A heredoc allows interpolation and the escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+You may disable interpolation and the escaping by surrounding the opening
+identifier with single quotes:
+
+ expected_result = <<-'EXPECTED'
+ One plus one is #{1 + 1}
+ EXPECTED
+
+ p expected_result # prints: "One plus one is \#{1 + 1}\n"
+
+The identifier may also be surrounded with double quotes (which is the same as
+no quotes) or with backticks. When surrounded by backticks the HEREDOC
+behaves like Kernel#`:
+
+ puts <<-`HEREDOC`
+ cat #{__FILE__}
+ HEREDOC
+
+When surrounding with quotes, any character but that quote and newline
+(CR and/or LF) can be used as the identifier.
+
+To call a method on a heredoc place it after the opening identifier:
+
+ expected_result = <<-EXPECTED.chomp
+ One plus one is #{1 + 1}
+ EXPECTED
+
+You may open multiple heredocs on the same line, but this can be difficult to
+read:
+
+ puts(<<-ONE, <<-TWO)
+ content for heredoc one
+ ONE
+ content for heredoc two
+ TWO
+
+== \Symbol Literals
+
+A Symbol represents a name inside the ruby interpreter. See Symbol for more
+details on what symbols are and when ruby creates them internally.
+
+You may reference a symbol using a colon: <tt>:my_symbol</tt>.
+
+You may also create symbols by interpolation and escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences] with double-quotes:
+
+ :"my_symbol1"
+ :"my_symbol#{1 + 1}"
+ :"foo\sbar"
+
+Like strings, a single-quote may be used to disable interpolation and
+escape sequences:
+
+ :'my_symbol#{1 + 1}' #=> :"my_symbol\#{1 + 1}"
+
+When creating a Hash, there is a special syntax for referencing a Symbol as
+well.
+
+See also:
+
+* {%s: Symbol Literals}[#label-25s-3A+Symbol+Literals]
+
+
+== \Array Literals
+
+An array is created using the objects between <tt>[</tt> and <tt>]</tt>:
+
+ [1, 2, 3]
+
+You may place expressions inside the array:
+
+ [1, 1 + 1, 1 + 2]
+ [1, [1 + 1, [1 + 2]]]
+
+See also:
+
+* {%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals]
+* {%i and %I: Symbol-Array Literals}[#label-25i+and+-25I-3A+Symbol-Array+Literals]
+
+See Array for the methods you may use with an array.
+
+== \Hash Literals
+
+A hash is created using key-value pairs between <tt>{</tt> and <tt>}</tt>:
+
+ { "a" => 1, "b" => 2 }
+
+Both the key and value may be any object.
+
+You can create a hash using symbol keys with the following syntax:
+
+ { a: 1, b: 2 }
+
+This same syntax is used for keyword arguments for a method.
+
+Like Symbol literals, you can quote symbol keys.
+
+ { "a 1": 1, "b #{1 + 1}": 2 }
+
+is equal to
+
+ { :"a 1" => 1, :"b 2" => 2 }
+
+Hash values can be omitted, meaning that value will be fetched from the context
+by the name of the key:
+
+ x = 100
+ y = 200
+ h = { x:, y: }
+ #=> {:x=>100, :y=>200}
+
+See Hash for the methods you may use with a hash.
+
+== \Range Literals
+
+A range represents an interval of values. The range may include or exclude
+its ending value.
+
+ (1..2) # includes its ending value
+ (1...2) # excludes its ending value
+ (1..) # endless range, representing infinite sequence from 1 to Infinity
+ (..1) # beginless range, representing infinite sequence from -Infinity to 1
+
+You may create a range of any object. See the Range documentation for details
+on the methods you need to implement.
+
+== \Regexp Literals
+
+A regular expression may be created using leading and trailing
+slash (<tt>'/'</tt>) characters:
+
+ re = /foo/ # => /foo/
+ re.class # => Regexp
+
+The trailing slash may be followed by one or more modifiers characters
+that set modes for the regexp.
+See {Regexp modes}[rdoc-ref:Regexp@Modes] for details.
+
+Interpolation may be used inside regular expressions along with escaped
+characters. Note that a regular expression may require additional escaped
+characters than a string.
+
+See also:
+
+* {%r: Regexp Literals}[#label-25r-3A+Regexp+Literals]
+
+See Regexp for a description of the syntax of regular expressions.
+
+== Lambda Proc Literals
+
+A lambda proc can be created with <tt>-></tt>:
+
+ -> { 1 + 1 }
+
+Calling the above proc will give a result of <tt>2</tt>.
+
+You can require arguments for the proc as follows:
+
+ ->(v) { 1 + v }
+
+This proc will add one to its argument.
+
+== Percent Literals
+
+Each of the literals in described in this section
+may use these paired delimiters:
+
+* <tt>[</tt> and <tt>]</tt>.
+* <tt>(</tt> and <tt>)</tt>.
+* <tt>{</tt> and <tt>}</tt>.
+* <tt><</tt> and <tt>></tt>.
+* Non-alphanumeric ASCII character except above, as both beginning and ending delimiters.
+
+The delimiters can be escaped with a backslash.
+However, the first four pairs (brackets, parenthesis, braces, and
+angle brackets) are allowed without backslash as far as they are correctly
+paired.
+
+These are demonstrated in the next section.
+
+=== <tt>%q</tt>: Non-Interpolable String Literals
+
+You can write a non-interpolable string with <tt>%q</tt>.
+The created string is the same as if you created it with single quotes:
+
+ %q[foo bar baz] # => "foo bar baz" # Using [].
+ %q(foo bar baz) # => "foo bar baz" # Using ().
+ %q{foo bar baz} # => "foo bar baz" # Using {}.
+ %q<foo bar baz> # => "foo bar baz" # Using <>.
+ %q|foo bar baz| # => "foo bar baz" # Using two |.
+ %q:foo bar baz: # => "foo bar baz" # Using two :.
+ %q(1 + 1 is #{1 + 1}) # => "1 + 1 is \#{1 + 1}" # No interpolation.
+ %q[foo[bar]baz] # => "foo[bar]baz" # brackets can be nested.
+ %q(foo(bar)baz) # => "foo(bar)baz" # parenthesis can be nested.
+ %q{foo{bar}baz} # => "foo{bar}baz" # braces can be nested.
+ %q<foo<bar>baz> # => "foo<bar>baz" # angle brackets can be nested.
+
+This is similar to single-quoted string but only backslashes and
+the specified delimiters can be escaped with a backslash.
+
+=== <tt>% and %Q</tt>: Interpolable String Literals
+
+You can write an interpolable string with <tt>%Q</tt>
+or with its alias <tt>%</tt>:
+
+ %[foo bar baz] # => "foo bar baz"
+ %(1 + 1 is #{1 + 1}) # => "1 + 1 is 2" # Interpolation.
+
+This is similar to double-quoted string.
+It allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+Other escaped characters (a backslash followed by a character) are
+interpreted as the character.
+
+=== <tt>%w and %W</tt>: String-Array Literals
+
+You can write an array of strings as whitespace-separated words
+with <tt>%w</tt> (non-interpolable) or <tt>%W</tt> (interpolable):
+
+ %w[foo bar baz] # => ["foo", "bar", "baz"]
+ %w[1 % *] # => ["1", "%", "*"]
+ # Use backslash to embed spaces in the strings.
+ %w[foo\ bar baz\ bat] # => ["foo bar", "baz bat"]
+ %W[foo\ bar baz\ bat] # => ["foo bar", "baz bat"]
+ %w(#{1 + 1}) # => ["\#{1", "+", "1}"]
+ %W(#{1 + 1}) # => ["2"]
+
+ # The nested delimiters evaluated to a flat array of strings
+ # (not nested array).
+ %w[foo[bar baz]qux] # => ["foo[bar", "baz]qux"]
+
+The following characters are considered as white spaces to separate words:
+
+* space, ASCII 20h (SPC)
+* form feed, ASCII 0Ch (FF)
+* newline (line feed), ASCII 0Ah (LF)
+* carriage return, ASCII 0Dh (CR)
+* horizontal tab, ASCII 09h (TAB)
+* vertical tab, ASCII 0Bh (VT)
+
+The white space characters can be escaped with a backslash to make them
+part of a word.
+
+<tt>%W</tt> allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
+However the continuation line <tt>\<newline></tt> is not usable because
+it is interpreted as the escaped newline described above.
+
+=== <tt>%i and %I</tt>: Symbol-Array Literals
+
+You can write an array of symbols as whitespace-separated words
+with <tt>%i</tt> (non-interpolable) or <tt>%I</tt> (interpolable):
+
+ %i[foo bar baz] # => [:foo, :bar, :baz]
+ %i[1 % *] # => [:"1", :%, :*]
+ # Use backslash to embed spaces in the symbols.
+ %i[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"]
+ %I[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"]
+ %i(#{1 + 1}) # => [:"\#{1", :+, :"1}"]
+ %I(#{1 + 1}) # => [:"2"]
+
+The white space characters and its escapes are interpreted as the same as
+string-array literals described in
+{%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals].
+
+=== <tt>%s</tt>: Symbol Literals
+
+You can write a symbol with <tt>%s</tt>:
+
+ %s[foo] # => :foo
+ %s[foo bar] # => :"foo bar"
+
+This is non-interpolable.
+No interpolation allowed.
+Only backslashes and the specified delimiters can be escaped with a backslash.
+
+=== <tt>%r</tt>: Regexp Literals
+
+You can write a regular expression with <tt>%r</tt>;
+the character used as the leading and trailing delimiter
+may be (almost) any character:
+
+ %r/foo/ # => /foo/
+ %r:name/value pair: # => /name\/value pair/
+
+A few "symmetrical" character pairs may be used as delimiters:
+
+ %r[foo] # => /foo/
+ %r{foo} # => /foo/
+ %r(foo) # => /foo/
+ %r<foo> # => /foo/
+
+The trailing delimiter may be followed by one or more modifier characters
+that set modes for the regexp.
+See {Regexp modes}[rdoc-ref:Regexp@Modes] for details.
+
+=== <tt>%x</tt>: Backtick Literals
+
+You can write and execute a shell command with <tt>%x</tt>:
+
+ %x(echo 1) # => "1\n"
+ %x[echo #{1 + 2}] # => "3\n"
+ %x[echo \u0030] # => "0\n"
+
+This is interpolable.
+<tt>%x</tt> allow escape sequences described in
+{Escape Sequences}[#label-Escape+Sequences].
diff --git a/doc/syntax/methods.rdoc b/doc/syntax/methods.rdoc
new file mode 100644
index 0000000000..14810a188f
--- /dev/null
+++ b/doc/syntax/methods.rdoc
@@ -0,0 +1,653 @@
+= Methods
+
+Methods implement the functionality of your program. Here is a simple method
+definition:
+
+ def one_plus_one
+ 1 + 1
+ end
+
+A method definition consists of the +def+ keyword, a method name, the body of
+the method, +return+ value and the +end+ keyword. When called the method will
+execute the body of the method. This method returns +2+.
+
+Since Ruby 3.0, there is also a shorthand syntax for methods consisting
+of exactly one expression:
+
+ def one_plus_one = 1 + 1
+
+This section only covers defining methods. See also the {syntax documentation
+on calling methods}[rdoc-ref:syntax/calling_methods.rdoc].
+
+== Method Names
+
+Method names may be one of the operators or must start a letter or a character
+with the eighth bit set. It may contain letters, numbers, an <code>_</code>
+(underscore or low line) or a character with the eighth bit set. The convention
+is to use underscores to separate words in a multiword method name:
+
+ def method_name
+ puts "use underscores to separate words"
+ end
+
+Ruby programs must be written in a US-ASCII-compatible character set such as
+UTF-8, ISO-8859-1 etc. In such character sets if the eighth bit is set it
+indicates an extended character. Ruby allows method names and other identifiers
+to contain such characters. Ruby programs cannot contain some characters like
+ASCII NUL (<code>\x00</code>).
+
+The following are examples of valid Ruby methods:
+
+ def hello
+ "hello"
+ end
+
+ def こんにちは
+ puts "means hello in Japanese"
+ end
+
+Typically method names are US-ASCII compatible since the keys to type them
+exist on all keyboards.
+
+Method names may end with a <code>!</code> (bang or exclamation mark), a
+<code>?</code> (question mark), or <code>=</code> (equals sign).
+
+The bang methods (<code>!</code> at the end of the method name) are called and
+executed just like any other method. However, by convention, a method with an
+exclamation point or bang is considered dangerous. In Ruby's core library the
+dangerous method implies that when a method ends with a bang (<code>!</code>),
+it indicates that unlike its non-bang equivalent, permanently modifies its
+receiver. Almost always, the Ruby core library will have a non-bang
+counterpart (method name which does NOT end with <code>!</code>) of every bang
+method (method name which does end with <code>!</code>) that does not modify
+the receiver. This convention is typically true for the Ruby core library but
+may or may not hold true for other Ruby libraries.
+
+Methods that end with a question mark by convention return boolean, but they
+may not always return just +true+ or +false+. Often, they will return an
+object to indicate a true value (or "truthy" value).
+
+Methods that end with an equals sign indicate an assignment method.
+
+ class C
+ def attr
+ @attr
+ end
+
+ def attr=(val)
+ @attr = val
+ end
+ end
+
+ c = C.new
+ c.attr #=> nil
+ c.attr = 10 # calls "attr=(10)"
+ c.attr #=> 10
+
+Assignment methods can not be defined using the shorthand syntax.
+
+These are method names for the various Ruby operators. Each of these
+operators accepts only one argument. Following the operator is the typical
+use or name of the operator. Creating an alternate meaning for the operator
+may lead to confusion as the user expects plus to add things, minus to
+subtract things, etc. Additionally, you cannot alter the precedence of the
+operators.
+
+<code>+</code> :: add
+<code>-</code> :: subtract
+<code>*</code> :: multiply
+<code>**</code> :: power
+<code>/</code> :: divide
+<code>%</code> :: modulus division, String#%
+<code>&</code> :: AND
+<code>|</code> :: OR
+<code>^</code> :: XOR (exclusive OR)
+<code>>></code> :: right-shift
+<code><<</code> :: left-shift, append
+<code>==</code> :: equal
+<code>!=</code> :: not equal
+<code>===</code> :: case equality. See Object#===
+<code>=~</code> :: pattern match. (Not just for regular expressions)
+<code>!~</code> :: does not match
+<code><=></code> :: comparison aka spaceship operator. See Comparable
+<code><</code> :: less-than
+<code><=</code> :: less-than or equal
+<code>></code> :: greater-than
+<code>>=</code> :: greater-than or equal
+
+To define unary methods minus and plus, follow the operator with an
+<code>@</code> as in <code>+@</code>:
+
+ class C
+ def -@
+ puts "you inverted this object"
+ end
+ end
+
+ obj = C.new
+
+ -obj # prints "you inverted this object"
+
+The <code>@</code> is needed to differentiate unary minus and plus
+operators from binary minus and plus operators.
+
+You can also follow tilde and not (<code>!</code>) unary methods with
+<code>@</code>, but it is not required as there are no binary tilde
+and not operators.
+
+Unary methods accept zero arguments.
+
+Additionally, methods for element reference and assignment may be defined:
+<code>[]</code> and <code>[]=</code> respectively. Both can take one or more
+arguments, and element reference can take none.
+
+ class C
+ def [](a, b)
+ puts a + b
+ end
+
+ def []=(a, b, c)
+ puts a * b + c
+ end
+ end
+
+ obj = C.new
+
+ obj[2, 3] # prints "5"
+ obj[2, 3] = 4 # prints "10"
+
+== Return Values
+
+By default, a method returns the last expression that was evaluated in the body
+of the method. In the example above, the last (and only) expression evaluated
+was the simple sum <code>1 + 1</code>. The +return+ keyword can be used to
+make it explicit that a method returns a value.
+
+ def one_plus_one
+ return 1 + 1
+ end
+
+It can also be used to make a method return before the last expression is
+evaluated.
+
+ def two_plus_two
+ return 2 + 2
+ 1 + 1 # this expression is never evaluated
+ end
+
+Note that for assignment methods the return value will be ignored when using
+the assignment syntax. Instead, the argument will be returned:
+
+ def a=(value)
+ return 1 + value
+ end
+
+ p(self.a = 5) # prints 5
+
+The actual return value will be returned when invoking the method directly:
+
+ p send(:a=, 5) # prints 6
+
+== Scope
+
+The standard syntax to define a method:
+
+ def my_method
+ # ...
+ end
+
+adds the method to a class. You can define an instance method on a specific
+class with the +class+ keyword:
+
+ class C
+ def my_method
+ # ...
+ end
+ end
+
+A method may be defined on another object. You may define a "class method" (a
+method that is defined on the class, not an instance of the class) like this:
+
+ class C
+ def self.my_method
+ # ...
+ end
+ end
+
+However, this is simply a special case of a greater syntactical power in Ruby,
+the ability to add methods to any object. Classes are objects, so adding
+class methods is simply adding methods to the Class object.
+
+The syntax for adding a method to an object is as follows:
+
+ greeting = "Hello"
+
+ def greeting.broaden
+ self + ", world!"
+ end
+
+ greeting.broaden # returns "Hello, world!"
+
++self+ is a keyword referring to the current object under consideration
+by the compiler, which might make the use of +self+ in defining a class
+method above a little clearer. Indeed, the example of adding a +hello+
+method to the class +String+ can be rewritten thus:
+
+ def String.hello
+ "Hello, world!"
+ end
+
+A method defined like this is called a "singleton method". +broaden+ will only
+exist on the string instance +greeting+. Other strings will not have +broaden+.
+
+== Overriding
+
+When Ruby encounters the +def+ keyword, it doesn't consider it an error if the
+method already exists: it simply redefines it. This is called
+_overriding_. Rather like extending core classes, this is a potentially
+dangerous ability, and should be used sparingly because it can cause unexpected
+results. For example, consider this irb session:
+
+ >> "43".to_i
+ => 43
+ >> class String
+ >> def to_i
+ >> 42
+ >> end
+ >> end
+ => nil
+ >> "43".to_i
+ => 42
+
+This will effectively sabotage any code which makes use of the method
+<code>String#to_i</code> to parse numbers from strings.
+
+== Arguments
+
+A method may accept arguments. The argument list follows the method name:
+
+ def add_one(value)
+ value + 1
+ end
+
+When called, the user of the +add_one+ method must provide an argument. The
+argument is a local variable in the method body. The method will then add one
+to this argument and return the value. If given +1+ this method will
+return +2+.
+
+The parentheses around the arguments are optional:
+
+ def add_one value
+ value + 1
+ end
+
+The parentheses are mandatory in shorthand method definitions:
+
+ # OK
+ def add_one(value) = value + 1
+ # SyntaxError
+ def add_one value = value + 1
+
+Multiple arguments are separated by a comma:
+
+ def add_values(a, b)
+ a + b
+ end
+
+When called, the arguments must be provided in the exact order. In other
+words, the arguments are positional.
+
+=== Default Values
+
+Arguments may have default values:
+
+ def add_values(a, b = 1)
+ a + b
+ end
+
+The default value does not need to appear first, but arguments with defaults
+must be grouped together. This is ok:
+
+ def add_values(a = 1, b = 2, c)
+ a + b + c
+ end
+
+This will raise a SyntaxError:
+
+ def add_values(a = 1, b, c = 1)
+ a + b + c
+ end
+
+Default argument values can refer to arguments that have already been
+evaluated as local variables, and argument values are always evaluated
+left to right. So this is allowed:
+
+ def add_values(a = 1, b = a)
+ a + b
+ end
+ add_values
+ # => 2
+
+But this will raise a +NameError+ (unless there is a method named
++b+ defined):
+
+ def add_values(a = b, b = 1)
+ a + b
+ end
+ add_values
+ # NameError (undefined local variable or method `b' for main:Object)
+
+=== Array Decomposition
+
+You can decompose (unpack or extract values from) an Array using extra
+parentheses in the arguments:
+
+ def my_method((a, b))
+ p a: a, b: b
+ end
+
+ my_method([1, 2])
+
+This prints:
+
+ {:a=>1, :b=>2}
+
+If the argument has extra elements in the Array they will be ignored:
+
+ def my_method((a, b))
+ p a: a, b: b
+ end
+
+ my_method([1, 2, 3])
+
+This has the same output as above.
+
+You can use a <code>*</code> to collect the remaining arguments. This splits
+an Array into a first element and the rest:
+
+ def my_method((a, *b))
+ p a: a, b: b
+ end
+
+ my_method([1, 2, 3])
+
+This prints:
+
+ {:a=>1, :b=>[2, 3]}
+
+The argument will be decomposed if it responds to #to_ary. You should only
+define #to_ary if you can use your object in place of an Array.
+
+Use of the inner parentheses only uses one of the sent arguments. If the
+argument is not an Array it will be assigned to the first argument in the
+decomposition and the remaining arguments in the decomposition will be +nil+:
+
+ def my_method(a, (b, c), d)
+ p a: a, b: b, c: c, d: d
+ end
+
+ my_method(1, 2, 3)
+
+This prints:
+
+ {:a=>1, :b=>2, :c=>nil, :d=>3}
+
+You can nest decomposition arbitrarily:
+
+ def my_method(((a, b), c))
+ # ...
+ end
+
+=== Array/Hash Argument
+
+Prefixing an argument with <code>*</code> causes any remaining arguments to be
+converted to an Array:
+
+ def gather_arguments(*arguments)
+ p arguments
+ end
+
+ gather_arguments 1, 2, 3 # prints [1, 2, 3]
+
+The array argument must appear before any keyword arguments.
+
+It is possible to gather arguments at the beginning or in the middle:
+
+ def gather_arguments(first_arg, *middle_arguments, last_arg)
+ p middle_arguments
+ end
+
+ gather_arguments 1, 2, 3, 4 # prints [2, 3]
+
+The array argument will capture a Hash as the last entry if keywords were
+provided by the caller after all positional arguments.
+
+ def gather_arguments(*arguments)
+ p arguments
+ end
+
+ gather_arguments 1, a: 2 # prints [1, {:a=>2}]
+
+However, this only occurs if the method does not declare any keyword arguments.
+
+ def gather_arguments_keyword(*positional, keyword: nil)
+ p positional: positional, keyword: keyword
+ end
+
+ gather_arguments_keyword 1, 2, three: 3
+ #=> raises: unknown keyword: three (ArgumentError)
+
+Also, note that a bare <code>*</code> can be used to ignore arguments:
+
+ def ignore_arguments(*)
+ end
+
+You can also use a bare <code>*</code> when calling a method to pass the
+arguments directly to another method:
+
+ def delegate_arguments(*)
+ other_method(*)
+ end
+
+=== Keyword Arguments
+
+Keyword arguments are similar to positional arguments with default values:
+
+ def add_values(first: 1, second: 2)
+ first + second
+ end
+
+Arbitrary keyword arguments will be accepted with <code>**</code>:
+
+ def gather_arguments(first: nil, **rest)
+ p first, rest
+ end
+
+ gather_arguments first: 1, second: 2, third: 3
+ # prints 1 then {:second=>2, :third=>3}
+
+When calling a method with keyword arguments the arguments may appear in any
+order. If an unknown keyword argument is sent by the caller, and the method
+does not accept arbitrary keyword arguments, an ArgumentError is raised.
+
+To require a specific keyword argument, do not include a default value
+for the keyword argument:
+
+ def add_values(first:, second:)
+ first + second
+ end
+ add_values
+ # ArgumentError (missing keywords: first, second)
+ add_values(first: 1, second: 2)
+ # => 3
+
+When mixing keyword arguments and positional arguments, all positional
+arguments must appear before any keyword arguments.
+
+Also, note that <code>**</code> can be used to ignore keyword arguments:
+
+ def ignore_keywords(**)
+ end
+
+You can also use <code>**</code> when calling a method to delegate
+keyword arguments to another method:
+
+ def delegate_keywords(**)
+ other_method(**)
+ end
+
+To mark a method as accepting keywords, but not actually accepting
+keywords, you can use the <code>**nil</code>:
+
+ def no_keywords(**nil)
+ end
+
+Calling such a method with keywords or a non-empty keyword splat will
+result in an ArgumentError. This syntax is supported so that keywords
+can be added to the method later without affected backwards compatibility.
+
+If a method definition does not accept any keywords, and the
+<code>**nil</code> syntax is not used, any keywords provided when calling
+the method will be converted to a Hash positional argument:
+
+ def meth(arg)
+ arg
+ end
+ meth(a: 1)
+ # => {:a=>1}
+
+=== Block Argument
+
+The block argument is indicated by <code>&</code> and must come last:
+
+ def my_method(&my_block)
+ my_block.call(self)
+ end
+
+Most frequently the block argument is used to pass a block to another method:
+
+ def each_item(&block)
+ @items.each(&block)
+ end
+
+You are not required to give a name to the block if you will just be passing
+it to another method:
+
+ def each_item(&)
+ @items.each(&)
+ end
+
+If you are only going to call the block and will not otherwise manipulate it
+or send it to another method, using <code>yield</code> without an explicit
+block parameter is preferred. This method is equivalent to the first method
+in this section:
+
+ def my_method
+ yield self
+ end
+
+=== Argument Forwarding
+
+Since Ruby 2.7, an all-arguments forwarding syntax is available:
+
+ def concrete_method(*positional_args, **keyword_args, &block)
+ [positional_args, keyword_args, block]
+ end
+
+ def forwarding_method(...)
+ concrete_method(...)
+ end
+
+ forwarding_method(1, b: 2) { puts 3 }
+ #=> [[1], {:b=>2}, #<Proc:...skip...>]
+
+Calling with forwarding <code>...</code> is available only in methods
+defined with <code>...</code>.
+
+ def regular_method(arg, **kwarg)
+ concrete_method(...) # Syntax error
+ end
+
+Since Ruby 3.0, there can be leading arguments before <code>...</code>
+both in definitions and in invocations (but in definitions they can be
+only positional arguments without default values).
+
+ def request(method, path, **headers)
+ puts "#{method.upcase} #{path} #{headers}"
+ end
+
+ def get(...)
+ request(:GET, ...) # leading argument in invoking
+ end
+
+ get('http://ruby-lang.org', 'Accept' => 'text/html')
+ # Prints: GET http://ruby-lang.org {"Accept"=>"text/html"}
+
+ def logged_get(msg, ...) # leading argument in definition
+ puts "Invoking #get: #{msg}"
+ get(...)
+ end
+
+ logged_get('Ruby site', 'http://ruby-lang.org')
+ # Prints:
+ # Invoking #get: Ruby site
+ # GET http://ruby-lang.org {}
+
+Note that omitting parentheses in forwarding calls may lead to
+unexpected results:
+
+ def log(...)
+ puts ... # This would be treated as `puts()...',
+ # i.e. endless range from puts result
+ end
+
+ log("test")
+ # Prints: warning: ... at EOL, should be parenthesized?
+ # ...and then empty line
+
+== Exception Handling
+
+Methods have an implied exception handling block so you do not need to use
++begin+ or +end+ to handle exceptions. This:
+
+ def my_method
+ begin
+ # code that may raise an exception
+ rescue
+ # handle exception
+ end
+ end
+
+May be written as:
+
+ def my_method
+ # code that may raise an exception
+ rescue
+ # handle exception
+ end
+
+Similarly, if you wish to always run code even if an exception is raised,
+you can use +ensure+ without +begin+ and +end+:
+
+ def my_method
+ # code that may raise an exception
+ ensure
+ # code that runs even if previous code raised an exception
+ end
+
+You can also combine +rescue+ with +ensure+ and/or +else+, without
++begin+ and +end+:
+
+ def my_method
+ # code that may raise an exception
+ rescue
+ # handle exception
+ else
+ # only run if no exception raised above
+ ensure
+ # code that runs even if previous code raised an exception
+ end
+
+If you wish to rescue an exception for only part of your method, use +begin+ and
++end+. For more details see the page on {exception
+handling}[rdoc-ref:syntax/exceptions.rdoc].
diff --git a/doc/syntax/miscellaneous.rdoc b/doc/syntax/miscellaneous.rdoc
new file mode 100644
index 0000000000..d5cfd3e474
--- /dev/null
+++ b/doc/syntax/miscellaneous.rdoc
@@ -0,0 +1,136 @@
+= Miscellaneous Syntax
+
+== Ending an Expression
+
+Ruby uses a newline as the end of an expression. When ending a line with an
+operator, open parentheses, comma, etc. the expression will continue.
+
+You can end an expression with a <code>;</code> (semicolon). Semicolons are
+most frequently used with <code>ruby -e</code>.
+
+== Indentation
+
+Ruby does not require any indentation. Typically, ruby programs are indented
+two spaces.
+
+If you run ruby with warnings enabled and have an indentation mismatch, you
+will receive a warning.
+
+== +alias+
+
+The +alias+ keyword is most frequently used to alias methods. When aliasing a
+method, you can use either its name or a symbol:
+
+ alias new_name old_name
+ alias :new_name :old_name
+
+For methods, Module#alias_method can often be used instead of +alias+.
+
+You can also use +alias+ to alias global variables:
+
+ $old = 0
+
+ alias $new $old
+
+ p $new # prints 0
+
+You may use +alias+ in any scope.
+
+== +undef+
+
+The +undef+ keyword prevents the current class from responding to calls to the
+named methods.
+
+ undef my_method
+
+You may use symbols instead of method names:
+
+ undef :my_method
+
+You may undef multiple methods:
+
+ undef method1, method2
+
+You may use +undef+ in any scope. See also Module#undef_method
+
+== +defined?+
+
++defined?+ is a keyword that returns a string describing its argument:
+
+ p defined?(UNDEFINED_CONSTANT) # prints nil
+ p defined?(RUBY_VERSION) # prints "constant"
+ p defined?(1 + 1) # prints "method"
+
+You don't need to use parenthesis with +defined?+, but they are recommended due
+to the {low precedence}[rdoc-ref:syntax/precedence.rdoc] of +defined?+.
+
+For example, if you wish to check if an instance variable exists and that the
+instance variable is zero:
+
+ defined? @instance_variable && @instance_variable.zero?
+
+This returns <code>"expression"</code>, which is not what you want if the
+instance variable is not defined.
+
+ @instance_variable = 1
+ defined?(@instance_variable) && @instance_variable.zero?
+
+Adding parentheses when checking if the instance variable is defined is a
+better check. This correctly returns +nil+ when the instance variable is not
+defined and +false+ when the instance variable is not zero.
+
+Using the specific reflection methods such as instance_variable_defined? for
+instance variables or const_defined? for constants is less error prone than
+using +defined?+.
+
++defined?+ handles some regexp global variables specially based on whether
+there is an active regexp match and how many capture groups there are:
+
+ /b/ =~ 'a'
+ defined?($~) # => "global-variable"
+ defined?($&) # => nil
+ defined?($`) # => nil
+ defined?($') # => nil
+ defined?($+) # => nil
+ defined?($1) # => nil
+ defined?($2) # => nil
+
+ /./ =~ 'a'
+ defined?($~) # => "global-variable"
+ defined?($&) # => "global-variable"
+ defined?($`) # => "global-variable"
+ defined?($') # => "global-variable"
+ defined?($+) # => nil
+ defined?($1) # => nil
+ defined?($2) # => nil
+
+ /(.)/ =~ 'a'
+ defined?($~) # => "global-variable"
+ defined?($&) # => "global-variable"
+ defined?($`) # => "global-variable"
+ defined?($') # => "global-variable"
+ defined?($+) # => "global-variable"
+ defined?($1) # => "global-variable"
+ defined?($2) # => nil
+
+== +BEGIN+ and +END+
+
++BEGIN+ defines a block that is run before any other code in the current file.
+It is typically used in one-liners with <code>ruby -e</code>. Similarly +END+
+defines a block that is run after any other code.
+
++BEGIN+ must appear at top-level and +END+ will issue a warning when you use it
+inside a method.
+
+Here is an example:
+
+ BEGIN {
+ count = 0
+ }
+
+You must use <code>{</code> and <code>}</code> you may not use +do+ and +end+.
+
+Here is an example one-liner that adds numbers from standard input or any files
+in the argument list:
+
+ ruby -ne 'BEGIN { count = 0 }; END { puts count }; count += gets.to_i'
diff --git a/doc/syntax/modules_and_classes.rdoc b/doc/syntax/modules_and_classes.rdoc
new file mode 100644
index 0000000000..9e05c5c774
--- /dev/null
+++ b/doc/syntax/modules_and_classes.rdoc
@@ -0,0 +1,398 @@
+= Modules
+
+Modules serve two purposes in Ruby, namespacing and mix-in functionality.
+
+A namespace can be used to organize code by package or functionality that
+separates common names from interference by other packages. For example, the
+IRB namespace provides functionality for irb that prevents a collision
+for the common name "Context".
+
+Mix-in functionality allows sharing common methods across multiple classes or
+modules. Ruby comes with the Enumerable mix-in module which provides many
+enumeration methods based on the +each+ method and Comparable allows comparison
+of objects based on the <code><=></code> comparison method.
+
+Note that there are many similarities between modules and classes. Besides the
+ability to mix-in a module, the description of modules below also applies to
+classes.
+
+== Module Definition
+
+A module is created using the +module+ keyword:
+
+ module MyModule
+ # ...
+ end
+
+A module may be reopened any number of times to add, change or remove
+functionality:
+
+ module MyModule
+ def my_method
+ end
+ end
+
+ module MyModule
+ alias my_alias my_method
+ end
+
+ module MyModule
+ remove_method :my_method
+ end
+
+Reopening modules (or classes) is a very powerful feature of Ruby, but it is
+best to only reopen modules you own. Reopening modules you do not own may lead
+to naming conflicts or difficult to diagnose bugs.
+
+== Nesting
+
+Modules may be nested:
+
+ module Outer
+ module Inner
+ end
+ end
+
+Many packages create a single outermost module (or class) to provide a
+namespace for their functionality.
+
+You may also define inner modules using <code>::</code> provided the outer
+modules (or classes) are already defined:
+
+ module Outer::Inner::GrandChild
+ end
+
+Note that this will raise a +NameError+ if +Outer+ and
+<code>Outer::Inner</code> are not already defined.
+
+This style has the benefit of allowing the author to reduce the amount
+of indentation. Instead of 3 levels of indentation only one is necessary.
+However, the scope of constant lookup is different for creating a namespace
+using this syntax instead of the more verbose syntax.
+
+== Scope
+
+=== +self+
+
++self+ refers to the object that defines the current scope. +self+ will change
+when entering a different method or when defining a new module.
+
+=== Constants
+
+Accessible constants are different depending on the module nesting (which
+syntax was used to define the module). In the following example
+the constant <code>A::Z</code> is accessible from B as A is part of the
+nesting:
+
+ module A
+ Z = 1
+
+ module B
+ p Module.nesting #=> [A::B, A]
+ p Z #=> 1
+ end
+ end
+
+However, if you use <code>::</code> to define <code>A::B</code> without
+nesting it inside +A+, a NameError exception will be raised because the nesting
+does not include +A+:
+
+ module A
+ Z = 1
+ end
+
+ module A::B
+ p Module.nesting #=> [A::B]
+ p Z #=> raises NameError
+ end
+
+If a constant is defined at the top-level you may preceded it with
+<code>::</code> to reference it:
+
+ Z = 0
+
+ module A
+ Z = 1
+
+ module B
+ p ::Z #=> 0
+ end
+ end
+
+=== Methods
+
+For method definition documentation see the {syntax documentation for
+methods}[rdoc-ref:syntax/methods.rdoc].
+
+Class methods may be called directly. (This is slightly confusing, but a
+method on a module is often called a "class method" instead of a "module
+method". See also Module#module_function which can convert an instance method
+into a class method.)
+
+When a class method references a constant, it uses the same rules as referencing
+it outside the method as the scope is the same.
+
+Instance methods defined in a module are only callable when included. These
+methods have access to the constants defined when they were included through
+the ancestors list:
+
+ module A
+ Z = 1
+
+ def z
+ Z
+ end
+ end
+
+ include A
+
+ p self.class.ancestors #=> [Object, A, Kernel, BasicObject]
+ p z #=> 1
+
+=== Visibility
+
+Ruby has three types of visibility. The default is +public+. A public method
+may be called from any other object.
+
+The second visibility is +protected+. When calling a protected method the
+sender must inherit the Class or Module which defines the method. Otherwise a
+NoMethodError will be raised.
+
+Protected visibility is most frequently used to define <code>==</code> and
+other comparison methods where the author does not wish to expose an object's
+state to any caller and would like to restrict it only to inherited classes.
+
+Here is an example:
+
+ class A
+ def n(other)
+ other.m
+ end
+ end
+
+ class B < A
+ def m
+ 1
+ end
+
+ protected :m
+
+ end
+
+ class C < B
+ end
+
+ a = A.new
+ b = B.new
+ c = C.new
+
+ c.n b #=> 1 -- C is a subclass of B
+ b.n b #=> 1 -- m called on defining class
+ a.n b # raises NoMethodError A is not a subclass of B
+
+The third visibility is +private+. A private method may only be called from
+inside the owner class without a receiver, or with a literal +self+
+as a receiver. If a private method is called with a
+receiver other than a literal +self+, a NoMethodError will be raised.
+
+ class A
+ def without
+ m
+ end
+
+ def with_self
+ self.m
+ end
+
+ def with_other
+ A.new.m
+ end
+
+ def with_renamed
+ copy = self
+ copy.m
+ end
+
+ def m
+ 1
+ end
+
+ private :m
+ end
+
+ a = A.new
+ a.without #=> 1
+ a.with_self #=> 1
+ a.with_other # NoMethodError (private method `m' called for #<A:0x0000559c287f27d0>)
+ a.with_renamed # NoMethodError (private method `m' called for #<A:0x0000559c285f8330>)
+
+=== +alias+ and +undef+
+
+You may also alias or undefine methods, but these operations are not
+restricted to modules or classes. See the {miscellaneous syntax
+section}[rdoc-ref:syntax/miscellaneous.rdoc] for documentation.
+
+= Classes
+
+Every class is also a module, but unlike modules a class may not be mixed-in to
+another module (or class). Like a module, a class can be used as a namespace.
+A class also inherits methods and constants from its superclass.
+
+== Defining a class
+
+Use the +class+ keyword to create a class:
+
+ class MyClass
+ # ...
+ end
+
+If you do not supply a superclass your new class will inherit from Object. You
+may inherit from a different class using <code><</code> followed by a class
+name:
+
+ class MySubclass < MyClass
+ # ...
+ end
+
+There is a special class BasicObject which is designed as a blank class and
+includes a minimum of built-in methods. You can use BasicObject to create an
+independent inheritance structure. See the BasicObject documentation for
+further details.
+
+Just like modules, classes can also be reopened. You can omit its superclass
+when you reopen a class. Specifying a different superclass than the previous
+definition will raise an error.
+
+ class C
+ end
+
+ class D < C
+ end
+
+ # OK
+ class D < C
+ end
+
+ # OK
+ class D
+ end
+
+ # TypeError: superclass mismatch for class D
+ class D < String
+ end
+
+== Inheritance
+
+Any method defined on a class is callable from its subclass:
+
+ class A
+ Z = 1
+
+ def z
+ Z
+ end
+ end
+
+ class B < A
+ end
+
+ p B.new.z #=> 1
+
+The same is true for constants:
+
+ class A
+ Z = 1
+ end
+
+ class B < A
+ def z
+ Z
+ end
+ end
+
+ p B.new.z #=> 1
+
+You can override the functionality of a superclass method by redefining the
+method:
+
+ class A
+ def m
+ 1
+ end
+ end
+
+ class B < A
+ def m
+ 2
+ end
+ end
+
+ p B.new.m #=> 2
+
+If you wish to invoke the superclass functionality from a method use +super+:
+
+ class A
+ def m
+ 1
+ end
+ end
+
+ class B < A
+ def m
+ 2 + super
+ end
+ end
+
+ p B.new.m #=> 3
+
+When used without any arguments +super+ uses the arguments given to the
+subclass method. To send no arguments to the superclass method use
+<code>super()</code>. To send specific arguments to the superclass method
+provide them manually like <code>super(2)</code>.
+
++super+ may be called as many times as you like in the subclass method.
+
+= Singleton Classes
+
+The singleton class (also known as the metaclass or eigenclass) of an object is
+a class that holds methods for only that instance. You can access the
+singleton class of an object using <code>class << object</code> like this:
+
+ class C
+ end
+
+ class << C
+ # self is the singleton class here
+ end
+
+Most frequently you'll see the singleton class accessed like this:
+
+ class C
+ class << self
+ # ...
+ end
+ end
+
+This allows definition of methods and attributes on a class (or module) without
+needing to write <code>def self.my_method</code>.
+
+Since you can open the singleton class of any object this means that this code
+block:
+
+ o = Object.new
+
+ def o.my_method
+ 1 + 1
+ end
+
+is equivalent to this code block:
+
+ o = Object.new
+
+ class << o
+ def my_method
+ 1 + 1
+ end
+ end
+
+Both objects will have a +my_method+ that returns +2+.
diff --git a/doc/syntax/operators.rdoc b/doc/syntax/operators.rdoc
new file mode 100644
index 0000000000..d3045ac99e
--- /dev/null
+++ b/doc/syntax/operators.rdoc
@@ -0,0 +1,75 @@
+= Operators
+
+In Ruby, operators such as <code>+</code>, are defined as methods on the class.
+Literals[rdoc-ref:syntax/literals.rdoc] define their methods within the lower
+level, C language. String class, for example.
+
+Ruby objects can define or overload their own implementation for most operators.
+
+Here is an example:
+
+ class Foo < String
+ def +(str)
+ self.concat(str).concat("another string")
+ end
+ end
+
+ foobar = Foo.new("test ")
+ puts foobar + "baz "
+
+This prints:
+
+ test baz another string
+
+What operators are available is dependent on the implementing class.
+
+== Operator Behavior
+
+How a class behaves to a given operator is specific to that class, since
+operators are method implementations.
+
+When using an operator, it's the expression on the left-hand side of the
+operation that specifies the behavior.
+
+ 'a' * 3 #=> "aaa"
+ 3 * 'a' # TypeError: String can't be coerced into Integer
+
+== Logical Operators
+
+Logical operators are not methods, and therefore cannot be
+redefined/overloaded. They are tokenized at a lower level.
+
+Short-circuit logical operators (<code>&&</code>, <code>||</code>,
+<code>and</code>, and <code>or</code>) do not always result in a boolean value.
+Similar to blocks, it's the last evaluated expression that defines the result
+of the operation.
+
+=== <code>&&</code>, <code>and</code>
+
+Both <code>&&</code>/<code>and</code> operators provide short-circuiting by executing each
+side of the operator, left to right, and stopping at the first occurrence of a
+falsey expression. The expression that defines the result is the last one
+executed, whether it be the final expression, or the first occurrence of a falsey
+expression.
+
+Some examples:
+
+ true && 9 && "string" #=> "string"
+ (1 + 2) && nil && "string" #=> nil
+ (a = 1) && (b = false) && (c = "string") #=> false
+
+ puts a #=> 1
+ puts b #=> false
+ puts c #=> nil
+
+In this last example, <code>c</code> was initialized, but not defined.
+
+=== <code>||</code>, <code>or</code>
+
+The means by which <code>||</code>/<code>or</code> short-circuits, is to return the result of
+the first expression that is truthy.
+
+Some examples:
+
+ (1 + 2) || true || "string" #=> 3
+ false || nil || "string" #=> "string"
diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc
new file mode 100644
index 0000000000..06aae26d49
--- /dev/null
+++ b/doc/syntax/pattern_matching.rdoc
@@ -0,0 +1,528 @@
+= Pattern matching
+
+Pattern matching is a feature allowing deep matching of structured values: checking the structure and binding the matched parts to local variables.
+
+Pattern matching in Ruby is implemented with the +case+/+in+ expression:
+
+ case <expression>
+ in <pattern1>
+ ...
+ in <pattern2>
+ ...
+ in <pattern3>
+ ...
+ else
+ ...
+ end
+
+(Note that +in+ and +when+ branches can NOT be mixed in one +case+ expression.)
+
+Or with the <code>=></code> operator and the +in+ operator, which can be used in a standalone expression:
+
+ <expression> => <pattern>
+
+ <expression> in <pattern>
+
+The +case+/+in+ expression is _exhaustive_: if the value of the expression does not match any branch of the +case+ expression (and the +else+ branch is absent), +NoMatchingPatternError+ is raised.
+
+Therefore, the +case+ expression might be used for conditional matching and unpacking:
+
+ config = {db: {user: 'admin', password: 'abc123'}}
+
+ case config
+ in db: {user:} # matches subhash and puts matched value in variable user
+ puts "Connect with user '#{user}'"
+ in connection: {username: }
+ puts "Connect with user '#{username}'"
+ else
+ puts "Unrecognized structure of config"
+ end
+ # Prints: "Connect with user 'admin'"
+
+whilst the <code>=></code> operator is most useful when the expected data structure is known beforehand, to just unpack parts of it:
+
+ config = {db: {user: 'admin', password: 'abc123'}}
+
+ config => {db: {user:}} # will raise if the config's structure is unexpected
+
+ puts "Connect with user '#{user}'"
+ # Prints: "Connect with user 'admin'"
+
+<code><expression> in <pattern></code> is the same as <code>case <expression>; in <pattern>; true; else false; end</code>.
+You can use it when you only want to know if a pattern has been matched or not:
+
+ users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}]
+ users.any? {|user| user in {name: /B/, age: 20..} } #=> true
+
+See below for more examples and explanations of the syntax.
+
+== Patterns
+
+Patterns can be:
+
+* any Ruby object (matched by the <code>===</code> operator, like in +when+); (<em>Value pattern</em>)
+* array pattern: <code>[<subpattern>, <subpattern>, <subpattern>, ...]</code>; (<em>Array pattern</em>)
+* find pattern: <code>[*variable, <subpattern>, <subpattern>, <subpattern>, ..., *variable]</code>; (<em>Find pattern</em>)
+* hash pattern: <code>{key: <subpattern>, key: <subpattern>, ...}</code>; (<em>Hash pattern</em>)
+* combination of patterns with <code>|</code>; (<em>Alternative pattern</em>)
+* variable capture: <code><pattern> => variable</code> or <code>variable</code>; (<em>As pattern</em>, <em>Variable pattern</em>)
+
+Any pattern can be nested inside array/find/hash patterns where <code><subpattern></code> is specified.
+
+Array patterns and find patterns match arrays, or objects that respond to +deconstruct+ (see below about the latter).
+Hash patterns match hashes, or objects that respond to +deconstruct_keys+ (see below about the latter). Note that only symbol keys are supported for hash patterns.
+
+An important difference between array and hash pattern behavior is that arrays match only a _whole_ array:
+
+ case [1, 2, 3]
+ in [Integer, Integer]
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+while the hash matches even if there are other keys besides the specified part:
+
+ case {a: 1, b: 2, c: 3}
+ in {a: Integer}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+<code>{}</code> is the only exclusion from this rule. It matches only if an empty hash is given:
+
+ case {a: 1, b: 2, c: 3}
+ in {}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+ case {}
+ in {}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+There is also a way to specify there should be no other keys in the matched hash except those explicitly specified by the pattern, with <code>**nil</code>:
+
+ case {a: 1, b: 2}
+ in {a: Integer, **nil} # this will not match the pattern having keys other than a:
+ "matched a part"
+ in {a: Integer, b: Integer, **nil}
+ "matched a whole"
+ else
+ "not matched"
+ end
+ #=> "matched a whole"
+
+Both array and hash patterns support "rest" specification:
+
+ case [1, 2, 3]
+ in [Integer, *]
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+ case {a: 1, b: 2, c: 3}
+ in {a: Integer, **}
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+Parentheses around both kinds of patterns could be omitted:
+
+ case [1, 2]
+ in Integer, Integer
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+ case {a: 1, b: 2, c: 3}
+ in a: Integer
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+ [1, 2] => a, b
+ [1, 2] in a, b
+
+ {a: 1, b: 2, c: 3} => a:
+ {a: 1, b: 2, c: 3} in a:
+
+Find pattern is similar to array pattern but it can be used to check if the given object has any elements that match the pattern:
+
+ case ["a", 1, "b", "c", 2]
+ in [*, String, String, *]
+ "matched"
+ else
+ "not matched"
+ end
+
+== Variable binding
+
+Besides deep structural checks, one of the very important features of the pattern matching is the binding of the matched parts to local variables. The basic form of binding is just specifying <code>=> variable_name</code> after the matched (sub)pattern (one might find this similar to storing exceptions in local variables in a <code>rescue ExceptionClass => var</code> clause):
+
+ case [1, 2]
+ in Integer => a, Integer
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+ case {a: 1, b: 2, c: 3}
+ in a: Integer => m
+ "matched: #{m}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+If no additional check is required, for only binding some part of the data to a variable, a simpler form could be used:
+
+ case [1, 2]
+ in a, Integer
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+ case {a: 1, b: 2, c: 3}
+ in a: m
+ "matched: #{m}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+For hash patterns, even a simpler form exists: key-only specification (without any sub-pattern) binds the local variable with the key's name, too:
+
+ case {a: 1, b: 2, c: 3}
+ in a:
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+\Binding works for nested patterns as well:
+
+ case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]}
+ in name:, friends: [{name: first_friend}, *]
+ "matched: #{first_friend}"
+ else
+ "not matched"
+ end
+ #=> "matched: Jane"
+
+The "rest" part of a pattern also can be bound to a variable:
+
+ case [1, 2, 3]
+ in a, *rest
+ "matched: #{a}, #{rest}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1, [2, 3]"
+
+ case {a: 1, b: 2, c: 3}
+ in a:, **rest
+ "matched: #{a}, #{rest}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1, {b: 2, c: 3}"
+
+\Binding to variables currently does NOT work for alternative patterns joined with <code>|</code>:
+
+ case {a: 1, b: 2}
+ in {a: } | Array
+ # ^ SyntaxError (variable capture in alternative pattern)
+ "matched: #{a}"
+ else
+ "not matched"
+ end
+
+Variables that start with <code>_</code> are the only exclusions from this rule:
+
+ case {a: 1, b: 2}
+ in {a: _, b: _foo} | Array
+ "matched: #{_}, #{_foo}"
+ else
+ "not matched"
+ end
+ # => "matched: 1, 2"
+
+It is, though, not advised to reuse the bound value, as this pattern's goal is to signify a discarded value.
+
+== Variable pinning
+
+Due to the variable binding feature, existing local variable can not be straightforwardly used as a sub-pattern:
+
+ expectation = 18
+
+ case [1, 2]
+ in expectation, *rest
+ "matched. expectation was: #{expectation}"
+ else
+ "not matched. expectation was: #{expectation}"
+ end
+ # expected: "not matched. expectation was: 18"
+ # real: "matched. expectation was: 1" -- local variable just rewritten
+
+For this case, the pin operator <code>^</code> can be used, to tell Ruby "just use this value as part of the pattern":
+
+ expectation = 18
+ case [1, 2]
+ in ^expectation, *rest
+ "matched. expectation was: #{expectation}"
+ else
+ "not matched. expectation was: #{expectation}"
+ end
+ #=> "not matched. expectation was: 18"
+
+One important usage of variable pinning is specifying that the same value should occur in the pattern several times:
+
+ jane = {school: 'high', schools: [{id: 1, level: 'middle'}, {id: 2, level: 'high'}]}
+ john = {school: 'high', schools: [{id: 1, level: 'middle'}]}
+
+ case jane
+ in school:, schools: [*, {id:, level: ^school}] # select the last school, level should match
+ "matched. school: #{id}"
+ else
+ "not matched"
+ end
+ #=> "matched. school: 2"
+
+ case john # the specified school level is "high", but last school does not match
+ in school:, schools: [*, {id:, level: ^school}]
+ "matched. school: #{id}"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+In addition to pinning local variables, you can also pin instance, global, and class variables:
+
+ $gvar = 1
+ class A
+ @ivar = 2
+ @@cvar = 3
+ case [1, 2, 3]
+ in ^$gvar, ^@ivar, ^@@cvar
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+ end
+
+You can also pin the result of arbitrary expressions using parentheses:
+
+ a = 1
+ b = 2
+ case 3
+ in ^(a + b)
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+== Matching non-primitive objects: +deconstruct+ and +deconstruct_keys+
+
+As already mentioned above, array, find, and hash patterns besides literal arrays and hashes will try to match any object implementing +deconstruct+ (for array/find patterns) or +deconstruct_keys+ (for hash patterns).
+
+ class Point
+ def initialize(x, y)
+ @x, @y = x, y
+ end
+
+ def deconstruct
+ puts "deconstruct called"
+ [@x, @y]
+ end
+
+ def deconstruct_keys(keys)
+ puts "deconstruct_keys called with #{keys.inspect}"
+ {x: @x, y: @y}
+ end
+ end
+
+ case Point.new(1, -2)
+ in px, Integer # sub-patterns and variable binding works
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ # prints "deconstruct called"
+ "matched: 1"
+
+ case Point.new(1, -2)
+ in x: 0.. => px
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ # prints: deconstruct_keys called with [:x]
+ #=> "matched: 1"
+
++keys+ are passed to +deconstruct_keys+ to provide a room for optimization in the matched class: if calculating a full hash representation is expensive, one may calculate only the necessary subhash. When the <code>**rest</code> pattern is used, +nil+ is passed as a +keys+ value:
+
+ case Point.new(1, -2)
+ in x: 0.. => px, **rest
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ # prints: deconstruct_keys called with nil
+ #=> "matched: 1"
+
+Additionally, when matching custom classes, the expected class can be specified as part of the pattern and is checked with <code>===</code>
+
+ class SuperPoint < Point
+ end
+
+ case Point.new(1, -2)
+ in SuperPoint(x: 0.. => px)
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
+ case SuperPoint.new(1, -2)
+ in SuperPoint[x: 0.. => px] # [] or () parentheses are allowed
+ "matched: #{px}"
+ else
+ "not matched"
+ end
+ #=> "matched: 1"
+
+These core and library classes implement deconstruction:
+
+* MatchData#deconstruct and MatchData#deconstruct_keys;
+* Time#deconstruct_keys, Date#deconstruct_keys, DateTime#deconstruct_keys.
+
+== Guard clauses
+
++if+ can be used to attach an additional condition (guard clause) when the pattern matches in +case+/+in+ expressions.
+This condition may use bound variables:
+
+ case [1, 2]
+ in a, b if b == a*2
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+ case [1, 1]
+ in a, b if b == a*2
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "not matched"
+
++unless+ works, too:
+
+ case [1, 1]
+ in a, b unless b == a*2
+ "matched"
+ else
+ "not matched"
+ end
+ #=> "matched"
+
+Note that <code>=></code> and +in+ operator can not have a guard clause.
+The following examples is parsed as a standalone expression with modifier +if+.
+
+ [1, 2] in a, b if b == a*2
+
+== Appendix A. Pattern syntax
+
+Approximate syntax is:
+
+ pattern: value_pattern
+ | variable_pattern
+ | alternative_pattern
+ | as_pattern
+ | array_pattern
+ | find_pattern
+ | hash_pattern
+
+ value_pattern: literal
+ | Constant
+ | ^local_variable
+ | ^instance_variable
+ | ^class_variable
+ | ^global_variable
+ | ^(expression)
+
+ variable_pattern: variable
+
+ alternative_pattern: pattern | pattern | ...
+
+ as_pattern: pattern => variable
+
+ array_pattern: [pattern, ..., *variable]
+ | Constant(pattern, ..., *variable)
+ | Constant[pattern, ..., *variable]
+
+ find_pattern: [*variable, pattern, ..., *variable]
+ | Constant(*variable, pattern, ..., *variable)
+ | Constant[*variable, pattern, ..., *variable]
+
+ hash_pattern: {key: pattern, key:, ..., **variable}
+ | Constant(key: pattern, key:, ..., **variable)
+ | Constant[key: pattern, key:, ..., **variable]
+
+== Appendix B. Some undefined behavior examples
+
+To leave room for optimization in the future, the specification contains some undefined behavior.
+
+Use of a variable in an unmatched pattern:
+
+ case [0, 1]
+ in [a, 2]
+ "not matched"
+ in b
+ "matched"
+ in c
+ "not matched"
+ end
+ a #=> undefined
+ c #=> undefined
+
+Number of +deconstruct+, +deconstruct_keys+ method calls:
+
+ $i = 0
+ ary = [0]
+ def ary.deconstruct
+ $i += 1
+ self
+ end
+ case ary
+ in [0, 1]
+ "not matched"
+ in [0]
+ "matched"
+ end
+ $i #=> undefined
diff --git a/doc/syntax/precedence.rdoc b/doc/syntax/precedence.rdoc
new file mode 100644
index 0000000000..f0ca92b571
--- /dev/null
+++ b/doc/syntax/precedence.rdoc
@@ -0,0 +1,64 @@
+= Precedence
+
+From highest to lowest, this is the precedence table for ruby. High precedence
+operations happen before low precedence operations.
+
+ !, ~, unary +
+
+ **
+
+ unary -
+
+ *, /, %
+
+ +, -
+
+ <<, >>
+
+ &
+
+ |, ^
+
+ >, >=, <, <=
+
+ <=>, ==, ===, !=, =~, !~
+
+ &&
+
+ ||
+
+ .., ...
+
+ ?, :
+
+ modifier-rescue
+
+ =, +=, -=, etc.
+
+ defined?
+
+ not
+
+ or, and
+
+ modifier-if, modifier-unless, modifier-while, modifier-until
+
+ { } blocks
+
+Unary <code>+</code> and unary <code>-</code> are for <code>+1</code>,
+<code>-1</code> or <code>-(a + b)</code>.
+
+Modifier-if, modifier-unless, etc. are for the modifier versions of those
+keywords. For example, this is a modifier-unless statement:
+
+ a += 1 unless a.zero?
+
+Note that <code>(a if b rescue c)</code> is parsed as <code>((a if b) rescue
+c)</code> due to reasons not related to precedence. See {modifier
+statements}[control_expressions.rdoc#label-Modifier+Statements].
+
+<code>{ ... }</code> blocks have priority below all listed operations, but
+<code>do ... end</code> blocks have lower priority.
+
+All other words in the precedence table above are keywords.
+
diff --git a/doc/syntax/refinements.rdoc b/doc/syntax/refinements.rdoc
new file mode 100644
index 0000000000..4095977284
--- /dev/null
+++ b/doc/syntax/refinements.rdoc
@@ -0,0 +1,281 @@
+= Refinements
+
+Due to Ruby's open classes you can redefine or add functionality to existing
+classes. This is called a "monkey patch". Unfortunately the scope of such
+changes is global. All users of the monkey-patched class see the same
+changes. This can cause unintended side-effects or breakage of programs.
+
+Refinements are designed to reduce the impact of monkey patching on other
+users of the monkey-patched class. Refinements provide a way to extend a
+class locally. Refinements can modify both classes and modules.
+
+Here is a basic refinement:
+
+ class C
+ def foo
+ puts "C#foo"
+ end
+ end
+
+ module M
+ refine C do
+ def foo
+ puts "C#foo in M"
+ end
+ end
+ end
+
+First, a class +C+ is defined. Next a refinement for +C+ is created using
+Module#refine.
+
+Module#refine creates an anonymous module that contains the changes or
+refinements to the class (+C+ in the example). +self+ in the refine block is
+this anonymous module similar to Module#module_eval.
+
+Activate the refinement with #using:
+
+ using M
+
+ c = C.new
+
+ c.foo # prints "C#foo in M"
+
+== Scope
+
+You may activate refinements at top-level, and inside classes and modules.
+You may not activate refinements in method scope. Refinements are activated
+until the end of the current class or module definition, or until the end of
+the current file if used at the top-level.
+
+You may activate refinements in a string passed to Kernel#eval. Refinements
+are active until the end of the eval string.
+
+Refinements are lexical in scope. Refinements are only active within a scope
+after the call to +using+. Any code before the +using+ statement will not have the
+refinement activated.
+
+When control is transferred outside the scope, the refinement is deactivated.
+This means that if you require or load a file or call a method that is defined
+outside the current scope the refinement will be deactivated:
+
+ class C
+ end
+
+ module M
+ refine C do
+ def foo
+ puts "C#foo in M"
+ end
+ end
+ end
+
+ def call_foo(x)
+ x.foo
+ end
+
+ using M
+
+ x = C.new
+ x.foo # prints "C#foo in M"
+ call_foo(x) #=> raises NoMethodError
+
+If a method is defined in a scope where a refinement is active, the refinement
+will be active when the method is called. This example spans multiple files:
+
+c.rb:
+
+ class C
+ end
+
+m.rb:
+
+ require "c"
+
+ module M
+ refine C do
+ def foo
+ puts "C#foo in M"
+ end
+ end
+ end
+
+m_user.rb:
+
+ require "m"
+
+ using M
+
+ class MUser
+ def call_foo(x)
+ x.foo
+ end
+ end
+
+main.rb:
+
+ require "m_user"
+
+ x = C.new
+ m_user = MUser.new
+ m_user.call_foo(x) # prints "C#foo in M"
+ x.foo #=> raises NoMethodError
+
+Since the refinement +M+ is active in <code>m_user.rb</code> where
+<code>MUser#call_foo</code> is defined it is also active when
+<code>main.rb</code> calls +call_foo+.
+
+Since #using is a method, refinements are only active when it is called. Here
+are examples of where a refinement +M+ is and is not active.
+
+In a file:
+
+ # not activated here
+ using M
+ # activated here
+ class Foo
+ # activated here
+ def foo
+ # activated here
+ end
+ # activated here
+ end
+ # activated here
+
+In a class:
+
+ # not activated here
+ class Foo
+ # not activated here
+ def foo
+ # not activated here
+ end
+ using M
+ # activated here
+ def bar
+ # activated here
+ end
+ # activated here
+ end
+ # not activated here
+
+Note that the refinements in +M+ are *not* activated automatically if the class
++Foo+ is reopened later.
+
+In eval:
+
+ # not activated here
+ eval <<EOF
+ # not activated here
+ using M
+ # activated here
+ EOF
+ # not activated here
+
+When not evaluated:
+
+ # not activated here
+ if false
+ using M
+ end
+ # not activated here
+
+When defining multiple refinements in the same module inside multiple +refine+ blocks,
+all refinements from the same module are active when a refined method
+(any of the +to_json+ methods from the example below) is called:
+
+ module ToJSON
+ refine Integer do
+ def to_json
+ to_s
+ end
+ end
+
+ refine Array do
+ def to_json
+ "[" + map { |i| i.to_json }.join(",") + "]"
+ end
+ end
+
+ refine Hash do
+ def to_json
+ "{" + map { |k, v| k.to_s.dump + ":" + v.to_json }.join(",") + "}"
+ end
+ end
+ end
+
+ using ToJSON
+
+ p [{1=>2}, {3=>4}].to_json # prints "[{\"1\":2},{\"3\":4}]"
+
+
+== Method Lookup
+
+When looking up a method for an instance of class +C+ Ruby checks:
+
+* The refinements of +C+, in reverse order of activation
+* The prepended modules of +C+
+* +C+
+* The included modules of +C+
+
+If no method was found at any point this repeats with the superclass of +C+.
+
+Note that methods in a subclass have priority over refinements in a
+superclass. For example, if the method <code>/</code> is defined in a
+refinement for Numeric <code>1 / 2</code> invokes the original Integer#/
+because Integer is a subclass of Numeric and is searched before the refinements
+for the superclass Numeric. Since the method <code>/</code> is also present
+in child +Integer+, the method lookup does not move up to the superclass.
+
+However, if a method +foo+ is defined on Numeric in a refinement, <code>1.foo</code>
+invokes that method since +foo+ does not exist on Integer.
+
+== +super+
+
+When +super+ is invoked method lookup checks:
+
+* The included modules of the current class. Note that the current class may
+ be a refinement.
+* If the current class is a refinement, the method lookup proceeds as in the
+ Method Lookup section above.
+* If the current class has a direct superclass, the method proceeds as in the
+ Method Lookup section above using the superclass.
+
+Note that +super+ in a method of a refinement invokes the method in the
+refined class even if there is another refinement which has been activated in
+the same context. This is only true for +super+ in a method of a refinement, it
+does not apply to +super+ in a method in a module that is included in a refinement.
+
+== Methods Introspection
+
+When using introspection methods such as Kernel#method or Kernel#methods refinements are not honored.
+
+This behavior may be changed in the future.
+
+== Refinement inheritance by Module#include
+
+When a module X is included into a module Y, Y inherits refinements from X.
+
+For example, C inherits refinements from A and B in the following code:
+
+ module A
+ refine X do ... end
+ refine Y do ... end
+ end
+ module B
+ refine Z do ... end
+ end
+ module C
+ include A
+ include B
+ end
+
+ using C
+ # Refinements in A and B are activated here.
+
+Refinements in descendants have higher precedence than those of ancestors.
+
+== Further Reading
+
+See https://github.com/ruby/ruby/wiki/Refinements-Spec for the
+current specification for implementing refinements. The specification also
+contains more details.