def __init__(self, space, name, superclass): self.name = name self.klass = None self.superclass = superclass self.version = VersionTag() self.methods_w = {} self.constants_w = {} self.class_variables = CellDict() self.instance_variables = CellDict() self.lexical_scope = None self.included_modules = [] self.descendants = []
class W_ModuleObject(W_RootObject): _immutable_fields_ = [ "version?", "included_modules?[*]", "lexical_scope?", "klass?" ] classdef = ClassDef("Module", W_RootObject.classdef) def __init__(self, space, name, superclass): self.name = name self.klass = None self.superclass = superclass self.version = VersionTag() self.methods_w = {} self.constants_w = {} self.class_variables = CellDict() self.instance_variables = CellDict() self.lexical_scope = None self.included_modules = [] self.descendants = [] def __deepcopy__(self, memo): obj = super(W_ModuleObject, self).__deepcopy__(memo) obj.name = self.name obj.klass = copy.deepcopy(self.klass, memo) obj.superclass = copy.deepcopy(self.superclass, memo) obj.version = copy.deepcopy(self.version, memo) obj.methods_w = copy.deepcopy(self.methods_w, memo) obj.constants_w = copy.deepcopy(self.constants_w, memo) obj.class_variables = copy.deepcopy(self.class_variables, memo) obj.instance_variables = copy.deepcopy(self.instance_variables, memo) obj.lexical_scope = copy.deepcopy(self.lexical_scope, memo) obj.included_modules = copy.deepcopy(self.included_modules, memo) obj.descendants = copy.deepcopy(self.descendants, memo) return obj def getclass(self, space): if self.klass is not None: return self.klass return W_RootObject.getclass(self, space) def getsingletonclass(self, space): if self.klass is None: self.klass = space.newclass("#<Class:%s>" % self.name, space.w_module, is_singleton=True) return self.klass def mutated(self): self.version = VersionTag() def define_method(self, space, name, method): self.mutated() self.methods_w[name] = method @jit.unroll_safe def find_method(self, space, name): method = self._find_method_pure(space, name, self.version) if method is None: for module in self.included_modules: method = module.find_method(space, name) if method is not None: return method return method @jit.unroll_safe def find_method_super(self, space, name): for module in self.included_modules: method = module.find_method(space, name) if method is not None: return method return None @jit.elidable def _find_method_pure(self, space, method, version): return self.methods_w.get(method, None) def set_lexical_scope(self, space, w_mod): self.lexical_scope = w_mod def set_const(self, space, name, w_obj): self.mutated() self.constants_w[name] = w_obj def find_const(self, space, name): res = self._find_const_pure(name, self.version) if res is None and self.lexical_scope is not None: res = self.lexical_scope.find_lexical_const(space, name) if res is None and self.superclass is not None: res = self.superclass.find_inherited_const(space, name) return res def find_lexical_const(self, space, name): res = self._find_const_pure(name, self.version) if res is None and self.lexical_scope is not None: return self.lexical_scope.find_lexical_const(space, name) return res def find_inherited_const(self, space, name): res = self._find_const_pure(name, self.version) if res is None and self.superclass is not None: return self.superclass.find_inherited_const(space, name) return res def find_local_const(self, space, name): return self._find_const_pure(name, self.version) @jit.elidable def _find_const_pure(self, name, version): return self.constants_w.get(name, None) @jit.unroll_safe def set_class_var(self, space, name, w_obj): ancestors = self.ancestors() for idx in xrange(len(ancestors) - 1, -1, -1): module = ancestors[idx] assert isinstance(module, W_ModuleObject) w_res = module.class_variables.get(name) if w_res is not None or module is self: module.class_variables.set(name, w_obj) if module is self: for descendant in self.descendants: descendant.remove_class_var(space, name) @jit.unroll_safe def find_class_var(self, space, name): w_res = self.class_variables.get(name) if w_res is None: ancestors = self.ancestors() for idx in xrange(1, len(ancestors)): module = ancestors[idx] assert isinstance(module, W_ModuleObject) w_res = module.class_variables.get(name) if w_res is not None: break return w_res @jit.unroll_safe def remove_class_var(self, space, name): self.class_variables.delete(name) for descendant in self.descendants: descendant.remove_class_var(space, name) def set_instance_var(self, space, name, w_value): return self.instance_variables.set(name, w_value) def find_instance_var(self, space, name): return self.instance_variables.get(name) or space.w_nil def ancestors(self, include_singleton=True, include_self=True): if include_self: return [self] + self.included_modules else: return self.included_modules[:] def is_ancestor_of(self, w_cls): if self is w_cls or self in w_cls.included_modules: return True elif w_cls.superclass is not None: return self.is_ancestor_of(w_cls.superclass) else: return False def include_module(self, space, w_mod): assert isinstance(w_mod, W_ModuleObject) if w_mod not in self.ancestors(): self.included_modules = [w_mod] + self.included_modules w_mod.included(space, self) def included(self, space, w_mod): self.descendants.append(w_mod) space.send(self, space.newsymbol("included"), [w_mod]) def inherited(self, space, w_mod): self.descendants.append(w_mod) if not space.bootstrap: space.send(self, space.newsymbol("inherited"), [w_mod]) def set_visibility(self, space, names_w, visibility): names = [space.symbol_w(w_name) for w_name in names_w] if names: for name in names: self.set_method_visibility(space, name, visibility) else: self.set_default_visibility(space, visibility) def set_default_visibility(self, space, visibility): pass def set_method_visibility(self, space, name, visibility): pass @classdef.method("to_s") def method_to_s(self, space): return space.newstr_fromstr(self.name) @classdef.method("include") def method_include(self, space, w_mod): space.send(w_mod, space.newsymbol("append_features"), [self]) @classdef.method("append_features") def method_append_features(self, space, w_mod): ancestors = self.ancestors() for idx in xrange(len(ancestors) - 1, -1, -1): w_mod.include_module(space, ancestors[idx]) @classdef.method("attr_accessor") def method_attr_accessor(self, space, args_w): self.method_attr_reader(space, args_w) for w_arg in args_w: varname = space.symbol_w(w_arg) self.define_method(space, varname + "=", AttributeWriter("@" + varname)) @classdef.method("attr_reader") def method_attr_reader(self, space, args_w): for w_arg in args_w: varname = space.symbol_w(w_arg) self.define_method(space, varname, AttributeReader("@" + varname)) @classdef.method("module_function", name="symbol") def method_module_function(self, space, name): self.attach_method(space, name, self._find_method_pure(space, name, self.version)) @classdef.method("private_class_method") def method_private_class_method(self, space, w_name): w_cls = self.getsingletonclass(space) return space.send(w_cls, space.newsymbol("private"), [w_name]) @classdef.method("public_class_method") def method_public_class_method(self, space, w_name): w_cls = self.getsingletonclass(space) return space.send(w_cls, space.newsymbol("public"), [w_name]) @classdef.method("alias_method", new_name="symbol", old_name="symbol") def method_alias_method(self, space, new_name, old_name): self.define_method(space, new_name, self.find_method(space, old_name)) @classdef.method("ancestors") def method_ancestors(self, space): return space.newarray(self.ancestors(include_singleton=False)) @classdef.method("inherited") def method_inherited(self, space, w_mod): pass @classdef.method("included") def method_included(self, space, w_mod): pass @classdef.method("name") def method_name(self, space): return space.newstr_fromstr(self.name) @classdef.method("private") def method_private(self, space, args_w): self.set_visibility(space, args_w, "private") @classdef.method("public") def method_public(self, space, args_w): self.set_visibility(space, args_w, "public") @classdef.method("protected") def method_protected(self, space, args_w): self.set_visibility(space, args_w, "protected") @classdef.method("constants") def method_constants(self, space): return space.newarray([space.newsymbol(n) for n in self.constants_w]) @classdef.method("const_missing", name="symbol") def method_const_missing(self, space, name): raise space.error(space.w_NameError, "uninitialized constant %s" % name) @classdef.method("class_eval", string="str", filename="str") @classdef.method("module_eval", string="str", filename="str") def method_module_eval(self, space, string=None, filename=None, w_lineno=None, block=None): if string is not None: if filename is None: filename = "module_eval" if w_lineno is not None: lineno = space.int_w(w_lineno) else: lineno = 1 return space.execute(string, self, self, filename, lineno) else: space.invoke_block(block.copy(w_self=self, w_scope=self), []) @classdef.method("const_defined?", const="str", inherit="bool") def method_const_definedp(self, space, const, inherit=True): if inherit: return space.newbool( self.find_inherited_const(space, const) is not None) else: return space.newbool( self._find_const_pure(const, self.version) is not None) @classdef.method("method_defined?", name="str") def method_method_definedp(self, space, name): return space.newbool(self.find_method(space, name) is not None) @classdef.method("===") def method_eqeqeq(self, space, w_obj): return space.newbool(self.is_ancestor_of(space.getclass(w_obj)))
def __init__(self): self.cache = SpaceCache(self) self.symbol_cache = {} self._executioncontext = None self.globals = CellDict() self.bootstrap = True self.exit_handlers_w = [] self.w_true = W_TrueObject(self) self.w_false = W_FalseObject(self) self.w_nil = W_NilObject(self) # Force the setup of a few key classes self.w_basicobject = self.getclassfor(W_BaseObject) self.w_object = self.getclassfor(W_Object) self.w_class = self.getclassfor(W_ClassObject) self.w_array = self.getclassfor(W_ArrayObject) self.w_proc = self.getclassfor(W_ProcObject) self.w_fixnum = self.getclassfor(W_FixnumObject) self.w_module = self.getclassfor(W_ModuleObject) self.w_string = self.getclassfor(W_StringObject) self.w_NoMethodError = self.getclassfor(W_NoMethodError) self.w_ArgumentError = self.getclassfor(W_ArgumentError) self.w_NameError = self.getclassfor(W_NameError) self.w_NotImplementedError = self.getclassfor(W_NotImplementedError) self.w_IndexError = self.getclassfor(W_IndexError) self.w_LoadError = self.getclassfor(W_LoadError) self.w_RangeError = self.getclassfor(W_RangeError) self.w_RuntimeError = self.getclassfor(W_RuntimeError) self.w_StopIteration = self.getclassfor(W_StopIteration) self.w_SyntaxError = self.getclassfor(W_SyntaxError) self.w_SystemCallError = self.getclassfor(W_SystemCallError) self.w_SystemExit = self.getclassfor(W_SystemExit) self.w_TypeError = self.getclassfor(W_TypeError) self.w_ZeroDivisionError = self.getclassfor(W_ZeroDivisionError) self.w_kernel = self.getmoduleobject(Kernel.moduledef) self.w_topaz = self.getmoduleobject(Topaz.moduledef) for w_cls in [ self.w_basicobject, self.w_object, self.w_array, self.w_proc, self.w_fixnum, self.w_string, self.w_class, self.w_module, self.w_NoMethodError, self.w_ArgumentError, self.w_TypeError, self.w_ZeroDivisionError, self.w_SystemExit, self.w_RangeError, self.w_RuntimeError, self.w_SystemCallError, self.w_LoadError, self.w_StopIteration, self.w_SyntaxError, self.w_kernel, self.w_topaz, self.getclassfor(W_NilObject), self.getclassfor(W_TrueObject), self.getclassfor(W_FalseObject), self.getclassfor(W_SymbolObject), self.getclassfor(W_NumericObject), self.getclassfor(W_HashObject), self.getclassfor(W_RangeObject), self.getclassfor(W_IOObject), self.getclassfor(W_FileObject), self.getclassfor(W_Dir), self.getclassfor(W_EncodingObject), self.getclassfor(W_RandomObject), self.getclassfor(W_ThreadObject), self.getclassfor(W_TimeObject), self.getclassfor(W_ExceptionObject), self.getclassfor(W_StandardError), self.getmoduleobject(Comparable.moduledef), self.getmoduleobject(Enumerable.moduledef), self.getmoduleobject(Math.moduledef), self.getmoduleobject(Process.moduledef), ]: self.set_const( self.w_object, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls ) for w_cls in [ self.getclassfor(W_EnvObject), self.getclassfor(W_HashIterator), ]: self.set_const( self.w_topaz, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls ) self.w_top_self = W_Object(self, self.w_object) # This is bootstrap. We have to delay sending until true, false and nil # are defined self.send(self.w_object, self.newsymbol("include"), [self.w_kernel]) self.bootstrap = False w_load_path = self.newarray([ self.newstr_fromstr( os.path.join(os.path.dirname(__file__), os.path.pardir, "lib-ruby") ) ]) self.globals.set("$LOAD_PATH", w_load_path) self.globals.set("$:", w_load_path) w_loaded_features = self.newarray([]) self.globals.set("$LOADED_FEATURES", w_loaded_features) self.globals.set('$"', w_loaded_features)
class ObjectSpace(object): def __init__(self): self.cache = SpaceCache(self) self.symbol_cache = {} self._executioncontext = None self.globals = CellDict() self.bootstrap = True self.exit_handlers_w = [] self.w_true = W_TrueObject(self) self.w_false = W_FalseObject(self) self.w_nil = W_NilObject(self) # Force the setup of a few key classes self.w_basicobject = self.getclassfor(W_BaseObject) self.w_object = self.getclassfor(W_Object) self.w_class = self.getclassfor(W_ClassObject) self.w_array = self.getclassfor(W_ArrayObject) self.w_proc = self.getclassfor(W_ProcObject) self.w_fixnum = self.getclassfor(W_FixnumObject) self.w_module = self.getclassfor(W_ModuleObject) self.w_string = self.getclassfor(W_StringObject) self.w_NoMethodError = self.getclassfor(W_NoMethodError) self.w_ArgumentError = self.getclassfor(W_ArgumentError) self.w_NameError = self.getclassfor(W_NameError) self.w_NotImplementedError = self.getclassfor(W_NotImplementedError) self.w_IndexError = self.getclassfor(W_IndexError) self.w_LoadError = self.getclassfor(W_LoadError) self.w_RangeError = self.getclassfor(W_RangeError) self.w_RuntimeError = self.getclassfor(W_RuntimeError) self.w_StopIteration = self.getclassfor(W_StopIteration) self.w_SyntaxError = self.getclassfor(W_SyntaxError) self.w_SystemCallError = self.getclassfor(W_SystemCallError) self.w_SystemExit = self.getclassfor(W_SystemExit) self.w_TypeError = self.getclassfor(W_TypeError) self.w_ZeroDivisionError = self.getclassfor(W_ZeroDivisionError) self.w_kernel = self.getmoduleobject(Kernel.moduledef) self.w_topaz = self.getmoduleobject(Topaz.moduledef) for w_cls in [ self.w_basicobject, self.w_object, self.w_array, self.w_proc, self.w_fixnum, self.w_string, self.w_class, self.w_module, self.w_NoMethodError, self.w_ArgumentError, self.w_TypeError, self.w_ZeroDivisionError, self.w_SystemExit, self.w_RangeError, self.w_RuntimeError, self.w_SystemCallError, self.w_LoadError, self.w_StopIteration, self.w_SyntaxError, self.w_kernel, self.w_topaz, self.getclassfor(W_NilObject), self.getclassfor(W_TrueObject), self.getclassfor(W_FalseObject), self.getclassfor(W_SymbolObject), self.getclassfor(W_NumericObject), self.getclassfor(W_HashObject), self.getclassfor(W_RangeObject), self.getclassfor(W_IOObject), self.getclassfor(W_FileObject), self.getclassfor(W_Dir), self.getclassfor(W_EncodingObject), self.getclassfor(W_RandomObject), self.getclassfor(W_ThreadObject), self.getclassfor(W_TimeObject), self.getclassfor(W_ExceptionObject), self.getclassfor(W_StandardError), self.getmoduleobject(Comparable.moduledef), self.getmoduleobject(Enumerable.moduledef), self.getmoduleobject(Math.moduledef), self.getmoduleobject(Process.moduledef), ]: self.set_const( self.w_object, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls ) for w_cls in [ self.getclassfor(W_EnvObject), self.getclassfor(W_HashIterator), ]: self.set_const( self.w_topaz, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls ) self.w_top_self = W_Object(self, self.w_object) # This is bootstrap. We have to delay sending until true, false and nil # are defined self.send(self.w_object, self.newsymbol("include"), [self.w_kernel]) self.bootstrap = False w_load_path = self.newarray([ self.newstr_fromstr( os.path.join(os.path.dirname(__file__), os.path.pardir, "lib-ruby") ) ]) self.globals.set("$LOAD_PATH", w_load_path) self.globals.set("$:", w_load_path) w_loaded_features = self.newarray([]) self.globals.set("$LOADED_FEATURES", w_loaded_features) self.globals.set('$"', w_loaded_features) def _freeze_(self): return True @specialize.memo() def fromcache(self, key): return self.cache.getorbuild(key) # Methods for dealing with source code. def parse(self, source, initial_lineno=1, symtable=None): if symtable is None: symtable = SymbolTable() parser = Parser(Lexer(source, initial_lineno=initial_lineno, symtable=symtable)) try: return parser.parse().getast() except ParsingError as e: raise self.error(self.w_SyntaxError, "line %d" % e.getsourcepos().lineno) except LexerError as e: raise self.error(self.w_SyntaxError, "line %d" % e.pos.lineno) def compile(self, source, filepath, initial_lineno=1): symtable = SymbolTable() astnode = self.parse(source, initial_lineno=initial_lineno, symtable=symtable) ctx = CompilerContext(self, "<main>", symtable, filepath) with ctx.set_lineno(initial_lineno): astnode.compile(ctx) return ctx.create_bytecode([], [], None, None) def execute(self, source, w_self=None, w_scope=None, filepath="-e", initial_lineno=1): bc = self.compile(source, filepath, initial_lineno=initial_lineno) frame = self.create_frame(bc, w_self=w_self, w_scope=w_scope) with self.getexecutioncontext().visit_frame(frame): return self.execute_frame(frame, bc) @jit.loop_invariant def getexecutioncontext(self): # When we have threads this should become a thread local. if self._executioncontext is None: self._executioncontext = ExecutionContext(self) return self._executioncontext def create_frame(self, bc, w_self=None, w_scope=None, block=None, parent_interp=None): if w_self is None: w_self = self.w_top_self if w_scope is None: w_scope = self.w_object return Frame(jit.promote(bc), w_self, w_scope, block, parent_interp) def execute_frame(self, frame, bc): return Interpreter().interpret(self, frame, bc) # Methods for allocating new objects. def newbool(self, boolvalue): if boolvalue: return self.w_true else: return self.w_false def newint(self, intvalue): return W_FixnumObject(self, intvalue) def newfloat(self, floatvalue): return W_FloatObject(self, floatvalue) @jit.elidable def newsymbol(self, symbol): try: w_sym = self.symbol_cache[symbol] except KeyError: w_sym = self.symbol_cache[symbol] = W_SymbolObject(self, symbol) return w_sym def newstr_fromchars(self, chars): return W_StringObject.newstr_fromchars(self, chars) def newstr_fromstr(self, strvalue): return W_StringObject.newstr_fromstr(self, strvalue) def newarray(self, items_w): return W_ArrayObject(self, items_w) def newhash(self): return W_HashObject(self) def newrange(self, w_start, w_end, exclusive): return W_RangeObject(self, w_start, w_end, exclusive) def newregexp(self, regexp): return W_RegexpObject(self, regexp) def newmodule(self, name): return W_ModuleObject(self, name, self.w_object) def newclass(self, name, superclass, is_singleton=False): return W_ClassObject(self, name, superclass, is_singleton=is_singleton) def newfunction(self, w_name, w_code): name = self.symbol_w(w_name) assert isinstance(w_code, W_CodeObject) return W_UserFunction(name, w_code) def newproc(self, block, is_lambda=False): return W_ProcObject(self, block, is_lambda) def int_w(self, w_obj): return w_obj.int_w(self) def float_w(self, w_obj): return w_obj.float_w(self) def symbol_w(self, w_obj): return w_obj.symbol_w(self) def str_w(self, w_obj): """Unpacks a string object as an rstr.""" return w_obj.str_w(self) def listview(self, w_obj): return w_obj.listview(self) # Methods for implementing the language semantics. def is_true(self, w_obj): return w_obj.is_true(self) def getclass(self, w_receiver): return w_receiver.getclass(self) def getsingletonclass(self, w_receiver): return w_receiver.getsingletonclass(self) def getscope(self, w_receiver): if isinstance(w_receiver, W_ModuleObject): return w_receiver else: return self.getclass(w_receiver) @jit.unroll_safe def getnonsingletonclass(self, w_receiver): cls = self.getclass(w_receiver) while cls.is_singleton: cls = cls.superclass return cls def getclassfor(self, cls): return self.getclassobject(cls.classdef) def getclassobject(self, classdef): return self.fromcache(ClassCache).getorbuild(classdef) def getmoduleobject(self, moduledef): return self.fromcache(ModuleCache).getorbuild(moduledef) def find_const(self, w_module, name): w_obj = w_module.find_const(self, name) if w_obj is None: w_obj = self.send(w_module, self.newsymbol("const_missing"), [self.newsymbol(name)]) return w_obj def set_const(self, module, name, w_value): module.set_const(self, name, w_value) def set_lexical_scope(self, module, scope): module.set_lexical_scope(self, scope) def find_instance_var(self, w_obj, name): w_res = w_obj.find_instance_var(self, name) return w_res if w_res is not None else self.w_nil def set_instance_var(self, w_obj, name, w_value): w_obj.set_instance_var(self, name, w_value) def find_class_var(self, w_module, name): return w_module.find_class_var(self, name) def set_class_var(self, w_module, name, w_value): w_module.set_class_var(self, name, w_value) def send(self, w_receiver, w_method, args_w=None, block=None): if args_w is None: args_w = [] name = self.symbol_w(w_method) w_cls = self.getclass(w_receiver) raw_method = w_cls.find_method(self, name) return self._send_raw(w_method, raw_method, w_receiver, w_cls, args_w, block) def send_super(self, w_cls, w_receiver, w_method, args_w, block=None): name = self.symbol_w(w_method) raw_method = w_cls.find_method_super(self, name) return self._send_raw(w_method, raw_method, w_receiver, w_cls, args_w, block) def _send_raw(self, w_method, raw_method, w_receiver, w_cls, args_w, block): if raw_method is None: method_missing = w_cls.find_method(self, "method_missing") assert method_missing is not None args_w.insert(0, w_method) return method_missing.call(self, w_receiver, args_w, block) return raw_method.call(self, w_receiver, args_w, block) def respond_to(self, w_receiver, w_method): name = self.symbol_w(w_method) w_cls = self.getclass(w_receiver) raw_method = w_cls.find_method(self, name) return raw_method is not None @jit.unroll_safe def invoke_block(self, block, args_w): bc = block.bytecode frame = self.create_frame( bc, w_self=block.w_self, w_scope=block.w_scope, block=block.block, parent_interp=block.parent_interp, ) if (len(args_w) == 1 and isinstance(args_w[0], W_ArrayObject) and len(bc.arg_locs) >= 2): w_arg = args_w[0] assert isinstance(w_arg, W_ArrayObject) args_w = w_arg.items_w if len(bc.arg_locs) != 0: frame.handle_block_args(self, bc, args_w, None) assert len(block.cells) == len(bc.freevars) for idx, cell in enumerate(block.cells): frame.cells[len(bc.cellvars) + idx] = cell with self.getexecutioncontext().visit_frame(frame): return self.execute_frame(frame, bc) def error(self, w_type, msg="", optargs=None): if not optargs: optargs = [] w_new_sym = self.newsymbol("new") args_w = [self.newstr_fromstr(msg)] + optargs w_exc = self.send(w_type, w_new_sym, args_w) assert isinstance(w_exc, W_ExceptionObject) return RubyError(w_exc) def hash_w(self, w_obj): return self.int_w(self.send(w_obj, self.newsymbol("hash"))) def eq_w(self, w_obj1, w_obj2): return self.is_true(self.send(w_obj1, self.newsymbol("=="), [w_obj2])) def register_exit_handler(self, w_proc): self.exit_handlers_w.append(w_proc) def run_exit_handlers(self): while self.exit_handlers_w: w_proc = self.exit_handlers_w.pop() try: self.send(w_proc, self.newsymbol("call")) except RubyError as e: print_traceback(self, e.w_value) def subscript_access(self, length, w_idx, w_count): inclusive = False as_range = False end = 0 if isinstance(w_idx, W_RangeObject) and not w_count: start = self.int_w(self.convert_type(w_idx.w_start, self.w_fixnum, "to_int")) end = self.int_w(self.convert_type(w_idx.w_end, self.w_fixnum, "to_int")) inclusive = not w_idx.exclusive as_range = True else: start = self.int_w(self.convert_type(w_idx, self.w_fixnum, "to_int")) if w_count: end = self.int_w(self.convert_type(w_count, self.w_fixnum, "to_int")) if end >= 0: as_range = True if start < 0: start += length if as_range: if w_count: end += start if end < 0: end += length if inclusive: end += 1 if end < start: end = start elif end > length: end = length nil = ((not as_range and start >= length) or start < 0 or end < 0 or (start > 0 and start > length)) return (start, end, as_range, nil) def convert_type(self, w_obj, w_cls, method, raise_error=True): if w_obj.is_kind_of(self, w_cls): return w_obj try: w_res = self.send(w_obj, self.newsymbol(method)) except RubyError: src_cls = self.getclass(w_obj).name raise self.error( self.w_TypeError, "can't convert %s into %s" % (src_cls, w_cls.name) ) if not w_res or w_res is self.w_nil and not raise_error: return self.w_nil elif not w_res.is_kind_of(self, w_cls): src_cls = self.getclass(w_obj).name res_cls = self.getclass(w_res).name raise self.error(self.w_TypeError, "can't convert %s to %s (%s#%s gives %s)" % ( src_cls, w_cls.name, src_cls, method, res_cls ) ) else: return w_res
def __init__(self): self.cache = SpaceCache(self) self.symbol_cache = {} self._executioncontext = None self.globals = CellDict() self.bootstrap = True self.exit_handlers_w = [] self.w_true = W_TrueObject(self) self.w_false = W_FalseObject(self) self.w_nil = W_NilObject(self) # Force the setup of a few key classes self.w_basicobject = self.getclassfor(W_BaseObject) self.w_object = self.getclassfor(W_Object) self.w_class = self.getclassfor(W_ClassObject) self.w_array = self.getclassfor(W_ArrayObject) self.w_proc = self.getclassfor(W_ProcObject) self.w_fixnum = self.getclassfor(W_FixnumObject) self.w_module = self.getclassfor(W_ModuleObject) self.w_string = self.getclassfor(W_StringObject) self.w_NoMethodError = self.getclassfor(W_NoMethodError) self.w_ArgumentError = self.getclassfor(W_ArgumentError) self.w_NameError = self.getclassfor(W_NameError) self.w_NotImplementedError = self.getclassfor(W_NotImplementedError) self.w_IndexError = self.getclassfor(W_IndexError) self.w_LoadError = self.getclassfor(W_LoadError) self.w_RangeError = self.getclassfor(W_RangeError) self.w_RuntimeError = self.getclassfor(W_RuntimeError) self.w_StopIteration = self.getclassfor(W_StopIteration) self.w_SyntaxError = self.getclassfor(W_SyntaxError) self.w_SystemCallError = self.getclassfor(W_SystemCallError) self.w_SystemExit = self.getclassfor(W_SystemExit) self.w_TypeError = self.getclassfor(W_TypeError) self.w_ZeroDivisionError = self.getclassfor(W_ZeroDivisionError) self.w_kernel = self.getmoduleobject(Kernel.moduledef) self.w_topaz = self.getmoduleobject(Topaz.moduledef) for w_cls in [ self.w_basicobject, self.w_object, self.w_array, self.w_proc, self.w_fixnum, self.w_string, self.w_class, self.w_module, self.w_NoMethodError, self.w_ArgumentError, self.w_TypeError, self.w_ZeroDivisionError, self.w_SystemExit, self.w_RangeError, self.w_RuntimeError, self.w_SystemCallError, self.w_LoadError, self.w_StopIteration, self.w_SyntaxError, self.w_kernel, self.w_topaz, self.getclassfor(W_NilObject), self.getclassfor(W_TrueObject), self.getclassfor(W_FalseObject), self.getclassfor(W_SymbolObject), self.getclassfor(W_NumericObject), self.getclassfor(W_HashObject), self.getclassfor(W_RangeObject), self.getclassfor(W_IOObject), self.getclassfor(W_FileObject), self.getclassfor(W_Dir), self.getclassfor(W_EncodingObject), self.getclassfor(W_RandomObject), self.getclassfor(W_ThreadObject), self.getclassfor(W_TimeObject), self.getclassfor(W_ExceptionObject), self.getclassfor(W_StandardError), self.getmoduleobject(Comparable.moduledef), self.getmoduleobject(Enumerable.moduledef), self.getmoduleobject(Math.moduledef), self.getmoduleobject(Process.moduledef), ]: self.set_const( self.w_object, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls) for w_cls in [ self.getclassfor(W_EnvObject), self.getclassfor(W_HashIterator), ]: self.set_const( self.w_topaz, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls) self.w_top_self = W_Object(self, self.w_object) # This is bootstrap. We have to delay sending until true, false and nil # are defined self.send(self.w_object, self.newsymbol("include"), [self.w_kernel]) self.bootstrap = False w_load_path = self.newarray([ self.newstr_fromstr( os.path.join(os.path.dirname(__file__), os.path.pardir, "lib-ruby")) ]) self.globals.set("$LOAD_PATH", w_load_path) self.globals.set("$:", w_load_path) w_loaded_features = self.newarray([]) self.globals.set("$LOADED_FEATURES", w_loaded_features) self.globals.set('$"', w_loaded_features)
class ObjectSpace(object): def __init__(self): self.cache = SpaceCache(self) self.symbol_cache = {} self._executioncontext = None self.globals = CellDict() self.bootstrap = True self.exit_handlers_w = [] self.w_true = W_TrueObject(self) self.w_false = W_FalseObject(self) self.w_nil = W_NilObject(self) # Force the setup of a few key classes self.w_basicobject = self.getclassfor(W_BaseObject) self.w_object = self.getclassfor(W_Object) self.w_class = self.getclassfor(W_ClassObject) self.w_array = self.getclassfor(W_ArrayObject) self.w_proc = self.getclassfor(W_ProcObject) self.w_fixnum = self.getclassfor(W_FixnumObject) self.w_module = self.getclassfor(W_ModuleObject) self.w_string = self.getclassfor(W_StringObject) self.w_NoMethodError = self.getclassfor(W_NoMethodError) self.w_ArgumentError = self.getclassfor(W_ArgumentError) self.w_NameError = self.getclassfor(W_NameError) self.w_NotImplementedError = self.getclassfor(W_NotImplementedError) self.w_IndexError = self.getclassfor(W_IndexError) self.w_LoadError = self.getclassfor(W_LoadError) self.w_RangeError = self.getclassfor(W_RangeError) self.w_RuntimeError = self.getclassfor(W_RuntimeError) self.w_StopIteration = self.getclassfor(W_StopIteration) self.w_SyntaxError = self.getclassfor(W_SyntaxError) self.w_SystemCallError = self.getclassfor(W_SystemCallError) self.w_SystemExit = self.getclassfor(W_SystemExit) self.w_TypeError = self.getclassfor(W_TypeError) self.w_ZeroDivisionError = self.getclassfor(W_ZeroDivisionError) self.w_kernel = self.getmoduleobject(Kernel.moduledef) self.w_topaz = self.getmoduleobject(Topaz.moduledef) for w_cls in [ self.w_basicobject, self.w_object, self.w_array, self.w_proc, self.w_fixnum, self.w_string, self.w_class, self.w_module, self.w_NoMethodError, self.w_ArgumentError, self.w_TypeError, self.w_ZeroDivisionError, self.w_SystemExit, self.w_RangeError, self.w_RuntimeError, self.w_SystemCallError, self.w_LoadError, self.w_StopIteration, self.w_SyntaxError, self.w_kernel, self.w_topaz, self.getclassfor(W_NilObject), self.getclassfor(W_TrueObject), self.getclassfor(W_FalseObject), self.getclassfor(W_SymbolObject), self.getclassfor(W_NumericObject), self.getclassfor(W_HashObject), self.getclassfor(W_RangeObject), self.getclassfor(W_IOObject), self.getclassfor(W_FileObject), self.getclassfor(W_Dir), self.getclassfor(W_EncodingObject), self.getclassfor(W_RandomObject), self.getclassfor(W_ThreadObject), self.getclassfor(W_TimeObject), self.getclassfor(W_ExceptionObject), self.getclassfor(W_StandardError), self.getmoduleobject(Comparable.moduledef), self.getmoduleobject(Enumerable.moduledef), self.getmoduleobject(Math.moduledef), self.getmoduleobject(Process.moduledef), ]: self.set_const( self.w_object, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls) for w_cls in [ self.getclassfor(W_EnvObject), self.getclassfor(W_HashIterator), ]: self.set_const( self.w_topaz, self.str_w(self.send(w_cls, self.newsymbol("name"))), w_cls) self.w_top_self = W_Object(self, self.w_object) # This is bootstrap. We have to delay sending until true, false and nil # are defined self.send(self.w_object, self.newsymbol("include"), [self.w_kernel]) self.bootstrap = False w_load_path = self.newarray([ self.newstr_fromstr( os.path.join(os.path.dirname(__file__), os.path.pardir, "lib-ruby")) ]) self.globals.set("$LOAD_PATH", w_load_path) self.globals.set("$:", w_load_path) w_loaded_features = self.newarray([]) self.globals.set("$LOADED_FEATURES", w_loaded_features) self.globals.set('$"', w_loaded_features) def _freeze_(self): return True @specialize.memo() def fromcache(self, key): return self.cache.getorbuild(key) # Methods for dealing with source code. def parse(self, source, initial_lineno=1, symtable=None): if symtable is None: symtable = SymbolTable() parser = Parser( Lexer(source, initial_lineno=initial_lineno, symtable=symtable)) try: return parser.parse().getast() except ParsingError as e: raise self.error(self.w_SyntaxError, "line %d" % e.getsourcepos().lineno) except LexerError as e: raise self.error(self.w_SyntaxError, "line %d" % e.pos.lineno) def compile(self, source, filepath, initial_lineno=1): symtable = SymbolTable() astnode = self.parse(source, initial_lineno=initial_lineno, symtable=symtable) ctx = CompilerContext(self, "<main>", symtable, filepath) with ctx.set_lineno(initial_lineno): astnode.compile(ctx) return ctx.create_bytecode([], [], None, None) def execute(self, source, w_self=None, w_scope=None, filepath="-e", initial_lineno=1): bc = self.compile(source, filepath, initial_lineno=initial_lineno) frame = self.create_frame(bc, w_self=w_self, w_scope=w_scope) with self.getexecutioncontext().visit_frame(frame): return self.execute_frame(frame, bc) @jit.loop_invariant def getexecutioncontext(self): # When we have threads this should become a thread local. if self._executioncontext is None: self._executioncontext = ExecutionContext(self) return self._executioncontext def create_frame(self, bc, w_self=None, w_scope=None, block=None, parent_interp=None): if w_self is None: w_self = self.w_top_self if w_scope is None: w_scope = self.w_object return Frame(jit.promote(bc), w_self, w_scope, block, parent_interp) def execute_frame(self, frame, bc): return Interpreter().interpret(self, frame, bc) # Methods for allocating new objects. def newbool(self, boolvalue): if boolvalue: return self.w_true else: return self.w_false def newint(self, intvalue): return W_FixnumObject(self, intvalue) def newfloat(self, floatvalue): return W_FloatObject(self, floatvalue) @jit.elidable def newsymbol(self, symbol): try: w_sym = self.symbol_cache[symbol] except KeyError: w_sym = self.symbol_cache[symbol] = W_SymbolObject(self, symbol) return w_sym def newstr_fromchars(self, chars): return W_StringObject.newstr_fromchars(self, chars) def newstr_fromstr(self, strvalue): return W_StringObject.newstr_fromstr(self, strvalue) def newarray(self, items_w): return W_ArrayObject(self, items_w) def newhash(self): return W_HashObject(self) def newrange(self, w_start, w_end, exclusive): return W_RangeObject(self, w_start, w_end, exclusive) def newregexp(self, regexp): return W_RegexpObject(self, regexp) def newmodule(self, name): return W_ModuleObject(self, name, self.w_object) def newclass(self, name, superclass, is_singleton=False): return W_ClassObject(self, name, superclass, is_singleton=is_singleton) def newfunction(self, w_name, w_code): name = self.symbol_w(w_name) assert isinstance(w_code, W_CodeObject) return W_UserFunction(name, w_code) def newproc(self, block, is_lambda=False): return W_ProcObject(self, block, is_lambda) def int_w(self, w_obj): return w_obj.int_w(self) def float_w(self, w_obj): return w_obj.float_w(self) def symbol_w(self, w_obj): return w_obj.symbol_w(self) def str_w(self, w_obj): """Unpacks a string object as an rstr.""" return w_obj.str_w(self) def listview(self, w_obj): return w_obj.listview(self) # Methods for implementing the language semantics. def is_true(self, w_obj): return w_obj.is_true(self) def getclass(self, w_receiver): return w_receiver.getclass(self) def getsingletonclass(self, w_receiver): return w_receiver.getsingletonclass(self) def getscope(self, w_receiver): if isinstance(w_receiver, W_ModuleObject): return w_receiver else: return self.getclass(w_receiver) @jit.unroll_safe def getnonsingletonclass(self, w_receiver): cls = self.getclass(w_receiver) while cls.is_singleton: cls = cls.superclass return cls def getclassfor(self, cls): return self.getclassobject(cls.classdef) def getclassobject(self, classdef): return self.fromcache(ClassCache).getorbuild(classdef) def getmoduleobject(self, moduledef): return self.fromcache(ModuleCache).getorbuild(moduledef) def find_const(self, w_module, name): w_obj = w_module.find_const(self, name) if w_obj is None: w_obj = self.send(w_module, self.newsymbol("const_missing"), [self.newsymbol(name)]) return w_obj def set_const(self, module, name, w_value): module.set_const(self, name, w_value) def set_lexical_scope(self, module, scope): module.set_lexical_scope(self, scope) def find_instance_var(self, w_obj, name): w_res = w_obj.find_instance_var(self, name) return w_res if w_res is not None else self.w_nil def set_instance_var(self, w_obj, name, w_value): w_obj.set_instance_var(self, name, w_value) def find_class_var(self, w_module, name): return w_module.find_class_var(self, name) def set_class_var(self, w_module, name, w_value): w_module.set_class_var(self, name, w_value) def send(self, w_receiver, w_method, args_w=None, block=None): if args_w is None: args_w = [] name = self.symbol_w(w_method) w_cls = self.getclass(w_receiver) raw_method = w_cls.find_method(self, name) return self._send_raw(w_method, raw_method, w_receiver, w_cls, args_w, block) def send_super(self, w_cls, w_receiver, w_method, args_w, block=None): name = self.symbol_w(w_method) raw_method = w_cls.find_method_super(self, name) return self._send_raw(w_method, raw_method, w_receiver, w_cls, args_w, block) def _send_raw(self, w_method, raw_method, w_receiver, w_cls, args_w, block): if raw_method is None: method_missing = w_cls.find_method(self, "method_missing") assert method_missing is not None args_w.insert(0, w_method) return method_missing.call(self, w_receiver, args_w, block) return raw_method.call(self, w_receiver, args_w, block) def respond_to(self, w_receiver, w_method): name = self.symbol_w(w_method) w_cls = self.getclass(w_receiver) raw_method = w_cls.find_method(self, name) return raw_method is not None @jit.unroll_safe def invoke_block(self, block, args_w): bc = block.bytecode frame = self.create_frame( bc, w_self=block.w_self, w_scope=block.w_scope, block=block.block, parent_interp=block.parent_interp, ) if (len(args_w) == 1 and isinstance(args_w[0], W_ArrayObject) and len(bc.arg_locs) >= 2): w_arg = args_w[0] assert isinstance(w_arg, W_ArrayObject) args_w = w_arg.items_w if len(bc.arg_locs) != 0: frame.handle_block_args(self, bc, args_w, None) assert len(block.cells) == len(bc.freevars) for idx, cell in enumerate(block.cells): frame.cells[len(bc.cellvars) + idx] = cell with self.getexecutioncontext().visit_frame(frame): return self.execute_frame(frame, bc) def error(self, w_type, msg="", optargs=None): if not optargs: optargs = [] w_new_sym = self.newsymbol("new") args_w = [self.newstr_fromstr(msg)] + optargs w_exc = self.send(w_type, w_new_sym, args_w) assert isinstance(w_exc, W_ExceptionObject) return RubyError(w_exc) def hash_w(self, w_obj): return self.int_w(self.send(w_obj, self.newsymbol("hash"))) def eq_w(self, w_obj1, w_obj2): return self.is_true(self.send(w_obj1, self.newsymbol("=="), [w_obj2])) def register_exit_handler(self, w_proc): self.exit_handlers_w.append(w_proc) def run_exit_handlers(self): while self.exit_handlers_w: w_proc = self.exit_handlers_w.pop() try: self.send(w_proc, self.newsymbol("call")) except RubyError as e: print_traceback(self, e.w_value) def subscript_access(self, length, w_idx, w_count): inclusive = False as_range = False end = 0 if isinstance(w_idx, W_RangeObject) and not w_count: start = self.int_w( self.convert_type(w_idx.w_start, self.w_fixnum, "to_int")) end = self.int_w( self.convert_type(w_idx.w_end, self.w_fixnum, "to_int")) inclusive = not w_idx.exclusive as_range = True else: start = self.int_w( self.convert_type(w_idx, self.w_fixnum, "to_int")) if w_count: end = self.int_w( self.convert_type(w_count, self.w_fixnum, "to_int")) if end >= 0: as_range = True if start < 0: start += length if as_range: if w_count: end += start if end < 0: end += length if inclusive: end += 1 if end < start: end = start elif end > length: end = length nil = ((not as_range and start >= length) or start < 0 or end < 0 or (start > 0 and start > length)) return (start, end, as_range, nil) def convert_type(self, w_obj, w_cls, method, raise_error=True): if w_obj.is_kind_of(self, w_cls): return w_obj try: w_res = self.send(w_obj, self.newsymbol(method)) except RubyError: src_cls = self.getclass(w_obj).name raise self.error( self.w_TypeError, "can't convert %s into %s" % (src_cls, w_cls.name)) if not w_res or w_res is self.w_nil and not raise_error: return self.w_nil elif not w_res.is_kind_of(self, w_cls): src_cls = self.getclass(w_obj).name res_cls = self.getclass(w_res).name raise self.error( self.w_TypeError, "can't convert %s to %s (%s#%s gives %s)" % (src_cls, w_cls.name, src_cls, method, res_cls)) else: return w_res
class W_ModuleObject(W_RootObject): _immutable_fields_ = [ "version?", "included_modules?[*]", "lexical_scope?", "klass?" ] classdef = ClassDef("Module", W_RootObject.classdef) def __init__(self, space, name, superclass): self.name = name self.klass = None self.superclass = superclass self.version = VersionTag() self.methods_w = {} self.constants_w = {} self.class_variables = CellDict() self.instance_variables = CellDict() self.lexical_scope = None self.included_modules = [] self.descendants = [] def __deepcopy__(self, memo): obj = super(W_ModuleObject, self).__deepcopy__(memo) obj.name = self.name obj.klass = copy.deepcopy(self.klass, memo) obj.superclass = copy.deepcopy(self.superclass, memo) obj.version = copy.deepcopy(self.version, memo) obj.methods_w = copy.deepcopy(self.methods_w, memo) obj.constants_w = copy.deepcopy(self.constants_w, memo) obj.class_variables = copy.deepcopy(self.class_variables, memo) obj.instance_variables = copy.deepcopy(self.instance_variables, memo) obj.lexical_scope = copy.deepcopy(self.lexical_scope, memo) obj.included_modules = copy.deepcopy(self.included_modules, memo) obj.descendants = copy.deepcopy(self.descendants, memo) return obj def getclass(self, space): if self.klass is not None: return self.klass return W_RootObject.getclass(self, space) def getsingletonclass(self, space): if self.klass is None: self.klass = space.newclass( "#<Class:%s>" % self.name, space.w_module, is_singleton=True ) return self.klass def mutated(self): self.version = VersionTag() def define_method(self, space, name, method): self.mutated() self.methods_w[name] = method @jit.unroll_safe def find_method(self, space, name): method = self._find_method_pure(space, name, self.version) if method is None: for module in self.included_modules: method = module.find_method(space, name) if method is not None: return method return method @jit.unroll_safe def find_method_super(self, space, name): for module in self.included_modules: method = module.find_method(space, name) if method is not None: return method return None @jit.elidable def _find_method_pure(self, space, method, version): return self.methods_w.get(method, None) def set_lexical_scope(self, space, w_mod): self.lexical_scope = w_mod def set_const(self, space, name, w_obj): self.mutated() self.constants_w[name] = w_obj def find_const(self, space, name): res = self._find_const_pure(name, self.version) if res is None and self.lexical_scope is not None: res = self.lexical_scope.find_lexical_const(space, name) if res is None and self.superclass is not None: res = self.superclass.find_inherited_const(space, name) return res def find_lexical_const(self, space, name): res = self._find_const_pure(name, self.version) if res is None and self.lexical_scope is not None: return self.lexical_scope.find_lexical_const(space, name) return res def find_inherited_const(self, space, name): res = self._find_const_pure(name, self.version) if res is None and self.superclass is not None: return self.superclass.find_inherited_const(space, name) return res def find_local_const(self, space, name): return self._find_const_pure(name, self.version) @jit.elidable def _find_const_pure(self, name, version): return self.constants_w.get(name, None) @jit.unroll_safe def set_class_var(self, space, name, w_obj): ancestors = self.ancestors() for idx in xrange(len(ancestors) - 1, -1, -1): module = ancestors[idx] assert isinstance(module, W_ModuleObject) w_res = module.class_variables.get(name) if w_res is not None or module is self: module.class_variables.set(name, w_obj) if module is self: for descendant in self.descendants: descendant.remove_class_var(space, name) @jit.unroll_safe def find_class_var(self, space, name): w_res = self.class_variables.get(name) if w_res is None: ancestors = self.ancestors() for idx in xrange(1, len(ancestors)): module = ancestors[idx] assert isinstance(module, W_ModuleObject) w_res = module.class_variables.get(name) if w_res is not None: break return w_res @jit.unroll_safe def remove_class_var(self, space, name): self.class_variables.delete(name) for descendant in self.descendants: descendant.remove_class_var(space, name) def set_instance_var(self, space, name, w_value): return self.instance_variables.set(name, w_value) def find_instance_var(self, space, name): return self.instance_variables.get(name) or space.w_nil def ancestors(self, include_singleton=True, include_self=True): if include_self: return [self] + self.included_modules else: return self.included_modules[:] def is_ancestor_of(self, w_cls): if self is w_cls or self in w_cls.included_modules: return True elif w_cls.superclass is not None: return self.is_ancestor_of(w_cls.superclass) else: return False def include_module(self, space, w_mod): assert isinstance(w_mod, W_ModuleObject) if w_mod not in self.ancestors(): self.included_modules = [w_mod] + self.included_modules w_mod.included(space, self) def included(self, space, w_mod): self.descendants.append(w_mod) space.send(self, space.newsymbol("included"), [w_mod]) def inherited(self, space, w_mod): self.descendants.append(w_mod) if not space.bootstrap: space.send(self, space.newsymbol("inherited"), [w_mod]) def set_visibility(self, space, names_w, visibility): names = [space.symbol_w(w_name) for w_name in names_w] if names: for name in names: self.set_method_visibility(space, name, visibility) else: self.set_default_visibility(space, visibility) def set_default_visibility(self, space, visibility): pass def set_method_visibility(self, space, name, visibility): pass @classdef.method("to_s") def method_to_s(self, space): return space.newstr_fromstr(self.name) @classdef.method("include") def method_include(self, space, w_mod): space.send(w_mod, space.newsymbol("append_features"), [self]) @classdef.method("append_features") def method_append_features(self, space, w_mod): ancestors = self.ancestors() for idx in xrange(len(ancestors) - 1, -1, -1): w_mod.include_module(space, ancestors[idx]) @classdef.method("attr_accessor") def method_attr_accessor(self, space, args_w): self.method_attr_reader(space, args_w) for w_arg in args_w: varname = space.symbol_w(w_arg) self.define_method(space, varname + "=", AttributeWriter("@" + varname)) @classdef.method("attr_reader") def method_attr_reader(self, space, args_w): for w_arg in args_w: varname = space.symbol_w(w_arg) self.define_method(space, varname, AttributeReader("@" + varname)) @classdef.method("module_function", name="symbol") def method_module_function(self, space, name): self.attach_method(space, name, self._find_method_pure(space, name, self.version)) @classdef.method("private_class_method") def method_private_class_method(self, space, w_name): w_cls = self.getsingletonclass(space) return space.send(w_cls, space.newsymbol("private"), [w_name]) @classdef.method("public_class_method") def method_public_class_method(self, space, w_name): w_cls = self.getsingletonclass(space) return space.send(w_cls, space.newsymbol("public"), [w_name]) @classdef.method("alias_method", new_name="symbol", old_name="symbol") def method_alias_method(self, space, new_name, old_name): self.define_method(space, new_name, self.find_method(space, old_name)) @classdef.method("ancestors") def method_ancestors(self, space): return space.newarray(self.ancestors(include_singleton=False)) @classdef.method("inherited") def method_inherited(self, space, w_mod): pass @classdef.method("included") def method_included(self, space, w_mod): pass @classdef.method("name") def method_name(self, space): return space.newstr_fromstr(self.name) @classdef.method("private") def method_private(self, space, args_w): self.set_visibility(space, args_w, "private") @classdef.method("public") def method_public(self, space, args_w): self.set_visibility(space, args_w, "public") @classdef.method("protected") def method_protected(self, space, args_w): self.set_visibility(space, args_w, "protected") @classdef.method("constants") def method_constants(self, space): return space.newarray([space.newsymbol(n) for n in self.constants_w]) @classdef.method("const_missing", name="symbol") def method_const_missing(self, space, name): raise space.error(space.w_NameError, "uninitialized constant %s" % name) @classdef.method("class_eval", string="str", filename="str") @classdef.method("module_eval", string="str", filename="str") def method_module_eval(self, space, string=None, filename=None, w_lineno=None, block=None): if string is not None: if filename is None: filename = "module_eval" if w_lineno is not None: lineno = space.int_w(w_lineno) else: lineno = 1 return space.execute(string, self, self, filename, lineno) else: space.invoke_block(block.copy(w_self=self, w_scope=self), []) @classdef.method("const_defined?", const="str", inherit="bool") def method_const_definedp(self, space, const, inherit=True): if inherit: return space.newbool(self.find_inherited_const(space, const) is not None) else: return space.newbool(self._find_const_pure(const, self.version) is not None) @classdef.method("method_defined?", name="str") def method_method_definedp(self, space, name): return space.newbool(self.find_method(space, name) is not None) @classdef.method("===") def method_eqeqeq(self, space, w_obj): return space.newbool(self.is_ancestor_of(space.getclass(w_obj)))