Class: Module
Class Method Summary collapse
-
.load(String) ⇒ Module
Load a module from a string.
Instance Method Summary collapse
-
#dump(limit) ⇒ String
Dump a module to a string.
-
#add_method(id, node) ⇒ Object
Adds the method as an instance method to the given class.
-
#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.
-
#real_superclass ⇒ Class
Return the immediate superclass of a class or module.
Class Method Details
.load(String) ⇒ Module
Load a module from a string.
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, , , 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); = 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); = marshal_load(); if(RTEST()) { rb_singleton_class_attached(, module); RBASIC(module)->klass = ; } 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.
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, , 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)) { = Qnil; class_name = Qnil; } else { = 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(, 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_superclass ⇒ Class
Return the immediate superclass of a class or module. This may be a base class, a singleton class, or a module singleton.
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; } |