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.
- checksums.yaml +7 -0
- data/Gemfile +8 -0
- data/LICENSE +19 -0
- data/README.md +21 -0
- data/Rakefile +55 -0
- data/examples/binary_ops.rb +138 -0
- data/examples/node_finder.rb +96 -0
- data/examples/visitors.rb +105 -0
- data/lib/core_ext.rb +4 -0
- data/lib/core_ext/class.rb +13 -0
- data/lib/core_ext/enumerable.rb +47 -0
- data/lib/core_ext/kernel.rb +16 -0
- data/lib/core_ext/string.rb +32 -0
- data/lib/wood.rb +13 -0
- data/lib/wood/indented_printer.rb +48 -0
- data/lib/wood/node.rb +259 -0
- data/lib/wood/node_rewriter.rb +29 -0
- data/lib/wood/node_visitor.rb +60 -0
- data/lib/wood/nodes.rb +22 -0
- data/lib/wood/nodes/assignment.rb +34 -0
- data/lib/wood/nodes/break.rb +4 -0
- data/lib/wood/nodes/code_block.rb +44 -0
- data/lib/wood/nodes/continue.rb +4 -0
- data/lib/wood/nodes/for_loop.rb +11 -0
- data/lib/wood/nodes/function.rb +45 -0
- data/lib/wood/nodes/if_else.rb +6 -0
- data/lib/wood/nodes/literals.rb +68 -0
- data/lib/wood/nodes/nested_node.rb +5 -0
- data/lib/wood/nodes/no_op.rb +7 -0
- data/lib/wood/nodes/null.rb +4 -0
- data/lib/wood/nodes/operator.rb +28 -0
- data/lib/wood/nodes/return.rb +15 -0
- data/lib/wood/nodes/switch.rb +13 -0
- data/lib/wood/nodes/variable.rb +24 -0
- data/lib/wood/nodes/while_loop.rb +10 -0
- data/lib/wood/tree_pattern.rb +14 -0
- data/lib/wood/tree_pattern/any_matcher.rb +20 -0
- data/lib/wood/tree_pattern/matcher.rb +40 -0
- data/lib/wood/tree_pattern/node_finder.rb +164 -0
- data/lib/wood/tree_pattern/or_matcher.rb +33 -0
- data/lib/wood/tree_pattern/pattern_builder.rb +57 -0
- data/lib/wood/tree_pattern/pattern_callback.rb +5 -0
- data/lib/wood/tree_pattern/replacement_builder.rb +27 -0
- data/lib/wood/tree_pattern/type_matcher.rb +59 -0
- data/lib/wood/tree_pattern/variable_matcher.rb +31 -0
- data/lib/wood/tree_rewriter.rb +67 -0
- data/lib/wood/types.rb +318 -0
- data/lib/wood/version.rb +3 -0
- data/spec/core_ext/enumerable_spec.rb +34 -0
- data/spec/core_ext/string_spec.rb +25 -0
- data/spec/spec_cov.rb +2 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/wood/indented_printer_spec.rb +61 -0
- data/spec/wood/node_spec.rb +258 -0
- data/spec/wood/node_visitor_spec.rb +43 -0
- data/spec/wood/nodes/code_block_spec.rb +32 -0
- data/spec/wood/nodes/no_op_spec.rb +5 -0
- data/spec/wood/nodes/operator_spec.rb +31 -0
- data/spec/wood/tree_pattern/any_matcher_spec.rb +32 -0
- data/spec/wood/tree_pattern/matcher_spec.rb +316 -0
- data/spec/wood/tree_pattern/node_finder_spec.rb +104 -0
- data/spec/wood/tree_pattern/or_matcher_spec.rb +43 -0
- data/spec/wood/tree_pattern/type_matcher_spec.rb +69 -0
- data/spec/wood/tree_pattern/variable_matcher_spec.rb +37 -0
- data/spec/wood/tree_rewriter_spec.rb +351 -0
- 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
|
data/lib/wood/nodes.rb
ADDED
@@ -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,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,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,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,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,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,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"
|