Module: CShadow::CShadowClassMethods
- Defined in:
- lib/cgen/cshadow.rb
Instance Method Summary collapse
-
#_alloc_method ⇒ Object
Return the object for managing the
alloc
method of the class. -
#_dump_data_method ⇒ Object
Return the object for managing the
_dump_data
method of the class. -
#_load_data_method ⇒ Object
Return the object for managing the
_load_data
method of the class. -
#after_commit(&block) ⇒ Object
Register
block
to be called after the #commit happens. - #attr_accessor(*args) ⇒ Object
- #attr_reader(*args) ⇒ Object
- #attr_writer(*args) ⇒ Object
-
#base_class ⇒ Object
Return the base class, which is the ancestor which first included CShadow.
-
#before_commit(&block) ⇒ Object
Register
block
to be called before the #commit happens. - #c_function_templates ⇒ Object
-
#check_inherited_functions ⇒ Object
For each function referenced in this class, but not defined, resolve the reference by defining a macro to evaluate to the first implementation found by ascending the class tree.
-
#commit ⇒ Object
Generate code and load the dynamically linked library.
-
#committed? ⇒ Boolean
Returns true if and only if the class haas been committed.
-
#define_c_class_method(name, subclass = CGenerator::SingletonMethod, &block) ⇒ Object
Define a class method for this class.
-
#define_c_function(name, subclass = CGenerator::Function, &block) ⇒ Object
Define a function in the library of this class.
-
#define_c_method(name, subclass = CGenerator::Method, &block) ⇒ Object
The block is evaluated in a context that allows commands for listing arguments, declarations, C body code, etc.
-
#define_inheritable_c_function(name, subclass = CGenerator::Function, &block) ⇒ Object
Define a function in the library of this class.
-
#each_shadow_attr(&bl) ⇒ Object
Each class which includes the CShadow module has this method to iterate over its shadow attributes.
-
#fill_in_defs ⇒ Object
Internal methods ==#.
-
#find_super_function(sym) ⇒ Object
Note that {} nondeterministic, so these should only be used to check existence or get value, not to iterate.
-
#free_function ⇒ Object
Return the object for managing the free function of the class.
- #inherited_function ⇒ Object
-
#mark_function ⇒ Object
Return the object for managing the mark function of the class.
-
#new ⇒ Object
:nodoc:.
-
#new_from_hash(h) ⇒ Object
Primarily for loading yaml data.
-
#new_method ⇒ Object
Return the object for managing the
new
method of the class. - #persistent? ⇒ Boolean
-
#refer_to_function(sym) ⇒ Object
Generate a string which, by convention, names the function for instances of this particular class.
-
#referenced_functions ⇒ Object
Set of function names (symbols) that have been referenced in the implementation of this class.
-
#shadow_attrs ⇒ Object
Returns a proxy Enumerable object referring to the same attributes as #each_shadow_attr.
-
#shadow_library(lib = nil) ⇒ Object
If
lib
provided and this class doesn’t have a library yet, set the library tolib
.. -
#shadow_library_file(file = nil) ⇒ Object
Set or return the shadow library file.
-
#shadow_library_include_file ⇒ Object
Return the main C include file for the library.
-
#shadow_library_source_file ⇒ Object
Return the main C source file for the library.
-
#shadow_struct ⇒ Object
Return the object for managing the shadow struct.
-
#shadow_struct_name ⇒ Object
Construct the name used for the shadow struct.
Instance Method Details
#_alloc_method ⇒ Object
Return the object for managing the alloc
method of the class.
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 |
# File 'lib/cgen/cshadow.rb', line 765 def _alloc_method ## same as new_method, but no initialize -- factor this ## can we use define_c_class_method? return nil unless persistent? unless defined?(@_alloc_method) and @_alloc_method sf = shadow_library_source_file ssn = shadow_struct_name mark_name = refer_to_function :mark free_name = refer_to_function :free @_alloc_method = sf.define_alloc_func(self) @_alloc_method.instance_eval { scope :extern arguments 'VALUE klass' return_type 'VALUE' klass_c_name = "klass" declare :object => "VALUE object" declare :shadow => "#{ssn} *shadow" body %{ object = Data_Make_Struct(#{klass_c_name}, #{ssn}, #{mark_name}, #{free_name}, shadow); shadow->self = object; } returns "object" } end @_alloc_method end |
#_dump_data_method ⇒ Object
Return the object for managing the _dump_data
method of the class. See ruby’s marshal.c.
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 |
# File 'lib/cgen/cshadow.rb', line 730 def _dump_data_method return nil unless persistent? unless defined?(@_dump_data_method) and @_dump_data_method @_dump_data_method = define_c_method(:_dump_data, AttrMethod) { declare :result => "VALUE result" setup :result => "result = rb_ary_new()" body pre_code!, attr_code!, post_code! returns "result" } if superclass.respond_to? :shadow_struct @_dump_data_method.attr_code superclass._dump_data_method.body! end end @_dump_data_method end |
#_load_data_method ⇒ Object
Return the object for managing the _load_data
method of the class. See ruby’s marshal.c.
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 |
# File 'lib/cgen/cshadow.rb', line 748 def _load_data_method return nil unless persistent? unless defined?(@_load_data_method) and @_load_data_method @_load_data_method = define_c_method(:_load_data, AttrMethod) { arguments :from_array declare :tmp => "VALUE tmp" body pre_code!, attr_code!, post_code! returns "from_array" ## needed? } if superclass.respond_to? :shadow_struct @_load_data_method.attr_code superclass._load_data_method.body! end end @_load_data_method end |
#after_commit(&block) ⇒ Object
Register block
to be called after the #commit happens.
377 378 379 |
# File 'lib/cgen/cshadow.rb', line 377 def after_commit(&block) shadow_library.after_commit(&block) end |
#attr_accessor(*args) ⇒ Object
809 810 811 812 |
# File 'lib/cgen/cshadow.rb', line 809 def attr_accessor(*args) check_overwrite_shadow_attrs(*args) super end |
#attr_reader(*args) ⇒ Object
814 815 816 817 |
# File 'lib/cgen/cshadow.rb', line 814 def attr_reader(*args) check_overwrite_shadow_attrs(*args) super end |
#attr_writer(*args) ⇒ Object
819 820 821 822 |
# File 'lib/cgen/cshadow.rb', line 819 def attr_writer(*args) check_overwrite_shadow_attrs(*args) super end |
#base_class ⇒ Object
Return the base class, which is the ancestor which first included CShadow.
335 336 337 |
# File 'lib/cgen/cshadow.rb', line 335 def base_class @base_class ||= superclass.base_class end |
#before_commit(&block) ⇒ Object
Register block
to be called before the #commit happens.
372 373 374 |
# File 'lib/cgen/cshadow.rb', line 372 def before_commit(&block) shadow_library.before_commit(&block) end |
#c_function_templates ⇒ Object
580 |
# File 'lib/cgen/cshadow.rb', line 580 def c_function_templates; @c_function_templates ||= {}; end |
#check_inherited_functions ⇒ Object
For each function referenced in this class, but not defined, resolve the reference by defining a macro to evaluate to the first implementation found by ascending the class tree.
681 682 683 684 685 686 687 688 689 690 691 692 |
# File 'lib/cgen/cshadow.rb', line 681 def check_inherited_functions syms = referenced_functions.keys.sort_by{|k|k.to_s} syms.reject {|sym| c_function_templates[sym]}.each do |sym| fname = "#{sym}_#{shadow_struct_name}" pf = find_super_function(sym) inherited_function[sym] = true pf_str = pf ? pf.name : (sym == :free ? -1 : 0) # -1 means free the struct; See README.EXT shadow_library_source_file.declare fname.intern => "#define #{fname} #{pf_str}" end end |
#commit ⇒ Object
Generate code and load the dynamically linked library. No further C attrs or methods can be defined after calling #commit.
362 363 364 |
# File 'lib/cgen/cshadow.rb', line 362 def commit shadow_library.commit end |
#committed? ⇒ Boolean
Returns true if and only if the class haas been committed.
367 368 369 |
# File 'lib/cgen/cshadow.rb', line 367 def committed? shadow_library.committed? end |
#define_c_class_method(name, subclass = CGenerator::SingletonMethod, &block) ⇒ Object
Define a class method for this class.
528 529 530 531 532 533 534 535 |
# File 'lib/cgen/cshadow.rb', line 528 def define_c_class_method name, subclass = CGenerator::SingletonMethod, &block sf = shadow_library_source_file m = sf.define_c_singleton_method self, name, subclass m.scope :extern m.instance_eval(&block) if block m end |
#define_c_function(name, subclass = CGenerator::Function, &block) ⇒ Object
Define a function in the library of this class. By default, the function has extern scope. The name
is just the function name (as a C function).
540 541 542 543 544 545 546 |
# File 'lib/cgen/cshadow.rb', line 540 def define_c_function name, subclass = CGenerator::Function, &block sf = shadow_library_source_file m = sf.define_c_function name, subclass m.scope :extern m.instance_eval(&block) if block m end |
#define_c_method(name, subclass = CGenerator::Method, &block) ⇒ Object
The block is evaluated in a context that allows commands for listing arguments, declarations, C body code, etc. See CGenerator for details. See examples in examples/matrix.rb and examples/complex.rb. The subclass
argument is optional and allows the template to belong to a subclass of the function template it would normally belong to.
In the case of #define_c_method, a pointer to the object’s shadow struct is available in the C variable shadow
.
516 517 518 519 520 521 522 523 524 525 |
# File 'lib/cgen/cshadow.rb', line 516 def define_c_method name, subclass = CGenerator::Method, &block sf = shadow_library_source_file m = sf.define_c_method self, name, subclass m.scope :extern m.declare :shadow => "#{shadow_struct_name} *shadow" m.setup :shadow => "Data_Get_Struct(self, #{shadow_struct_name}, shadow)" m.instance_eval(&block) if block m end |
#define_inheritable_c_function(name, subclass = CGenerator::Function, &block) ⇒ Object
Define a function in the library of this class. By default, the function has extern scope. The name
is typically a symbol (like :mark) which is used to generate a function name in combination with the shadow struct name.
If a class defines a function with name
, and the child class does not do so (i.e. doesn’t instantiate the function template to add code), then the child can call the parent’s implementation using #refer_to_function (see #new_method for an example).
557 558 559 560 561 562 563 564 565 |
# File 'lib/cgen/cshadow.rb', line 557 def define_inheritable_c_function name, subclass = CGenerator::Function, &block sf = shadow_library_source_file m = sf.define_c_function "#{name}_#{shadow_struct_name}", subclass c_function_templates[name] = m m.scope :extern m.instance_eval(&block) if block m end |
#each_shadow_attr(&bl) ⇒ Object
Each class which includes the CShadow module has this method to iterate over its shadow attributes.
Note that the shadow attributes dynamically include inherited ones. (Dynamically in the sense that subsequent changes to superclasses are automatically reflected.) The order is from root to leaf of the inheritance chain, and within each class in order of definition. (TEST THIS)
389 390 391 392 393 394 395 |
# File 'lib/cgen/cshadow.rb', line 389 def each_shadow_attr(&bl) if superclass.respond_to? :each_shadow_attr superclass.each_shadow_attr(&bl) end @shadow_attrs ||= [] @shadow_attrs.each(&bl) end |
#fill_in_defs ⇒ Object
Internal methods ==#
569 570 571 572 573 574 575 576 577 578 |
# File 'lib/cgen/cshadow.rb', line 569 def fill_in_defs shadow_struct new_method; _alloc_method check_inherited_functions if self == base_class _dump_data_method; _load_data_method end end |
#find_super_function(sym) ⇒ Object
Note that {} nondeterministic, so these should only be used to check existence or get value, not to iterate.
584 585 586 587 588 |
# File 'lib/cgen/cshadow.rb', line 584 def find_super_function sym c_function_templates[sym] || ( defined?(superclass.find_super_function) && superclass.find_super_function(sym)) end |
#free_function ⇒ Object
Return the object for managing the free function of the class.
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 |
# File 'lib/cgen/cshadow.rb', line 712 def free_function unless defined?(@free_function) and @free_function raise if inherited_function[:free] sf = shadow_library_source_file ssn = shadow_struct_name @free_function = define_inheritable_c_function(:free, FreeFunction) do arguments "#{ssn} *shadow" return_type "void" end if superclass.respond_to? :shadow_struct @free_function.free superclass.free_function.free! end end @free_function end |
#inherited_function ⇒ Object
674 675 676 |
# File 'lib/cgen/cshadow.rb', line 674 def inherited_function @inherited_function ||= {} end |
#mark_function ⇒ Object
Return the object for managing the mark function of the class.
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 |
# File 'lib/cgen/cshadow.rb', line 695 def mark_function unless defined?(@mark_function) and @mark_function raise if inherited_function[:mark] sf = shadow_library_source_file ssn = shadow_struct_name @mark_function = define_inheritable_c_function(:mark, MarkFunction) do arguments "#{ssn} *shadow" return_type "void" end if superclass.respond_to? :shadow_struct @mark_function.mark superclass.mark_function.mark! end end @mark_function end |
#new ⇒ Object
:nodoc:
304 305 306 307 |
# File 'lib/cgen/cshadow.rb', line 304 def new # :nodoc: raise Library::CommitError, "Cannot create shadow objects before committing library" end |
#new_from_hash(h) ⇒ Object
Primarily for loading yaml data. The hash is of the form
{ 'attr' => value, ... }
where attr
is either the name of a shadow attr, or the name (without @) of an attribute.
Warning: The hash h
is modified.
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
# File 'lib/cgen/cshadow.rb', line 317 def new_from_hash(h) obj = allocate psa = shadow_attrs.select {|attr| attr.persists} shadow_vars = psa.map{|attr|attr.var.to_s} from_array = h.values_at(*shadow_vars) obj._load_data(from_array) shadow_vars.each {|v| h.delete(v) } h.each do |ivar, value| obj.instance_variable_set("@#{ivar}", value) end obj end |
#new_method ⇒ Object
Return the object for managing the new
method of the class.
624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 |
# File 'lib/cgen/cshadow.rb', line 624 def new_method unless defined?(@new_method) and @new_method sf = shadow_library_source_file ssn = shadow_struct_name mark_name = refer_to_function :mark free_name = refer_to_function :free @new_method = sf.define_c_singleton_method self, :new, AttrClassMethod @new_method.instance_eval { scope :extern c_array_args declare :object => "VALUE object" declare :shadow => "#{ssn} *shadow" setup :shadow_struct => %{ object = Data_Make_Struct(self, #{ssn}, #{mark_name}, #{free_name}, shadow); shadow->self = object; } body attr_code! body %{ rb_obj_call_init(object, argc, argv); } returns "object" } if superclass.respond_to? :shadow_struct @new_method.attr_code superclass.new_method.attr_code! end end @new_method end |
#persistent? ⇒ Boolean
351 352 353 354 355 356 357 358 |
# File 'lib/cgen/cshadow.rb', line 351 def persistent? bc = @base_class if self == bc @persistent else bc.persistent? end end |
#refer_to_function(sym) ⇒ Object
Generate a string which, by convention, names the function for instances of this particular class. Also, keeps track of referenced_functions.
669 670 671 672 |
# File 'lib/cgen/cshadow.rb', line 669 def refer_to_function sym referenced_functions[sym] = true "#{sym}_#{shadow_struct_name}" end |
#referenced_functions ⇒ Object
Set of function names (symbols) that have been referenced in the implementation of this class. The names are like :free or :mark, rather than :free_in_class_C, to give a common identity to all free functions.
662 663 664 |
# File 'lib/cgen/cshadow.rb', line 662 def referenced_functions @referenced_functions ||= {} end |
#shadow_attrs ⇒ Object
Returns a proxy Enumerable object referring to the same attributes as #each_shadow_attr. For example:
sub_class.shadow_attrs.collect { |attr| attr.var }
returns an array of variable names for all attributes of the class.
403 404 405 406 407 408 409 410 411 |
# File 'lib/cgen/cshadow.rb', line 403 def shadow_attrs proxy = Object.new.extend Enumerable shadow_class = self proxy.instance_eval {@target = shadow_class} def proxy.each(&bl) @target.each_shadow_attr(&bl) end proxy end |
#shadow_library(lib = nil) ⇒ Object
If lib
provided and this class doesn’t have a library yet, set the library to lib
..
If lib
not proivided, and the class has a library, return it.
If lib
not proivided, and the class doesn’t have a library, construct a library with a reasonable name, and return it. The name is based on the full path of this class.
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 |
# File 'lib/cgen/cshadow.rb', line 422 def shadow_library lib = nil bc = base_class if self == bc if defined?(@shadow_library) and @shadow_library if lib raise RuntimeError, "Class #{name} is already associated" + " with library #{@shadow_library.name}." end else case lib when Library @shadow_library = lib when Class begin @shadow_library = lib.shadow_library rescue NameError raise ScriptError, "#{lib} does not include CShadow." end when String @shadow_library = Library.new(lib) when nil n = name.dup n.gsub!(/_/, '__') n.gsub!(/::/, '_') # almost reversible @shadow_library = Library.new(n) else raise ArgumentError, "#{lib} is not a CShadow::Library, String, or Class. " + "Its class is #{lib.class}" end end @shadow_library else bc.shadow_library lib end end |
#shadow_library_file(file = nil) ⇒ Object
Set or return the shadow library file.
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 |
# File 'lib/cgen/cshadow.rb', line 461 def shadow_library_file file = nil if defined? @shadow_library_file if file raise RuntimeError, "Cannot assign class #{self} to file #{file.inspect}; class" + " is already associated" + " with file #{@shadow_library_file[0].name}." end @shadow_library_file elsif file case file when CGenerator::CFile file_name = file.name when String file_name = file else raise ArgumentError, "#{file} is not a String or CFile." end file_name = file_name.sub(/\.[ch]$/, "") @shadow_library_file = shadow_library.add_file file_name else if superclass.respond_to? :shadow_library_file superclass.shadow_library_file else [shadow_library.include_file, shadow_library.source_file] end end end |
#shadow_library_include_file ⇒ Object
Return the main C include file for the library.
491 492 493 |
# File 'lib/cgen/cshadow.rb', line 491 def shadow_library_include_file shadow_library_file[0] end |
#shadow_library_source_file ⇒ Object
Return the main C source file for the library.
496 497 498 |
# File 'lib/cgen/cshadow.rb', line 496 def shadow_library_source_file shadow_library_file[1] end |
#shadow_struct ⇒ Object
Return the object for managing the shadow struct.
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 |
# File 'lib/cgen/cshadow.rb', line 598 def shadow_struct unless defined?(@shadow_struct) and @shadow_struct raise if @inherited_shadow_struct sf = shadow_library_source_file ssn = shadow_struct_name @shadow_struct = sf.declare_extern_struct(ssn) if self == base_class @shadow_struct.declare :self => "VALUE self" else sss = superclass.shadow_struct shadow_struct.inherit\ sss.inherit!, "/* #{superclass.shadow_struct_name} members */", sss.declare!, " " unless superclass.shadow_library_source_file == shadow_library_source_file shadow_library_include_file.include( superclass.shadow_library_include_file) end end end @shadow_struct end |
#shadow_struct_name ⇒ Object
Construct the name used for the shadow struct. Attempts to preserve the full class path.
592 593 594 595 |
# File 'lib/cgen/cshadow.rb', line 592 def shadow_struct_name @shadow_struct_name ||= name.gsub(/_/, '__').gsub(/::/, '_o_') + CShadow::SHADOW_SUFFIX end |