maccro 0.1.0

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.
@@ -0,0 +1,100 @@
1
+ require_relative "node"
2
+
3
+ module Maccro
4
+ module DSL
5
+ class MultiAssignment < Node
6
+ def type; :MASGN; end
7
+ def self.match?(node); node.type == :MASGN ; end
8
+ end
9
+
10
+ class LocalVariableAssignment < Node
11
+ def type; :LASGN; end
12
+ def self.match?(node); node.type == :LASGN ; end
13
+ end
14
+
15
+ class DynamicVariableAssignmentOutOfScope < Node
16
+ # x = 1; 1.times{ x = 1 }
17
+ def type; :DASGN; end
18
+ def self.match?(node); node.type == :DASGN ; end
19
+ end
20
+
21
+ class DynamicVariableAssignmentCurrentScope < Node
22
+ # 1.times{ x = 1 }
23
+ def type; :DASGN_CUPR; end
24
+ def self.match?(node); node.type == :DASGN_CUPR ; end
25
+ end
26
+
27
+ class InstanceVariableAssignment < Node
28
+ def type; :IASGN; end
29
+ def self.match?(node); node.type == :IASGN ; end
30
+ end
31
+
32
+ class ClassVariableAssignment < Node
33
+ def type; :CVASGN; end
34
+ def self.match?(node); node.type == :CVASGN ; end
35
+ end
36
+
37
+ class GlobalVariableAssignment < Node
38
+ def type; :GASGN; end
39
+ def self.match?(node); node.type == :GASGN ; end
40
+ end
41
+
42
+ class AttributeAssignment < Node
43
+ # x[1] = 1
44
+ # x.a = 1
45
+ def type; :ATTRASGN; end
46
+ def self.match?(node); node.type == :ATTRASGN ; end
47
+ end
48
+
49
+ class ArrayAssignmentWithOperator < Node
50
+ # x[1] += 1
51
+ def type; :OP_ASGN1; end
52
+ def self.match?(node); node.type == :OP_ASGN1 ; end
53
+ end
54
+
55
+ class AttributeAssignmentWithOperator < Node
56
+ # x.a += 1
57
+ def type; :OP_ASGN2; end
58
+ def self.match?(node); node.type == :OP_ASGN2 ; end
59
+ end
60
+
61
+ class AndAssignment < Node
62
+ # x &&= y
63
+ def type; :OP_ASGN_AND; end
64
+ def self.match?(node); node.type == :OP_ASGN_AND ; end
65
+ end
66
+
67
+ class OrAssignment < Node
68
+ # x ||= y
69
+ def type; :OP_ASGN_OR; end
70
+ def self.match?(node); node.type == :OP_ASGN_OR ; end
71
+ end
72
+
73
+ class ConstantDeclaration < Node
74
+ def type; :CDECL; end
75
+ def self.match?(node); node.type == :CDECL ; end
76
+ end
77
+
78
+ class ConstantDeclarationWithOperator < Node
79
+ # A::B ||= 1
80
+ # A::B += 1
81
+ def type; :OP_CDECL; end
82
+ def self.match?(node); node.type == :OP_CDECL ; end
83
+ end
84
+
85
+ class Assignment < Node
86
+ SUB_TYPES = [
87
+ MultiAssignment, LocalVariableAssignment,
88
+ DynamicVariableAssignmentOutOfScope, DynamicVariableAssignmentCurrentScope,
89
+ InstanceVariableAssignment, ClassVariableAssignment, GlobalVariableAssignment,
90
+ AttributeAssignment, ArrayAssignmentWithOperator, AttributeAssignmentWithOperator,
91
+ AndAssignment, OrAssignment,
92
+ ConstantDeclaration, ConstantDeclarationWithOperator,
93
+ ].freeze
94
+
95
+ def self.match?(node)
96
+ SUB_TYPES.any?{|s| s.match?(node) }
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,166 @@
1
+ require_relative "node"
2
+ require_relative "value"
3
+ require_relative "assign"
4
+
5
+ module Maccro
6
+ module DSL
7
+ class IfExp < Node
8
+ def type; :IF; end
9
+ def self.match?(node); node.type == :IF; end
10
+ end
11
+
12
+ class UnlessExp < Node
13
+ def type; :UNLESS; end
14
+ def self.match?(node); node.type == :UNLESS; end
15
+ end
16
+
17
+ class CaseExp < Node
18
+ def type; :MACCRO_CASE; end
19
+ def self.match?(node)
20
+ node.type == :CASE || node.type == :CASE2
21
+ end
22
+ end
23
+
24
+ # class BeginExp < Node
25
+ # # TODO: getting source of begin node DOES drop the beggining "begin" and tailing "end"
26
+ # def type; :"BEGIN"; end
27
+ # def self.match?(node); node.type == :"BEGIN"; end
28
+ # end
29
+
30
+ # class RescueExp < Node
31
+ # # TODO: getting source of rescue node DOES drop the beggining "begin" and tailing "end"
32
+ # def type; :"RESCUE"; end
33
+ # def self.match?(node); node.type == :"RESCUE"; end
34
+ # end
35
+
36
+ class AndExp < Node
37
+ def type; :AND; end
38
+ def self.match?(node); node.type == :AND; end
39
+ end
40
+
41
+ class OrExp < Node
42
+ def type; :OR; end
43
+ def self.match?(node); node.type == :OR; end
44
+ end
45
+
46
+ class CallExp < Node
47
+ def type; :CALL; end
48
+ def self.match?(node); node.type == :CALL; end
49
+ end
50
+
51
+ class OperatorCallExp < Node
52
+ def type; :OPCALL; end
53
+ def self.match?(node); node.type == :OPCALL; end
54
+ end
55
+
56
+ class SafeCallExp < Node
57
+ # x&.foo(1)
58
+ def type; :QCALL; end
59
+ def self.match?(node); node.type == :QCALL; end
60
+ end
61
+
62
+ class FunctionCallExp < Node
63
+ def type; :FCALL; end
64
+ def self.match?(node); node.type == :FCALL; end
65
+ end
66
+
67
+ class VCallExp < Node
68
+ # function call without arguments
69
+ def type; :VCALL; end
70
+ def self.match?(node); node.type == :VCALL; end
71
+ end
72
+
73
+ class SuperExp < Node
74
+ # super or super without arguments
75
+ def type; :MACCRO_SUPER; end
76
+ def self.match?(node)
77
+ node.type == :SUPER || node.type == :ZSUPER
78
+ end
79
+ end
80
+
81
+ class YieldExp < Node
82
+ def type; :YIELD; end
83
+ def self.match?(node); node.type == :YIELD; end
84
+ end
85
+
86
+ class MatchExp < Node
87
+ # MATCH: /.../ without `=~` (matches to $_ implicitly)
88
+ # MATCH2: /.../ =~ "..." (left side)
89
+ # MATCH3: "..." =~ /.../ (right side)
90
+ def type; :MACCRO_MATCH; end
91
+ def self.match?(node)
92
+ t = node.type
93
+ t == :MATCH || t == :MATCH2 || t == :MATCH3
94
+ end
95
+ end
96
+
97
+ class DefineMethod < Node
98
+ def type; :DEFN; end
99
+ def self.match?(node); node.type == :DEFN; end
100
+ end
101
+
102
+ class DefineSingletonMethod < Node
103
+ def type; :DEFS; end
104
+ def self.match?(node); node.type == :DEFS; end
105
+ end
106
+
107
+ class Colon2Exp < Node
108
+ def type; :COLON2; end
109
+ def self.match?(node); node.type == :COLON2; end
110
+ end
111
+
112
+ class Colon3Exp < Node
113
+ # top level reference (::A)
114
+ def type; :COLON3; end
115
+ def self.match?(node); node.type == :COLON3; end
116
+ end
117
+
118
+ class Dot2Exp < Node
119
+ # range constructor (inclusive)
120
+ def type; :DOT2; end
121
+ def self.match?(node); node.type == :DOT2; end
122
+ end
123
+
124
+ class Dot3Exp < Node
125
+ # range constructor (exclusive)
126
+ def type; :DOT3; end
127
+ def self.match?(node); node.type == :DOT3; end
128
+ end
129
+
130
+ class Flip2Exp < Node
131
+ # flip-flop (inclusive)
132
+ def type; :FLIP2; end
133
+ def self.match?(node); node.type == :FLIP2; end
134
+ end
135
+
136
+ class Flip3Exp < Node
137
+ # flip-flop (exclusive)
138
+ def type; :FLIP3; end
139
+ def self.match?(node); node.type == :FLIP3; end
140
+ end
141
+
142
+ class DefinedExp < Node
143
+ def type; :DEFINED; end
144
+ def self.match?(node); node.type == :DEFINED; end
145
+ end
146
+
147
+ class Expression < Node
148
+ SUB_TYPES = [
149
+ Value, Assignment,
150
+ IfExp, UnlessExp, CaseExp,
151
+ # BeginExp, RescueExp,
152
+ AndExp, OrExp,
153
+ CallExp, OperatorCallExp, SafeCallExp, FunctionCallExp, VCallExp,
154
+ SuperExp, YieldExp,
155
+ MatchExp,
156
+ DefineMethod, DefineSingletonMethod,
157
+ Colon2Exp, Colon3Exp, Dot2Exp, Dot3Exp, Flip2Exp, Flip3Exp,
158
+ DefinedExp,
159
+ ].freeze
160
+
161
+ def self.match?(node)
162
+ SUB_TYPES.any?{|s| s.match?(node) }
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,121 @@
1
+ require_relative "node"
2
+
3
+ module Maccro
4
+ module DSL
5
+ class Literal < Node
6
+ # integer, float, symbol, regex, ...
7
+ def type; :LIT; end
8
+ def self.match?(node); node.type == :LIT; end
9
+ end
10
+
11
+ class DSymbol < Node
12
+ # symbol with string interpolation
13
+ def type; :DSYM; end
14
+ def self.match?(node); node.type == :DSYM; end
15
+ end
16
+
17
+ class Symbol < Node
18
+ def type; :LIT; end
19
+ def self.match?(node)
20
+ (node.type == :LIT && node.children[0].is_a?(::Symbol)) || DSymbol.match?(node)
21
+ end
22
+ end
23
+
24
+ class Number < Node
25
+ def type; :LIT; end
26
+ def self.match?(node)
27
+ node.type == :LIT && node.children[0].is_a?(::Numeric)
28
+ end
29
+ end
30
+
31
+ class RegexpCompiledOnce < Node
32
+ # regex with RE_OPTION_ONCE (see new_regexp() in parse.y)
33
+ def type; :ONCE; end
34
+ def self.match?(node); node.type == :ONCE; end
35
+ end
36
+
37
+ class DRegexp < Node
38
+ # regex with string interpolation
39
+ def type; :DREGX; end
40
+ def self.match?(node); node.type == :DREGX; end
41
+ end
42
+
43
+ class RegularExpression < Node
44
+ def type; :LIT; end
45
+ def self.match?(node)
46
+ node.type == :LIT && node.children[0].is_a?(Regexp)
47
+ end
48
+ end
49
+
50
+ class FString < Node
51
+ # string literal without interpolation
52
+ def type; :STR; end
53
+ def self.match?(node); node.type == :STR; end
54
+ end
55
+
56
+ class DString < Node
57
+ # string literal with interpolation ?
58
+ def type; :DSTR; end
59
+ def self.match?(node); node.type == :DSTR; end
60
+ end
61
+
62
+ class XString < Node
63
+ # string from back quote: `...`
64
+ # is it a literal?
65
+ def type; :XSTR; end
66
+ def self.match?(node); node.type == :XSTR; end
67
+ end
68
+
69
+ class DXString < Node
70
+ # string from back quote with string interpolation: `... #{..} ...`
71
+ # is it a literal?
72
+ def type; :DXSTR; end
73
+ def self.match?(node); node.type == :DXSTR; end
74
+ end
75
+
76
+ class String < Node
77
+ SUB_TYPES = [FString, DString, XString, DXString].freeze
78
+
79
+ def type; :MACCRO_STRING; end
80
+
81
+ def self.match?(node)
82
+ SUB_TYPES.any?{|s| s.match?(node) }
83
+ end
84
+ end
85
+
86
+ class NilValue < Node
87
+ def type; :NIL; end
88
+ def self.match?(node); node.type == :NIL; end
89
+ end
90
+
91
+ class TrueValue < Node
92
+ def type; :TRUE; end
93
+ def self.match?(node); node.type == :TRUE; end
94
+ end
95
+
96
+ class FalseValue < Node
97
+ def type; :FALSE; end
98
+ def self.match?(node); node.type == :FALSE; end
99
+ end
100
+
101
+ class Lambda < Node
102
+ def type; :LAMBDA; end
103
+ def self.match?(node); node.type == :LAMBDA; end
104
+ end
105
+
106
+ class Array < Node
107
+ # ARRAY and ZARRAY
108
+ def type; :MACCRO_ARRAY; end
109
+ def self.match?(node)
110
+ node.type == :ARRAY || node.type == :ZARRAY
111
+ end
112
+ end
113
+
114
+ class Hash < Node
115
+ # HASH may be a hash literal, or keyword argument assignment `"a: 1" of f(a: 1)`
116
+ # HASH(nd_alen == 0) is a keyword argument assignment, but no way to get it via AST::Node
117
+ def type; :HASH; end
118
+ def self.match?(node); node.type == :HASH; end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,89 @@
1
+ require_relative '../code_range'
2
+
3
+ module Maccro
4
+ module DSL
5
+ module ASTNodeWrapper
6
+ def children
7
+ @child_nodes ||= super
8
+ end
9
+
10
+ def to_code_range
11
+ CodeRange.from_node(self)
12
+ end
13
+
14
+ def match?(node)
15
+ return false unless node.is_a?(ASTNodeWrapper)
16
+ return false if node.type != self.type
17
+ self.children.each_with_index do |c, i|
18
+ if c.is_a?(ASTNodeWrapper)
19
+ return false unless c.match?(node.children[i])
20
+ else
21
+ return false unless c == node.children[i]
22
+ end
23
+ end
24
+ # same type, all children match with others
25
+ true
26
+ end
27
+
28
+ def capture(ast, placeholders)
29
+ self.children.each_with_index do |c, i|
30
+ if c.is_a?(ASTNodeWrapper)
31
+ c.capture(ast.children[i], placeholders)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ class Node
38
+ attr_reader :name, :first_lineno, :first_column, :last_lineno, :last_column
39
+
40
+ include ASTNodeWrapper
41
+
42
+ def initialize(name, code_range)
43
+ @name = name
44
+ @code_range = code_range
45
+ @first_lineno = code_range.first_lineno
46
+ @first_column = code_range.first_column
47
+ @last_lineno = code_range.last_lineno
48
+ @last_column = code_range.last_column
49
+ end
50
+
51
+ def to_code_range
52
+ @code_range
53
+ end
54
+
55
+ def type
56
+ :MACCRO_NODE
57
+ end
58
+
59
+ def children
60
+ []
61
+ end
62
+
63
+ def match?(node)
64
+ # literals are not Node in any cases
65
+ return false unless node.respond_to?(:type)
66
+
67
+ if self.class.respond_to?(:match?)
68
+ self.class.match?(node)
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ def capture(ast, placeholders)
75
+ placeholders[@name] = ast.to_code_range
76
+ end
77
+ end
78
+
79
+ class AnyNode < Node
80
+ def match?(node)
81
+ true
82
+ end
83
+
84
+ def capture(ast, placeholders)
85
+ placeholders[:__target__] = ast
86
+ end
87
+ end
88
+ end
89
+ end