Exemplo n.º 1
0
  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);
  }
Exemplo n.º 2
0
  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);
  }
Exemplo n.º 3
0
  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;
  }
Exemplo n.º 4
0
  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;
  }