[前][次][番号順一覧][スレッド一覧]

ruby-changes:56102

From: Nobuyoshi <ko1@a...>
Date: Thu, 13 Jun 2019 18:48:20 +0900 (JST)
Subject: [ruby-changes:56102] Nobuyoshi Nakada: f169043d81 (trunk): Add pipeline operator [Feature #15799]

https://git.ruby-lang.org/ruby.git/commit/?id=f169043d81

From f169043d81524b5b529f2c1e9c35437ba5bc3a7a Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Tue, 23 Apr 2019 13:14:27 +0900
Subject: Add pipeline operator [Feature #15799]


diff --git a/NEWS b/NEWS
index 4ad38c9..a332cf3 100644
--- a/NEWS
+++ b/NEWS
@@ -48,6 +48,18 @@ sufficient information, see the ChangeLog file or Redmine https://github.com/ruby/ruby/blob/trunk/NEWS#L48
      " # This has been warned since 2.4
      EOS
 
+* Pipeline operator is added.
+
+  This code equals to the next code.
+
+     foo()
+      |> bar 1, 2
+      |> display
+
+     foo()
+      .bar(1, 2)
+      .display
+
 === Core classes updates (outstanding ones only)
 
 Enumerable::
diff --git a/defs/id.def b/defs/id.def
index 44890cf..66dfdf9 100644
--- a/defs/id.def
+++ b/defs/id.def
@@ -111,6 +111,7 @@ token_ops = %[\ https://github.com/ruby/ruby/blob/trunk/defs/id.def#L111
   OROP          ||
   ANDDOT        &.
   METHREF       .:
+  PIPE          |>
 ]
 
 class KeywordError < RuntimeError
diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c
index 88985ac..66e7c8f 100644
--- a/ext/ripper/eventids2.c
+++ b/ext/ripper/eventids2.c
@@ -262,6 +262,7 @@ static const struct token_assoc { https://github.com/ruby/ruby/blob/trunk/ext/ripper/eventids2.c#L262
     {tDSTAR,			O(op)},
     {tANDDOT,			O(op)},
     {tMETHREF,			O(op)},
+    {tPIPE,			O(op)},
     {tSTRING_BEG,		O(tstring_beg)},
     {tSTRING_CONTENT,		O(tstring_content)},
     {tSTRING_DBEG,		O(embexpr_beg)},
diff --git a/parse.y b/parse.y
index c78f513..6f282d8 100644
--- a/parse.y
+++ b/parse.y
@@ -1002,7 +1002,7 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in https://github.com/ruby/ruby/blob/trunk/parse.y#L1002
 %type <node> literal numeric simple_numeric ssym dsym symbol cpath
 %type <node> top_compstmt top_stmts top_stmt begin_block
 %type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
-%type <node> expr_value expr_value_do arg_value primary_value fcall rel_expr
+%type <node> expr_value expr_value_do arg_value primary_value fcall rel_expr pipeline
 %type <node> if_tail opt_else case_body case_args cases opt_rescue exc_list exc_var opt_ensure
 %type <node> args call_args opt_call_args
 %type <node> paren_args opt_paren_args args_tail opt_args_tail block_args_tail opt_block_args_tail
@@ -1060,6 +1060,7 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in https://github.com/ruby/ruby/blob/trunk/parse.y#L1060
 %token <id> tANDDOT	RUBY_TOKEN(ANDDOT) "&."
 %token <id> tCOLON2	RUBY_TOKEN(COLON2) "::"
 %token <id> tMETHREF	RUBY_TOKEN(METHREF) ".:"
+%token tPIPE		RUBY_TOKEN(PIPE) "|>"
 %token tCOLON3		":: at EXPR_BEG"
 %token <id> tOP_ASGN	"operator-assignment" /* +=, -=  etc. */
 %token tASSOC		"=>"
@@ -1095,6 +1096,7 @@ static void token_info_warn(struct parser_params *p, const char *token, token_in https://github.com/ruby/ruby/blob/trunk/parse.y#L1096
 %nonassoc  modifier_if modifier_unless modifier_while modifier_until
 %left  keyword_or keyword_and
 %right keyword_not
+%left  tPIPE
 %nonassoc keyword_defined
 %right '=' tOP_ASGN
 %left modifier_rescue
@@ -2269,12 +2271,29 @@ arg		: lhs '=' arg_rhs https://github.com/ruby/ruby/blob/trunk/parse.y#L2271
 		    /*% %*/
 		    /*% ripper: ifop!($1, $3, $6) %*/
 		    }
+		| pipeline
 		| primary
 		    {
 			$$ = $1;
 		    }
 		;
 
+pipeline	: arg tPIPE operation2 opt_paren_args
+		    {
+		    /*%%%*/
+			$$ = new_command_qcall(p, ID2VAL(idPIPE), $1, $3, $4, Qnull, &@3, &@$);
+		    /*% %*/
+		    /*% ripper: command_call!($1, ID2VAL(idPIPE), $3, $4) %*/
+		    }
+		| arg tPIPE operation2 opt_paren_args brace_block
+		    {
+		    /*%%%*/
+			$$ = new_command_qcall(p, ID2VAL(idPIPE), $1, $3, $4, $5, &@3, &@$);
+		    /*% %*/
+		    /*% ripper: method_add_block!(command_call!($1, ID2VAL(idPIPE), $3, $4), $5) %*/
+		    }
+		;
+
 relop		: '>'  {$$ = '>';}
 		| '<'  {$$ = '<';}
 		| tGEQ {$$ = idGE;}
@@ -8924,6 +8943,10 @@ parser_yylex(struct parser_params *p) https://github.com/ruby/ruby/blob/trunk/parse.y#L8943
 	    SET_LEX_STATE(EXPR_BEG);
 	    return tOP_ASGN;
 	}
+	if (c == '>') {
+	    SET_LEX_STATE(EXPR_DOT);
+	    return tPIPE;
+	}
 	SET_LEX_STATE(IS_AFTER_OPERATOR() ? EXPR_ARG : EXPR_BEG|EXPR_LABEL);
 	pushback(p, c);
 	return '|';
diff --git a/test/ripper/test_scanner_events.rb b/test/ripper/test_scanner_events.rb
index 339a66d..323c409 100644
--- a/test/ripper/test_scanner_events.rb
+++ b/test/ripper/test_scanner_events.rb
@@ -573,6 +573,8 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ripper/test_scanner_events.rb#L573
                  scan('op', 'obj.:foo')
     assert_equal [],
                  scan('op', %q[`make all`])
+    assert_equal %w[|>],
+                 scan('op', %q[x|>y])
   end
 
   def test_symbeg
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index f2fcf67..7bffb87 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -1379,6 +1379,13 @@ eom https://github.com/ruby/ruby/blob/trunk/test/ruby/test_syntax.rb#L1379
     assert_syntax_error('@1', /outside block/)
   end
 
+  def test_pipeline_operator
+    assert_valid_syntax('x |> y')
+    x = nil
+    assert_equal("121", eval('x = 12 |> pow(2) |> to_s(11)'))
+    assert_equal(12, x)
+  end
+
   private
 
   def not_label(x) @result = x; @not_label ||= nil end
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]