cgen 0.16.4 → 0.16.5

Sign up to get free protection for your applications and to get access to all the features.
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