wood 0.1.1

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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +8 -0
  3. data/LICENSE +19 -0
  4. data/README.md +21 -0
  5. data/Rakefile +55 -0
  6. data/examples/binary_ops.rb +138 -0
  7. data/examples/node_finder.rb +96 -0
  8. data/examples/visitors.rb +105 -0
  9. data/lib/core_ext.rb +4 -0
  10. data/lib/core_ext/class.rb +13 -0
  11. data/lib/core_ext/enumerable.rb +47 -0
  12. data/lib/core_ext/kernel.rb +16 -0
  13. data/lib/core_ext/string.rb +32 -0
  14. data/lib/wood.rb +13 -0
  15. data/lib/wood/indented_printer.rb +48 -0
  16. data/lib/wood/node.rb +259 -0
  17. data/lib/wood/node_rewriter.rb +29 -0
  18. data/lib/wood/node_visitor.rb +60 -0
  19. data/lib/wood/nodes.rb +22 -0
  20. data/lib/wood/nodes/assignment.rb +34 -0
  21. data/lib/wood/nodes/break.rb +4 -0
  22. data/lib/wood/nodes/code_block.rb +44 -0
  23. data/lib/wood/nodes/continue.rb +4 -0
  24. data/lib/wood/nodes/for_loop.rb +11 -0
  25. data/lib/wood/nodes/function.rb +45 -0
  26. data/lib/wood/nodes/if_else.rb +6 -0
  27. data/lib/wood/nodes/literals.rb +68 -0
  28. data/lib/wood/nodes/nested_node.rb +5 -0
  29. data/lib/wood/nodes/no_op.rb +7 -0
  30. data/lib/wood/nodes/null.rb +4 -0
  31. data/lib/wood/nodes/operator.rb +28 -0
  32. data/lib/wood/nodes/return.rb +15 -0
  33. data/lib/wood/nodes/switch.rb +13 -0
  34. data/lib/wood/nodes/variable.rb +24 -0
  35. data/lib/wood/nodes/while_loop.rb +10 -0
  36. data/lib/wood/tree_pattern.rb +14 -0
  37. data/lib/wood/tree_pattern/any_matcher.rb +20 -0
  38. data/lib/wood/tree_pattern/matcher.rb +40 -0
  39. data/lib/wood/tree_pattern/node_finder.rb +164 -0
  40. data/lib/wood/tree_pattern/or_matcher.rb +33 -0
  41. data/lib/wood/tree_pattern/pattern_builder.rb +57 -0
  42. data/lib/wood/tree_pattern/pattern_callback.rb +5 -0
  43. data/lib/wood/tree_pattern/replacement_builder.rb +27 -0
  44. data/lib/wood/tree_pattern/type_matcher.rb +59 -0
  45. data/lib/wood/tree_pattern/variable_matcher.rb +31 -0
  46. data/lib/wood/tree_rewriter.rb +67 -0
  47. data/lib/wood/types.rb +318 -0
  48. data/lib/wood/version.rb +3 -0
  49. data/spec/core_ext/enumerable_spec.rb +34 -0
  50. data/spec/core_ext/string_spec.rb +25 -0
  51. data/spec/spec_cov.rb +2 -0
  52. data/spec/spec_helper.rb +3 -0
  53. data/spec/wood/indented_printer_spec.rb +61 -0
  54. data/spec/wood/node_spec.rb +258 -0
  55. data/spec/wood/node_visitor_spec.rb +43 -0
  56. data/spec/wood/nodes/code_block_spec.rb +32 -0
  57. data/spec/wood/nodes/no_op_spec.rb +5 -0
  58. data/spec/wood/nodes/operator_spec.rb +31 -0
  59. data/spec/wood/tree_pattern/any_matcher_spec.rb +32 -0
  60. data/spec/wood/tree_pattern/matcher_spec.rb +316 -0
  61. data/spec/wood/tree_pattern/node_finder_spec.rb +104 -0
  62. data/spec/wood/tree_pattern/or_matcher_spec.rb +43 -0
  63. data/spec/wood/tree_pattern/type_matcher_spec.rb +69 -0
  64. data/spec/wood/tree_pattern/variable_matcher_spec.rb +37 -0
  65. data/spec/wood/tree_rewriter_spec.rb +351 -0
  66. metadata +114 -0
@@ -0,0 +1,67 @@
1
+ module Wood
2
+ module TreeRewriter
3
+ class Rewriter
4
+ def initialize
5
+ self.class.patterns self
6
+ end
7
+
8
+ def self.inherited(klass)
9
+ klass.include Wood::TreePattern::Matcher
10
+ klass.include Wood::TreeRewriter
11
+ end
12
+ end
13
+
14
+ def self.new(&block)
15
+ Class.new(Rewriter, &block).new
16
+ end
17
+
18
+ module ClassMethods
19
+ def patterns(*patterns)
20
+ @patterns ||= []
21
+ @patterns = patterns unless patterns.empty?
22
+ @patterns
23
+ end
24
+ end
25
+
26
+ def self.included(klass)
27
+ klass.extend ClassMethods
28
+ end
29
+
30
+ def rewrite(node, repeat = false)
31
+ return do_rewrite(node, repeat) unless repeat
32
+
33
+ changed = true
34
+ while changed
35
+ tmp = do_rewrite(node, repeat)
36
+ changed = tmp != node
37
+ node = tmp
38
+ end
39
+
40
+ return do_rewrite(node, false)
41
+ end
42
+
43
+ def do_rewrite(node, repeat = false)
44
+ patterns.each do |p|
45
+ node = p.replacement_for(node)
46
+ end
47
+
48
+ if node.respond_to? :each_child
49
+ node.each_child do |c|
50
+ node.set_child(c, rewrite(node.get_child(c), repeat))
51
+ end
52
+ else
53
+ if Array === node
54
+ node = node.map do |c|
55
+ rewrite(c, repeat)
56
+ end
57
+ end
58
+ end
59
+
60
+ return node
61
+ end
62
+
63
+ def patterns
64
+ self.class.patterns
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,318 @@
1
+ require "set"
2
+
3
+ module Wood
4
+ module Types
5
+ module TypeMatching
6
+ def self.included(klass)
7
+ klass.__send__ :include, Wood::TreePattern::CombinatorialMatching
8
+ klass.extend Wood::TreePattern::CombinatorialMatching
9
+ end
10
+ end
11
+
12
+ class CompoundType
13
+ include TypeMatching
14
+ def self.[](type)
15
+ new(type)
16
+ end
17
+
18
+ attr_accessor :type
19
+ def initialize(type)
20
+ @type = type
21
+ end
22
+
23
+ def == other
24
+ case other
25
+ when self.class
26
+ return type == other.type
27
+ else
28
+ return false
29
+ end
30
+ end
31
+
32
+ def numeric?
33
+ false
34
+ end
35
+
36
+ def builtin?
37
+ type && type.builtin?
38
+ end
39
+
40
+ def zero_value
41
+ @zero_value ||= Wood::Nodes::Null.new
42
+ end
43
+ end
44
+
45
+
46
+ class Array < CompoundType
47
+ def self.[](*options)
48
+ case options.first
49
+ when Hash
50
+ options = options.first
51
+ new(options[:type], options[:size])
52
+ else
53
+ new(*options)
54
+ end
55
+ end
56
+
57
+ attr_reader :size
58
+ def initialize(type, size = nil)
59
+ super(type)
60
+ @size = size
61
+ end
62
+
63
+ def name
64
+ [:array, type.name]
65
+ end
66
+
67
+ def node_name
68
+ :array_type
69
+ end
70
+
71
+ def == other
72
+ case other
73
+ when Array
74
+ if size && other.size
75
+ return type == other.type && size == other.size
76
+ else
77
+ return type == other.type
78
+ end
79
+ else
80
+ return false
81
+ end
82
+ end
83
+
84
+ def === other
85
+ case other
86
+ when Array
87
+ if size && other.size
88
+ return type === other.type && size === other.size
89
+ else
90
+ return type === other.type
91
+ end
92
+ else
93
+ return false
94
+ end
95
+ end
96
+
97
+ def numeric?
98
+ type && type.numeric?
99
+ end
100
+
101
+ def builtin?
102
+ type && type.builtin?
103
+ end
104
+
105
+ def sexp
106
+ [:array, type.sexp, size.sexp]
107
+ end
108
+ end
109
+
110
+ class CustomType < Struct.new(:type)
111
+ include TypeMatching
112
+ def self.[](type)
113
+ case type
114
+ when BuiltinType
115
+ return type
116
+ when CustomType
117
+ return type
118
+ when CompoundType
119
+ return type
120
+ else
121
+ new(type)
122
+ end
123
+ end
124
+
125
+ def node_name
126
+ :custom_type
127
+ end
128
+
129
+ def sexp
130
+ [:custom_type, type.sexp]
131
+ end
132
+
133
+ def == other
134
+ case other
135
+ when CustomType
136
+ return type == other.type
137
+ else
138
+ return type == other
139
+ end
140
+ end
141
+
142
+ def === other
143
+ case other
144
+ when CustomType
145
+ return type === other.type
146
+ else
147
+ return type === other
148
+ end
149
+ end
150
+
151
+ def numeric?
152
+ false
153
+ end
154
+
155
+ def builtin?
156
+ false
157
+ end
158
+
159
+ def name
160
+ type.name
161
+ end
162
+
163
+ def method_missing(method, *args)
164
+ type.__send__(method, *args)
165
+ end
166
+ end
167
+
168
+ class BuiltinType < Struct.new(:name)
169
+ include TypeMatching
170
+ attr_reader :aliases
171
+ attr_accessor :zero_value
172
+ def initialize(name, numeric = false, *aliases)
173
+ super(name)
174
+
175
+ @aliases = aliases
176
+ @numeric = numeric
177
+
178
+ if numeric?
179
+ Types::NUMERIC_TYPES << self
180
+ else
181
+ Types::NON_NUMERIC_TYPES << self
182
+ end
183
+ end
184
+
185
+ def numeric?
186
+ @numeric
187
+ end
188
+
189
+ def builtin?
190
+ true
191
+ end
192
+
193
+ def sexp
194
+ name
195
+ end
196
+
197
+ def node_name
198
+ (Array(name).map(&:to_s).join("_") + "_type").snake_cased.to_sym
199
+ end
200
+
201
+ def == other
202
+ case other
203
+ when BuiltinType
204
+ return name == other.name
205
+ else
206
+ return false
207
+ end
208
+ end
209
+
210
+ def type
211
+ self
212
+ end
213
+
214
+ def zero_value
215
+ @zero_value ||= Wood::Nodes::Null.new
216
+ end
217
+ end
218
+
219
+ class NumericType < BuiltinType
220
+ def initialize(name, *aliases)
221
+ super(name, true, *aliases)
222
+ end
223
+
224
+ def zero_value
225
+ @zero_value ||= Wood::Nodes::Literal[type: self, value: 0]
226
+ end
227
+ end
228
+
229
+ class BooleanType < BuiltinType
230
+ def initialize(name, *aliases)
231
+ super(name, false, *aliases)
232
+ end
233
+
234
+ def zero_value
235
+ @zero_value ||= Wood::Nodes::FalseLiteral.new
236
+ end
237
+ end
238
+
239
+ module CommonType
240
+ def self.[](*types)
241
+ common_type_for(*types)
242
+ end
243
+
244
+ def self.type_order
245
+ @@order ||= [
246
+ Any,
247
+ Bool,
248
+ U8,
249
+ I8,
250
+ U16,
251
+ Short,
252
+ U32,
253
+ I32,
254
+ Int,
255
+ U64,
256
+ I64
257
+ ]
258
+ end
259
+
260
+ def self.common_type_for(*types)
261
+ type_order[types_to_indices(types).last]
262
+
263
+ end
264
+
265
+ def self.smallest_type_of(*types)
266
+ type_order[types_to_indices(types).first]
267
+ end
268
+
269
+ private
270
+
271
+ def self.types_to_indices(types)
272
+ idx = Set.new(types).map do |t|
273
+ type_order.index(t).to_i
274
+ end.sort
275
+ end
276
+ end
277
+
278
+ class AnyType < BuiltinType
279
+ def initialize(name, *aliases)
280
+ super(name, false, *aliases)
281
+ end
282
+
283
+ def == other
284
+ true
285
+ end
286
+
287
+ def === other
288
+ true
289
+ end
290
+ end
291
+
292
+
293
+ NUMERIC_TYPES = Set.new
294
+ NON_NUMERIC_TYPES = Set.new
295
+
296
+ Any = AnyType.new :Any, :any, :Object, :object
297
+ Int = NumericType.new :int
298
+ Float = NumericType.new :float
299
+ Short = NumericType.new :short
300
+ Long = NumericType.new :long
301
+ Double = NumericType.new :double
302
+ Char = BuiltinType.new :char
303
+ String = BuiltinType.new :string
304
+ Void = BuiltinType.new :void
305
+ Null = BuiltinType.new :null
306
+ Bool = BooleanType.new :bool
307
+
308
+ U8 = NumericType.new :u8, :uint8_t
309
+ U16 = NumericType.new :u16, :uint16_t
310
+ U32 = NumericType.new :u32, :uint32_t
311
+ U64 = NumericType.new :u64, :uint64_t
312
+
313
+ I8 = NumericType.new :i8, :int8_t
314
+ I16 = NumericType.new :i16, :int16_t
315
+ I32 = NumericType.new :i32, :int32_t
316
+ I64 = NumericType.new :i64, :int64_t
317
+ end
318
+ end
@@ -0,0 +1,3 @@
1
+ module Wood
2
+ VERSION = "0.1.1"
3
+ end
@@ -0,0 +1,34 @@
1
+ describe Enumerable do
2
+ it "calls a block in between calling another block for each object via in_between" do
3
+ s = ""
4
+ [1,2,3].in_between{ s << "," }.each do |x|
5
+ s << x.to_s
6
+ end
7
+
8
+ s.should == "1,2,3"
9
+ end
10
+
11
+ it "allows calling each twice" do
12
+ s = ""
13
+ enum = [1,2,3].in_between{ s << "," }
14
+ enum.each do |x|
15
+ s << x.to_s
16
+ end
17
+ s.should == "1,2,3"
18
+ s << "-"
19
+ enum.each do |x|
20
+ s << (x * 10).to_s
21
+ end
22
+ s.should == "1,2,3-10,20,30"
23
+ end
24
+
25
+ it "maps with an index parameter" do
26
+ [1,2,3].map_with_index do |x, i|
27
+ if i % 2 == 0
28
+ :even
29
+ else
30
+ x * 2
31
+ end
32
+ end.should == [:even, 4, :even]
33
+ end
34
+ end
@@ -0,0 +1,25 @@
1
+ describe String do
2
+ it "returns a snake-cased version of self" do
3
+ "FooBar".snake_cased.should == "foo_bar"
4
+ "Foobar".snake_cased.should == "foobar"
5
+ "fooBar".snake_cased.should == "foo_bar"
6
+ "HelloWorld-Yo".snake_cased.should == "hello_world_yo"
7
+ end
8
+
9
+ it "returns a camel-cased version of self" do
10
+ "foo_bar".camel_cased.should == "FooBar"
11
+ "foo_bar_baz".camel_cased.should == "FooBarBaz"
12
+ "foo_Bar".camel_cased.should == "FooBar"
13
+ end
14
+
15
+ it "returns true if it is capitalized" do
16
+ "".capitalized?.should be_falsey
17
+ "foo".capitalized?.should be_falsey
18
+ "fFoo".capitalized?.should be_falsey
19
+
20
+ "_".capitalized?.should be_truthy
21
+ "F".capitalized?.should be_truthy
22
+ "Foo".capitalized?.should be_truthy
23
+ "FFoo".capitalized?.should be_truthy
24
+ end
25
+ end