void MethodVisibility::Info::show(STATE, Object* self, int level) { MethodVisibility* mv = as<MethodVisibility>(self); class_header(state, self); indent_attribute(++level, "visibility"); mv->visibility()->show(state, level); indent_attribute(level, "method"); mv->method()->show(state, level); close_body(level); }
void capi_define_method(const char* file, VALUE target, const char* name, CApiGenericFunction fptr, int arity, CApiMethodKind kind) { NativeMethodEnvironment* env = NativeMethodEnvironment::get(); VM* state = env->state(); Symbol* method_name = state->symbol(name); Module* module = NULL; if (kind == cCApiSingletonMethod) { module = c_as<Module>(env->get_object(target)->metaclass(env->state())); } else { module = c_as<Module>(env->get_object(target)); } NativeMethod* method = NULL; method = NativeMethod::create(state, String::create(state, file), module, method_name, fptr, Fixnum::from(arity)); MethodVisibility* visibility = MethodVisibility::create(state); visibility->method(state, method); switch(kind) { case cCApiPrivateMethod: visibility->visibility(state, state->symbol("private")); break; case cCApiProtectedMethod: visibility->visibility(state, state->symbol("protected")); break; default: /* Also catches singletons for now. @todo Verify OK. --rue */ visibility->visibility(state, state->symbol("public")); break; } module->method_table()->store(state, method_name, visibility); state->global_cache->clear(module, method_name); }
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; }