Class: Module

Inherits:
Object show all
Defined in:
lib/as_code.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.load(String) ⇒ Module

Load a module from a string.

Returns:



1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
# File 'ext/nodewrap.c', line 1710

static VALUE module_load(VALUE klass, VALUE str)
{
  VALUE arr, class_name, metaclass_str, metaclass, superclass_name,
        included_modules, class_variables_str, class_variables,
        instance_methods_str, instance_methods, flags, module;

  if(   ruby_safe_level >= 4
     || (ruby_safe_level >= 1 && OBJ_TAINTED(str)))
  {
    /* no playing with knives in the sandbox */
    rb_raise(rb_eSecurityError, "Insecure: can't load module");
  }

  arr = marshal_load(str);
  class_name = rb_ary_pop(arr);
  metaclass_str = rb_ary_pop(arr);
  superclass_name = rb_ary_pop(arr);
  included_modules = rb_ary_pop(arr);
  class_variables_str = rb_ary_pop(arr);
  instance_methods_str = rb_ary_pop(arr);
  flags = rb_ary_pop(arr);

  if(RTEST(superclass_name))
  {
    VALUE superclass;
    rb_check_type(superclass_name, T_STRING);
    superclass = rb_funcall(
        lookup_module_proc,
        rb_intern("call"),
        1,
        superclass_name);
#if RUBY_VERSION_CODE >= 180
    /* Can't make subclass of Class on 1.8.x */
    module = rb_class_boot(superclass);
    rb_define_alloc_func(module, module_instance_allocate);
#else
    module = rb_class_new(superclass);
#endif
  }
  else
  {
    module = rb_module_new();
  }

  if(!NIL_P(class_name))
  {
    VALUE outer_module = rb_funcall(outer_module_proc, rb_intern("call"), 1, class_name);
    VALUE module_name = rb_funcall(module_name_proc, rb_intern("call"), 1, class_name);
    rb_const_set(outer_module, SYM2ID(module_name), module);
  }

  RBASIC(module)->flags = NUM2INT(flags);
  include_modules(module, included_modules);
  class_variables = marshal_load(class_variables_str);
  add_class_variables(module, class_variables);
  instance_methods = marshal_load(instance_methods_str);
  add_methods(module, instance_methods);

  metaclass = marshal_load(metaclass_str);
  if(RTEST(metaclass))
  {
    rb_singleton_class_attached(metaclass, module);
    RBASIC(module)->klass = metaclass;
  }

  return module;
}

Instance Method Details

#dump(limit) ⇒ String

Dump a module to a string. The module will be dumped along with its instance methods, class variables, names of included modules, name of superclass, its entire metaclass, and the name of the class.

Note that on ruby 1.8 and newer the module is temporarily modified while dumping in order to allow singleton classes to be dumped. To prevent access to the modifed module, Thread.critical is temporarily set, then restored to its original value once dumping is complete. Note also that because YARV does not support Thread.critical, the user must synchronize access to the class with a Mutex in order to prevent accessing the modified class.

Returns:

  • (String)


1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
# File 'ext/nodewrap.c', line 1599

static VALUE module_dump(VALUE self, VALUE limit)
{
  VALUE flags, instance_methods, class_variables;
  VALUE included_modules, superclass, metaclass, arr, str, class_name;

  limit = INT2NUM(NUM2INT(limit) - 1);

  if(ruby_safe_level >= 4)
  {
    /* no access to potentially sensitive data from the sandbox */
    rb_raise(rb_eSecurityError, "Insecure: can't dump module");
  }

  flags = INT2NUM(RBASIC(self)->flags);
  instance_methods = instance_method_hash(self);
  class_variables = class_variable_hash(self);
  included_modules = included_modules_list(self);
  superclass = superclass_name(self);
  arr = rb_ary_new();

  if(FL_TEST(self, FL_SINGLETON))
  {
    metaclass = Qnil;
    class_name = Qnil;
  }
  else
  {
    metaclass = rb_singleton_class(self);
    class_name = rb_class_path(self);
  }

  rb_ary_push(arr, flags);
  rb_ary_push(arr, marshal_dump(instance_methods, limit));
  rb_ary_push(arr, marshal_dump(class_variables, limit));
  rb_ary_push(arr, included_modules);
  rb_ary_push(arr, superclass);
  rb_ary_push(arr, marshal_dump(metaclass, limit));
  rb_ary_push(arr, class_name);

  str = marshal_dump(arr, limit);

#if RUBY_VERSION_CODE > 180
  {
    VALUE class_restorer = create_class_restorer(self);
    rb_iv_set(str, "__class_restorer__", class_restorer);
    set_class_restore_state(self);
  }
#endif

  return str;
}

#add_method(id, node) ⇒ Object

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.



518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
# File 'ext/nodewrap.c', line 518

static VALUE module_add_method(VALUE klass, VALUE id, VALUE node, VALUE noex)
{
  NODE * n = 0;

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

#ifdef RUBY_HAS_YARV
  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);

#ifdef RUBY_HAS_YARV
  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
  /* 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;
}

#as_code(indent = 0) ⇒ Object

TODO: it would be nice if we could go back and find the AST for the class instead of recreating the code from the class’s current state.



303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/as_code.rb', line 303

def as_code(indent=0)
  imethods = self.instance_methods - self.superclass.instance_methods
  cmethods = self.instance_methods - self.superclass.instance_methods
  constants = self.constants - self.superclass.constants
  name = self.name.gsub(/.*::/, '')

  # TODO: included modules?
  if self.class == Class then
    s = "#{'  '*indent}class #{name} < #{self.superclass}\n"
  else
    s = "#{'  '*indent}module #{name}\n"
  end

  constants.each do |constant|
    s += "#{'  '*indent} #{constant}=#{self.const_get(constant).as_code}\n"
  end

  # TODO: protected/private
  imethods.each do |method|
    s += self.instance_method(method).as_code(indent+1)
    s += "\n"
  end

  cmethods.each do |method|
    s += self.instance_method(method).as_code(indent+1, "self.#{method}")
    s += "\n"
  end

  # TODO: singleton class constants
  # TODO: class variables
  # TODO: singleton instance variables

  s += "#{'  '*indent}end"

  return s
end

#real_superclassClass

Return the immediate superclass of a class or module. This may be a base class, a singleton class, or a module singleton.

Returns:

  • (Class)


2277
2278
2279
2280
2281
# File 'ext/nodewrap.c', line 2277

VALUE real_superclass(VALUE self)
{
  rb_include_module(rb_class_of(RCLASS(self)->super), rb_mKernel);
  return RCLASS(self)->super;
}