Ejemplo n.º 1
0
  @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;
  }
Ejemplo n.º 2
0
  /**
   * 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;
  }
Ejemplo n.º 3
0
  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;
  }
Ejemplo n.º 4
0
  /** 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();
      }
    }
  }
Ejemplo n.º 5
0
  @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;
  }