protected Object interpretSuper( ThreadContext context, IRubyObject self, IRubyObject[] args, Block block) { // SSS FIXME: We should check in the current module (for instance methods) or the current // module's meta class (for class methods) // // RubyModule currM = context.getCurrentScope().getStaticScope().getModule(); // RubyModule klazz = (isInstanceMethodSuper) ? currM : currM.getMetaClass(); // // The question is how do we know what this 'super' ought to do? // For 'super' that occurs in a method scope, this is easy to figure out. // But, what about 'super' that occurs in block scope? How do we figure that out? RubyModule klazz = context.getFrameKlazz(); // SSS FIXME: Even though we may know the method name in some instances, // we are not making use of it here. String methodName = context.getCurrentFrame().getName(); // methAddr.getName(); checkSuperDisabledOrOutOfMethod(context, klazz, methodName); RubyClass superClass = RuntimeHelpers.findImplementerIfNecessary(self.getMetaClass(), klazz).getSuperClass(); DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE; Object rVal = method.isUndefined() ? RuntimeHelpers.callMethodMissing( context, self, method.getVisibility(), methodName, CallType.SUPER, args, block) : method.call(context, self, superClass, methodName, args, block); return hasUnusedResult() ? null : rVal; }
@Override public Object interpret( ThreadContext context, DynamicScope currDynScope, IRubyObject self, Object[] temp, Block aBlock) { // FIXME: Receiver is not being used...should we be retrieving it? IRubyObject receiver = (IRubyObject) getReceiver().retrieve(context, self, currDynScope, temp); IRubyObject[] args = prepareArguments(context, self, getCallArgs(), currDynScope, temp); Block block = prepareBlock(context, self, currDynScope, temp); RubyModule klazz = context.getFrameKlazz(); // SSS FIXME: Even though we may know the method name in some instances, // we are not making use of it here. It is cleaner in the sense of not // relying on implicit information whose data flow doesn't show up in the IR. String methodName = context.getCurrentFrame().getName(); // methAddr.getName(); checkSuperDisabledOrOutOfMethod(context, klazz, methodName); RubyClass superClass = RuntimeHelpers.findImplementerIfNecessary(self.getMetaClass(), klazz).getSuperClass(); DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE; Object rVal = method.isUndefined() ? RuntimeHelpers.callMethodMissing( context, self, method.getVisibility(), methodName, CallType.SUPER, args, block) : method.call(context, self, superClass, methodName, args, block); return hasUnusedResult() ? null : rVal; }
protected static boolean methodMissing( CacheEntry entry, CallType callType, String name, IRubyObject caller) { DynamicMethod method = entry.method; return method.isUndefined() || (callType == CallType.NORMAL && !name.equals("method_missing") && !method.isCallableFrom(caller, callType)); }
private DynamicMethod cacheAndGet( ThreadContext context, RubyClass selfType, int index, String methodName) { CacheEntry entry = selfType.searchWithCache(methodName); DynamicMethod method = entry.method; if (method.isUndefined()) { return RuntimeHelpers.selectMethodMissing( context, selfType, method.getVisibility(), methodName, CallType.FUNCTIONAL); } methodCache[index] = entry; return method; }
@Override public boolean methodMissing(CacheEntry entry, IRubyObject caller) { DynamicMethod method = entry.method; return method.isUndefined(); }
@JRubyMethod(name = "new", meta = true) public static final IRubyObject newMappedType( ThreadContext context, IRubyObject klass, IRubyObject converter) { if (!converter.respondsTo("native_type")) { throw context.runtime.newNoMethodError( "converter needs a native_type method", "native_type", converter.getMetaClass()); } DynamicMethod toNativeMethod = converter.getMetaClass().searchMethod("to_native"); if (toNativeMethod.isUndefined()) { throw context.runtime.newNoMethodError( "converter needs a to_native method", "to_native", converter.getMetaClass()); } if (toNativeMethod.getArity().required() < 1 || toNativeMethod.getArity().required() > 2) { throw context.runtime.newArgumentError("to_native should accept one or two arguments"); } DynamicMethod fromNativeMethod = converter.getMetaClass().searchMethod("from_native"); if (fromNativeMethod.isUndefined()) { throw context.runtime.newNoMethodError( "converter needs a from_native method", "from_native", converter.getMetaClass()); } if (fromNativeMethod.getArity().required() < 1 || fromNativeMethod.getArity().required() > 2) { throw context.runtime.newArgumentError("from_native should accept one or two arguments"); } Type nativeType; try { nativeType = (Type) converter.callMethod(context, "native_type"); } catch (ClassCastException ex) { throw context.runtime.newTypeError("native_type did not return instance of FFI::Type"); } boolean isReferenceRequired; if (converter.respondsTo("reference_required?")) { isReferenceRequired = converter.callMethod(context, "reference_required?").isTrue(); } else { switch (nativeType.nativeType) { case BOOL: case CHAR: case UCHAR: case SHORT: case USHORT: case INT: case UINT: case LONG: case ULONG: case LONG_LONG: case ULONG_LONG: case FLOAT: case DOUBLE: isReferenceRequired = false; break; default: isReferenceRequired = true; break; } } return new MappedType( context.runtime, (RubyClass) klass, nativeType, converter, toNativeMethod, fromNativeMethod, isReferenceRequired); }