bool HierarchyResolver::resolve(STATE, Dispatch& msg, LookupData& lookup) { Module* module = lookup.from; Object* entry; MethodVisibility* vis; do { entry = module->method_table()->fetch(state, msg.name); /* Nothing, there? Ok, keep looking. */ if(entry->nil_p()) goto keep_looking; /* A 'false' method means to terminate method lookup. * (eg. undef_method) */ if(entry == Qfalse) return false; vis = try_as<MethodVisibility>(entry); /* If this was a private send, then we can handle use * any method seen. */ if(lookup.priv) { /* nil means that the actual method object is 'up' from here */ if(vis && vis->method()->nil_p()) goto keep_looking; msg.method = as<Executable>(vis ? vis->method() : entry); msg.module = module; break; } else if(vis) { /* The method is private, but this wasn't a private send. */ if(vis->private_p(state)) { return false; } else if(vis->protected_p(state)) { /* The method is protected, but it's not being called from * the same module */ if(!lookup.recv->kind_of_p(state, module)) { return false; } } /* The method was callable, but we need to keep looking * for the implementation, so make the invocation bypass all further * visibility checks */ if(vis->method()->nil_p()) { lookup.priv = true; goto keep_looking; } msg.method = as<Executable>(vis->method()); msg.module = module; break; } else { msg.method = as<Executable>(entry); msg.module = module; break; } keep_looking: module = module->superclass(); /* No more places to look, we couldn't find it. */ if(module->nil_p()) return false; } while(1); return true; }
static bool find_method(STATE, Module* module, Symbol* name, bool priv, Object* self, Executable** found_method, Module** found_module) { Object* entry; MethodVisibility* vis; do { entry = module->method_table()->fetch(state, name); /* Nothing, there? Ok, keep looking. */ if(entry->nil_p()) goto keep_looking; /* A 'false' method means to terminate method lookup. * (eg. undef_method) */ if(entry == Qfalse) return false; vis = try_as<MethodVisibility>(entry); /* If this was a private send, then we can handle use * any method seen. */ if(priv) { /* nil means that the actual method object is 'up' from here */ if(vis && vis->method()->nil_p()) goto keep_looking; *found_method = as<Executable>(vis ? vis->method() : entry); *found_module = module; break; } else if(vis) { /* The method is private, but this wasn't a private send. */ if(vis->private_p(state)) { return false; } else if(vis->protected_p(state)) { /* The method is protected, but it's not being called from * the same module */ if(!self->kind_of_p(state, module)) { return false; } } /* The method was callable, but we need to keep looking * for the implementation, so make the invocation bypass all further * visibility checks */ if(vis->method()->nil_p()) { priv = true; goto keep_looking; } *found_method = as<Executable>(vis->method()); *found_module = module; break; } else { *found_method = as<Executable>(entry); *found_module = module; break; } keep_looking: module = module->superclass(); /* No more places to look, we couldn't find it. */ if(module->nil_p()) return false; } while(1); return true; }