cauterize 0.0.1.pre1

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.
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