std::string LLVMState::enclosure_name(CompiledMethod* cm) { StaticScope* ss = cm->scope(); if(!kind_of<StaticScope>(ss) || !kind_of<Module>(ss->module())) { return "ANONYMOUS"; } return symbol_debug_str(ss->module()->name()); }
Object* rbx_add_scope(STATE, CallFrame* call_frame, Object* top) { Module* mod = as<Module>(top); StaticScope* scope = StaticScope::create(state); scope->module(state, mod); scope->parent(state, call_frame->static_scope()); call_frame->cm->scope(state, scope); // call_frame->static_scope_ = scope; return Qnil; }
void attach_method(STATE, CallFrame* call_frame, Object* recv, Symbol* name, CompiledMethod* method) { if(Module* mod = try_as<Module>(recv)) { StaticScope* ss = StaticScope::create(state); ss->module(state, mod); ss->parent(state, method->scope()); method->scope(state, ss); } else { /* Push the current scope down. */ method->scope(state, call_frame->static_scope()); } add_method(state, call_frame, recv->metaclass(state), name, method); }
Object* const_missing(STATE, Symbol* sym, CallFrame* call_frame) { Module* under; StaticScope* scope = call_frame->static_scope(); if(scope->nil_p()) { under = G(object); } else { under = scope->module(); } Array* args = Array::create(state, 1); args->set(state, 0, sym); return under->send(state, call_frame, G(sym_const_missing), args); }
CompiledMethod* CompiledMethod::generate_tramp(STATE, size_t stack_size) { CompiledMethod* cm = CompiledMethod::create(state); cm->stack_size(state, Fixnum::from(stack_size)); cm->required_args(state, Fixnum::from(0)); cm->total_args(state, cm->required_args()); cm->name(state, state->symbol("__halt__")); cm->iseq(state, InstructionSequence::create(state, 1)); cm->iseq()->opcodes()->put(state, 0, Fixnum::from(InstructionSequence::insn_halt)); StaticScope* ss = StaticScope::create(state); ss->module(state, G(object)); cm->scope(state, ss); cm->formalize(state, false); return cm; }
Object* const_get(STATE, CallFrame* call_frame, Symbol* name, bool* found) { StaticScope *cur; Object* result; *found = false; call_frame = call_frame->top_ruby_frame(); // Ok, this has to be explained or it will be considered black magic. // The scope chain always ends with an entry at the top that contains // a parent of nil, and a module of Object. This entry is put in // regardless of lexical scoping, it's the default scope. // // When looking up a constant, we don't want to consider the default // scope (ie, Object) initially because we need to lookup up // the superclass chain first, because falling back on the default. // // The rub comes from the fact that if a user explicitly opens up // Object in their code, we DO consider it. Like: // // class Idiot // A = 2 // end // // class ::Object // A = 1 // class Stupid < Idiot // def foo // p A // end // end // end // // In this code, when A is looked up, Object must be considering during // the scope walk, NOT during the superclass walk. // // So, in this case, foo would print "1", not "2". // cur = call_frame->static_scope(); while(!cur->nil_p()) { // Detect the toplevel scope (the default) and get outta dodge. if(cur->top_level_p(state)) break; result = cur->module()->get_const(state, name, found); if(*found) return result; cur = cur->parent(); } // Now look up the superclass chain. cur = call_frame->static_scope(); if(!cur->nil_p()) { Module* mod = cur->module(); while(!mod->nil_p()) { result = mod->get_const(state, name, found); if(*found) return result; mod = mod->superclass(); } } // Lastly, check Object specifically result = G(object)->get_const(state, name, found, true); if(*found) return result; return Qnil; }