@Override public Label interpret(InterpreterContext interp) { RubyModule clazz = (RubyModule) getArg().retrieve(interp); String name = method.getName(); ThreadContext context = interp.getContext(); Visibility visibility = context.getCurrentVisibility(); if (name == "initialize" || name == "initialize_copy" || visibility == Visibility.MODULE_FUNCTION) { visibility = Visibility.PRIVATE; } DynamicMethod newMethod = new InterpretedIRMethod(method, visibility, clazz); clazz.addMethod(name, newMethod); if (visibility == Visibility.MODULE_FUNCTION) { clazz .getSingletonClass() .addMethod( name, new WrapperMethod(clazz.getSingletonClass(), newMethod, Visibility.PUBLIC)); clazz.callMethod(context, "singleton_method_added", interp.getRuntime().fastNewSymbol(name)); } // 'class << state.self' and 'class << obj' uses defn as opposed to defs if (clazz.isSingleton()) { ((MetaClass) clazz) .getAttached() .callMethod(context, "singleton_method_added", interp.getRuntime().fastNewSymbol(name)); } else { clazz.callMethod(context, "method_added", interp.getRuntime().fastNewSymbol(name)); } return null; }
/** * Calculate, based on given RubyModule, which class in its hierarchy should be used to determine * protected access. * * @param cls The class from which to calculate * @return The class to be used for protected access checking. */ protected static RubyModule calculateProtectedClass(RubyModule cls) { // singleton classes don't get their own visibility domain if (cls.isSingleton()) cls = cls.getSuperClass(); while (cls.isIncluded()) cls = cls.getMetaClass(); // For visibility we need real meta class and not anonymous one from class << self if (cls instanceof MetaClass) cls = ((MetaClass) cls).getRealClass(); return cls; }
public static RubyModule getClassVariableBase(Ruby runtime, StaticScope scope) { RubyModule rubyClass = scope.getModule(); while (rubyClass.isSingleton() || rubyClass == runtime.getDummy()) { // We ran out of scopes to check if (scope == null) return null; scope = scope.getPreviousCRefScope(); rubyClass = scope.getModule(); if (scope.getPreviousCRefScope() == null) { runtime .getWarnings() .warn( ID.CVAR_FROM_TOPLEVEL_SINGLETON_METHOD, "class variable access from toplevel singleton method"); } } return rubyClass; }
/** Evaluates the body in a class or module definition statement. */ public static IRubyObject evalClassDefinitionBody( Ruby runtime, ThreadContext context, StaticScope scope, Node bodyNode, RubyModule type, IRubyObject self, Block block) { context.preClassEval(scope, type); try { if (runtime.hasEventHooks()) { callTraceFunction(runtime, context, RubyEvent.CLASS); } if (bodyNode == null) return runtime.getNil(); String name = type.getBaseName(); if (name == null) { if (type.isSingleton()) { name = "__singleton__"; } else if (type.isModule()) { // can these two happen? name = "<anonymous module>"; } else { name = "<anonymous class>"; } } return INTERPRET_CLASS(runtime, context, bodyNode, name, type, block); } finally { try { if (runtime.hasEventHooks()) { callTraceFunction(runtime, context, RubyEvent.END); } } finally { context.postClassEval(); } } }
@Override public Label interpret(InterpreterContext interp) { String name; Object receiver; Ruby rt = interp.getRuntime(); Object rVal = null; switch (this.implMethod) { // SSS FIXME: Note that compiler/impl/BaseBodyCompiler is using op_match2 for match() and // and op_match for match2, // and we are replicating it here ... Is this a bug there? case MATCH: receiver = getReceiver().retrieve(interp); rVal = ((RubyRegexp) receiver).op_match2(interp.getContext()); break; case MATCH2: receiver = getReceiver().retrieve(interp); rVal = ((RubyRegexp) receiver) .op_match(interp.getContext(), (IRubyObject) getCallArgs()[0].retrieve(interp)); break; case MATCH3: { // ENEBO: Only for rubystring? receiver = getReceiver().retrieve(interp); IRubyObject value = (IRubyObject) getCallArgs()[0].retrieve(interp); if (value instanceof RubyString) { rVal = ((RubyRegexp) receiver).op_match(interp.getContext(), value); } else { rVal = value.callMethod(interp.getContext(), "=~", (IRubyObject) receiver); } break; } case SET_WITHIN_DEFINED: interp.getContext().setWithinDefined(((BooleanLiteral) getCallArgs()[0]).isTrue()); break; case RTH_GET_DEFINED_CONSTANT_OR_BOUND_METHOD: { IRubyObject v = (IRubyObject) getCallArgs()[0].retrieve(interp); name = ((StringLiteral) getCallArgs()[1])._str_value; ByteList definedType = RuntimeHelpers.getDefinedConstantOrBoundMethod(v, name); rVal = (definedType == null ? Nil.NIL : (new StringLiteral(definedType))).retrieve(interp); break; } case BLOCK_GIVEN: rVal = rt.newBoolean(interp.getBlock().isGiven()); break; case RT_IS_GLOBAL_DEFINED: // name = getCallArgs()[0].retrieve(interp).toString(); name = ((StringLiteral) getCallArgs()[0])._str_value; rVal = rt.newBoolean(rt.getGlobalVariables().isDefined(name)); break; case RT_GET_OBJECT: rVal = rt.getObject(); break; case RT_GET_BACKREF: // SSS: FIXME: Or use this directly? "context.getCurrentScope().getBackRef(rt)" What is the // diff?? rVal = RuntimeHelpers.getBackref(rt, interp.getContext()); break; case SELF_METACLASS: rVal = ((IRubyObject) getReceiver().retrieve(interp)).getMetaClass(); break; case CHECK_ARITY: { Operand[] args = getCallArgs(); int required = ((Fixnum) args[0]).value.intValue(); int opt = ((Fixnum) args[1]).value.intValue(); int rest = ((Fixnum) args[2]).value.intValue(); int numArgs = interp.getParameterCount(); if ((numArgs < required) || ((rest == -1) && (numArgs > (required + opt)))) { Arity.raiseArgumentError(interp.getRuntime(), numArgs, required, required + opt); } break; } case RAISE_ARGUMENT_ERROR: { Operand[] args = getCallArgs(); int required = ((Fixnum) args[0]).value.intValue(); int opt = ((Fixnum) args[1]).value.intValue(); int rest = ((Fixnum) args[2]).value.intValue(); int numArgs = ((Fixnum) args[3]).value.intValue(); Arity.raiseArgumentError(interp.getRuntime(), numArgs, required, required + opt); break; } case SELF_HAS_INSTANCE_VARIABLE: { receiver = getReceiver().retrieve(interp); // name = getCallArgs()[0].retrieve(interp).toString(); name = ((StringLiteral) getCallArgs()[0])._str_value; rVal = rt.newBoolean( ((IRubyObject) receiver).getInstanceVariables().hasInstanceVariable(name)); break; } case SELF_IS_METHOD_BOUND: { receiver = getReceiver().retrieve(interp); boolean bound = ((IRubyObject) receiver) .getMetaClass() .isMethodBound(((StringLiteral) getCallArgs()[0])._str_value, false); rVal = rt.newBoolean(bound); break; } case TC_SAVE_ERR_INFO: rVal = interp.getContext().getErrorInfo(); break; case TC_RESTORE_ERR_INFO: interp.getContext().setErrorInfo((IRubyObject) getCallArgs()[0].retrieve(interp)); break; case TC_GET_CONSTANT_DEFINED: // name = getCallArgs()[0].retrieve(interp).toString(); name = ((StringLiteral) getCallArgs()[0])._str_value; rVal = rt.newBoolean(interp.getContext().getConstantDefined(name)); break; case TC_GET_CURRENT_MODULE: rVal = interp.getContext().getCurrentScope().getStaticScope().getModule(); break; case BACKREF_IS_RUBY_MATCH_DATA: // bRef = getBackref() // flag = bRef instanceof RubyMatchData try { // SSS: FIXME: Or use this directly? "context.getCurrentScope().getBackRef(rt)" What is // the diff?? IRubyObject bRef = RuntimeHelpers.getBackref(rt, interp.getContext()); rVal = rt.newBoolean( Class.forName("RubyMatchData").isInstance(bRef)); // SSS FIXME: Is this correct? } catch (ClassNotFoundException e) { // Should never get here! throw new RuntimeException(e); } break; case METHOD_PUBLIC_ACCESSIBLE: { /* ------------------------------------------------------------ * mc = r.metaClass * v = mc.getVisibility(methodName) * v.isPrivate? || (v.isProtected? && receiver/self? instanceof mc.getRealClass) * ------------------------------------------------------------ */ IRubyObject r = (IRubyObject) getReceiver().retrieve(interp); RubyClass mc = r.getMetaClass(); String arg = ((StringLiteral) getCallArgs()[0])._str_value; Visibility v = mc.searchMethod(arg).getVisibility(); rVal = rt.newBoolean( (v != null) && !v.isPrivate() && !(v.isProtected() && mc.getRealClass().isInstance(r))); break; } case CLASS_VAR_DEFINED: { // cm.classVarDefined(name) || (cm.isSingleton && !(cm.attached instanceof RubyModule) && // cm.attached.classVarDefined(name)) boolean flag; RubyModule cm = (RubyModule) getReceiver().retrieve(interp); name = ((StringLiteral) getCallArgs()[0])._str_value; flag = cm.isClassVarDefined(name); if (!flag) { if (cm.isSingleton()) { IRubyObject ao = ((MetaClass) cm).getAttached(); if (ao instanceof RubyModule) flag = ((RubyModule) ao).isClassVarDefined(name); } } rVal = rt.newBoolean(flag); break; } case FRAME_SUPER_METHOD_BOUND: { receiver = getReceiver().retrieve(interp); boolean flag = false; ThreadContext tc = interp.getContext(); String fn = tc.getFrameName(); if (fn != null) { RubyModule fc = tc.getFrameKlazz(); if (fc != null) { flag = RuntimeHelpers.findImplementerIfNecessary( ((IRubyObject) receiver).getMetaClass(), fc) .getSuperClass() .isMethodBound(fn, false); } } rVal = rt.newBoolean(flag); break; } } // Store the result if (rVal != null) getResult().store(interp, rVal); return null; }