mirror of
https://github.com/mistergibson/gxg-web-client.git
synced 2026-08-15 03:26:00 -07:00
348 lines
7.2 KiB
Ruby
348 lines
7.2 KiB
Ruby
module Rubinius
|
|
class CodeLoader
|
|
def self.registry
|
|
Rubinius.synchronize(self) { @registry ||= [] }
|
|
end
|
|
|
|
def self.loading?(path)
|
|
feature = nil
|
|
|
|
resource = Feature.new path
|
|
if resource.loadable? or resource.search
|
|
feature = resource.feature
|
|
end
|
|
|
|
unless feature
|
|
resource = Library.new path
|
|
if resource.loadable? or resource.search
|
|
feature = resource.feature
|
|
end
|
|
end
|
|
|
|
if feature
|
|
Rubinius.synchronize(registry) do
|
|
return true if registry.include? feature
|
|
end
|
|
end
|
|
|
|
false
|
|
end
|
|
|
|
class Resource
|
|
attr_reader :feature
|
|
|
|
def initialize(stem, ext)
|
|
stem = Type.coerce_to_path stem
|
|
stem = "#{stem}#{ext}" unless stem.suffix? ext
|
|
|
|
@relative = false
|
|
|
|
if stem[0] == ?~
|
|
@prefix = ""
|
|
stem = File.expand_path stem
|
|
elsif stem[0] == ?/
|
|
@prefix = ""
|
|
elsif stem[0] == ?. and (stem[1] == ?/ or
|
|
(stem[1] == ?. and stem[2] == ?/))
|
|
@relative = true
|
|
@prefix = Dir.pwd
|
|
else
|
|
@prefix = nil
|
|
end
|
|
|
|
@stem = stem
|
|
@feature = nil
|
|
@record = true
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def resolve
|
|
return true if loadable?
|
|
return true if search
|
|
return false
|
|
end
|
|
|
|
def search
|
|
return false if @relative
|
|
|
|
$LOAD_PATH.each do |dir|
|
|
if dir[-1] == ?/
|
|
@prefix = dir[0...-1]
|
|
else
|
|
@prefix = dir
|
|
end
|
|
|
|
return true if loadable?
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
def loadable?
|
|
feature = "#{@prefix}/#{@stem}"
|
|
|
|
stat = File::Stat.stat feature
|
|
|
|
if stat and stat.file? and stat.readable?
|
|
@feature = File.expand_path feature
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
def unload_feature
|
|
Rubinius.synchronize($LOADED_FEATURES) do
|
|
$LOADED_FEATURES.delete_if { |f| f == @feature }
|
|
end
|
|
end
|
|
end
|
|
|
|
class Source < Resource
|
|
def initialize(stem, ext)
|
|
super stem, ext
|
|
|
|
@code = nil
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def load
|
|
if @code
|
|
@feature = @code.file.to_s
|
|
else
|
|
@code = ToolSets::Runtime::Compiler.compile_file @feature
|
|
CoreDB.store @code, @stem, @prefix, @feature, @record
|
|
end
|
|
|
|
run_script
|
|
|
|
return true
|
|
end
|
|
|
|
def make_script
|
|
script = @code.create_script @wrap
|
|
script.file_path = script.data_path = @code.file.to_s
|
|
script
|
|
end
|
|
|
|
def run_script
|
|
make_script
|
|
Rubinius.run_script @code
|
|
rescue Object
|
|
unload_feature
|
|
raise
|
|
end
|
|
end
|
|
|
|
class Feature < Source
|
|
def initialize(stem)
|
|
super stem, CodeLoader.source_extension
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def resolve
|
|
@code = CoreDB.load_feature @stem, CodeLoader.source_extension, false, @record
|
|
|
|
return true if @code or false.equal? @code
|
|
return true if loadable?
|
|
return true if search
|
|
|
|
return false
|
|
end
|
|
|
|
def load
|
|
return false if false.equal? @code
|
|
|
|
super()
|
|
end
|
|
end
|
|
|
|
class CodeModule < Source
|
|
def initialize(stem, wrap)
|
|
super stem, ""
|
|
|
|
@wrap = wrap
|
|
@record = false
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def resolve
|
|
@code = CoreDB.load_feature @stem, CodeLoader.source_extension, true, @record
|
|
|
|
return true if @code
|
|
return true if loadable?
|
|
return true if search
|
|
|
|
@prefix = Dir.pwd
|
|
return true if loadable?
|
|
|
|
return false
|
|
end
|
|
end
|
|
|
|
class Script < Source
|
|
def initialize(stem)
|
|
super File.expand_path(stem), ""
|
|
|
|
@file = stem
|
|
@record = false
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def resolve
|
|
@code = CoreDB.load_feature @stem, "", true, @record
|
|
|
|
return true if @code
|
|
return true if loadable?
|
|
return false
|
|
end
|
|
|
|
def make_script
|
|
script = super()
|
|
script.file_path = @file
|
|
script.make_main!
|
|
end
|
|
end
|
|
|
|
class Library < Resource
|
|
def initialize(stem)
|
|
if stem.suffix? ".so"
|
|
super stem[0...-3], CodeLoader.library_extension
|
|
else
|
|
super stem, CodeLoader.library_extension
|
|
end
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def load
|
|
CoreDB.store nil, @stem, @prefix, @feature, @record
|
|
|
|
name = File.basename @feature, CodeLoader.library_extension
|
|
NativeMethod.load_extension(@feature, name)
|
|
|
|
return true
|
|
rescue Object
|
|
unload_feature
|
|
raise
|
|
end
|
|
end
|
|
|
|
def self.source_extension
|
|
".rb"
|
|
end
|
|
|
|
def self.library_extension
|
|
LIBSUFFIX
|
|
end
|
|
|
|
# Loads rubygems using the bootstrap standard library files.
|
|
def self.load_rubygems
|
|
require "rubygems"
|
|
end
|
|
|
|
# Loads the pre-compiled bytecode compiler. Sets up paths needed by the
|
|
# compiler to find dependencies like the parser.
|
|
def self.load_compiler
|
|
begin
|
|
require "rubinius/code/toolset"
|
|
|
|
ToolSets.create :runtime do
|
|
begin
|
|
require "rubinius/code/melbourne"
|
|
rescue LoadError
|
|
STDERR.puts "Melbourne failed to load, Ruby source parsing disabled"
|
|
end
|
|
require "rubinius/code/processor"
|
|
require "rubinius/code/compiler"
|
|
require "rubinius/code/ast"
|
|
end
|
|
rescue Object => e
|
|
raise LoadError, "Unable to load the bytecode compiler", e
|
|
end
|
|
end
|
|
|
|
def initialize(stem)
|
|
@stem = stem
|
|
end
|
|
|
|
private :initialize
|
|
|
|
def load_script
|
|
resource = Script.new @stem
|
|
|
|
load_error unless resource.resolve
|
|
resource.load
|
|
end
|
|
|
|
def load(wrap)
|
|
resource = CodeModule.new @stem, wrap
|
|
|
|
load_error unless resource.resolve
|
|
resource.load
|
|
end
|
|
|
|
def require
|
|
resource = Feature.new @stem
|
|
if resource.resolve
|
|
register_file resource.feature
|
|
return resource.load
|
|
end
|
|
|
|
resource = Library.new @stem
|
|
if resource.resolve
|
|
register_file resource.feature
|
|
return resource.load
|
|
end
|
|
|
|
load_error
|
|
ensure
|
|
unregister_file resource.feature if resource
|
|
end
|
|
|
|
def require_relative(scope)
|
|
script = scope.current_script
|
|
if script
|
|
if script.data_path
|
|
path = File.dirname(File.realdirpath(script.data_path))
|
|
else
|
|
path = Dir.pwd
|
|
end
|
|
|
|
@stem = File.expand_path(@stem, path)
|
|
|
|
require
|
|
else
|
|
raise LoadError.new "unable to get relative path"
|
|
end
|
|
end
|
|
|
|
def register_file(path)
|
|
registry = self.class.registry
|
|
|
|
Rubinius.synchronize(registry) do
|
|
registry << path
|
|
end
|
|
end
|
|
|
|
def unregister_file(path)
|
|
registry = self.class.registry
|
|
|
|
Rubinius.synchronize(registry) do
|
|
registry.delete_if { |x| x == path }
|
|
end
|
|
end
|
|
|
|
def load_error
|
|
# Some versions of Rails override LoadError.new but do NOT override
|
|
# LoadError.exception, so we must use LoadError.new here to match MRI
|
|
# behavior.
|
|
raise LoadError.new("no such file to load -- #{@stem}", path: @stem)
|
|
end
|
|
end
|
|
end
|