diff --git a/doc/syntax.rdoc b/doc/syntax.rdoc
index cb427b6f0f03a2..a48c83ff152dc2 100644
--- a/doc/syntax.rdoc
+++ b/doc/syntax.rdoc
@@ -2,6 +2,9 @@
The Ruby syntax is large and is split up into the following sections:
+{Code Layout}[rdoc-ref:syntax/layout.rdoc] ::
+ Breaking code in lines
+
Literals[rdoc-ref:syntax/literals.rdoc] ::
Numbers, Strings, Arrays, Hashes, etc.
diff --git a/doc/syntax/layout.rdoc b/doc/syntax/layout.rdoc
new file mode 100644
index 00000000000000..f07447587ba333
--- /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
+
+; 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 ; 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 . ("leading dot" style of method calls) or logical operators &&/|| and and/or:
+
+ # 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 \\:
+
+ # 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 \\ 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/proc.c b/proc.c
index 637a30e0c64885..4f775c899228b5 100644
--- a/proc.c
+++ b/proc.c
@@ -2642,13 +2642,20 @@ method_dup(VALUE self)
return clone;
}
-/* Document-method: Method#===
- *
+/*
* call-seq:
- * method === obj -> result_of_method
+ * meth.call(args, ...) -> obj
+ * meth[args, ...] -> obj
+ * method === obj -> result_of_method
+ *
+ * Invokes the meth with the specified arguments, returning the
+ * method's return value.
*
- * Invokes the method with +obj+ as the parameter like #call.
- * This allows a method object to be the target of a +when+ clause
+ * m = 12.method("+")
+ * m.call(3) #=> 15
+ * m.call(20) #=> 32
+ *
+ * Using Method#=== allows a method object to be the target of a +when+ clause
* in a case statement.
*
* require 'prime'
@@ -2659,32 +2666,6 @@ method_dup(VALUE self)
* end
*/
-
-/* Document-method: Method#[]
- *
- * call-seq:
- * meth[args, ...] -> obj
- *
- * Invokes the meth with the specified arguments, returning the
- * method's return value, like #call.
- *
- * m = 12.method("+")
- * m[3] #=> 15
- * m[20] #=> 32
- */
-
-/*
- * call-seq:
- * meth.call(args, ...) -> obj
- *
- * Invokes the meth with the specified arguments, returning the
- * method's return value.
- *
- * m = 12.method("+")
- * m.call(3) #=> 15
- * m.call(20) #=> 32
- */
-
static VALUE
rb_method_call_pass_called_kw(int argc, const VALUE *argv, VALUE method)
{
diff --git a/test/ruby/test_box.rb b/test/ruby/test_box.rb
index b62ac3c544722d..e584d233ca0145 100644
--- a/test/ruby/test_box.rb
+++ b/test/ruby/test_box.rb
@@ -780,7 +780,7 @@ def foo_box = Ruby::Box.current
end;
end
- def test_loading_extension_libs_in_main_box
+ def test_loading_extension_libs_in_main_box_1
pend if /mswin|mingw/ =~ RUBY_PLATFORM # timeout on windows environments
assert_separately([ENV_ENABLE_BOX], __FILE__, __LINE__, "#{<<~"begin;"}\n#{<<~'end;'}", ignore_stderr: true)
begin;
@@ -797,6 +797,15 @@ def test_loading_extension_libs_in_main_box
require "json"
require "psych"
require "yaml"
+ expected = 1
+ assert_equal expected, 1
+ end;
+ end
+
+ def test_loading_extension_libs_in_main_box_2
+ pend if /mswin|mingw/ =~ RUBY_PLATFORM # timeout on windows environments
+ assert_separately([ENV_ENABLE_BOX], __FILE__, __LINE__, "#{<<~"begin;"}\n#{<<~'end;'}", ignore_stderr: true)
+ begin;
require "zlib"
require "open3"
require "ipaddr"