76
76
import org .truffleruby .interop .ToJavaStringNode ;
77
77
import org .truffleruby .language .LexicalScope ;
78
78
import org .truffleruby .language .Nil ;
79
- import org .truffleruby .language .NotProvided ;
80
79
import org .truffleruby .language .RubyBaseNode ;
81
80
import org .truffleruby .language .RubyBaseNodeWithExecute ;
82
81
import org .truffleruby .language .RubyConstant ;
@@ -1225,52 +1224,90 @@ private void warnAlreadyInitializedConstant(RubyModule module, String name,
1225
1224
1226
1225
}
1227
1226
1227
+ @ GenerateUncached
1228
1228
@ CoreMethod (
1229
1229
names = "define_method" ,
1230
1230
needsBlock = true ,
1231
1231
required = 1 ,
1232
1232
optional = 1 ,
1233
- split = Split .NEVER ,
1234
- argumentNames = { "name" , "proc_or_method" , "block" })
1235
- @ NodeChild (value = "module" , type = RubyNode .class )
1236
- @ NodeChild (value = "name" , type = RubyBaseNodeWithExecute .class )
1237
- @ NodeChild (value = "proc" , type = RubyNode .class )
1238
- @ NodeChild (value = "block" , type = RubyNode .class )
1239
- public abstract static class DefineMethodNode extends CoreMethodNode {
1233
+ argumentNames = { "name" , "proc_or_method" , "block" },
1234
+ alwaysInlined = true )
1235
+ @ ImportStatic (RubyArguments .class )
1236
+ public abstract static class DefineMethodNode extends AlwaysInlinedMethodNode {
1237
+
1238
+ //Checkstyle: stop
1239
+ @ Specialization (guards = { "isMethodParameterProvided(rubyArgs)" , "isRubyMethod(getArgument(rubyArgs, 1))" })
1240
+ //Checkstyle: resume
1241
+ protected RubySymbol defineMethodWithMethod (
1242
+ Frame callerFrame , RubyModule module , Object [] rubyArgs , RootCallTarget target ,
1243
+ @ Cached NameToJavaStringNode nameToJavaStringNode ,
1244
+ @ Cached (allowUncached = true ) CanBindMethodToModuleNode canBindMethodToModuleNode ) {
1245
+ final String name = nameToJavaStringNode .execute (RubyArguments .getArgument (rubyArgs , 0 ));
1246
+ final Object method = RubyArguments .getArgument (rubyArgs , 1 );
1247
+
1248
+ return addMethod (module , name , (RubyMethod ) method , canBindMethodToModuleNode );
1249
+ }
1250
+
1251
+ //Checkstyle: stop
1252
+ @ Specialization (guards = { "isMethodParameterProvided(rubyArgs)" , "isRubyProc(getArgument(rubyArgs, 1))" })
1253
+ //Checkstyle: resume
1254
+ protected RubySymbol defineMethodWithProc (
1255
+ Frame callerFrame , RubyModule module , Object [] rubyArgs , RootCallTarget target ,
1256
+ @ Cached NameToJavaStringNode nameToJavaStringNode ) {
1257
+ final String name = nameToJavaStringNode .execute (RubyArguments .getArgument (rubyArgs , 0 ));
1258
+ final Object method = RubyArguments .getArgument (rubyArgs , 1 );
1240
1259
1241
- @ Child private ReadCallerFrameNode readCallerFrame = ReadCallerFrameNode .create ();
1260
+ needCallerFrame (callerFrame , target );
1261
+ return addProc (module , name , (RubyProc ) method , callerFrame .materialize ());
1262
+ }
1242
1263
1243
- @ CreateCast ("name" )
1244
- protected RubyBaseNodeWithExecute coerceToString (RubyBaseNodeWithExecute name ) {
1245
- return NameToJavaStringNode .create (name );
1264
+ //Checkstyle: stop
1265
+ @ Specialization (
1266
+ guards = { "isMethodParameterProvided(rubyArgs)" , "isRubyUnboundMethod(getArgument(rubyArgs, 1))" })
1267
+ //Checkstyle: resume
1268
+ protected RubySymbol defineMethodWithUnboundMethod (
1269
+ Frame callerFrame , RubyModule module , Object [] rubyArgs , RootCallTarget target ,
1270
+ @ Cached NameToJavaStringNode nameToJavaStringNode ) {
1271
+ final String name = nameToJavaStringNode .execute (RubyArguments .getArgument (rubyArgs , 0 ));
1272
+ final Object method = RubyArguments .getArgument (rubyArgs , 1 );
1273
+
1274
+ needCallerFrame (callerFrame , target );
1275
+ return addUnboundMethod (module , name , (RubyUnboundMethod ) method , callerFrame .materialize ());
1246
1276
}
1247
1277
1248
- @ TruffleBoundary
1249
- @ Specialization
1250
- protected RubySymbol defineMethod (RubyModule module , String name , NotProvided proc , Nil block ) {
1251
- throw new RaiseException (getContext (), coreExceptions ().argumentError ("needs either proc or block" , this ));
1278
+ @ Specialization (guards = {
1279
+ "isMethodParameterProvided(rubyArgs)" ,
1280
+ "!isExpectedMethodParameterType(getArgument(rubyArgs, 1))" })
1281
+ protected RubySymbol defineMethodWithUnexpectedMethodParameterType (
1282
+ Frame callerFrame , RubyModule module , Object [] rubyArgs , RootCallTarget target ) {
1283
+ final Object method = RubyArguments .getArgument (rubyArgs , 1 );
1284
+ throw new RaiseException (getContext (),
1285
+ coreExceptions ().typeErrorExpectedProcOrMethodOrUnboundMethod (method , this ));
1252
1286
}
1253
1287
1254
- @ Specialization
1255
- protected RubySymbol defineMethodBlock (
1256
- VirtualFrame frame , RubyModule module , String name , NotProvided proc , RubyProc block ) {
1257
- return defineMethodProc (frame , module , name , block , nil );
1288
+ @ Specialization (guards = { "!isMethodParameterProvided(rubyArgs)" , "isBlockProvided(rubyArgs)" })
1289
+ protected RubySymbol defineMethodWithBlock (
1290
+ Frame callerFrame , RubyModule module , Object [] rubyArgs , RootCallTarget target ,
1291
+ @ Cached NameToJavaStringNode nameToJavaStringNode ) {
1292
+ final String name = nameToJavaStringNode .execute (RubyArguments .getArgument (rubyArgs , 0 ));
1293
+ final Object block = RubyArguments .getBlock (rubyArgs );
1294
+ needCallerFrame (callerFrame , target );
1295
+ return addProc (module , name , (RubyProc ) block , callerFrame .materialize ());
1258
1296
}
1259
1297
1260
- @ Specialization
1261
- protected RubySymbol defineMethodProc (
1262
- VirtualFrame frame , RubyModule module , String name , RubyProc proc , Nil block ) {
1263
- return defineMethod ( module , name , proc , readCallerFrame . execute ( frame ));
1298
+ @ Specialization ( guards = { "!isMethodParameterProvided(rubyArgs)" , "!isBlockProvided(rubyArgs)" })
1299
+ protected RubySymbol defineMethodWithoutMethodAndBlock (
1300
+ Frame callerFrame , RubyModule nodule , Object [] rubyArgs , RootCallTarget target ) {
1301
+ throw new RaiseException ( getContext (), coreExceptions (). argumentErrorProcWithoutBlock ( this ));
1264
1302
}
1265
1303
1266
1304
@ TruffleBoundary
1267
- @ Specialization
1268
- protected RubySymbol defineMethodMethod (RubyModule module , String name , RubyMethod methodObject , Nil block ,
1305
+ private RubySymbol addMethod (RubyModule module , String name , RubyMethod method ,
1269
1306
@ Cached CanBindMethodToModuleNode canBindMethodToModuleNode ) {
1270
- final InternalMethod method = methodObject .method ;
1307
+ final InternalMethod internalMethod = method .method ;
1271
1308
1272
- if (!canBindMethodToModuleNode .executeCanBindMethodToModule (method , module )) {
1273
- final RubyModule declaringModule = method .getDeclaringModule ();
1309
+ if (!canBindMethodToModuleNode .executeCanBindMethodToModule (internalMethod , module )) {
1310
+ final RubyModule declaringModule = internalMethod .getDeclaringModule ();
1274
1311
if (RubyGuards .isSingletonClass (declaringModule )) {
1275
1312
throw new RaiseException (getContext (), coreExceptions ().typeError (
1276
1313
"can't bind singleton method to a different class" ,
@@ -1282,20 +1319,13 @@ protected RubySymbol defineMethodMethod(RubyModule module, String name, RubyMeth
1282
1319
}
1283
1320
}
1284
1321
1285
- module .fields .addMethod (getContext (), this , method .withName (name ));
1322
+ module .fields .addMethod (getContext (), this , internalMethod .withName (name ));
1286
1323
return getSymbol (name );
1287
1324
}
1288
1325
1289
- @ Specialization
1290
- protected RubySymbol defineMethod (
1291
- VirtualFrame frame , RubyModule module , String name , RubyUnboundMethod method , Nil block ) {
1292
- final MaterializedFrame callerFrame = readCallerFrame .execute (frame );
1293
- return defineMethodInternal (module , name , method , callerFrame );
1294
- }
1295
-
1296
1326
@ TruffleBoundary
1297
- private RubySymbol defineMethodInternal (RubyModule module , String name , RubyUnboundMethod method ,
1298
- final MaterializedFrame callerFrame ) {
1327
+ private RubySymbol addUnboundMethod (RubyModule module , String name , RubyUnboundMethod method ,
1328
+ MaterializedFrame callerFrame ) {
1299
1329
final InternalMethod internalMethod = method .method ;
1300
1330
if (!ModuleOperations .canBindMethodTo (internalMethod , module )) {
1301
1331
final RubyModule declaringModule = internalMethod .getDeclaringModule ();
@@ -1313,12 +1343,11 @@ private RubySymbol defineMethodInternal(RubyModule module, String name, RubyUnbo
1313
1343
}
1314
1344
}
1315
1345
1316
- return addMethod (module , name , internalMethod , callerFrame );
1346
+ return addInternalMethod (module , name , internalMethod , callerFrame );
1317
1347
}
1318
1348
1319
1349
@ TruffleBoundary
1320
- private RubySymbol defineMethod (RubyModule module , String name , RubyProc proc ,
1321
- MaterializedFrame callerFrame ) {
1350
+ private RubySymbol addProc (RubyModule module , String name , RubyProc proc , MaterializedFrame callerFrame ) {
1322
1351
final RootCallTarget callTargetForLambda = proc .callTargets .getCallTargetForLambda ();
1323
1352
final RubyLambdaRootNode rootNode = RubyLambdaRootNode .of (callTargetForLambda );
1324
1353
final SharedMethodInfo info = proc .getSharedMethodInfo ().forDefineMethod (module , name , proc );
@@ -1329,7 +1358,7 @@ private RubySymbol defineMethod(RubyModule module, String name, RubyProc proc,
1329
1358
final RubyLambdaRootNode newRootNode = rootNode .copyRootNode (info , newBody );
1330
1359
final RootCallTarget newCallTarget = newRootNode .getCallTarget ();
1331
1360
1332
- final InternalMethod method = InternalMethod .fromProc (
1361
+ final InternalMethod internalMethod = InternalMethod .fromProc (
1333
1362
getContext (),
1334
1363
info ,
1335
1364
proc .declarationContext ,
@@ -1338,7 +1367,7 @@ private RubySymbol defineMethod(RubyModule module, String name, RubyProc proc,
1338
1367
Visibility .PUBLIC ,
1339
1368
proc ,
1340
1369
newCallTarget );
1341
- return addMethod (module , name , method , callerFrame );
1370
+ return addInternalMethod (module , name , internalMethod , callerFrame );
1342
1371
}
1343
1372
1344
1373
private static class CallMethodWithLambdaBody extends RubyContextSourceNode {
@@ -1371,7 +1400,7 @@ public Object execute(VirtualFrame frame) {
1371
1400
}
1372
1401
1373
1402
@ TruffleBoundary
1374
- private RubySymbol addMethod (RubyModule module , String name , InternalMethod method ,
1403
+ private RubySymbol addInternalMethod (RubyModule module , String name , InternalMethod method ,
1375
1404
MaterializedFrame callerFrame ) {
1376
1405
method = method .withName (name );
1377
1406
@@ -1381,6 +1410,16 @@ private RubySymbol addMethod(RubyModule module, String name, InternalMethod meth
1381
1410
return getSymbol (method .getName ());
1382
1411
}
1383
1412
1413
+ protected boolean isMethodParameterProvided (Object [] rubyArgs ) {
1414
+ final int count = RubyArguments .getPositionalArgumentsCount (rubyArgs , false );
1415
+ return count >= 2 ;
1416
+ }
1417
+
1418
+ protected boolean isExpectedMethodParameterType (Object method ) {
1419
+ return RubyGuards .isRubyMethod (method ) || RubyGuards .isRubyUnboundMethod (method ) ||
1420
+ RubyGuards .isRubyProc (method );
1421
+ }
1422
+
1384
1423
}
1385
1424
1386
1425
@ CoreMethod (names = "extend_object" , required = 1 , visibility = Visibility .PRIVATE )
0 commit comments