コード例 #1
0
ファイル: class.c プロジェクト: asimoov/emscripted-ruby
static int
clone_method(ID mid, NODE *body, VALUE nklass)
{
    NODE *fbody = body->nd_body;

    if (fbody) {
	VALUE nbody;

	switch (nd_type(fbody)) {
	  case NODE_SCOPE:
	    fbody = rb_copy_node_scope(fbody, ruby_cref);
    	    break;
	  case NODE_BMETHOD:
	    nbody = rb_block_dup(fbody->nd_cval, nklass, (VALUE)ruby_cref);
	    fbody = NEW_BMETHOD(nbody);
	    break;
	  case NODE_DMETHOD:
	    nbody = rb_method_dup(fbody->nd_cval, nklass, (VALUE)ruby_cref);
	    fbody = NEW_DMETHOD(nbody);
	    break;
	}
    }
    st_insert(RCLASS(nklass)->m_tbl, mid, (st_data_t)NEW_METHOD(fbody, body->nd_noex));
    return ST_CONTINUE;
}
コード例 #2
0
ファイル: vm_method.c プロジェクト: iriscouch/ruby-inabox
void
rb_alias(VALUE klass, ID name, ID def)
{
    NODE *orig_fbody, *node, *method;
    VALUE singleton = 0;
    st_data_t data;

    rb_frozen_class_p(klass);
    if (klass == rb_cObject) {
	rb_secure(4);
    }
    orig_fbody = search_method(klass, def, 0);
    if (!orig_fbody || !orig_fbody->nd_body) {
	if (TYPE(klass) == T_MODULE) {
	    orig_fbody = search_method(rb_cObject, def, 0);
	}
    }
    if (!orig_fbody || !orig_fbody->nd_body) {
	rb_print_undef(klass, def, 0);
    }
    if (FL_TEST(klass, FL_SINGLETON)) {
	singleton = rb_iv_get(klass, "__attached__");
    }

    orig_fbody->nd_cnt++;

    if (st_lookup(RCLASS_M_TBL(klass), name, &data)) {
	node = (NODE *)data;
	if (node) {
	    if (RTEST(ruby_verbose) && node->nd_cnt == 0 && node->nd_body) {
		rb_warning("discarding old %s", rb_id2name(name));
	    }
	    if (nd_type(node->nd_body->nd_body) == NODE_CFUNC) {
		rb_vm_check_redefinition_opt_method(node);
	    }
	}
    }

    st_insert(RCLASS_M_TBL(klass), name,
	      (st_data_t) NEW_FBODY(
		  method = NEW_METHOD(orig_fbody->nd_body->nd_body,
			     orig_fbody->nd_body->nd_clss,
			     NOEX_WITH_SAFE(orig_fbody->nd_body->nd_noex)), def));
    method->nd_file = (void *)def;

    rb_clear_cache_by_id(name);

    if (!ruby_running) return;

    if (singleton) {
	rb_funcall(singleton, singleton_added, 1, ID2SYM(name));
    }
    else {
	rb_funcall(klass, added, 1, ID2SYM(name));
    }
}
コード例 #3
0
ファイル: class.c プロジェクト: genki/ruby
static int
clone_method(ID mid, NODE *body, struct clone_method_data *data)
{
    if (body == 0) {
	st_insert(data->tbl, mid, 0);
    }
    else {
	st_insert(data->tbl, mid,
		  (st_data_t)
		  NEW_FBODY(
		      NEW_METHOD(body->nd_body->nd_body,
				 data->klass, /* TODO */
				 body->nd_body->nd_noex),
		      0));
    }
    return ST_CONTINUE;
}
コード例 #4
0
ファイル: vm_method.c プロジェクト: genki/ruby
void
rb_add_method(VALUE klass, ID mid, NODE * node, int noex)
{
    NODE *body;

    if (NIL_P(klass)) {
	klass = rb_cObject;
    }
    if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) {
	rb_raise(rb_eSecurityError, "Insecure: can't define method");
    }
    if (!FL_TEST(klass, FL_SINGLETON) &&
	node && nd_type(node) != NODE_ZSUPER &&
	(mid == rb_intern("initialize") || mid == rb_intern("initialize_copy"))) {
	noex = NOEX_PRIVATE | noex;
    }
    else if (FL_TEST(klass, FL_SINGLETON) && node
	     && nd_type(node) == NODE_CFUNC && mid == rb_intern("allocate")) {
	rb_warn
	    ("defining %s.allocate is deprecated; use rb_define_alloc_func()",
	     rb_class2name(rb_iv_get(klass, "__attached__")));
	mid = ID_ALLOCATOR;
    }
    if (OBJ_FROZEN(klass)) {
	rb_error_frozen("class/module");
    }
    rb_clear_cache_by_id(mid);

    /*
     * NODE_METHOD (NEW_METHOD(body, klass, vis)):
     *   nd_body : method body   // (2) // mark
     *   nd_clss : klass         // (1) // mark
     *   nd_noex : visibility    // (3)
     *
     * NODE_FBODY (NEW_FBODY(method, alias)):
     *   nd_body : method (NODE_METHOD)  // (2) // mark
     *   nd_oid  : original id           // (1)
     *   nd_cnt  : alias count           // (3)
     */
    if (node) {
	body = NEW_FBODY(NEW_METHOD(node, klass, NOEX_WITH_SAFE(noex)), 0);
    }
    else {
	body = 0;
    }

    {
	/* check re-definition */
	st_data_t data;
	NODE *old_node;

	if (st_lookup(RCLASS_M_TBL(klass), mid, &data)) {
	    old_node = (NODE *)data;
	    if (old_node) {
		if (nd_type(old_node->nd_body->nd_body) == NODE_CFUNC) {
		    rb_vm_check_redefinition_opt_method(old_node);
		}
		if (RTEST(ruby_verbose) && node && old_node->nd_cnt == 0 && old_node->nd_body) {
		    rb_warning("method redefined; discarding old %s", rb_id2name(mid));
		}
	    }
	}
	if (klass == rb_cObject && node && mid == idInitialize) {
	    rb_warn("redefining Object#initialize may cause infinite loop");
	}

	if (mid == object_id || mid == __send__) {
	    if (node && nd_type(node) == RUBY_VM_METHOD_NODE) {
		rb_warn("redefining `%s' may cause serious problem",
			rb_id2name(mid));
	    }
	}
    }

    st_insert(RCLASS_M_TBL(klass), mid, (st_data_t) body);

    if (node && mid != ID_ALLOCATOR && ruby_running) {
	if (FL_TEST(klass, FL_SINGLETON)) {
	    rb_funcall(rb_iv_get(klass, "__attached__"), singleton_added, 1,
		       ID2SYM(mid));
	}
	else {
	    rb_funcall(klass, added, 1, ID2SYM(mid));
	}
    }
}
コード例 #5
0
ファイル: module.c プロジェクト: shmulim/ruby-internal
/*
 * call-seq:
 *   class.add_method(id, node or iseq, noex) #=> nil
 *
 * Adds the method as an instance method to the given class.
 *
 * To add a singleton method to a class, add the method to its singleton
 * class.
 */
static VALUE module_add_method(VALUE klass, VALUE id, VALUE node, VALUE noex)
{
  NODE * n = 0;

  if(rb_safe_level() >= 2)
  {
    /* adding a method with the wrong node type can cause a crash */
    rb_raise(rb_eSecurityError, "Insecure: can't add method");
  }

#if RUBY_VERSION_CODE >= 192
  if(rb_obj_is_kind_of(node, rb_cISeq))
  {
    rb_iseq_t *iseqdat = iseq_check(node);
    set_cref_stack(iseqdat, klass, noex);
    iseqdat->klass = klass;
    iseqdat->defined_method_id = SYM2ID(id);

#ifdef HAVE_RB_ADD_METHOD
    rb_add_method(klass, SYM2ID(id), VM_METHOD_TYPE_ISEQ, iseqdat, NUM2INT(noex));
#else
    rb_funcall(rb_mRubyVMFrozenCore, rb_intern("core#define_method"), 3, klass, id, node); /* TODO: noex */
#endif

    return Qnil;
  }

#elif RUBY_VERSION_CODE >= 190
  if(rb_obj_is_kind_of(node, rb_cISeq))
  {
    rb_iseq_t *iseqdat = iseq_check(node);
    /* TODO: any restrictions on what kinds of iseqs we can add here? */
    set_cref_stack(iseqdat, klass, noex);
    iseqdat->klass = klass;
    iseqdat->defined_method_id = SYM2ID(id);
    n = NEW_METHOD(iseqdat->self, klass, NUM2INT(noex));
    goto add_node;
  }
#endif

  if(!rb_obj_is_kind_of(node, rb_cNode))
  {
    rb_raise(
        rb_eTypeError,
        "Expected Node for 2nd parameter, got %s",
        rb_class2name(CLASS_OF(n)));
  }

  Data_Get_Struct(node, NODE, n);

#if RUBY_VERSION_CODE >= 192
  rb_raise(rb_eRuntimeError, "Unable to add node on this version of ruby");
#elif RUBY_VERSION_CODE >= 190
  if(nd_type(n) != NODE_METHOD)
  {
    rb_raise(
        rb_eTypeError,
        "Expected METHOD node, got %s",
        rb_class2name(CLASS_OF(n)));
  }

  {
    rb_iseq_t *iseqdat = iseq_check((VALUE)n->nd_body);
    set_cref_stack(iseqdat, klass, noex);
    iseqdat->klass = klass;
    iseqdat->defined_method_id = SYM2ID(id);
    n = NEW_METHOD(iseqdat->self, klass, NUM2INT(noex));
  }

add_node:

#endif

#if RUBY_VERSION_CODE >= 192
  rb_raise(rb_eRuntimeError, "Unable to add node on this version of ruby");
#else
  /* TODO: if noex is NOEX_MODFUNC, add this method as a module function
   * (that is, both as an instance and singleton method)
   */
  rb_add_method(klass, SYM2ID(id), n, NUM2INT(noex));
  return Qnil;
#endif
}