cgen 0.16.4 → 0.16.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. data/History.txt +15 -0
  2. data/lib/cgen/cgen.rb +14 -1
  3. data/lib/cgen/cshadow.rb +75 -20
  4. data/rakefile +2 -0
  5. metadata +4 -4
@@ -1,3 +1,18 @@
1
+ cgen 0.16.5
2
+
3
+ - api addition: define_inheritable_c_function
4
+
5
+ - optimization: if mark and free same as parent class
6
+ implementation, reference the latter directly
7
+
8
+ - optimization: preserve Makefile mtime when nothing changes
9
+
10
+ - optimization: do not generate load and dump methods when
11
+ super implementation is equivalent
12
+
13
+ - optimization: if mark or free do nothing, don't generate a function,
14
+ just use 0 or -1 (resp.) in Data_Make_Struct
15
+
1
16
  cgen 0.16.4
2
17
 
3
18
  - api addition: module and symbol declarations can optionally be sent
@@ -418,7 +418,7 @@ require 'cgen/inherit'
418
418
  # way that makes clear that the problem is really with commit.
419
419
  module CGenerator
420
420
 
421
- VERSION = '0.16.4'
421
+ VERSION = '0.16.5'
422
422
 
423
423
  class Accumulator ## should be a mixin? "Cumulative"?
424
424
 
@@ -949,9 +949,22 @@ class Library < Template
949
949
  need_to_make_clean = true
950
950
  end
951
951
 
952
+ ## it would be better to capture the output of extconf.rb before
953
+ ## it writes it to Makefile, but mkmf.rb is not written that way :(
954
+ if File.exist?("Makefile")
955
+ old_makefile = File.read("Makefile")
956
+ require 'fileutils'
957
+ FileUtils.mv("Makefile", "Makefile.old")
958
+ end
959
+
952
960
  system %{
953
961
  #{ruby} extconf.rb > #{@logname}
954
962
  }
963
+
964
+ if old_makefile and old_makefile == File.read("Makefile")
965
+ FileUtils.rm("Makefile")
966
+ FileUtils.mv("Makefile.old", "Makefile")
967
+ end
955
968
  end
956
969
 
957
970
  make "clean" if need_to_make_clean
@@ -123,7 +123,8 @@ require "cgen/attribute"
123
123
  # simplicity, CShadow defines three methods in the client class for defining
124
124
  # methods and class methods:
125
125
  #
126
- # CShadow.define_c_method CShadow.define_c_class_method
126
+ # CShadow.define_c_method
127
+ # CShadow.define_c_class_method
127
128
  # CShadow.define_c_function
128
129
  #
129
130
  # ===Memory management
@@ -269,8 +270,11 @@ module CShadow
269
270
  classes.each do |cl|
270
271
  # make sure the following have been defined by now
271
272
  cl.shadow_struct
272
- cl.new_method; cl.mark_function; cl.free_function
273
- cl._dump_data_method; cl._load_data_method; cl._alloc_method
273
+ cl.new_method; cl._alloc_method
274
+ cl.check_inherited_functions
275
+ if cl == cl.base_class
276
+ cl._dump_data_method; cl._load_data_method
277
+ end
274
278
  end
275
279
  end
276
280
 
@@ -535,7 +539,9 @@ module CShadow
535
539
  m
536
540
  end
537
541
 
538
- # Define a global function in the library of this class.
542
+ # Define a function in the library of this class. By
543
+ # default, the function has extern scope.
544
+ # The +name+ is just the function name (as a C function).
539
545
  def define_c_function name, subclass = CGenerator::Function, &block
540
546
  sf = shadow_library_source_file
541
547
  m = sf.define_c_function name, subclass
@@ -543,9 +549,38 @@ module CShadow
543
549
  m.instance_eval(&block) if block
544
550
  m
545
551
  end
546
-
552
+
553
+ # Define a function in the library of this class. By
554
+ # default, the function has extern scope.
555
+ # The +name+ is typically a symbol (like :mark) which is used to
556
+ # generate a function name in combination with the shadow struct name.
557
+ #
558
+ # If a class defines a function with +name+, and the child class does
559
+ # not do so (i.e. doesn't instantiate the function template to add
560
+ # code), then the child can call the parent's implementation using
561
+ # #refer_to_function (see #new_method for an example).
562
+ def define_inheritable_c_function name,
563
+ subclass = CGenerator::Function, &block
564
+ sf = shadow_library_source_file
565
+ m = sf.define_c_function "#{name}_#{shadow_struct.name}", subclass
566
+ c_function_templates[name] = m
567
+ m.scope :extern
568
+ m.instance_eval(&block) if block
569
+ m
570
+ end
571
+
547
572
  #== Internal methods ==#
548
573
 
574
+ def c_function_templates; @c_function_templates ||= {}; end
575
+ # Note that {} nondeterministic, so these should only be used to
576
+ # check existence or get value, not to iterate.
577
+
578
+ def find_super_function sym
579
+ c_function_templates[sym] || (
580
+ defined?(superclass.find_super_function) &&
581
+ superclass.find_super_function(sym))
582
+ end
583
+
549
584
  # Construct the name used for the shadow struct.
550
585
  def shadow_struct_name
551
586
  name.gsub(/_/, '__').gsub(/::/, '_o_') + CShadow::SHADOW_SUFFIX
@@ -582,6 +617,8 @@ module CShadow
582
617
  unless defined?(@new_method) and @new_method
583
618
  sf = shadow_library_source_file
584
619
  ssn = shadow_struct.name
620
+ mark_name = refer_to_function :mark
621
+ free_name = refer_to_function :free
585
622
  @new_method = sf.define_c_singleton_method self,
586
623
  :new, AttrClassMethod
587
624
  @new_method.instance_eval {
@@ -592,11 +629,11 @@ module CShadow
592
629
  setup :shadow_struct => %{
593
630
  object = Data_Make_Struct(self,
594
631
  #{ssn},
595
- mark_#{ssn},
596
- free_#{ssn},
632
+ #{mark_name},
633
+ #{free_name},
597
634
  shadow);
598
635
  shadow->self = object;
599
- }.tabto(0)
636
+ }
600
637
  body attr_code!
601
638
  body %{
602
639
  rb_obj_call_init(object, argc, argv);
@@ -609,18 +646,37 @@ module CShadow
609
646
  end
610
647
  @new_method
611
648
  end
612
-
649
+
650
+ def referenced_functions
651
+ @referenced_functions ||= {}
652
+ end
653
+
654
+ def refer_to_function sym
655
+ referenced_functions[sym] = true
656
+ "#{sym}_#{shadow_struct.name}"
657
+ end
658
+
659
+ def check_inherited_functions
660
+ syms = referenced_functions.keys.sort_by{|k|k.to_s}
661
+ syms.reject {|sym| c_function_templates[sym]}.each do |sym|
662
+ fname = "#{sym}_#{shadow_struct.name}"
663
+ pf = find_super_function(sym)
664
+ pf_str = pf ? pf.name : (sym == :free ? -1 : 0)
665
+ # -1 means free the struct; See README.EXT
666
+ shadow_library_source_file.declare fname.intern =>
667
+ "#define #{fname} #{pf_str}"
668
+ end
669
+ end
670
+
613
671
  # Return the object for managing the mark function of the class.
614
672
  def mark_function
615
673
  unless defined?(@mark_function) and @mark_function
616
674
  sf = shadow_library_source_file
617
675
  ssn = shadow_struct.name
618
- @mark_function = sf.define_c_function("mark_#{ssn}", MarkFunction)
619
- @mark_function.instance_eval {
620
- scope :static
676
+ @mark_function = define_inheritable_c_function(:mark, MarkFunction) do
621
677
  arguments "#{ssn} *shadow"
622
678
  return_type "void"
623
- }
679
+ end
624
680
  if superclass.respond_to? :shadow_struct
625
681
  @mark_function.mark superclass.mark_function.mark!
626
682
  end
@@ -633,12 +689,10 @@ module CShadow
633
689
  unless defined?(@free_function) and @free_function
634
690
  sf = shadow_library_source_file
635
691
  ssn = shadow_struct.name
636
- @free_function = sf.define_c_function("free_#{ssn}", FreeFunction)
637
- @free_function.instance_eval {
638
- scope :static
692
+ @free_function = define_inheritable_c_function(:free, FreeFunction) do
639
693
  arguments "#{ssn} *shadow"
640
694
  return_type "void"
641
- }
695
+ end
642
696
  if superclass.respond_to? :shadow_struct
643
697
  @free_function.free superclass.free_function.free!
644
698
  end
@@ -690,6 +744,8 @@ module CShadow
690
744
  unless defined?(@_alloc_method) and @_alloc_method
691
745
  sf = shadow_library_source_file
692
746
  ssn = shadow_struct.name
747
+ mark_name = refer_to_function :mark
748
+ free_name = refer_to_function :free
693
749
  @_alloc_method = sf.define_alloc_func(self)
694
750
  @_alloc_method.instance_eval {
695
751
  scope :extern
@@ -701,8 +757,8 @@ module CShadow
701
757
  body %{
702
758
  object = Data_Make_Struct(#{klass_c_name},
703
759
  #{ssn},
704
- mark_#{ssn},
705
- free_#{ssn},
760
+ #{mark_name},
761
+ #{free_name},
706
762
  shadow);
707
763
  shadow->self = object;
708
764
  }
@@ -899,7 +955,6 @@ module CShadow
899
955
  end
900
956
 
901
957
  unless base_class.ancestors.include? self
902
-
903
958
  base_class.class_eval {@base_class = self; @persistent = true}
904
959
  base_class.extend CShadowClassMethods
905
960
 
data/rakefile CHANGED
@@ -30,6 +30,8 @@ END
30
30
  test.files = Dir["test/test-*.rb"]
31
31
  }
32
32
 
33
+ ENV["VERSION"] = CGenerator::VERSION ## why isn't this automatic?
34
+
33
35
  task 'gem:release' => 'rubyforge:release' # to release to rubyforge as well
34
36
 
35
37
  task :release => ["rubyforge:release", "rubyforge:doc_release"]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cgen
3
3
  version: !ruby/object:Gem::Version
4
- hash: 87
4
+ hash: 85
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 16
9
- - 4
10
- version: 0.16.4
9
+ - 5
10
+ version: 0.16.5
11
11
  platform: ruby
12
12
  authors:
13
13
  - Joel VanderWerf
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-26 00:00:00 -07:00
18
+ date: 2010-07-08 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency