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

ruby-changes:49873

From: mame <ko1@a...>
Date: Sun, 21 Jan 2018 02:45:31 +0900 (JST)
Subject: [ruby-changes:49873] mame:r61991 (trunk): ext/ripper/tools/dsl.rb: Serialize dispatch calls

mame	2018-01-21 02:45:24 +0900 (Sun, 21 Jan 2018)

  New Revision: 61991

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61991

  Log:
    ext/ripper/tools/dsl.rb: Serialize dispatch calls
    
    To avoid the unspecified behavior (the evaluation order of arguments).
    In `$$ = foo(bar(), baz());`, it is unspecified which `bar` or `baz` is
    called earlier.
    
    This commit changes the code to `v1=bar(); v2=baz(); $$ = foo();`.

  Modified files:
    trunk/ext/ripper/tools/dsl.rb
Index: ext/ripper/tools/dsl.rb
===================================================================
--- ext/ripper/tools/dsl.rb	(revision 61990)
+++ ext/ripper/tools/dsl.rb	(revision 61991)
@@ -1,7 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ext/ripper/tools/dsl.rb#L1
 # Simple DSL implementation for Ripper code generation
 #
 # input: /*% ripper: stmts_add(stmts_new, void_stmt) %*/
-# output: $$ = dispatch2(stmts_add, dispatch0(stmts_new), dispatch0(void_stmt))
+# output:
+#   VALUE v1, v2;
+#   v1 = dispatch0(stmts_new);
+#   v2 = dispatch0(void_stmt);
+#   $$ = dispatch2(stmts_add, v1, v2);
 
 class DSL
   def initialize(code, options)
@@ -9,6 +13,7 @@ class DSL https://github.com/ruby/ruby/blob/trunk/ext/ripper/tools/dsl.rb#L13
     @error = options.include?("error")
     @brace = options.include?("brace")
     @final = options.include?("final")
+    @vars = 0
 
     # create $1 == "$1", $2 == "$2", ...
     re, s = "", ""
@@ -21,7 +26,8 @@ class DSL https://github.com/ruby/ruby/blob/trunk/ext/ripper/tools/dsl.rb#L26
     # struct parser_params *p
     p = "p"
 
-    @code = eval(code)
+    @code = ""
+    @last_value = eval(code)
   end
 
   attr_reader :events
@@ -33,17 +39,29 @@ class DSL https://github.com/ruby/ruby/blob/trunk/ext/ripper/tools/dsl.rb#L39
   def generate
     s = "$$"
     s = "p->result" if @final
-    s = "#{ s } = #@code;"
+    s = "#@code#{ s }=#@last_value;"
+    s = "{VALUE #{ (1..@vars).map {|v| "v#{ v }" }.join(",") };#{ s }}" if @vars > 0
     s << "ripper_error(p);" if @error
     s = "{#{ s }}" if @brace
     "\t\t\t#{s}"
   end
 
+  def new_var
+    "v#{ @vars += 1 }"
+  end
+
   def method_missing(event, *args)
     if event.to_s =~ /!\z/
       event = $`
       @events[event] = args.size
-      "dispatch#{ args.size }(#{ [event, *args].join(", ") })"
+      vars = []
+      args.each do |arg|
+        vars << v = new_var
+        @code << "#{ v }=#{ arg };"
+      end
+      v = new_var
+      @code << "#{ v }=dispatch#{ args.size }(#{ [event, *vars].join(",") });"
+      v
     elsif args.empty? and /\Aid[A-Z]/ =~ event.to_s
       event
     else

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

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