@@ -29,13 +29,37 @@ def scan(root)
29
29
30
30
private
31
31
32
+ def combine_and ( left , right )
33
+ -> ( node ) { left . call ( node ) && right . call ( node ) }
34
+ end
35
+
36
+ def combine_or ( left , right )
37
+ -> ( node ) { left . call ( node ) || right . call ( node ) }
38
+ end
39
+
32
40
def compile ( pattern )
33
41
case pattern
34
- in Binary [ left :, operator : :| , right :]
35
- compiled_left = compile ( left )
36
- compiled_right = compile ( right )
42
+ in AryPtn [ constant :, requireds :, rest : nil , posts : [ ] ]
43
+ compiled_constant = compile ( constant ) if constant
44
+
45
+ preprocessed = requireds . map { |required | compile ( required ) }
37
46
38
- -> ( node ) { compiled_left . call ( node ) || compiled_right . call ( node ) }
47
+ compiled_requireds = -> ( node ) do
48
+ deconstructed = node . deconstruct
49
+
50
+ deconstructed . length == preprocessed . length &&
51
+ preprocessed . zip ( deconstructed ) . all? do |( matcher , value ) |
52
+ matcher . call ( value )
53
+ end
54
+ end
55
+
56
+ if compiled_constant
57
+ combine_and ( compiled_constant , compiled_requireds )
58
+ else
59
+ compiled_requireds
60
+ end
61
+ in Binary [ left :, operator : :| , right :]
62
+ combine_or ( compile ( left ) , compile_right )
39
63
in Const [ value :] if SyntaxTree . const_defined? ( value )
40
64
clazz = SyntaxTree . const_get ( value )
41
65
@@ -46,33 +70,48 @@ def compile(pattern)
46
70
-> ( node ) { node . is_a? ( clazz ) }
47
71
in ConstPathRef [ parent : VarRef [ value : Const [ value : "SyntaxTree" ] ] ]
48
72
compile ( pattern . constant )
73
+ in DynaSymbol [ parts : [ TStringContent [ value :] ] ]
74
+ symbol = value . to_sym
75
+
76
+ -> ( attribute ) { attribute == value }
49
77
in HshPtn [ constant :, keywords :, keyword_rest : nil ]
50
78
compiled_constant = compile ( constant )
51
79
52
- preprocessed_keywords =
80
+ preprocessed =
53
81
keywords . to_h do |keyword , value |
54
82
raise NoMatchingPatternError unless keyword . is_a? ( Label )
55
83
[ keyword . value . chomp ( ":" ) . to_sym , compile ( value ) ]
56
84
end
57
85
58
86
compiled_keywords = -> ( node ) do
59
- deconstructed = node . deconstruct_keys ( preprocessed_keywords . keys )
60
- preprocessed_keywords . all? do |keyword , matcher |
87
+ deconstructed = node . deconstruct_keys ( preprocessed . keys )
88
+
89
+ preprocessed . all? do |keyword , matcher |
61
90
matcher . call ( deconstructed [ keyword ] )
62
91
end
63
92
end
64
93
65
- -> ( node ) do
66
- compiled_constant . call ( node ) && compiled_keywords . call ( node )
94
+ if compiled_constant
95
+ combine_and ( compiled_constant , compiled_keywords )
96
+ else
97
+ compiled_keywords
67
98
end
68
99
in RegexpLiteral [ parts : [ TStringContent [ value :] ] ]
69
100
regexp = /#{ value } /
70
101
71
102
-> ( attribute ) { regexp . match? ( attribute ) }
103
+ in StringLiteral [ parts : [ ] ]
104
+ -> ( attribute ) { attribute == "" }
72
105
in StringLiteral [ parts : [ TStringContent [ value :] ] ]
73
106
-> ( attribute ) { attribute == value }
107
+ in SymbolLiteral [ value :]
108
+ symbol = value . value . to_sym
109
+
110
+ -> ( attribute ) { attribute == symbol }
74
111
in VarRef [ value : Const => value ]
75
112
compile ( value )
113
+ in VarRef [ value : Kw [ value : "nil" ] ]
114
+ -> ( attribute ) { attribute . nil? }
76
115
end
77
116
rescue NoMatchingPatternError
78
117
raise UncompilableError , <<~ERROR
0 commit comments