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,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"