From 8a72c77c7920d129818b7b83bb4fa669cd7e3f7d Mon Sep 17 00:00:00 2001 From: shyouhei Date: Fri, 12 Jan 2018 08:38:11 +0000 Subject: [PATCH] tool/ruby_vm support for pre-2.1 BASERUBY as requested by devs, support for BASERUBY prior to 2.1 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61786 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- tool/insns2vm.rb | 4 +- tool/ruby_vm/helpers/dumper.rb | 116 +++++++++--------- tool/ruby_vm/helpers/scanner.rb | 21 ++-- tool/ruby_vm/loaders/insns_def.rb | 8 +- tool/ruby_vm/loaders/opt_insn_unif_def.rb | 6 +- tool/ruby_vm/loaders/opt_operand_def.rb | 13 +- tool/ruby_vm/loaders/vm_opts_h.rb | 4 +- tool/ruby_vm/models/attribute.rb | 10 +- tool/ruby_vm/models/bare_instructions.rb | 19 +-- tool/ruby_vm/models/c_expr.rb | 8 +- .../models/instructions_unifications.rb | 10 +- tool/ruby_vm/models/operands_unifications.rb | 10 +- tool/ruby_vm/models/trace_instructions.rb | 4 +- 13 files changed, 121 insertions(+), 112 deletions(-) diff --git a/tool/insns2vm.rb b/tool/insns2vm.rb index e6fe64d189..8117b789fb 100755 --- a/tool/insns2vm.rb +++ b/tool/insns2vm.rb @@ -8,6 +8,8 @@ require_relative 'ruby_vm/scripts/insns2vm' if $0 == __FILE__ router(ARGV).each do |(path, generator)| str = generator.generate path - path.write str, mode: 'wb:utf-8' + path.open 'wb:utf-8' do |fp| + fp.write str + end end end diff --git a/tool/ruby_vm/helpers/dumper.rb b/tool/ruby_vm/helpers/dumper.rb index 8f14d90d1f..3ba7310f56 100644 --- a/tool/ruby_vm/helpers/dumper.rb +++ b/tool/ruby_vm/helpers/dumper.rb @@ -16,67 +16,69 @@ require_relative 'c_escape' class RubyVM::Dumper include RubyVM::CEscape + private - # I learned this handy "super-private" maneuver from @a_matsuda - # cf: https://github.com/rails/rails/pull/27363/files - using Module.new { - refine RubyVM::Dumper do - private + def new_binding + # This `eval 'binding'` does not return the current binding + # but creates one on top of it. + return eval 'binding' + end - def new_binding - # This `eval 'binding'` does not return the current binding - # but creates one on top of it. - return eval 'binding' - end + def new_erb spec + path = Pathname.new __dir__ + path += '../views' + path += spec + src = path.read mode: 'rt:utf-8:utf-8' + rescue Errno::ENOENT + raise "don't know how to generate #{path}" + else + erb = ERB.new src, nil, '%-' + erb.filename = path.realpath.to_path + return erb + end - def new_erb spec - path = Pathname.new __dir__ - path += '../views' - path += spec - src = path.read mode: 'rt:utf-8:utf-8' - rescue Errno::ENOENT - raise "don't know how to generate #{path}" - else - erb = ERB.new src, nil, '%-' - erb.filename = path.realpath.to_path - return erb - end - - def finderb spec - return @erb.fetch spec do |k| - erb = new_erb k - @erb[k] = erb - end - end - - def replace_pragma_line str, lineno - if str == "#pragma RubyVM reset source\n" then - return "#line #{lineno + 2} #{@file}\n" - else - return str - end - end - - public - - def do_render source, locals - erb = finderb source - bnd = @empty.dup - locals.each_pair do |k, v| - bnd.local_variable_set k, v - end - return erb.result bnd - end - - def replace_pragma str - return str \ - . each_line \ - . with_index \ - . map {|i, j| replace_pragma_line i, j } \ - . join - end + def finderb spec + return @erb.fetch spec do |k| + erb = new_erb k + @erb[k] = erb end - } + end + + def replace_pragma_line str, lineno + if str == "#pragma RubyVM reset source\n" then + return "#line #{lineno + 2} #{@file}\n" + else + return str + end + end + + def local_variable_set bnd, var, val + eval '__locals__ ||= {}', bnd + locals = eval '__locals__', bnd + locals[var] = val + eval "#{var} = __locals__[:#{var}]", bnd + test = eval "#{var}", bnd + raise unless test == val + end + + public + + def do_render source, locals + erb = finderb source + bnd = @empty.dup + locals.each_pair do |k, v| + local_variable_set bnd, k, v + end + return erb.result bnd + end + + def replace_pragma str + return str \ + . each_line \ + . with_index \ + . map {|i, j| replace_pragma_line i, j } \ + . join + end def initialize path @erb = {} diff --git a/tool/ruby_vm/helpers/scanner.rb b/tool/ruby_vm/helpers/scanner.rb index 3dce6ffdfe..5ae1363480 100644 --- a/tool/ruby_vm/helpers/scanner.rb +++ b/tool/ruby_vm/helpers/scanner.rb @@ -11,8 +11,10 @@ # details. require 'pathname' -require 'strscan' +# Poor man's StringScanner. +# Sadly https://bugs.ruby-lang.org/issues/8343 is not backported to 2.0. We +# have to do it by hand. class RubyVM::Scanner attr_reader :__FILE__ attr_reader :__LINE__ @@ -22,28 +24,29 @@ class RubyVM::Scanner src += path @__LINE__ = 1 @__FILE__ = src.realpath.to_path - str = src.read mode: 'rt:utf-8:utf-8' - @scanner = StringScanner.new str + @str = src.read mode: 'rt:utf-8:utf-8' + @pos = 0 end def eos? - @scanner.eos? + return @pos >= @str.length end def scan re ret = @__LINE__ - match = @scanner.scan re - return unless match - @__LINE__ += match.count "\n" + @last_match = @str.match re, @pos + return unless @last_match + @__LINE__ += @last_match.to_s.count "\n" + @pos = @last_match.end 0 return ret end def scan! re scan re or raise sprintf "parse error at %s:%d near:\n %s...", \ - @__FILE__, @__LINE__, @scanner.peek(32) + @__FILE__, @__LINE__, @str[pos, 32] end def [] key - return @scanner[key] + return @last_match[key] end end diff --git a/tool/ruby_vm/loaders/insns_def.rb b/tool/ruby_vm/loaders/insns_def.rb index 58748c3ca6..987e29640a 100644 --- a/tool/ruby_vm/loaders/insns_def.rb +++ b/tool/ruby_vm/loaders/insns_def.rb @@ -41,7 +41,7 @@ grammar = %r' 'x until scanner.eos? do - next if scanner.scan(/#{grammar}\g+/o) + next if scanner.scan(/\G#{grammar}\g+/o) split = -> (v) { case v when /\Avoid\z/ then [] @@ -50,14 +50,14 @@ until scanner.eos? do end } - l1 = scanner.scan!(/#{grammar}\g/o) + l1 = scanner.scan!(/\G#{grammar}\g/o) name = scanner["insn:name"] ope = split.(scanner["insn:opes"]) pop = split.(scanner["insn:pops"]) ret = split.(scanner["insn:rets"]) attrs = [] - while l2 = scanner.scan(/#{grammar}\g/o) do + while l2 = scanner.scan(/\G#{grammar}\g/o) do attrs << { location: [path, l2], name: scanner["pragma:name"], @@ -66,7 +66,7 @@ until scanner.eos? do } end - l3 = scanner.scan!(/#{grammar}\g/o) + l3 = scanner.scan!(/\G#{grammar}\g/o) json << { name: name, location: [path, l1], diff --git a/tool/ruby_vm/loaders/opt_insn_unif_def.rb b/tool/ruby_vm/loaders/opt_insn_unif_def.rb index a5af409e71..0f5de69930 100644 --- a/tool/ruby_vm/loaders/opt_insn_unif_def.rb +++ b/tool/ruby_vm/loaders/opt_insn_unif_def.rb @@ -16,10 +16,10 @@ json = [] scanner = RubyVM::Scanner.new '../../../defs/opt_insn_unif.def' path = scanner.__FILE__ until scanner.eos? do - next if scanner.scan(/ ^ (?: \#.* )? \n /x) - break if scanner.scan(/ ^ __END__ $ /x) + next if scanner.scan(/\G ^ (?: \#.* )? \n /x) + break if scanner.scan(/\G ^ __END__ $ /x) - pos = scanner.scan!(/(? (?: [\ \t]* \w+ )+ ) \n /mx) + pos = scanner.scan!(/\G (? (?: [\ \t]* \w+ )+ ) \n /mx) json << { location: [path, pos], signature: scanner["series"].strip.split diff --git a/tool/ruby_vm/loaders/opt_operand_def.rb b/tool/ruby_vm/loaders/opt_operand_def.rb index 5c94b4bced..3022f9915d 100644 --- a/tool/ruby_vm/loaders/opt_operand_def.rb +++ b/tool/ruby_vm/loaders/opt_operand_def.rb @@ -29,18 +29,17 @@ grammar = %r/ /mx until scanner.eos? do - break if scanner.scan(/ ^ __END__ $ /x) - next if scanner.scan(/#{grammar} \g+ /ox) + break if scanner.scan(/\G ^ __END__ $ /x) + next if scanner.scan(/\G#{grammar} \g+ /ox) - line = scanner.scan!(/#{grammar} \g /mox) + line = scanner.scan!(/\G#{grammar} \g /mox) insn = scanner["insn"] args = scanner["args"] ary = [] until args.strip.empty? do - tmp = StringScanner.new args - tmp.scan(/#{grammar} \g /mox) - ary << tmp["arg"] - args = tmp["remain"] + md = /\G#{grammar} \g /mox.match(args) + ary << md["arg"] + args = md["remain"] break unless args end json << { diff --git a/tool/ruby_vm/loaders/vm_opts_h.rb b/tool/ruby_vm/loaders/vm_opts_h.rb index f898fb36a4..d28db4eaa2 100644 --- a/tool/ruby_vm/loaders/vm_opts_h.rb +++ b/tool/ruby_vm/loaders/vm_opts_h.rb @@ -18,14 +18,14 @@ grammar = %r/ (? \u0020 ){0} (? \w+ ){0} (? 0|1 ){0} - (? \#define \g+ OPT_\g \g+ \g \g*\n ) + (? \G \#define \g+ OPT_\g \g+ \g \g*\n ) /mx until scanner.eos? do if scanner.scan grammar then json[scanner['key']] = ! scanner['value'].to_i.zero? # not nonzero? else - scanner.scan(/.*\n/) + scanner.scan(/\G.*\n/) end end diff --git a/tool/ruby_vm/models/attribute.rb b/tool/ruby_vm/models/attribute.rb index 0b6d6e09b2..f6d95bd67c 100644 --- a/tool/ruby_vm/models/attribute.rb +++ b/tool/ruby_vm/models/attribute.rb @@ -16,11 +16,11 @@ class RubyVM::Attribute include RubyVM::CEscape attr_reader :insn, :key, :type, :expr - def initialize insn:, name:, type:, location:, expr: - @insn = insn - @key = name - @expr = RubyVM::CExpr.new location: location, expr: expr - @type = type + def initialize opts = {} + @insn = opts[:insn] + @key = opts[:name] + @expr = RubyVM::CExpr.new location: opts[:location], expr: opts[:expr] + @type = opts[:type] end def name diff --git a/tool/ruby_vm/models/bare_instructions.rb b/tool/ruby_vm/models/bare_instructions.rb index c3a96b8f08..a9cb4db953 100644 --- a/tool/ruby_vm/models/bare_instructions.rb +++ b/tool/ruby_vm/models/bare_instructions.rb @@ -18,16 +18,16 @@ require_relative 'attribute' class RubyVM::BareInstructions attr_reader :template, :name, :opes, :pops, :rets, :decls, :expr - def initialize template:, name:, location:, signature:, attributes:, expr: - @template = template - @name = name - @loc = location - @sig = signature - @expr = RubyVM::CExpr.new expr + def initialize opts = {} + @template = opts[:template] + @name = opts[:name] + @loc = opts[:location] + @sig = opts[:signature] + @expr = RubyVM::CExpr.new opts[:expr] @opes = typesplit @sig[:ope] @pops = typesplit @sig[:pop].reject {|i| i == '...' } @rets = typesplit @sig[:ret].reject {|i| i == '...' } - @attrs = attributes.map {|i| + @attrs = opts[:attributes].map {|i| RubyVM::Attribute.new insn: self, **i }.each_with_object({}) {|a, h| h[a.key] = a @@ -148,7 +148,10 @@ class RubyVM::BareInstructions end end - @instances = RubyVM::InsnsDef.map {|h| new template: h, **h } + @instances = RubyVM::InsnsDef.map {|h| + hh = h.merge(:template => h) + new hh + } def self.fetch name @instances.find do |insn| diff --git a/tool/ruby_vm/models/c_expr.rb b/tool/ruby_vm/models/c_expr.rb index b19dd8bb48..923651a26b 100644 --- a/tool/ruby_vm/models/c_expr.rb +++ b/tool/ruby_vm/models/c_expr.rb @@ -17,10 +17,10 @@ class RubyVM::CExpr attr_reader :__FILE__, :__LINE__, :expr - def initialize location:, expr: - @__FILE__ = location[0] - @__LINE__ = location[1] - @expr = expr + def initialize opts = {} + @__FILE__ = opts[:location][0] + @__LINE__ = opts[:location][1] + @expr = opts[:expr] end # blank, in sense of C program. diff --git a/tool/ruby_vm/models/instructions_unifications.rb b/tool/ruby_vm/models/instructions_unifications.rb index 346cebd709..aa8cef1bd5 100644 --- a/tool/ruby_vm/models/instructions_unifications.rb +++ b/tool/ruby_vm/models/instructions_unifications.rb @@ -19,10 +19,10 @@ class RubyVM::InstructionsUnifications attr_reader :name - def initialize location:, signature: - @location = location - @name = namegen signature - @series = signature.map do |i| + def initialize opts = {} + @location = opts[:location] + @name = namegen opts[:signature] + @series = opts[:signature].map do |i| RubyVM::BareInstructions.fetch i # Misshit is fatal end end @@ -34,7 +34,7 @@ class RubyVM::InstructionsUnifications end @instances = RubyVM::OptInsnUnifDef.map do |h| - new(**h) + new h end def self.to_a diff --git a/tool/ruby_vm/models/operands_unifications.rb b/tool/ruby_vm/models/operands_unifications.rb index c0ae0ece45..2a34ea0f62 100644 --- a/tool/ruby_vm/models/operands_unifications.rb +++ b/tool/ruby_vm/models/operands_unifications.rb @@ -19,13 +19,13 @@ class RubyVM::OperandsUnifications < RubyVM::BareInstructions attr_reader :preamble, :original, :spec - def initialize location:, signature: - name = signature[0] + def initialize opts = {} + name = opts[:signature][0] @original = RubyVM::BareInstructions.fetch name template = @original.template - parts = compose location, signature, template[:signature] + parts = compose opts[:location], opts[:signature], template[:signature] json = template.dup - json[:location] = location + json[:location] = opts[:location] json[:signature] = parts[:signature] json[:name] = parts[:name] @preamble = parts[:preamble] @@ -122,7 +122,7 @@ class RubyVM::OperandsUnifications < RubyVM::BareInstructions end @instances = RubyVM::OptOperandDef.map do |h| - new(**h) + new h end def self.to_a diff --git a/tool/ruby_vm/models/trace_instructions.rb b/tool/ruby_vm/models/trace_instructions.rb index a99a933ac7..fc904a11b5 100644 --- a/tool/ruby_vm/models/trace_instructions.rb +++ b/tool/ruby_vm/models/trace_instructions.rb @@ -18,7 +18,7 @@ class RubyVM::TraceInstructions attr_reader :name - def initialize orig: + def initialize orig @orig = orig @name = as_tr_cpp "trace @ #{@orig.name}" end @@ -61,7 +61,7 @@ class RubyVM::TraceInstructions private - @instances = RubyVM::Instructions.map {|i| new orig: i } + @instances = RubyVM::Instructions.map {|i| new i } def self.to_a @instances