cgen 0.16.6 → 0.16.7

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.
@@ -1,3 +1,11 @@
1
+ cgen 0.16.7
2
+
3
+ - misc refactoring, cleanup, docs, error checking
4
+
5
+ - added BooleanAttribute with tests
6
+
7
+ - improved placement of alloc funcs in library init code
8
+
1
9
  cgen 0.16.6
2
10
 
3
11
  - optimization: don't generate a mark or free function when an attribute
@@ -199,7 +199,7 @@ module CShadow
199
199
  super
200
200
  @class = @match
201
201
 
202
- ssn = @class.shadow_struct.name
202
+ ssn = @class.shadow_struct_name
203
203
 
204
204
  @cvar = @var
205
205
  if @class < CShadow
@@ -307,6 +307,18 @@ module CShadow
307
307
  end
308
308
  end
309
309
 
310
+ class BooleanAttribute < CNativeAttribute
311
+ @pattern = /\A(bool(?:ean)?)\s+(\w+)\z/
312
+ def initialize(*args)
313
+ super
314
+ @cdecl = @cdecl.sub(@match[1], "int")
315
+ @reader = "result = shadow->#{@cvar} ? Qtrue : Qfalse"
316
+ @writer = "shadow->#{@cvar} = RTEST(arg)" # type conversion
317
+ @dump = "rb_ary_push(result, shadow->#{@cvar} ? Qtrue : Qfalse)"
318
+ @load = "tmp = rb_ary_shift(from_array); shadow->#{@cvar} = RTEST(tmp)"
319
+ end
320
+ end
321
+
310
322
  # Does not check for overflow.
311
323
  class ShortAttribute < IntAttribute
312
324
  @pattern = /\A(short)\s+(\w+)\z/
@@ -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.6'
421
+ VERSION = '0.16.7'
422
422
 
423
423
  class Accumulator ## should be a mixin? "Cumulative"?
424
424
 
@@ -624,7 +624,8 @@ class Library < Template
624
624
  rb_define_method!,
625
625
  rb_define_module_function!,
626
626
  rb_define_global_function!,
627
- rb_define_singleton_method!
627
+ rb_define_singleton_method!,
628
+ rb_define_alloc_func!
628
629
  ## odd, putting an accum inside
629
630
  ## a template which is not the parent
630
631
  end
@@ -1101,6 +1102,34 @@ class Library < Template
1101
1102
  :rb_define_module_function,
1102
1103
  :rb_define_global_function,
1103
1104
  :rb_define_singleton_method) {RbDefineAccumulator}
1105
+
1106
+ class RbDefineAllocAccumulator < Accumulator
1107
+ def add spec
1108
+ klass = spec[:class]
1109
+ cfile = spec[:cfile]
1110
+
1111
+ if @pile.find {|s| s[:class] == klass}
1112
+ raise ArgumentError, "Duplicate alloc func definition for #{klass}"
1113
+ end
1114
+
1115
+ klass_c_name =
1116
+ spec[:class_c_name] ||= @parent.declare_class(klass, cfile) ## @parent ?
1117
+ spec[:c_name] ||= "alloc_func_#{klass_c_name}".intern
1118
+ @pile << spec
1119
+
1120
+ spec[:c_name]
1121
+ end
1122
+
1123
+ def to_s
1124
+ @pile.collect { |spec|
1125
+ c_name = spec[:c_name]
1126
+ klass_c_name = spec[:class_c_name]
1127
+ "rb_define_alloc_func(#{klass_c_name}, #{c_name});"
1128
+ }.join "\n"
1129
+ end
1130
+ end # class RbDefineAllocAccumulator
1131
+
1132
+ accumulator(:rb_define_alloc_func) {RbDefineAllocAccumulator}
1104
1133
 
1105
1134
  # call-seq:
1106
1135
  # define_c_method mod, name, subclass
@@ -1465,10 +1494,7 @@ class CFile < CFragment
1465
1494
  alias define_c_class_method define_c_singleton_method
1466
1495
 
1467
1496
  def define_alloc_func klass
1468
- klass_c_name = declare_class klass, self # cfile
1469
- c_name = "alloc_func_#{klass_c_name}"
1470
- library.init_library_function.body \
1471
- %{rb_define_alloc_func(#{klass_c_name}, #{c_name})}
1497
+ c_name = rb_define_alloc_func :class => klass, :cfile => self
1472
1498
  define c_name, Function
1473
1499
  end
1474
1500
 
@@ -268,13 +268,7 @@ module CShadow
268
268
  classes = Library.sort_class_tree(@classes_to_commit)
269
269
 
270
270
  classes.each do |cl|
271
- # make sure the following have been defined by now
272
- cl.shadow_struct
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
271
+ cl.fill_in_defs
278
272
  end
279
273
  end
280
274
 
@@ -468,8 +462,9 @@ module CShadow
468
462
  if defined? @shadow_library_file
469
463
  if file
470
464
  raise RuntimeError,
471
- "Class #{self} is already associated" +
472
- " with file #{@shadow_library_file}."
465
+ "Cannot assign class #{self} to file #{file.inspect}; class" +
466
+ " is already associated" +
467
+ " with file #{@shadow_library_file[0].name}."
473
468
  end
474
469
  @shadow_library_file
475
470
  elsif file
@@ -522,9 +517,9 @@ module CShadow
522
517
  sf = shadow_library_source_file
523
518
  m = sf.define_c_method self, name, subclass
524
519
  m.scope :extern
525
- m.declare :shadow => "#{shadow_struct.name} *shadow"
520
+ m.declare :shadow => "#{shadow_struct_name} *shadow"
526
521
  m.setup :shadow =>
527
- "Data_Get_Struct(self, #{shadow_struct.name}, shadow)"
522
+ "Data_Get_Struct(self, #{shadow_struct_name}, shadow)"
528
523
  m.instance_eval(&block) if block
529
524
  m
530
525
  end
@@ -562,7 +557,7 @@ module CShadow
562
557
  def define_inheritable_c_function name,
563
558
  subclass = CGenerator::Function, &block
564
559
  sf = shadow_library_source_file
565
- m = sf.define_c_function "#{name}_#{shadow_struct.name}", subclass
560
+ m = sf.define_c_function "#{name}_#{shadow_struct_name}", subclass
566
561
  c_function_templates[name] = m
567
562
  m.scope :extern
568
563
  m.instance_eval(&block) if block
@@ -571,7 +566,18 @@ module CShadow
571
566
 
572
567
  #== Internal methods ==#
573
568
 
574
- def c_function_templates; @c_function_templates ||= {}; end
569
+ def fill_in_defs
570
+ shadow_struct
571
+ new_method; _alloc_method
572
+
573
+ check_inherited_functions
574
+
575
+ if self == base_class
576
+ _dump_data_method; _load_data_method
577
+ end
578
+ end
579
+
580
+ def c_function_templates; @c_function_templates ||= {}; end
575
581
  # Note that {} nondeterministic, so these should only be used to
576
582
  # check existence or get value, not to iterate.
577
583
 
@@ -581,15 +587,17 @@ module CShadow
581
587
  superclass.find_super_function(sym))
582
588
  end
583
589
 
584
- # Construct the name used for the shadow struct.
590
+ # Construct the name used for the shadow struct. Attempts to preserve
591
+ # the full class path.
585
592
  def shadow_struct_name
586
- name.gsub(/_/, '__').gsub(/::/, '_o_') + CShadow::SHADOW_SUFFIX
587
- # To preserve differences.
593
+ @shadow_struct_name ||=
594
+ name.gsub(/_/, '__').gsub(/::/, '_o_') + CShadow::SHADOW_SUFFIX
588
595
  end
589
596
 
590
597
  # Return the object for managing the shadow struct.
591
598
  def shadow_struct
592
599
  unless defined?(@shadow_struct) and @shadow_struct
600
+ raise if @inherited_shadow_struct
593
601
  sf = shadow_library_source_file
594
602
  ssn = shadow_struct_name
595
603
  @shadow_struct = sf.declare_extern_struct(ssn)
@@ -599,7 +607,7 @@ module CShadow
599
607
  sss = superclass.shadow_struct
600
608
  shadow_struct.inherit\
601
609
  sss.inherit!,
602
- "/* #{superclass.shadow_struct.name} members */",
610
+ "/* #{superclass.shadow_struct_name} members */",
603
611
  sss.declare!, " "
604
612
 
605
613
  unless superclass.shadow_library_source_file ==
@@ -616,7 +624,7 @@ module CShadow
616
624
  def new_method
617
625
  unless defined?(@new_method) and @new_method
618
626
  sf = shadow_library_source_file
619
- ssn = shadow_struct.name
627
+ ssn = shadow_struct_name
620
628
  mark_name = refer_to_function :mark
621
629
  free_name = refer_to_function :free
622
630
  @new_method = sf.define_c_singleton_method self,
@@ -647,20 +655,35 @@ module CShadow
647
655
  @new_method
648
656
  end
649
657
 
658
+ # Set of function names (symbols) that have been referenced in the
659
+ # implementation of this class. The names are like :free or :mark,
660
+ # rather than :free_in_class_C, to give a common identity to all free
661
+ # functions.
650
662
  def referenced_functions
651
663
  @referenced_functions ||= {}
652
664
  end
653
665
 
666
+ # Generate a string which, by convention, names the function for
667
+ # instances of this particular class. Also, keeps track of
668
+ # referenced_functions.
654
669
  def refer_to_function sym
655
670
  referenced_functions[sym] = true
656
- "#{sym}_#{shadow_struct.name}"
671
+ "#{sym}_#{shadow_struct_name}"
672
+ end
673
+
674
+ def inherited_function
675
+ @inherited_function ||= {}
657
676
  end
658
677
 
678
+ # For each function referenced in this class, but not defined, resolve
679
+ # the reference by defining a macro to evaluate to the first
680
+ # implementation found by ascending the class tree.
659
681
  def check_inherited_functions
660
682
  syms = referenced_functions.keys.sort_by{|k|k.to_s}
661
683
  syms.reject {|sym| c_function_templates[sym]}.each do |sym|
662
- fname = "#{sym}_#{shadow_struct.name}"
684
+ fname = "#{sym}_#{shadow_struct_name}"
663
685
  pf = find_super_function(sym)
686
+ inherited_function[sym] = true
664
687
  pf_str = pf ? pf.name : (sym == :free ? -1 : 0)
665
688
  # -1 means free the struct; See README.EXT
666
689
  shadow_library_source_file.declare fname.intern =>
@@ -671,8 +694,9 @@ module CShadow
671
694
  # Return the object for managing the mark function of the class.
672
695
  def mark_function
673
696
  unless defined?(@mark_function) and @mark_function
697
+ raise if inherited_function[:mark]
674
698
  sf = shadow_library_source_file
675
- ssn = shadow_struct.name
699
+ ssn = shadow_struct_name
676
700
  @mark_function = define_inheritable_c_function(:mark, MarkFunction) do
677
701
  arguments "#{ssn} *shadow"
678
702
  return_type "void"
@@ -687,8 +711,9 @@ module CShadow
687
711
  # Return the object for managing the free function of the class.
688
712
  def free_function
689
713
  unless defined?(@free_function) and @free_function
714
+ raise if inherited_function[:free]
690
715
  sf = shadow_library_source_file
691
- ssn = shadow_struct.name
716
+ ssn = shadow_struct_name
692
717
  @free_function = define_inheritable_c_function(:free, FreeFunction) do
693
718
  arguments "#{ssn} *shadow"
694
719
  return_type "void"
@@ -706,8 +731,8 @@ module CShadow
706
731
  return nil unless persistent?
707
732
  unless defined?(@_dump_data_method) and @_dump_data_method
708
733
  @_dump_data_method = define_c_method(:_dump_data, AttrMethod) {
709
- declare :result => "VALUE result"
710
- setup :result => "result = rb_ary_new()"
734
+ declare :result => "VALUE result"
735
+ setup :result => "result = rb_ary_new()"
711
736
  body pre_code!, attr_code!, post_code!
712
737
  returns "result"
713
738
  }
@@ -743,7 +768,7 @@ module CShadow
743
768
  return nil unless persistent?
744
769
  unless defined?(@_alloc_method) and @_alloc_method
745
770
  sf = shadow_library_source_file
746
- ssn = shadow_struct.name
771
+ ssn = shadow_struct_name
747
772
  mark_name = refer_to_function :mark
748
773
  free_name = refer_to_function :free
749
774
  @_alloc_method = sf.define_alloc_func(self)
@@ -857,7 +882,7 @@ module CShadow
857
882
  end
858
883
 
859
884
  source_file = shadow_library_source_file
860
- ssn = shadow_struct.name
885
+ ssn = shadow_struct_name
861
886
  @shadow_attrs ||= []
862
887
 
863
888
  meths = nil
@@ -901,17 +926,15 @@ module CShadow
901
926
 
902
927
  new_method.attr_code attr.init if attr.init
903
928
 
904
- m = attr.mark
905
- mark_function.mark m if m
906
- f = attr.free
907
- free_function.free f if f
929
+ m = attr.mark and mark_function.mark m
930
+ f = attr.free and free_function.free f
908
931
 
909
932
  if persistent?
910
933
  if attr_persists
911
934
  _dump_data_method.attr_code attr.dump
912
935
  _load_data_method.attr_code attr.load
913
936
  else
914
- _load_data_method.attr_code attr.init if attr.init
937
+ i = attr.init and _load_data_method.attr_code i
915
938
  end
916
939
  end
917
940
 
@@ -154,7 +154,8 @@ class ShadowObjectAttributeTest < AttributeTest
154
154
  n = ObjectSpace.each_object(c) {}
155
155
  make_things c, 10
156
156
  GC.start
157
- assert_equal(n+1, ObjectSpace.each_object(c) {})
157
+ n2 = ObjectSpace.each_object(c) {}
158
+ assert_send( [[n, n+1], :include?, n2] )
158
159
  end
159
160
 
160
161
  def test_marshal_uninitialized
@@ -258,6 +259,48 @@ class IntAttributeTest < AttributeTest
258
259
  end
259
260
  end
260
261
 
262
+ class BooleanAttributeTest < AttributeTest
263
+ class BooleanAttributeSample < AttributeSample
264
+ shadow_attr_accessor :x => "boolean x"
265
+ end
266
+
267
+ def test__initial
268
+ @ias = BooleanAttributeSample.new
269
+ assert_equal(false, @ias.x)
270
+ end
271
+
272
+ def test_accessor
273
+ @ias = BooleanAttributeSample.new
274
+ @ias.x = true
275
+ assert_equal(true, @ias.x)
276
+ @ias.x = false
277
+ assert_equal(false, @ias.x)
278
+ @ias.x = nil
279
+ assert_equal(false, @ias.x)
280
+ end
281
+
282
+ def test_conversion
283
+ @ias = BooleanAttributeSample.new
284
+ @ias.x = 5
285
+ assert_equal(true, @ias.x)
286
+ @ias.x = {:foo => "bar"}
287
+ assert_equal(true, @ias.x)
288
+ end
289
+
290
+ def test_marshal
291
+ @ias = BooleanAttributeSample.new
292
+ @ias.x = true
293
+ s = Marshal.dump @ias
294
+ t = Marshal.load s
295
+ assert_equal(@ias.x, t.x)
296
+
297
+ @ias.x = false
298
+ s = Marshal.dump @ias
299
+ t = Marshal.load s
300
+ assert_equal(@ias.x, t.x)
301
+ end
302
+ end
303
+
261
304
  class LongAttributeTest < AttributeTest
262
305
  class LongAttributeSample < AttributeSample
263
306
  shadow_attr_accessor :x => "long x"
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: 83
4
+ hash: 81
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 16
9
- - 6
10
- version: 0.16.6
9
+ - 7
10
+ version: 0.16.7
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-07-08 00:00:00 -07:00
18
+ date: 2010-08-11 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -124,6 +124,6 @@ signing_key:
124
124
  specification_version: 3
125
125
  summary: C code generator
126
126
  test_files:
127
- - test/test-attribute.rb
128
127
  - test/test-cgen.rb
128
+ - test/test-attribute.rb
129
129
  - test/test-cshadow.rb