cauterize 0.0.1.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/.gitignore +24 -0
  2. data/.rspec +1 -0
  3. data/.travisci.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +152 -0
  7. data/Rakefile +38 -0
  8. data/bin/cauterize +53 -0
  9. data/c/src/cauterize.c +74 -0
  10. data/c/src/cauterize.h +46 -0
  11. data/c/src/cauterize_debug.h +29 -0
  12. data/c/src/cauterize_util.h +7 -0
  13. data/c/test/greatest.h +536 -0
  14. data/c/test/test.c +166 -0
  15. data/cauterize.gemspec +26 -0
  16. data/example/Cauterize +44 -0
  17. data/example/build.sh +4 -0
  18. data/lib/cauterize/base_type.rb +96 -0
  19. data/lib/cauterize/builders.rb +27 -0
  20. data/lib/cauterize/builders/c/buildable.rb +59 -0
  21. data/lib/cauterize/builders/c/composite.rb +55 -0
  22. data/lib/cauterize/builders/c/enumeration.rb +41 -0
  23. data/lib/cauterize/builders/c/fixed_array.rb +62 -0
  24. data/lib/cauterize/builders/c/group.rb +95 -0
  25. data/lib/cauterize/builders/c/scalar.rb +31 -0
  26. data/lib/cauterize/builders/c/variable_array.rb +90 -0
  27. data/lib/cauterize/c_builder.rb +63 -0
  28. data/lib/cauterize/cauterize.rb +33 -0
  29. data/lib/cauterize/composite.rb +50 -0
  30. data/lib/cauterize/enumeration.rb +77 -0
  31. data/lib/cauterize/fixed_array.rb +43 -0
  32. data/lib/cauterize/formatter.rb +59 -0
  33. data/lib/cauterize/group.rb +56 -0
  34. data/lib/cauterize/scalar.rb +38 -0
  35. data/lib/cauterize/snake_case.rb +21 -0
  36. data/lib/cauterize/variable_array.rb +56 -0
  37. data/lib/cauterize/version.rb +3 -0
  38. data/spec/base_type_spec.rb +167 -0
  39. data/spec/builders/c/buildable_spec.rb +25 -0
  40. data/spec/builders/c/composite_spec.rb +46 -0
  41. data/spec/builders/c/enumeration_spec.rb +32 -0
  42. data/spec/builders/c/fixed_array_spec.rb +36 -0
  43. data/spec/builders/c/group_spec.rb +112 -0
  44. data/spec/builders/c/scalar_spec.rb +8 -0
  45. data/spec/builders/c/variable_array_spec.rb +50 -0
  46. data/spec/builders_spec.rb +51 -0
  47. data/spec/c_builder_spec.rb +133 -0
  48. data/spec/cauterize_spec.rb +8 -0
  49. data/spec/composite_spec.rb +62 -0
  50. data/spec/enumeration_spec.rb +104 -0
  51. data/spec/fixed_array_spec.rb +62 -0
  52. data/spec/group_spec.rb +104 -0
  53. data/spec/scalar_spec.rb +36 -0
  54. data/spec/spec_helper.rb +115 -0
  55. data/spec/support/shared_examples_for_array_buildables.rb +22 -0
  56. data/spec/support/shared_examples_for_c_buildables.rb +91 -0
  57. data/spec/support/shared_examples_for_sane_c_buildables.rb +22 -0
  58. data/spec/support/shared_examples_for_stubbed_functions.rb +18 -0
  59. data/spec/test_main.c +13 -0
  60. data/spec/variable_array_spec.rb +92 -0
  61. metadata +212 -0
@@ -0,0 +1,77 @@
1
+ # enumeration.rb
2
+ #
3
+ # Enumerations correspond exactly to C enumerations.
4
+
5
+ require 'set'
6
+
7
+ module Cauterize
8
+ module_function
9
+ def enumeration(name)
10
+ e = enumerations[name] || enumerations[name] = Enumeration.new(name)
11
+ yield e if block_given?
12
+ return e
13
+ end
14
+
15
+ def enumeration!(name, &blk)
16
+ if enumerations[name]
17
+ raise Exception.new("Enumeration with name #{name} already exists.")
18
+ else
19
+ enumeration(name, &blk)
20
+ end
21
+ end
22
+
23
+ def enumerations
24
+ @enumerations ||= {}
25
+ end
26
+
27
+ class EnumerationValue
28
+ attr_reader :name, :value
29
+
30
+ def initialize(name, value)
31
+ @name = name
32
+ @value = value
33
+ end
34
+ end
35
+
36
+ class Enumeration < BaseType
37
+ attr_reader :values
38
+
39
+ def initialize(name)
40
+ super
41
+ @values = {}
42
+ @value_id = 0
43
+ @used_ids = Set.new
44
+ end
45
+
46
+ def value(name, id=nil)
47
+ if @values[name]
48
+ raise Exception.new("Cannot duplicate name #{name}.")
49
+ end
50
+
51
+ next_id = value_id(id)
52
+ @used_ids << next_id
53
+ @values[name] = EnumerationValue.new(name, next_id)
54
+ end
55
+
56
+ private
57
+
58
+ def value_id(next_id=nil)
59
+ if next_id
60
+ @value_id = next_id
61
+ end
62
+
63
+ v = @value_id
64
+
65
+ if @used_ids.include? v
66
+ raise Exception.new("Cannot duplicate constant #{v}.")
67
+ end
68
+
69
+ loop do
70
+ @value_id += 1
71
+ break unless @used_ids.include? @value_id
72
+ end
73
+
74
+ return v
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,43 @@
1
+ module Cauterize
2
+ module_function
3
+
4
+ def fixed_array(name)
5
+ a = fixed_arrays[name] || fixed_arrays[name] = FixedArray.new(name)
6
+ yield a if block_given?
7
+ return a
8
+ end
9
+
10
+ def fixed_array!(name, &blk)
11
+ if fixed_arrays[name]
12
+ raise Exception.new("FixedArray with name #{name} already exists.")
13
+ else
14
+ fixed_array(name, &blk)
15
+ end
16
+ end
17
+
18
+ def fixed_arrays
19
+ @fixed_ararys ||= {}
20
+ end
21
+
22
+ class FixedArray < BaseType
23
+ def initialize(name)
24
+ super
25
+ end
26
+
27
+ def array_type(t = nil)
28
+ if t
29
+ @array_type = BaseType.find_type!(t)
30
+ else
31
+ @array_type
32
+ end
33
+ end
34
+
35
+ def array_size(s = nil)
36
+ if s
37
+ @array_size = s
38
+ else
39
+ @array_size
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,59 @@
1
+ def default_formatter
2
+ Formatter.new
3
+ end
4
+
5
+ class Formatter
6
+ def initialize
7
+ @indent_level = 0
8
+ @indent_str = " "
9
+ @lines = []
10
+ end
11
+
12
+ def indent(line)
13
+ (@indent_str * @indent_level) + line
14
+ end
15
+
16
+ def <<(line)
17
+ @lines << indent(line)
18
+ end
19
+
20
+ # indent back one level
21
+ def backdent(line)
22
+ @indent_level -= 1
23
+ @lines << indent(line)
24
+ @indent_level += 1
25
+ end
26
+
27
+ def append(text)
28
+ if @lines.length == 0
29
+ @lines << ""
30
+ end
31
+
32
+ @lines[-1] += text
33
+ end
34
+
35
+ def braces
36
+ self << "{"
37
+ indented { yield self } if block_given?
38
+ self << "}"
39
+ end
40
+
41
+ def blank_line
42
+ @lines << ""
43
+ end
44
+
45
+ def to_s(extra_indent = 0)
46
+ @indent_level += extra_indent
47
+ s = @lines.map {|l| indent(l) }.join("\n")
48
+ @indent_level -= extra_indent
49
+ return s
50
+ end
51
+
52
+ private
53
+
54
+ def indented
55
+ @indent_level += 1
56
+ yield self
57
+ @indent_level -= 1
58
+ end
59
+ end
@@ -0,0 +1,56 @@
1
+ module Cauterize
2
+ module_function
3
+
4
+ def group(name)
5
+ a = groups[name] || groups[name] = Group.new(name)
6
+ yield a if block_given?
7
+ return a
8
+ end
9
+
10
+ def group!(name, &blk)
11
+ if groups[name]
12
+ raise Exception.new("Group with name #{name} already exists.")
13
+ else
14
+ group(name, &blk)
15
+ end
16
+ end
17
+
18
+ def groups
19
+ @groups ||= {}
20
+ end
21
+
22
+ class GroupField
23
+ attr_reader :name, :type
24
+
25
+ def initialize(name, type)
26
+ @name = name
27
+ @type = BaseType.find_type!(type)
28
+ end
29
+
30
+ def enum_sym
31
+ end
32
+ end
33
+
34
+ class Group < BaseType
35
+ attr_reader :fields, :tag_enum
36
+
37
+ def initialize(name)
38
+ super
39
+ @fields = {}
40
+ @tag_enum = Cauterize.enumeration!("group_#{name}_type".to_sym)
41
+ end
42
+
43
+ def field(name, type)
44
+ if @fields[name]
45
+ raise Exception.new("Field name #{name} already used.")
46
+ else
47
+ @fields[name] = GroupField.new(name, type)
48
+ @tag_enum.value(enum_sym(name))
49
+ end
50
+ end
51
+
52
+ def enum_sym(fname)
53
+ "group_#{@name}_type_#{fname}".up_snake.to_sym
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,38 @@
1
+ # scalar.rb
2
+ #
3
+ # scalars are types that, in C, can be updated with assignment. This includes
4
+ # native types in C and typedefs around these native types.
5
+ #
6
+ # scalars are not structs, enumerations, unions, or arrays.
7
+
8
+ module Cauterize
9
+ module_function
10
+
11
+ def scalar(name)
12
+ a = scalars[name] || scalars[name] = Scalar.new(name)
13
+ yield a if block_given?
14
+ return a
15
+ end
16
+
17
+ def scalar!(name, &blk)
18
+ if scalars[name]
19
+ raise Exception.new("Scalar with name #{name} already exists.")
20
+ else
21
+ scalar(name, &blk)
22
+ end
23
+ end
24
+
25
+ def scalars
26
+ @scalars ||= {}
27
+ end
28
+
29
+ def flush_scalars
30
+ @scalars = {}
31
+ end
32
+
33
+ class Scalar < BaseType
34
+ def initialize(name)
35
+ super
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,21 @@
1
+ class String
2
+ def snake
3
+ self.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_")
7
+ end
8
+
9
+ def up_snake
10
+ snake.upcase
11
+ end
12
+
13
+ def down_snake
14
+ snake.downcase
15
+ end
16
+
17
+ def camel
18
+ return self.capitalize if self !~ /_/ && self =~ /[A-z]+.*/
19
+ split('_').map{|e| e.capitalize}.join
20
+ end
21
+ end
@@ -0,0 +1,56 @@
1
+ module Cauterize
2
+ module_function
3
+
4
+ def variable_array(name)
5
+ a = variable_arrays[name] || variable_arrays[name] = VariableArray.new(name)
6
+ yield a if block_given?
7
+ return a
8
+ end
9
+
10
+ def variable_array!(name, &blk)
11
+ if variable_arrays[name]
12
+ raise Exception.new("VariableArray with name #{name} already exists.")
13
+ else
14
+ variable_array(name, &blk)
15
+ end
16
+ end
17
+
18
+ def variable_arrays
19
+ @variable_ararys ||= {}
20
+ end
21
+
22
+ class VariableArray < BaseType
23
+ def intialize(name)
24
+ super
25
+ end
26
+
27
+ def array_type(t = nil)
28
+ if t
29
+ @array_type = BaseType.find_type!(t)
30
+ else
31
+ @array_type
32
+ end
33
+ end
34
+
35
+ def array_size(s = nil)
36
+ if s
37
+ @array_size = s
38
+ else
39
+ @array_size
40
+ end
41
+ end
42
+
43
+ def size_type(t = nil)
44
+ if t
45
+ _t = BaseType.find_type!(t)
46
+ if _t.is_scalar?
47
+ @size_type = _t
48
+ else
49
+ raise Exception.new("The type #{t} is not an scalar")
50
+ end
51
+ else
52
+ @size_type
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module Cauterize
2
+ VERSION = "0.0.1.pre1"
3
+ end
@@ -0,0 +1,167 @@
1
+ include Cauterize
2
+
3
+ describe Cauterize do
4
+ before {
5
+ BaseType.class_variable_set(:@@next_id, {})
6
+ BaseType.class_variable_set(:@@instances, {})
7
+ }
8
+
9
+ describe BaseType do
10
+ describe :id do
11
+ it { has_a_unique_id_for_each_instance(BaseType) }
12
+ end
13
+
14
+ describe :type_str do
15
+ it "is the hexadecimal representation of type" do
16
+ f = enumeration(:foo) do |e|
17
+ e.value :a, 1
18
+ end
19
+ b = enumeration(:bar) do |e|
20
+ e.value :a, 1
21
+ end
22
+
23
+ b.type_str.should == "0x2001"
24
+ end
25
+ end
26
+
27
+ describe :tag do
28
+ it { is_tagged_as(Scalar, 0) }
29
+ it { is_tagged_as(Enumeration, 1) }
30
+ it { is_tagged_as(Composite, 2) }
31
+ it { is_tagged_as(FixedArray, 3) }
32
+ it { is_tagged_as(VariableArray, 4) }
33
+ it { is_tagged_as(Group, 5) }
34
+ end
35
+
36
+ describe :next_id do
37
+ it "is an incrementing value starting at 0" do
38
+ # the .new consumes the 0.
39
+ BaseType.new(:foo).instance_exec do
40
+ next_id.should == 1
41
+ next_id.should == 2
42
+ next_id.should == 3
43
+ next_id.should == 4
44
+ end
45
+ end
46
+
47
+ it "should not allow derived class ids to interact" do
48
+ a1 = Scalar.new(:foo)
49
+ a2 = Scalar.new(:bar)
50
+ e1 = Enumeration.new(:zoop)
51
+ e2 = Enumeration.new(:nih)
52
+
53
+ a1.id.should == 0
54
+ a2.id.should == 1
55
+ e1.id.should == 0
56
+ e2.id.should == 1
57
+ end
58
+ end
59
+
60
+ describe "bit stuff" do
61
+ it "is consistent" do
62
+ BaseType.class_exec do
63
+ (tag_bit_width + id_bit_width).should == type_bit_width
64
+ (tag_bit_mask >> id_bit_width).should == 0x7
65
+ end
66
+ end
67
+ end
68
+
69
+ describe :register_instance do
70
+ it "adds an instance to the instance list" do
71
+ class X < BaseType
72
+ def initialize(name); end
73
+ end
74
+ x = X.new(:foo)
75
+
76
+ x.instance_exec do
77
+ register_instance(x)
78
+ end
79
+
80
+ BaseType.all_instances[0].should be x
81
+ BaseType.all_instances.length.should == 1
82
+ end
83
+ end
84
+
85
+ describe :instances do
86
+ # Two things are being tested here.
87
+ # 1. That instances works.
88
+ # 2. That super() is called in each .new
89
+ it "is every instance of a BaseType-derived class" do
90
+ BaseType.all_instances.should == []
91
+
92
+ a = Scalar.new(:foo)
93
+ e = Enumeration.new(:emoo)
94
+ c = Composite.new(:cooo)
95
+ f = FixedArray.new(:moo)
96
+ v = VariableArray.new(:quack)
97
+ g = Group.new(:goo)
98
+
99
+ lst = [a, e, c, f, v, g]
100
+
101
+ instances = BaseType.all_instances
102
+ instances.length.should == lst.length + 1 # +1 because groups make an enum as well
103
+
104
+ # Check that each of our instances shows up in the list returned from
105
+ # all_instances. Do it this way in case there are other types created
106
+ # (like the enumeration for Group).
107
+ lst.all? do |l|
108
+ instances.any? {|i| i.equal? l}
109
+ end
110
+ end
111
+ end
112
+
113
+ describe :find_type do
114
+ it "returns the instance with the provided name" do
115
+ f = scalar(:foo)
116
+ b = scalar(:bar)
117
+
118
+ BaseType.find_type(:bar).should be b
119
+ BaseType.find_type(:foo).should be f
120
+ end
121
+
122
+ it "is nil on an unknown name" do
123
+ BaseType.find_type(:xxxxxxxxxxxxxxxxxx).should be_nil
124
+ end
125
+ end
126
+
127
+ describe :find_type! do
128
+ it "returns the instance with the provided name" do
129
+ f = scalar(:foo)
130
+ b = scalar(:bar)
131
+
132
+ BaseType.find_type!(:bar).should be b
133
+ BaseType.find_type!(:foo).should be f
134
+ end
135
+
136
+ it "errors on an unknown name" do
137
+ lambda { BaseType.find_type!(:foo) }.should raise_error /name foo does not/
138
+ end
139
+ end
140
+
141
+ describe "is_[type]?" do
142
+ it "supports scalar" do
143
+ scalar(:foo).is_scalar?.should be_true
144
+ end
145
+
146
+ it "supports enumeration" do
147
+ enumeration(:foo).is_enumeration?.should be_true
148
+ end
149
+
150
+ it "supports composite" do
151
+ composite(:foo).is_composite?.should be_true
152
+ end
153
+
154
+ it "supports fixed_array" do
155
+ fixed_array(:foo).is_fixed_array?.should be_true
156
+ end
157
+
158
+ it "supports variable_array" do
159
+ variable_array(:foo).is_variable_array?.should be_true
160
+ end
161
+
162
+ it "supports group" do
163
+ group(:foo).is_group?.should be_true
164
+ end
165
+ end
166
+ end
167
+ end