cgen 0.16.6 → 0.16.7
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +8 -0
- data/lib/cgen/attribute.rb +13 -1
- data/lib/cgen/cgen.rb +32 -6
- data/lib/cgen/cshadow.rb +54 -31
- data/test/test-attribute.rb +44 -1
- metadata +5 -5
data/History.txt
CHANGED
@@ -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
|
data/lib/cgen/attribute.rb
CHANGED
@@ -199,7 +199,7 @@ module CShadow
|
|
199
199
|
super
|
200
200
|
@class = @match
|
201
201
|
|
202
|
-
ssn = @class.
|
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/
|
data/lib/cgen/cgen.rb
CHANGED
@@ -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.
|
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
|
-
|
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
|
|
data/lib/cgen/cshadow.rb
CHANGED
@@ -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
|
-
|
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
|
-
"
|
472
|
-
"
|
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 => "#{
|
520
|
+
m.declare :shadow => "#{shadow_struct_name} *shadow"
|
526
521
|
m.setup :shadow =>
|
527
|
-
"Data_Get_Struct(self, #{
|
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}_#{
|
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
|
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
|
-
|
587
|
-
|
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.
|
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 =
|
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}_#{
|
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}_#{
|
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 =
|
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 =
|
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
|
710
|
-
setup :result => "result
|
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 =
|
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 =
|
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
|
-
|
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
|
-
|
937
|
+
i = attr.init and _load_data_method.attr_code i
|
915
938
|
end
|
916
939
|
end
|
917
940
|
|
data/test/test-attribute.rb
CHANGED
@@ -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
|
-
|
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:
|
4
|
+
hash: 81
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 16
|
9
|
-
-
|
10
|
-
version: 0.16.
|
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-
|
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
|