diff options
author | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-20 17:45:24 +0000 |
---|---|---|
committer | mame <mame@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-01-20 17:45:24 +0000 |
commit | d24f1fddd770ca5ac488602207649ac678fb10ad (patch) | |
tree | e4c0c6dda33d23f7a20a3dcb33cdfe0709f88814 /ext/ripper | |
parent | 7ba7a2f70ebc27fd097843bf866d46b665475cbb (diff) | |
download | ruby-d24f1fddd770ca5ac488602207649ac678fb10ad.tar.gz |
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();`.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61991 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/ripper')
-rw-r--r-- | ext/ripper/tools/dsl.rb | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb index c4c5a36e27..44a8f4233d 100644 --- a/ext/ripper/tools/dsl.rb +++ b/ext/ripper/tools/dsl.rb @@ -1,7 +1,11 @@ # 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 @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 # struct parser_params *p p = "p" - @code = eval(code) + @code = "" + @last_value = eval(code) end attr_reader :events @@ -33,17 +39,29 @@ class DSL 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 |