wood 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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,60 @@
1
+ module Wood
2
+ # Mixin module for {Wood::Node} visitors.
3
+ module NodeVisitor
4
+ module ClassMethods
5
+ # @param node_names [Array<Symbol>] List of node names to be ignored.
6
+ #
7
+ # Creates an empty visit handler for all node names in `node_names`.
8
+ def ignore_nodes(*node_names)
9
+ node_names.each do |n|
10
+ define_method(n) do |node|
11
+ context.ignored = true
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ def self.included(klass)
18
+ klass.extend ClassMethods
19
+ end
20
+
21
+ Context = Struct.new(:ignored)
22
+
23
+ def new_context
24
+ Context.new(false)
25
+ end
26
+
27
+ def contexts
28
+ @contexts ||= []
29
+ end
30
+
31
+ def context
32
+ @contexts.last
33
+ end
34
+
35
+ def visit(node)
36
+ contexts.push new_context
37
+ __send__(node.node_name, node)
38
+ contexts.pop
39
+ end
40
+
41
+ def visit_type(node)
42
+ case node.type
43
+ when Wood::Types::BuiltinType
44
+ visit node.type
45
+ when Wood::Types::CompoundType
46
+ visit node.type
47
+ when Wood::Types::CustomType
48
+ visit node.type
49
+ else
50
+ visit node.type.type if node.type
51
+ end
52
+ end
53
+
54
+ def array(nodes)
55
+ nodes.each do |n|
56
+ visit n
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ module Wood
2
+ module Nodes
3
+ Node = Wood::Node
4
+ end
5
+ end
6
+
7
+ require_relative "nodes/no_op"
8
+ require_relative "nodes/nested_node"
9
+ require_relative "nodes/literals"
10
+ require_relative "nodes/assignment"
11
+ require_relative "nodes/operator"
12
+ require_relative "nodes/null"
13
+ require_relative "nodes/code_block"
14
+ require_relative "nodes/function"
15
+ require_relative "nodes/if_else"
16
+ require_relative "nodes/return"
17
+ require_relative "nodes/break"
18
+ require_relative "nodes/continue"
19
+ require_relative "nodes/for_loop"
20
+ require_relative "nodes/while_loop"
21
+ require_relative "nodes/switch"
22
+ require_relative "nodes/variable"
@@ -0,0 +1,34 @@
1
+ module Wood::Nodes
2
+ class Assignment < Node
3
+ child_nodes :var, :value
4
+ node_name :assign
5
+ end
6
+
7
+ class AddAssignment < Assignment
8
+ node_name :add_assign
9
+ end
10
+
11
+ class SubAssignment < Assignment
12
+ node_name :sub_assign
13
+ end
14
+
15
+ class MulAssignment < Assignment
16
+ node_name :mul_assign
17
+ end
18
+
19
+ class DivAssignment < Assignment
20
+ node_name :div_assign
21
+ end
22
+
23
+ class BitwiseAndAssignment < Assignment
24
+ node_name :band_assign
25
+ end
26
+
27
+ class BitwiseNotAssignment < Assignment
28
+ node_name :bnot_assign
29
+ end
30
+
31
+ class BitwiseXORAssignment < Assignment
32
+ node_name :xor_assign
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ module Wood::Nodes
2
+ class Break < Node
3
+ end
4
+ end
@@ -0,0 +1,44 @@
1
+ module Wood::Nodes
2
+ class CodeBlock < Node
3
+ def self.[](*options)
4
+ case opts = options.first
5
+ when Hash
6
+ new(opts)
7
+ else
8
+ new(expressions: options)
9
+ end
10
+ end
11
+
12
+ include Enumerable
13
+
14
+ child_nodes :expressions
15
+
16
+ def setup
17
+ @expressions = Array(expressions).flatten
18
+ end
19
+
20
+ def sexp
21
+ expressions.map(&:sexp)
22
+ end
23
+
24
+ def empty?
25
+ expressions.empty?
26
+ end
27
+
28
+ def size
29
+ expressions.size
30
+ end
31
+
32
+ def each(&block)
33
+ @expressions.each(&block)
34
+ end
35
+
36
+ def << node
37
+ @expressions << node
38
+ end
39
+
40
+ def [](idx)
41
+ @expressions[idx]
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,4 @@
1
+ module Wood::Nodes
2
+ class Continue < Node
3
+ end
4
+ end
@@ -0,0 +1,11 @@
1
+ module Wood::Nodes
2
+ class ForLoop < Node
3
+ child_nodes :init_op, :condition, :post_op, :body
4
+
5
+ def setup
6
+ @init_op = init_op || NoOp[pos: pos]
7
+ @post_op = post_op || NoOp[pos: pos]
8
+ @body = body || CodeBlock[pos: pos]
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ module Wood::Nodes
2
+ module Function
3
+ class Argument < Node
4
+ child_nodes :storage, :type, :name
5
+
6
+ def sexp
7
+ [type.sexp, name]
8
+ end
9
+ end
10
+
11
+ class Declaration < Node
12
+ child_nodes :storage, :type, :name, :args
13
+
14
+ attr_accessor :scope
15
+ end
16
+
17
+ class Definition < Node
18
+ child_nodes :storage, :type, :name, :args, :body
19
+
20
+ attr_accessor :scope
21
+
22
+ def setup
23
+ @args = args || []
24
+ @body = body || CodeBlock[pos: pos]
25
+ end
26
+ end
27
+
28
+ class Call < Node
29
+ child_nodes :name, :args
30
+ node_name :call
31
+
32
+ attr_accessor :function
33
+
34
+ def setup
35
+ @args = args || []
36
+ end
37
+
38
+ def type
39
+ if @function
40
+ @function.type
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,6 @@
1
+ module Wood::Nodes
2
+ class IfElse < Node
3
+ child_nodes :condition, :then_branch, :else_branch
4
+ node_name :if
5
+ end
6
+ end
@@ -0,0 +1,68 @@
1
+ module Wood::Nodes
2
+ class Literal < Node
3
+ def self.[](options = nil)
4
+ case options
5
+ when Hash
6
+ new(options)
7
+ else
8
+ new(value: options)
9
+ end
10
+ end
11
+
12
+ child_nodes :type, :value
13
+
14
+ def sexp
15
+ [node_name, value]
16
+ end
17
+ end
18
+
19
+ class IntLiteral < Literal
20
+ child_nodes :base
21
+ def setup
22
+ @type = Wood::Types::Int
23
+ @base = base || 10
24
+ end
25
+ end
26
+
27
+ class LongLiteral < Literal
28
+ def setup
29
+ @type = Wood::Types::Long
30
+ end
31
+ end
32
+
33
+ class FloatLiteral < Literal
34
+ def setup
35
+ @type = Wood::Types::Float
36
+ end
37
+ end
38
+
39
+ class DoubleLiteral < Literal
40
+ def setup
41
+ @type = Wood::Types::Double
42
+ end
43
+ end
44
+
45
+ class StringLiteral < Literal
46
+ def setup
47
+ @type = Wood::Types::String
48
+ end
49
+ end
50
+
51
+ class CharLiteral < Literal
52
+ def setup
53
+ @type = Wood::Types::Char
54
+ end
55
+ end
56
+
57
+ class BoolLiteral < Literal
58
+ def setup
59
+ @type = Wood::Types::Bool
60
+ end
61
+ end
62
+
63
+ class TrueLiteral < BoolLiteral
64
+ end
65
+
66
+ class FalseLiteral < BoolLiteral
67
+ end
68
+ end
@@ -0,0 +1,5 @@
1
+ module Wood::Nodes
2
+ class NestedNode < Node
3
+ child_nodes :node
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module Wood::Nodes
2
+ class NoOp < Node
3
+ def type
4
+ Wood::Types::Void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module Wood::Nodes
2
+ class Null < Node
3
+ end
4
+ end
@@ -0,0 +1,28 @@
1
+ module Wood::Nodes
2
+ class Operator < Node
3
+ child_nodes :name, :left, :right
4
+
5
+ BOOL_OPS = [:<, :>, :<=, :>=, :==, :"!=", :"&&", :"||"]
6
+ NON_BOOL_OPS = [:*, :/, :+, :-, :>>, :<<, :&, :|]
7
+
8
+ def boolean?
9
+ BOOL_OPS.include? name
10
+ end
11
+
12
+ def to_boolean
13
+ if boolean?
14
+ return self
15
+ else
16
+ return Operator[name: :"!=", left: self, right: IntLiteral[0]]
17
+ end
18
+ end
19
+
20
+ def type
21
+ if boolean?
22
+ Wood::Types::Bool
23
+ else
24
+ @type || Wood::Types::CommonType[@left.type, @right.type]
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ module Wood::Nodes
2
+ class Return < Node
3
+ def self.[](options = nil)
4
+ case options
5
+ when Hash
6
+ new(options)
7
+ else
8
+ new(expression: options)
9
+ end
10
+ end
11
+
12
+ child_nodes :expression
13
+ attr_accessor :function_def
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Wood::Nodes
2
+ class Switch < Node
3
+ class Case < Node
4
+ child_nodes :expression, :body
5
+ end
6
+
7
+ class DefaultCase < Node
8
+ child_nodes :body
9
+ end
10
+
11
+ child_nodes :expression, :cases
12
+ end
13
+ end
@@ -0,0 +1,24 @@
1
+ module Wood::Nodes
2
+ module Variable
3
+ class Declaration < Node
4
+ child_nodes :type, :name, :init_val
5
+ node_name :var_decl
6
+ end
7
+
8
+ class Reference < Node
9
+ def self.[](options)
10
+ case options
11
+ when Hash
12
+ new(options)
13
+ else
14
+ new(name: options)
15
+ end
16
+ end
17
+
18
+ child_nodes :name
19
+ node_name :var_ref
20
+
21
+ attr_accessor :var
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ module Wood::Nodes
2
+ class WhileLoop < Node
3
+ child_nodes :condition, :body
4
+ node_name :while
5
+
6
+ def setup
7
+ @body = body || CodeBlock[pos: pos]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ module Wood
2
+ module TreePattern
3
+ end
4
+ end
5
+
6
+ require_relative "tree_pattern/any_matcher"
7
+ require_relative "tree_pattern/or_matcher"
8
+ require_relative "tree_pattern/variable_matcher"
9
+ require_relative "tree_pattern/type_matcher"
10
+ require_relative "tree_pattern/pattern_builder"
11
+ require_relative "tree_pattern/replacement_builder"
12
+ require_relative "tree_pattern/pattern_callback"
13
+ require_relative "tree_pattern/matcher"
14
+ require_relative "tree_pattern/node_finder"