cgen 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/.gitignore +5 -0
  2. data/History.txt +199 -0
  3. data/README.txt +34 -0
  4. data/examples/bench.rb +14 -0
  5. data/examples/complex.rb +63 -0
  6. data/examples/complex2.rb +48 -0
  7. data/examples/cshadow-example.rb +55 -0
  8. data/examples/cshadow-point.rb +58 -0
  9. data/examples/ctest.rb +34 -0
  10. data/examples/ctest2.rb +32 -0
  11. data/examples/ctest3.rb +179 -0
  12. data/examples/ctest4.rb +18 -0
  13. data/examples/ctest5.rb +27 -0
  14. data/examples/example-ruby-talk-30April2004.rb +65 -0
  15. data/examples/fixed-array.rb +221 -0
  16. data/examples/inherit-example.rb +26 -0
  17. data/examples/inherit-example.txt +80 -0
  18. data/examples/instance-eval.rb +66 -0
  19. data/examples/ivset.rb +55 -0
  20. data/examples/marshal-test.rb +19 -0
  21. data/examples/matrix.rb +91 -0
  22. data/examples/modular-def.rb +87 -0
  23. data/examples/objattr.rb +46 -0
  24. data/examples/opaque-struct-test.rb +36 -0
  25. data/examples/sample.rb +184 -0
  26. data/examples/struct.rb +103 -0
  27. data/examples/test.rb +24 -0
  28. data/examples/yaml.rb +56 -0
  29. data/install.rb +1015 -0
  30. data/lib/cgen/attribute.rb +414 -0
  31. data/lib/cgen/cgen.rb +2041 -0
  32. data/lib/cgen/cshadow.rb +1037 -0
  33. data/lib/cgen/inherit.rb +46 -0
  34. data/rakefile +42 -0
  35. data/tasks/ann.rake +80 -0
  36. data/tasks/bones.rake +20 -0
  37. data/tasks/gem.rake +201 -0
  38. data/tasks/git.rake +40 -0
  39. data/tasks/notes.rake +27 -0
  40. data/tasks/post_load.rake +34 -0
  41. data/tasks/rdoc.rake +51 -0
  42. data/tasks/rubyforge.rake +55 -0
  43. data/tasks/setup.rb +292 -0
  44. data/tasks/spec.rake +54 -0
  45. data/tasks/svn.rake +47 -0
  46. data/tasks/test.rake +40 -0
  47. data/tasks/zentest.rake +36 -0
  48. data/test/test-attribute.rb +430 -0
  49. data/test/test-cgen.rb +127 -0
  50. data/test/test-cshadow.rb +289 -0
  51. data/test/test.rb +17 -0
  52. metadata +123 -0
@@ -0,0 +1,26 @@
1
+ require 'cgen/cshadow'
2
+
3
+ class Parent
4
+ include CShadow
5
+
6
+ shadow_attr_accessor :ruby_str => String
7
+ shadow_attr_accessor :c_int => "int c_int"
8
+ end
9
+
10
+ class Child < Parent
11
+ shadow_attr_accessor :obj => Object # VALUE type
12
+ end
13
+
14
+ Parent.commit
15
+ # we're done adding attrs and methods, so make.
16
+
17
+ x = Child.new
18
+ x.ruby_str = "foo"
19
+ x.obj = [1,2,3]
20
+ x.c_int = 3
21
+
22
+ p x
23
+ # ==> #<Child:0xb7ba96f4 ruby_str="foo", c_int=3, obj=[1, 2, 3]>
24
+
25
+ CShadow.allow_yaml
26
+ y x
@@ -0,0 +1,80 @@
1
+
2
+ The generated code looks, in part, as follows. Note that CGenerator/CShadow produces quite readable C code. In the Parent.h header file we have:
3
+
4
+ typedef struct Parent_Shadow {
5
+ VALUE self;
6
+ VALUE ruby_str; // String;
7
+ int c_int;
8
+ } Parent_Shadow;
9
+
10
+ typedef struct Child_Shadow {
11
+
12
+ /* Parent_Shadow members */
13
+ VALUE self;
14
+ VALUE ruby_str; // String;
15
+ int c_int;
16
+
17
+ VALUE obj; // Object;
18
+ } Child_Shadow;
19
+
20
+ Again, members are duplicated, which would be awful if you wanted to manually maintain the code, but who wants to do that :-)
21
+
22
+ In the Parent.c file, we have:
23
+
24
+ void mark_Parent_Shadow(Parent_Shadow *shadow)
25
+ {
26
+ rb_gc_mark((void *)shadow->self);
27
+ rb_gc_mark((void *)shadow->ruby_str);
28
+ }
29
+
30
+ void mark_Child_Shadow(Child_Shadow *shadow)
31
+ {
32
+ rb_gc_mark((void *)shadow->self);
33
+ rb_gc_mark((void *)shadow->ruby_str);
34
+ rb_gc_mark((void *)shadow->obj);
35
+ }
36
+
37
+ and similarly for the free functions, persistence functions, etc. The #new method generated by CShadow is where rb_obj_call_init() gets called. Note that initialization of shadow attributes is customizable.
38
+
39
+ VALUE new_module_Child_singleton_method(int argc, VALUE *argv, VALUE self)
40
+ {
41
+ VALUE object;
42
+ Child_Shadow *shadow;
43
+
44
+ object = Data_Make_Struct(self,
45
+ Child_Shadow,
46
+ mark_Child_Shadow,
47
+ free_Child_Shadow,
48
+ shadow);
49
+ shadow->self = object;
50
+
51
+ shadow->ruby_str = Qnil;
52
+ shadow->obj = Qnil;
53
+
54
+ rb_obj_call_init(object, argc, argv);
55
+
56
+ return object;
57
+ }
58
+
59
+ The #ruby_str= method only needs to be defined for Parent, because, of course, Ruby itself handles inheritance of methods. Note the type checking, which is done for the ruby_str member but not for the obj member.
60
+
61
+ VALUE ruby__str_equals_module_Parent_method(int argc, VALUE *argv, VALUE self)
62
+ {
63
+ VALUE arg;
64
+ Parent_Shadow *shadow;
65
+
66
+ rb_scan_args(argc, argv, "1", &arg);
67
+
68
+ if (!NIL_P(arg) &&
69
+ rb_obj_is_kind_of(arg, module_String) != Qtrue)
70
+ rb_raise(module_TypeError,
71
+ "argument arg declared String but passed %s.",
72
+ STR2CSTR(rb_funcall(
73
+ rb_funcall(arg, ID_type, 0),
74
+ ID_to__s, 0)));
75
+
76
+ Data_Get_Struct(self, Parent_Shadow, shadow);
77
+ shadow->ruby_str = arg;
78
+ return arg;
79
+ }
80
+
@@ -0,0 +1,66 @@
1
+ require 'cgen/cshadow'
2
+
3
+ class A
4
+ include CShadow
5
+
6
+ define_c_method :instance_eval_proc do
7
+ c_array_args {
8
+ required :pr
9
+ typecheck :pr => Proc
10
+ }
11
+ body %{
12
+ printf("instance_eval_proc\\n");
13
+ }
14
+ returns "rb_iterate(my_instance_eval, shadow->self, call_block, pr)"
15
+ end
16
+
17
+ fn = shadow_library_source_file.define :my_instance_eval
18
+ fn.instance_eval do
19
+ arguments "VALUE obj"
20
+ return_type "VALUE"
21
+ body %{
22
+ printf("my_instance_eval\\n");
23
+ }
24
+ returns "rb_obj_instance_eval(0, 0, obj)"
25
+ end
26
+
27
+ fn = shadow_library_source_file.define :call_block
28
+ fn.instance_eval do
29
+ arguments "VALUE arg1", "VALUE block"
30
+ return_type "VALUE"
31
+ body %{
32
+ printf("call_block\\n");
33
+ }
34
+ returns "rb_funcall(block, #{declare_symbol :call}, 0)"
35
+ end
36
+
37
+ end
38
+
39
+ Dir.chdir "tmp" do
40
+ A.commit
41
+ end
42
+
43
+ a = A.new
44
+ pr = proc { "self is %p" % self }
45
+
46
+ p a.instance_eval(&pr)
47
+ puts '---'
48
+ p a.instance_eval_proc(pr)
49
+
50
+ __END__
51
+
52
+
53
+
54
+ static VALUE my_instance_eval(VALUE obj)
55
+ {
56
+ return rb_obj_instance_eval(0, 0, obj);
57
+ }
58
+
59
+ static VALUE call_block(VALUE arg1, VALUE block)
60
+ {
61
+ return rb_funcall(block, ID_call, 0);
62
+ }
63
+
64
+ //...
65
+ rb_iterate(my_instance_eval, obj, call_block, pr);
66
+
@@ -0,0 +1,55 @@
1
+ class Foo
2
+ def initialize
3
+ @a = 1
4
+ @b = 2
5
+ end
6
+
7
+ def inc_iv
8
+ [:@a, :@b].each { |iv|
9
+ eval "#{iv} += 1"
10
+ }
11
+ end
12
+ end
13
+
14
+ require 'cgen/cshadow'
15
+
16
+ class Bar
17
+ include CShadow
18
+
19
+ def initialize
20
+ @a = 1
21
+ @b = 2
22
+ end
23
+
24
+ def inc_iv
25
+ [:@a, :@b].each { |iv|
26
+ iv = iv
27
+ set_iv(iv, get_iv(iv) + 1)
28
+ }
29
+ end
30
+
31
+ define_method :set_iv do
32
+ arguments :attr, :value
33
+ body %{
34
+ rb_ivar_set(shadow->self, rb_to_id(attr), value);
35
+ }
36
+ returns %{shadow->self}
37
+ end
38
+ private :set_iv
39
+
40
+ define_method :get_iv do
41
+ arguments :attr
42
+ returns %{rb_ivar_get(shadow->self, rb_to_id(attr))}
43
+ end
44
+ private :get_iv
45
+
46
+ def inspect
47
+ "<Bar: a = #{@a}, b = #{@b}>"
48
+ end
49
+ end
50
+
51
+ Bar.commit # write to .c files, make, and require
52
+
53
+ bar = Bar.new
54
+ bar.inc_iv
55
+ p bar
@@ -0,0 +1,19 @@
1
+ require 'cgen/cshadow'
2
+
3
+ class MarshalTest
4
+ include CShadow
5
+
6
+ shadow_attr_accessor :x => Object
7
+ end
8
+
9
+ Dir.mkdir "tmp" rescue SystemCallError
10
+ Dir.chdir "tmp"
11
+
12
+ MarshalTest.commit
13
+
14
+ mt = MarshalTest.new
15
+
16
+ mt.x = "foo"
17
+ p mt.x
18
+
19
+ p Marshal.dump mt
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cgen/cshadow'
4
+
5
+ class MyMatrix
6
+ include CShadow
7
+
8
+ shadow_attr_reader :rows => "int rows", :cols => "int cols"
9
+ shadow_attr :matrix => "double *matrix"
10
+
11
+ define_c_method(:initialize) {
12
+ c_array_args {
13
+ required :rows, :cols
14
+ typecheck :rows => Fixnum, :cols => Fixnum
15
+ }
16
+ declare :size => "int size"
17
+ body %{
18
+ shadow->rows = FIX2INT(rows);
19
+ shadow->cols = FIX2INT(cols);
20
+
21
+ if (shadow->rows <= 0)
22
+ rb_raise(#{declare_class ArgumentError}, "Rows must be positive.");
23
+ if (shadow->cols <= 0)
24
+ rb_raise(#{declare_class ArgumentError}, "Cols must be positive.");
25
+
26
+ size = shadow->rows * shadow->cols;
27
+ shadow->matrix = ALLOC_N(double, size);
28
+ memset(shadow->matrix, 0, size * sizeof(double));
29
+ }
30
+ }
31
+
32
+ define_c_method(:[]) {
33
+ arguments :i, :j
34
+ declare :ii => "int ii", :jj => "int jj"
35
+ body %{
36
+ ii = NUM2INT(i);
37
+ jj = NUM2INT(j);
38
+
39
+ if (ii < 0 || ii >= shadow->rows)
40
+ rb_raise(#{declare_class IndexError},
41
+ "Row index %d out of range [0, %d]",
42
+ ii, shadow->rows - 1);
43
+
44
+ if (jj < 0 || jj >= shadow->cols)
45
+ rb_raise(#{declare_class IndexError},
46
+ "Column index %d out of range [0, %d]",
47
+ jj, shadow->cols - 1);
48
+ }
49
+ returns "rb_float_new(shadow->matrix[ii * shadow->cols + jj])"
50
+ }
51
+
52
+ define_c_method(:[]=) {
53
+ arguments :i, :j, :x
54
+ declare :ii => "int ii", :jj => "int jj", :xx => "double xx"
55
+ body %{
56
+ ii = NUM2INT(i);
57
+ jj = NUM2INT(j);
58
+ xx = NUM2DBL(x);
59
+
60
+ if (ii < 0 || ii >= shadow->rows)
61
+ rb_raise(#{declare_class IndexError},
62
+ "Row index %d out of range 0..%d",
63
+ ii, shadow->rows - 1);
64
+
65
+ if (jj < 0 || jj >= shadow->cols)
66
+ rb_raise(#{declare_class IndexError},
67
+ "Column index %d out of range 0..%d",
68
+ jj, shadow->cols - 1);
69
+
70
+ shadow->matrix[ii * shadow->cols + jj] = xx;
71
+ }
72
+ returns "x"
73
+ }
74
+ end
75
+
76
+ require 'ftools'
77
+ dir = File.join("tmp", RUBY_VERSION)
78
+ File.mkpath dir
79
+ Dir.chdir dir
80
+
81
+ MyMatrix.commit
82
+
83
+ m = MyMatrix.new 5, 2
84
+ m[3,1] = 8.2e+13
85
+ puts m[3,1]
86
+ puts m[3,0]
87
+ begin
88
+ puts m[3,2]
89
+ rescue IndexError
90
+ puts "Caught an IndexError: m[3,2] is out of range."
91
+ end
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # This example shows how to factor out definitions into a module. The
4
+ # only additional library code needed is the following:
5
+
6
+ module ModuleMethodSaver
7
+ def method_missing(meth, *args, &block)
8
+ @saved ||= []
9
+ @saved << [meth, args, block]
10
+ end
11
+
12
+ def included(m)
13
+ if @saved
14
+ @saved.each do |meth, args, block|
15
+ m.send(meth, *args, &block)
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+
22
+ require 'cgen/cshadow'
23
+
24
+ module ComplexStuff
25
+ extend ModuleMethodSaver
26
+
27
+ shadow_attr_accessor :re => "double re", :im => "double im"
28
+
29
+ def initialize re, im
30
+ self.re = re
31
+ self.im = im
32
+ end
33
+
34
+ define_c_method(:abs) {
35
+ include "<math.h>"
36
+ returns "rb_float_new(sqrt(pow(shadow->re, 2) + pow(shadow->im, 2)))"
37
+ }
38
+
39
+ define_c_method(:mul!) {
40
+ arguments :other
41
+ declare :other_shadow => "MyComplex_Shadow *other_shadow"
42
+ declare :new_re => "double new_re", :new_im => "double new_im"
43
+ body %{
44
+ switch (TYPE(other)) {
45
+ case T_FIXNUM: shadow->re *= FIX2INT(other);
46
+ shadow->im *= FIX2INT(other); break;
47
+ case T_FLOAT: shadow->re *= NUM2DBL(other);
48
+ shadow->im *= NUM2DBL(other); break;
49
+ default:
50
+ if (rb_obj_is_kind_of(other, #{declare_class MyComplex}) ==
51
+ Qtrue) {
52
+ Data_Get_Struct(other, MyComplex_Shadow, other_shadow);
53
+ new_re = shadow->re * other_shadow->re -
54
+ shadow->im * other_shadow->im;
55
+ new_im = shadow->re * other_shadow->im +
56
+ shadow->im * other_shadow->re;
57
+ shadow->re = new_re;
58
+ shadow->im = new_im;
59
+ }
60
+ else
61
+ rb_raise(#{declare_class ArgumentError},
62
+ "Argument to mul! is not numeric.");
63
+ }
64
+ }
65
+ returns "self"
66
+ }
67
+ end
68
+
69
+ class MyComplex < Numeric
70
+ include CShadow
71
+ include ComplexStuff
72
+ end
73
+
74
+ require 'ftools'
75
+ dir = File.join("tmp", RUBY_VERSION)
76
+ File.mkpath dir
77
+ Dir.chdir dir
78
+
79
+ MyComplex.commit
80
+
81
+ z = MyComplex.new 5, 1.3
82
+ puts z.abs
83
+ z.mul! 10
84
+ p [z.re, z.im]
85
+ w = MyComplex.new 7.9, -1.2
86
+ z.mul! w
87
+ p [z.re, z.im]
@@ -0,0 +1,46 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'cgen/cshadow'
4
+
5
+ SAME_LIBRARY = true
6
+
7
+ class A
8
+ include CShadow
9
+ shadow_attr_accessor :obj => Object, :sym => Symbol
10
+ end
11
+
12
+ class B
13
+ include CShadow
14
+
15
+ if SAME_LIBRARY
16
+ shadow_library A # in the same lib as A
17
+ shadow_library_file 'B' # but in a different file
18
+ else
19
+ # different lib, but connected with a '#include'
20
+ shadow_library_include_file.include '../A/A.h'
21
+ end
22
+
23
+ shadow_attr_accessor :a => [A]
24
+
25
+ def initialize
26
+ self.a = A.new
27
+ self.a.sym = :something
28
+ end
29
+ end
30
+
31
+ require 'ftools'
32
+ dir = File.join("tmp", RUBY_VERSION)
33
+ File.mkpath dir
34
+ Dir.chdir dir
35
+
36
+ A.commit
37
+ unless SAME_LIBRARY
38
+ B.commit
39
+ end
40
+
41
+ p B.new.a.sym
42
+
43
+ A.shadow_library.make 'distclean'
44
+ unless SAME_LIBRARY
45
+ B.shadow_library.make 'distclean'
46
+ end