cgen 0.16.6 → 0.16.7

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