зеркало из https://github.com/github/ruby.git
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
This commit is contained in:
Родитель
7ba7a2f70e
Коммит
d24f1fddd7
|
@ -1,7 +1,11 @@
|
||||||
# Simple DSL implementation for Ripper code generation
|
# Simple DSL implementation for Ripper code generation
|
||||||
#
|
#
|
||||||
# input: /*% ripper: stmts_add(stmts_new, void_stmt) %*/
|
# 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
|
class DSL
|
||||||
def initialize(code, options)
|
def initialize(code, options)
|
||||||
|
@ -9,6 +13,7 @@ class DSL
|
||||||
@error = options.include?("error")
|
@error = options.include?("error")
|
||||||
@brace = options.include?("brace")
|
@brace = options.include?("brace")
|
||||||
@final = options.include?("final")
|
@final = options.include?("final")
|
||||||
|
@vars = 0
|
||||||
|
|
||||||
# create $1 == "$1", $2 == "$2", ...
|
# create $1 == "$1", $2 == "$2", ...
|
||||||
re, s = "", ""
|
re, s = "", ""
|
||||||
|
@ -21,7 +26,8 @@ class DSL
|
||||||
# struct parser_params *p
|
# struct parser_params *p
|
||||||
p = "p"
|
p = "p"
|
||||||
|
|
||||||
@code = eval(code)
|
@code = ""
|
||||||
|
@last_value = eval(code)
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :events
|
attr_reader :events
|
||||||
|
@ -33,17 +39,29 @@ class DSL
|
||||||
def generate
|
def generate
|
||||||
s = "$$"
|
s = "$$"
|
||||||
s = "p->result" if @final
|
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 << "ripper_error(p);" if @error
|
||||||
s = "{#{ s }}" if @brace
|
s = "{#{ s }}" if @brace
|
||||||
"\t\t\t#{s}"
|
"\t\t\t#{s}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def new_var
|
||||||
|
"v#{ @vars += 1 }"
|
||||||
|
end
|
||||||
|
|
||||||
def method_missing(event, *args)
|
def method_missing(event, *args)
|
||||||
if event.to_s =~ /!\z/
|
if event.to_s =~ /!\z/
|
||||||
event = $`
|
event = $`
|
||||||
@events[event] = args.size
|
@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
|
elsif args.empty? and /\Aid[A-Z]/ =~ event.to_s
|
||||||
event
|
event
|
||||||
else
|
else
|
||||||
|
|
Загрузка…
Ссылка в новой задаче