зеркало из https://github.com/github/ruby.git
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
This commit is contained in:
Родитель
069e9ff52c
Коммит
8a72c77c79
|
@ -8,6 +8,8 @@ require_relative 'ruby_vm/scripts/insns2vm'
|
||||||
if $0 == __FILE__
|
if $0 == __FILE__
|
||||||
router(ARGV).each do |(path, generator)|
|
router(ARGV).each do |(path, generator)|
|
||||||
str = generator.generate path
|
str = generator.generate path
|
||||||
path.write str, mode: 'wb:utf-8'
|
path.open 'wb:utf-8' do |fp|
|
||||||
|
fp.write str
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,11 +16,6 @@ require_relative 'c_escape'
|
||||||
|
|
||||||
class RubyVM::Dumper
|
class RubyVM::Dumper
|
||||||
include RubyVM::CEscape
|
include RubyVM::CEscape
|
||||||
|
|
||||||
# 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
|
private
|
||||||
|
|
||||||
def new_binding
|
def new_binding
|
||||||
|
@ -57,13 +52,22 @@ class RubyVM::Dumper
|
||||||
end
|
end
|
||||||
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
|
public
|
||||||
|
|
||||||
def do_render source, locals
|
def do_render source, locals
|
||||||
erb = finderb source
|
erb = finderb source
|
||||||
bnd = @empty.dup
|
bnd = @empty.dup
|
||||||
locals.each_pair do |k, v|
|
locals.each_pair do |k, v|
|
||||||
bnd.local_variable_set k, v
|
local_variable_set bnd, k, v
|
||||||
end
|
end
|
||||||
return erb.result bnd
|
return erb.result bnd
|
||||||
end
|
end
|
||||||
|
@ -75,8 +79,6 @@ class RubyVM::Dumper
|
||||||
. map {|i, j| replace_pragma_line i, j } \
|
. map {|i, j| replace_pragma_line i, j } \
|
||||||
. join
|
. join
|
||||||
end
|
end
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
def initialize path
|
def initialize path
|
||||||
@erb = {}
|
@erb = {}
|
||||||
|
|
|
@ -11,8 +11,10 @@
|
||||||
# details.
|
# details.
|
||||||
|
|
||||||
require 'pathname'
|
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
|
class RubyVM::Scanner
|
||||||
attr_reader :__FILE__
|
attr_reader :__FILE__
|
||||||
attr_reader :__LINE__
|
attr_reader :__LINE__
|
||||||
|
@ -22,28 +24,29 @@ class RubyVM::Scanner
|
||||||
src += path
|
src += path
|
||||||
@__LINE__ = 1
|
@__LINE__ = 1
|
||||||
@__FILE__ = src.realpath.to_path
|
@__FILE__ = src.realpath.to_path
|
||||||
str = src.read mode: 'rt:utf-8:utf-8'
|
@str = src.read mode: 'rt:utf-8:utf-8'
|
||||||
@scanner = StringScanner.new str
|
@pos = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
def eos?
|
def eos?
|
||||||
@scanner.eos?
|
return @pos >= @str.length
|
||||||
end
|
end
|
||||||
|
|
||||||
def scan re
|
def scan re
|
||||||
ret = @__LINE__
|
ret = @__LINE__
|
||||||
match = @scanner.scan re
|
@last_match = @str.match re, @pos
|
||||||
return unless match
|
return unless @last_match
|
||||||
@__LINE__ += match.count "\n"
|
@__LINE__ += @last_match.to_s.count "\n"
|
||||||
|
@pos = @last_match.end 0
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
def scan! re
|
def scan! re
|
||||||
scan re or raise sprintf "parse error at %s:%d near:\n %s...", \
|
scan re or raise sprintf "parse error at %s:%d near:\n %s...", \
|
||||||
@__FILE__, @__LINE__, @scanner.peek(32)
|
@__FILE__, @__LINE__, @str[pos, 32]
|
||||||
end
|
end
|
||||||
|
|
||||||
def [] key
|
def [] key
|
||||||
return @scanner[key]
|
return @last_match[key]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,7 +41,7 @@ grammar = %r'
|
||||||
'x
|
'x
|
||||||
|
|
||||||
until scanner.eos? do
|
until scanner.eos? do
|
||||||
next if scanner.scan(/#{grammar}\g<ws>+/o)
|
next if scanner.scan(/\G#{grammar}\g<ws>+/o)
|
||||||
split = -> (v) {
|
split = -> (v) {
|
||||||
case v when /\Avoid\z/ then
|
case v when /\Avoid\z/ then
|
||||||
[]
|
[]
|
||||||
|
@ -50,14 +50,14 @@ until scanner.eos? do
|
||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
l1 = scanner.scan!(/#{grammar}\g<insn>/o)
|
l1 = scanner.scan!(/\G#{grammar}\g<insn>/o)
|
||||||
name = scanner["insn:name"]
|
name = scanner["insn:name"]
|
||||||
ope = split.(scanner["insn:opes"])
|
ope = split.(scanner["insn:opes"])
|
||||||
pop = split.(scanner["insn:pops"])
|
pop = split.(scanner["insn:pops"])
|
||||||
ret = split.(scanner["insn:rets"])
|
ret = split.(scanner["insn:rets"])
|
||||||
|
|
||||||
attrs = []
|
attrs = []
|
||||||
while l2 = scanner.scan(/#{grammar}\g<pragma>/o) do
|
while l2 = scanner.scan(/\G#{grammar}\g<pragma>/o) do
|
||||||
attrs << {
|
attrs << {
|
||||||
location: [path, l2],
|
location: [path, l2],
|
||||||
name: scanner["pragma:name"],
|
name: scanner["pragma:name"],
|
||||||
|
@ -66,7 +66,7 @@ until scanner.eos? do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
l3 = scanner.scan!(/#{grammar}\g<block>/o)
|
l3 = scanner.scan!(/\G#{grammar}\g<block>/o)
|
||||||
json << {
|
json << {
|
||||||
name: name,
|
name: name,
|
||||||
location: [path, l1],
|
location: [path, l1],
|
||||||
|
|
|
@ -16,10 +16,10 @@ json = []
|
||||||
scanner = RubyVM::Scanner.new '../../../defs/opt_insn_unif.def'
|
scanner = RubyVM::Scanner.new '../../../defs/opt_insn_unif.def'
|
||||||
path = scanner.__FILE__
|
path = scanner.__FILE__
|
||||||
until scanner.eos? do
|
until scanner.eos? do
|
||||||
next if scanner.scan(/ ^ (?: \#.* )? \n /x)
|
next if scanner.scan(/\G ^ (?: \#.* )? \n /x)
|
||||||
break if scanner.scan(/ ^ __END__ $ /x)
|
break if scanner.scan(/\G ^ __END__ $ /x)
|
||||||
|
|
||||||
pos = scanner.scan!(/(?<series> (?: [\ \t]* \w+ )+ ) \n /mx)
|
pos = scanner.scan!(/\G (?<series> (?: [\ \t]* \w+ )+ ) \n /mx)
|
||||||
json << {
|
json << {
|
||||||
location: [path, pos],
|
location: [path, pos],
|
||||||
signature: scanner["series"].strip.split
|
signature: scanner["series"].strip.split
|
||||||
|
|
|
@ -29,18 +29,17 @@ grammar = %r/
|
||||||
/mx
|
/mx
|
||||||
|
|
||||||
until scanner.eos? do
|
until scanner.eos? do
|
||||||
break if scanner.scan(/ ^ __END__ $ /x)
|
break if scanner.scan(/\G ^ __END__ $ /x)
|
||||||
next if scanner.scan(/#{grammar} \g<ws>+ /ox)
|
next if scanner.scan(/\G#{grammar} \g<ws>+ /ox)
|
||||||
|
|
||||||
line = scanner.scan!(/#{grammar} \g<decl> /mox)
|
line = scanner.scan!(/\G#{grammar} \g<decl> /mox)
|
||||||
insn = scanner["insn"]
|
insn = scanner["insn"]
|
||||||
args = scanner["args"]
|
args = scanner["args"]
|
||||||
ary = []
|
ary = []
|
||||||
until args.strip.empty? do
|
until args.strip.empty? do
|
||||||
tmp = StringScanner.new args
|
md = /\G#{grammar} \g<args> /mox.match(args)
|
||||||
tmp.scan(/#{grammar} \g<args> /mox)
|
ary << md["arg"]
|
||||||
ary << tmp["arg"]
|
args = md["remain"]
|
||||||
args = tmp["remain"]
|
|
||||||
break unless args
|
break unless args
|
||||||
end
|
end
|
||||||
json << {
|
json << {
|
||||||
|
|
|
@ -18,14 +18,14 @@ grammar = %r/
|
||||||
(?<ws> \u0020 ){0}
|
(?<ws> \u0020 ){0}
|
||||||
(?<key> \w+ ){0}
|
(?<key> \w+ ){0}
|
||||||
(?<value> 0|1 ){0}
|
(?<value> 0|1 ){0}
|
||||||
(?<define> \#define \g<ws>+ OPT_\g<key> \g<ws>+ \g<value> \g<ws>*\n )
|
(?<define> \G \#define \g<ws>+ OPT_\g<key> \g<ws>+ \g<value> \g<ws>*\n )
|
||||||
/mx
|
/mx
|
||||||
|
|
||||||
until scanner.eos? do
|
until scanner.eos? do
|
||||||
if scanner.scan grammar then
|
if scanner.scan grammar then
|
||||||
json[scanner['key']] = ! scanner['value'].to_i.zero? # not nonzero?
|
json[scanner['key']] = ! scanner['value'].to_i.zero? # not nonzero?
|
||||||
else
|
else
|
||||||
scanner.scan(/.*\n/)
|
scanner.scan(/\G.*\n/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,11 @@ class RubyVM::Attribute
|
||||||
include RubyVM::CEscape
|
include RubyVM::CEscape
|
||||||
attr_reader :insn, :key, :type, :expr
|
attr_reader :insn, :key, :type, :expr
|
||||||
|
|
||||||
def initialize insn:, name:, type:, location:, expr:
|
def initialize opts = {}
|
||||||
@insn = insn
|
@insn = opts[:insn]
|
||||||
@key = name
|
@key = opts[:name]
|
||||||
@expr = RubyVM::CExpr.new location: location, expr: expr
|
@expr = RubyVM::CExpr.new location: opts[:location], expr: opts[:expr]
|
||||||
@type = type
|
@type = opts[:type]
|
||||||
end
|
end
|
||||||
|
|
||||||
def name
|
def name
|
||||||
|
|
|
@ -18,16 +18,16 @@ require_relative 'attribute'
|
||||||
class RubyVM::BareInstructions
|
class RubyVM::BareInstructions
|
||||||
attr_reader :template, :name, :opes, :pops, :rets, :decls, :expr
|
attr_reader :template, :name, :opes, :pops, :rets, :decls, :expr
|
||||||
|
|
||||||
def initialize template:, name:, location:, signature:, attributes:, expr:
|
def initialize opts = {}
|
||||||
@template = template
|
@template = opts[:template]
|
||||||
@name = name
|
@name = opts[:name]
|
||||||
@loc = location
|
@loc = opts[:location]
|
||||||
@sig = signature
|
@sig = opts[:signature]
|
||||||
@expr = RubyVM::CExpr.new expr
|
@expr = RubyVM::CExpr.new opts[:expr]
|
||||||
@opes = typesplit @sig[:ope]
|
@opes = typesplit @sig[:ope]
|
||||||
@pops = typesplit @sig[:pop].reject {|i| i == '...' }
|
@pops = typesplit @sig[:pop].reject {|i| i == '...' }
|
||||||
@rets = typesplit @sig[:ret].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
|
RubyVM::Attribute.new insn: self, **i
|
||||||
}.each_with_object({}) {|a, h|
|
}.each_with_object({}) {|a, h|
|
||||||
h[a.key] = a
|
h[a.key] = a
|
||||||
|
@ -148,7 +148,10 @@ class RubyVM::BareInstructions
|
||||||
end
|
end
|
||||||
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
|
def self.fetch name
|
||||||
@instances.find do |insn|
|
@instances.find do |insn|
|
||||||
|
|
|
@ -17,10 +17,10 @@ class RubyVM::CExpr
|
||||||
|
|
||||||
attr_reader :__FILE__, :__LINE__, :expr
|
attr_reader :__FILE__, :__LINE__, :expr
|
||||||
|
|
||||||
def initialize location:, expr:
|
def initialize opts = {}
|
||||||
@__FILE__ = location[0]
|
@__FILE__ = opts[:location][0]
|
||||||
@__LINE__ = location[1]
|
@__LINE__ = opts[:location][1]
|
||||||
@expr = expr
|
@expr = opts[:expr]
|
||||||
end
|
end
|
||||||
|
|
||||||
# blank, in sense of C program.
|
# blank, in sense of C program.
|
||||||
|
|
|
@ -19,10 +19,10 @@ class RubyVM::InstructionsUnifications
|
||||||
|
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
def initialize location:, signature:
|
def initialize opts = {}
|
||||||
@location = location
|
@location = opts[:location]
|
||||||
@name = namegen signature
|
@name = namegen opts[:signature]
|
||||||
@series = signature.map do |i|
|
@series = opts[:signature].map do |i|
|
||||||
RubyVM::BareInstructions.fetch i # Misshit is fatal
|
RubyVM::BareInstructions.fetch i # Misshit is fatal
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -34,7 +34,7 @@ class RubyVM::InstructionsUnifications
|
||||||
end
|
end
|
||||||
|
|
||||||
@instances = RubyVM::OptInsnUnifDef.map do |h|
|
@instances = RubyVM::OptInsnUnifDef.map do |h|
|
||||||
new(**h)
|
new h
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_a
|
def self.to_a
|
||||||
|
|
|
@ -19,13 +19,13 @@ class RubyVM::OperandsUnifications < RubyVM::BareInstructions
|
||||||
|
|
||||||
attr_reader :preamble, :original, :spec
|
attr_reader :preamble, :original, :spec
|
||||||
|
|
||||||
def initialize location:, signature:
|
def initialize opts = {}
|
||||||
name = signature[0]
|
name = opts[:signature][0]
|
||||||
@original = RubyVM::BareInstructions.fetch name
|
@original = RubyVM::BareInstructions.fetch name
|
||||||
template = @original.template
|
template = @original.template
|
||||||
parts = compose location, signature, template[:signature]
|
parts = compose opts[:location], opts[:signature], template[:signature]
|
||||||
json = template.dup
|
json = template.dup
|
||||||
json[:location] = location
|
json[:location] = opts[:location]
|
||||||
json[:signature] = parts[:signature]
|
json[:signature] = parts[:signature]
|
||||||
json[:name] = parts[:name]
|
json[:name] = parts[:name]
|
||||||
@preamble = parts[:preamble]
|
@preamble = parts[:preamble]
|
||||||
|
@ -122,7 +122,7 @@ class RubyVM::OperandsUnifications < RubyVM::BareInstructions
|
||||||
end
|
end
|
||||||
|
|
||||||
@instances = RubyVM::OptOperandDef.map do |h|
|
@instances = RubyVM::OptOperandDef.map do |h|
|
||||||
new(**h)
|
new h
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.to_a
|
def self.to_a
|
||||||
|
|
|
@ -18,7 +18,7 @@ class RubyVM::TraceInstructions
|
||||||
|
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
|
|
||||||
def initialize orig:
|
def initialize orig
|
||||||
@orig = orig
|
@orig = orig
|
||||||
@name = as_tr_cpp "trace @ #{@orig.name}"
|
@name = as_tr_cpp "trace @ #{@orig.name}"
|
||||||
end
|
end
|
||||||
|
@ -61,7 +61,7 @@ class RubyVM::TraceInstructions
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
@instances = RubyVM::Instructions.map {|i| new orig: i }
|
@instances = RubyVM::Instructions.map {|i| new i }
|
||||||
|
|
||||||
def self.to_a
|
def self.to_a
|
||||||
@instances
|
@instances
|
||||||
|
|
Загрузка…
Ссылка в новой задаче