17
17
import org .truffleruby .core .array .ArraySliceNodeGen ;
18
18
import org .truffleruby .language .RubyNode ;
19
19
import org .truffleruby .language .SourceIndexLength ;
20
- import org .truffleruby .language .arguments .EmptyArgumentsDescriptor ;
21
20
import org .truffleruby .language .control .AndNode ;
22
21
import org .truffleruby .language .control .ExecuteAndReturnTrueNode ;
23
22
import org .truffleruby .language .control .NotNode ;
24
23
import org .truffleruby .language .control .RaiseException ;
25
- import org .truffleruby .language .dispatch .RubyCallNodeParameters ;
26
24
import org .truffleruby .language .literal .NilLiteralNode ;
27
25
import org .truffleruby .language .literal .TruffleInternalModuleLiteralNode ;
28
26
import org .truffleruby .language .locals .ReadLocalNode ;
@@ -77,6 +75,39 @@ public PatternMatchingTranslator(
77
75
this .bodyTranslator = bodyTranslator ;
78
76
}
79
77
78
+ public RubyNode translatePatternNode (ParseNode patternNode , RubyNode expressionValue ) {
79
+ currentValueToMatch = expressionValue ;
80
+
81
+ // TODO move the other cases to the visitor pattern
82
+ switch (patternNode .getNodeType ()) {
83
+ case ARRAYPATTERNNODE :
84
+ return this .visitArrayPatternNode ((ArrayPatternParseNode ) patternNode );
85
+ case HASHPATTERNNODE : // both of these throw the same exception, hence this is skipped.
86
+ case FINDPATTERNNODE :
87
+ final RubyContext context = RubyLanguage .getCurrentContext ();
88
+ throw new RaiseException (
89
+ context ,
90
+ context .getCoreExceptions ().syntaxError (
91
+ "not yet handled in pattern matching: " + patternNode + " " + patternNode .getPosition (),
92
+ currentNode ,
93
+ patternNode .getPosition ().toSourceSection (source )));
94
+ case IFNODE : // handles both if and unless
95
+ var ifNode = (IfParseNode ) patternNode ;
96
+ RubyNode pattern ;
97
+ RubyNode condition = ifNode .getCondition ().accept (bodyTranslator );
98
+ if (ifNode .getThenBody () != null ) {
99
+ pattern = translatePatternNode (ifNode .getThenBody (), expressionValue );
100
+ } else {
101
+ pattern = translatePatternNode (ifNode .getElseBody (), expressionValue );
102
+ condition = new NotNode (condition );
103
+ }
104
+
105
+ return new AndNode (pattern , condition );
106
+ default :
107
+ return createCallNode (patternNode .accept (this ), "===" , NodeUtil .cloneNode (expressionValue ));
108
+ }
109
+ }
110
+
80
111
@ Override
81
112
protected RubyNode defaultVisit (ParseNode node ) {
82
113
final RubyContext context = RubyLanguage .getCurrentContext ();
@@ -90,29 +121,17 @@ protected RubyNode defaultVisit(ParseNode node) {
90
121
91
122
@ Override
92
123
public RubyNode visitArrayPatternNode (ArrayPatternParseNode arrayPatternParseNode ) {
93
- final RubyCallNodeParameters deconstructCallParameters ;
94
- final RubyNode receiver ;
95
- final RubyNode deconstructed ;
96
124
final SourceIndexLength sourceSection = arrayPatternParseNode .getPosition ();
97
125
98
- ListParseNode preNodes = arrayPatternParseNode .getPreArgs ();
99
- ListParseNode postNodes = arrayPatternParseNode .getPostArgs ();
100
- ParseNode restNode = arrayPatternParseNode .getRestArg ();
101
-
102
- receiver = new TruffleInternalModuleLiteralNode ();
103
- receiver .unsafeSetSourceSection (sourceSection );
104
- deconstructCallParameters = new RubyCallNodeParameters (
105
- receiver ,
106
- "deconstruct_checked" ,
107
- null ,
108
- EmptyArgumentsDescriptor .INSTANCE ,
109
- new RubyNode []{ currentValueToMatch },
110
- false ,
111
- true );
112
- deconstructed = language .coreMethodAssumptions .createCallNode (deconstructCallParameters );
113
-
114
- final int deconSlot = environment .declareLocalTemp ("p_decon_array" );
115
- final ReadLocalNode readTemp = environment .readNode (deconSlot , sourceSection );
126
+ var preNodes = arrayPatternParseNode .getPreArgs ();
127
+ var postNodes = arrayPatternParseNode .getPostArgs ();
128
+ var restNode = arrayPatternParseNode .getRestArg ();
129
+
130
+ var deconstructed = createCallNode (new TruffleInternalModuleLiteralNode (), "deconstruct_checked" ,
131
+ currentValueToMatch );
132
+
133
+ final int deconstructedSlot = environment .declareLocalTemp ("p_decon_array" );
134
+ final ReadLocalNode readTemp = environment .readNode (deconstructedSlot , sourceSection );
116
135
final RubyNode assignTemp = readTemp .makeWriteNode (deconstructed );
117
136
currentValueToMatch = readTemp ;
118
137
@@ -121,44 +140,27 @@ public RubyNode visitArrayPatternNode(ArrayPatternParseNode arrayPatternParseNod
121
140
RubyNode condition = new ArrayPatternLengthCheckNode (arrayPatternParseNode .minimumArgsNum (),
122
141
currentValueToMatch , arrayPatternParseNode .hasRestArg ());
123
142
124
- // Constant == pattern.deconstruct
143
+ // Constant === pattern.deconstruct
125
144
if (arrayPatternParseNode .hasConstant ()) {
126
145
ConstParseNode constant = (ConstParseNode ) arrayPatternParseNode .getConstant ();
127
146
RubyNode constVal = constant .accept (this );
128
- final RubyCallNodeParameters instanceCheckParameters = new RubyCallNodeParameters (
129
- constVal ,
130
- "===" ,
131
- null ,
132
- EmptyArgumentsDescriptor .INSTANCE ,
133
- new RubyNode []{ currentValueToMatch },
134
- false ,
135
- true );
136
- RubyNode isInstance = language .coreMethodAssumptions .createCallNode (instanceCheckParameters );
147
+ var isInstance = createCallNode (constVal , "===" , currentValueToMatch );
137
148
condition = new AndNode (isInstance , condition );
138
149
}
139
150
140
151
for (int i = 0 ; i < preSize ; i ++) {
141
- ParseNode loopPreNode = preNodes .get (i );
152
+ var preNode = preNodes .get (i );
142
153
RubyNode translatedPatternElement ;
143
154
RubyNode prev = currentValueToMatch ;
144
155
var exprElement = ArrayIndexNodes .ReadConstantIndexNode .create (currentValueToMatch , i );
145
156
currentValueToMatch = exprElement ;
146
157
try {
147
- translatedPatternElement = loopPreNode .accept (this );
158
+ translatedPatternElement = preNode .accept (this );
148
159
} finally {
149
160
currentValueToMatch = prev ;
150
161
}
151
162
152
- var parameters = new RubyCallNodeParameters (
153
- translatedPatternElement ,
154
- "===" ,
155
- null ,
156
- EmptyArgumentsDescriptor .INSTANCE ,
157
- new RubyNode []{ NodeUtil .cloneNode (exprElement ) },
158
- false ,
159
- true );
160
-
161
- var callNode = language .coreMethodAssumptions .createCallNode (parameters );
163
+ var callNode = createCallNode (translatedPatternElement , "===" , NodeUtil .cloneNode (exprElement ));
162
164
condition = new AndNode (condition , callNode );
163
165
}
164
166
@@ -198,16 +200,11 @@ public RubyNode visitArrayPatternNode(ArrayPatternParseNode arrayPatternParseNod
198
200
currentValueToMatch = prev ;
199
201
}
200
202
201
- var parameters = new RubyCallNodeParameters (
203
+ var callNode = createCallNode (
202
204
translatedPatternElement ,
203
205
"===" ,
204
- null ,
205
- EmptyArgumentsDescriptor .INSTANCE ,
206
- new RubyNode []{ NodeUtil .cloneNode (exprElement ) },
207
- false ,
208
- true );
206
+ NodeUtil .cloneNode (exprElement ));
209
207
210
- var callNode = language .coreMethodAssumptions .createCallNode (parameters );
211
208
condition = new AndNode (condition , callNode );
212
209
}
213
210
}
@@ -221,79 +218,13 @@ public RubyNode visitFindPatternNode(FindPatternParseNode findPatternParseNode)
221
218
222
219
@ Override
223
220
public RubyNode visitHashPatternNode (HashPatternParseNode node ) {
224
- final RubyCallNodeParameters deconstructCallParameters ;
225
- final RubyCallNodeParameters matcherCallParameters ;
226
- final RubyCallNodeParameters matcherCallParametersPost ;
227
- final RubyNode receiver ;
228
- final RubyNode deconstructed ;
229
- deconstructCallParameters = new RubyCallNodeParameters (
230
- currentValueToMatch ,
231
- "deconstruct_keys" ,
232
- null ,
233
- EmptyArgumentsDescriptor .INSTANCE ,
234
- new RubyNode []{ new NilLiteralNode (true ) },
235
- false ,
236
- true );
237
- deconstructed = language .coreMethodAssumptions .createCallNode (deconstructCallParameters );
238
-
239
- receiver = new TruffleInternalModuleLiteralNode ();
240
- receiver .unsafeSetSourceSection (node .getPosition ());
241
-
242
- matcherCallParameters = new RubyCallNodeParameters (
243
- receiver ,
244
- "hash_pattern_matches?" ,
245
- null ,
246
- EmptyArgumentsDescriptor .INSTANCE ,
247
- new RubyNode []{ node .accept (this ), NodeUtil .cloneNode (deconstructed ) },
248
- false ,
249
- true );
221
+ var deconstructed = createCallNode (currentValueToMatch , "deconstruct_keys" , new NilLiteralNode (true ));
250
222
251
- return language .coreMethodAssumptions .createCallNode (matcherCallParameters );
252
- }
253
-
254
- public RubyNode translatePatternNode (ParseNode patternNode , RubyNode expressionValue ) {
255
- final RubyCallNodeParameters matcherCallParameters ;
256
-
257
- currentValueToMatch = expressionValue ;
258
-
259
-
260
- // TODO move the other cases to the visitor pattern
261
- switch (patternNode .getNodeType ()) {
262
- case ARRAYPATTERNNODE :
263
- return this .visitArrayPatternNode ((ArrayPatternParseNode ) patternNode );
264
- case HASHPATTERNNODE : // both of these throw the same exception, hence this is skipped.
265
- case FINDPATTERNNODE :
266
- final RubyContext context = RubyLanguage .getCurrentContext ();
267
- var node = patternNode ;
268
- throw new RaiseException (
269
- context ,
270
- context .getCoreExceptions ().syntaxError (
271
- "not yet handled in pattern matching: " + node + " " + node .getPosition (),
272
- currentNode ,
273
- node .getPosition ().toSourceSection (source )));
274
- case IFNODE : // handles both if and unless
275
- var ifNode = (IfParseNode ) patternNode ;
276
- RubyNode pattern ;
277
- RubyNode condition = ifNode .getCondition ().accept (bodyTranslator );
278
- if (ifNode .getThenBody () != null ) {
279
- pattern = translatePatternNode (ifNode .getThenBody (), expressionValue );
280
- } else {
281
- pattern = translatePatternNode (ifNode .getElseBody (), expressionValue );
282
- condition = new NotNode (condition );
283
- }
284
-
285
- return new AndNode (pattern , condition );
286
- default :
287
- matcherCallParameters = new RubyCallNodeParameters (
288
- patternNode .accept (this ),
289
- "===" ,
290
- null ,
291
- EmptyArgumentsDescriptor .INSTANCE ,
292
- new RubyNode []{ NodeUtil .cloneNode (expressionValue ) },
293
- false ,
294
- true );
295
- return language .coreMethodAssumptions .createCallNode (matcherCallParameters );
296
- }
223
+ return createCallNode (
224
+ new TruffleInternalModuleLiteralNode (),
225
+ "hash_pattern_matches?" ,
226
+ node .accept (this ),
227
+ NodeUtil .cloneNode (deconstructed ));
297
228
}
298
229
299
230
@ Override
0 commit comments