예제 #1
0
  public DynamicObject getNormalObjectSingletonClass(DynamicObject object) {
    CompilerAsserts.neverPartOfCompilation();

    if (RubyGuards.isRubyClass(object)) { // For the direct caller
      return ClassNodes.getSingletonClass(object);
    }

    if (Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(object))) {
      return Layouts.BASIC_OBJECT.getMetaClass(object);
    }

    CompilerDirectives.transferToInterpreter();
    final DynamicObject logicalClass = BasicObjectNodes.getLogicalClass(object);

    DynamicObject attached = null;
    if (RubyGuards.isRubyModule(object)) {
      attached = object;
    }

    final String name =
        String.format(
            "#<Class:#<%s:0x%x>>",
            Layouts.MODULE.getFields(logicalClass).getName(),
            BasicObjectNodes.verySlowGetObjectID(object));
    final DynamicObject singletonClass =
        ClassNodes.createSingletonClassOfObject(getContext(), logicalClass, attached, name);
    propagateFrozen(object, singletonClass);

    Layouts.BASIC_OBJECT.setMetaClass(object, singletonClass);

    return singletonClass;
  }
예제 #2
0
  public static void initialize(DynamicObject rubyClass, DynamicObject superclass) {
    assert RubyGuards.isRubyClass(superclass);

    Layouts.MODULE.getFields(rubyClass).parentModule = Layouts.MODULE.getFields(superclass).start;
    Layouts.MODULE.getFields(superclass).addDependent(rubyClass);

    Layouts.MODULE.getFields(rubyClass).newVersion();
    ensureSingletonConsistency(rubyClass);

    DynamicObjectFactory factory = Layouts.CLASS.getInstanceFactory(superclass);
    factory = Layouts.BASIC_OBJECT.setLogicalClass(factory, rubyClass);
    factory = Layouts.BASIC_OBJECT.setMetaClass(factory, rubyClass);
    Layouts.CLASS.setInstanceFactoryUnsafe(rubyClass, factory);
  }
예제 #3
0
  public void getAdoptedByLexicalParent(
      DynamicObject lexicalParent, String name, Node currentNode) {
    assert RubyGuards.isRubyModule(lexicalParent);

    Layouts.MODULE
        .getFields(lexicalParent)
        .setConstantInternal(currentNode, name, rubyModuleObject, false);
    Layouts.MODULE.getFields(lexicalParent).addLexicalDependent(rubyModuleObject);

    if (this.name == null) {
      // Tricky, we need to compare with the Object class, but we only have a Class at hand.
      final DynamicObject classClass = Layouts.BASIC_OBJECT.getLogicalClass(getLogicalClass());
      final DynamicObject objectClass =
          ClassNodes.getSuperClass(ClassNodes.getSuperClass(classClass));

      if (lexicalParent == objectClass) {
        this.name = name;
        updateAnonymousChildrenModules();
      } else if (Layouts.MODULE.getFields(lexicalParent).hasName()) {
        this.name = Layouts.MODULE.getFields(lexicalParent).getName() + "::" + name;
        updateAnonymousChildrenModules();
      }
      // else: Our lexicalParent is also an anonymous module
      // and will name us when it gets named via updateAnonymousChildrenModules()
    }
  }
예제 #4
0
  private Object coerceObject(VirtualFrame frame, Object object) {
    if (toIntNode == null) {
      CompilerDirectives.transferToInterpreter();
      toIntNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
    }

    final Object coerced;
    try {
      coerced = toIntNode.call(frame, object, "to_int", null);
    } catch (RaiseException e) {
      if (Layouts.BASIC_OBJECT.getLogicalClass(e.getRubyException())
          == getContext().getCoreLibrary().getNoMethodErrorClass()) {
        CompilerDirectives.transferToInterpreter();
        throw new RaiseException(
            getContext().getCoreLibrary().typeErrorNoImplicitConversion(object, "Integer", this));
      } else {
        throw e;
      }
    }

    if (getContext().getCoreLibrary().getLogicalClass(coerced)
        == getContext().getCoreLibrary().getFixnumClass()) {
      return coerced;
    } else {
      CompilerDirectives.transferToInterpreter();
      throw new RaiseException(
          getContext()
              .getCoreLibrary()
              .typeErrorBadCoercion(object, "Integer", "to_int", coerced, this));
    }
  }
예제 #5
0
  public static DynamicObject createOneSingletonClass(DynamicObject rubyClass) {
    CompilerAsserts.neverPartOfCompilation();

    if (Layouts.CLASS.getIsSingleton(Layouts.BASIC_OBJECT.getMetaClass(rubyClass))) {
      return Layouts.BASIC_OBJECT.getMetaClass(rubyClass);
    }

    final DynamicObject singletonSuperclass;
    if (getSuperClass(rubyClass) == null) {
      singletonSuperclass = Layouts.BASIC_OBJECT.getLogicalClass(rubyClass);
    } else {
      singletonSuperclass = createOneSingletonClass(getSuperClass(rubyClass));
    }

    String name = String.format("#<Class:%s>", Layouts.MODULE.getFields(rubyClass).getName());
    Layouts.BASIC_OBJECT.setMetaClass(
        rubyClass,
        ClassNodes.createRubyClass(
            Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(rubyClass)).getContext(),
            Layouts.BASIC_OBJECT.getLogicalClass(rubyClass),
            null,
            singletonSuperclass,
            name,
            true,
            rubyClass));

    return Layouts.BASIC_OBJECT.getMetaClass(rubyClass);
  }
예제 #6
0
  public static DynamicObject createRubyClass(
      RubyContext context,
      DynamicObject classClass,
      DynamicObject lexicalParent,
      DynamicObject superclass,
      String name,
      boolean isSingleton,
      DynamicObject attached) {
    final ModuleFields model = new ModuleFields(context, lexicalParent, name);

    final DynamicObject rubyClass =
        Layouts.CLASS.createClass(
            Layouts.CLASS.getInstanceFactory(classClass), model, isSingleton, attached, null);
    assert RubyGuards.isRubyClass(rubyClass) : classClass.getShape().getObjectType().getClass();
    assert RubyGuards.isRubyModule(rubyClass) : classClass.getShape().getObjectType().getClass();

    model.rubyModuleObject = rubyClass;

    if (model.lexicalParent == null) { // bootstrap or anonymous module
      Layouts.MODULE.getFields(rubyClass).name = Layouts.MODULE.getFields(rubyClass).givenBaseName;
    } else {
      Layouts.MODULE
          .getFields(rubyClass)
          .getAdoptedByLexicalParent(model.lexicalParent, model.givenBaseName, null);
    }

    if (superclass != null) {
      assert RubyGuards.isRubyClass(superclass);
      assert RubyGuards.isRubyClass(Layouts.MODULE.getFields(rubyClass).rubyModuleObject);

      Layouts.MODULE.getFields(rubyClass).parentModule = Layouts.MODULE.getFields(superclass).start;
      Layouts.MODULE
          .getFields(superclass)
          .addDependent(Layouts.MODULE.getFields(rubyClass).rubyModuleObject);

      Layouts.MODULE.getFields(rubyClass).newVersion();
    }

    DynamicObjectFactory factory = Layouts.CLASS.getInstanceFactory(superclass);
    factory = Layouts.BASIC_OBJECT.setLogicalClass(factory, rubyClass);
    factory = Layouts.BASIC_OBJECT.setMetaClass(factory, rubyClass);
    Layouts.CLASS.setInstanceFactoryUnsafe(rubyClass, factory);

    return rubyClass;
  }
예제 #7
0
 public static DynamicObject createRubyClass(
     RubyContext context, DynamicObject lexicalParent, DynamicObject superclass, String name) {
   final DynamicObject rubyClass =
       createRubyClass(
           context,
           Layouts.BASIC_OBJECT.getLogicalClass(superclass),
           lexicalParent,
           superclass,
           name,
           false,
           null);
   ensureSingletonConsistency(rubyClass);
   return rubyClass;
 }
예제 #8
0
 public static DynamicObject createSingletonClassOfObject(
     RubyContext context, DynamicObject superclass, DynamicObject attached, String name) {
   // We also need to create the singleton class of a singleton class for proper lookup and
   // consistency.
   // See rb_singleton_class() documentation in MRI.
   // Allocator is null here, we cannot create instances of singleton classes.
   assert RubyGuards.isRubyClass(superclass);
   assert attached == null || RubyGuards.isRubyModule(attached);
   return ensureSingletonConsistency(
       createRubyClass(
           context,
           Layouts.BASIC_OBJECT.getLogicalClass(superclass),
           null,
           superclass,
           name,
           true,
           attached));
 }
예제 #9
0
  /**
   * This constructor supports initialization and solves boot-order problems and should not normally
   * be used from outside this class.
   */
  public static DynamicObject createBootClass(
      DynamicObject classClass, DynamicObject superclass, String name) {
    assert RubyGuards.isRubyClass(classClass);
    assert superclass == null || RubyGuards.isRubyClass(superclass);
    final ModuleFields model =
        new ModuleFields(
            Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(classClass)).getContext(),
            null,
            name);

    final DynamicObject rubyClass =
        Layouts.CLASS.createClass(
            Layouts.CLASS.getInstanceFactory(classClass), model, false, null, null);
    assert RubyGuards.isRubyClass(rubyClass) : classClass.getShape().getObjectType().getClass();
    assert RubyGuards.isRubyModule(rubyClass) : classClass.getShape().getObjectType().getClass();

    model.rubyModuleObject = rubyClass;

    if (model.lexicalParent == null) { // bootstrap or anonymous module
      Layouts.MODULE.getFields(rubyClass).name = Layouts.MODULE.getFields(rubyClass).givenBaseName;
    } else {
      Layouts.MODULE
          .getFields(rubyClass)
          .getAdoptedByLexicalParent(model.lexicalParent, model.givenBaseName, null);
    }

    if (superclass != null) {
      assert RubyGuards.isRubyClass(superclass);
      assert RubyGuards.isRubyClass(Layouts.MODULE.getFields(rubyClass).rubyModuleObject);

      Layouts.MODULE.getFields(rubyClass).parentModule = Layouts.MODULE.getFields(superclass).start;
      Layouts.MODULE
          .getFields(superclass)
          .addDependent(Layouts.MODULE.getFields(rubyClass).rubyModuleObject);

      Layouts.MODULE.getFields(rubyClass).newVersion();
    }

    return rubyClass;
  }
예제 #10
0
  /** Special constructor for class Class */
  public static DynamicObject createClassClass(RubyContext context) {
    final ModuleFields model = new ModuleFields(context, null, "Class");

    final DynamicObject rubyClass = LAYOUT.newInstance(LAYOUT.createShape(new ObjectType()));

    final DynamicObjectFactory factory = Layouts.CLASS.createClassShape(rubyClass, rubyClass);

    rubyClass.setShapeAndGrow(rubyClass.getShape(), factory.getShape());
    assert RubyGuards.isRubyModule(rubyClass);
    assert RubyGuards.isRubyClass(rubyClass);

    model.rubyModuleObject = rubyClass;
    Layouts.CLASS.setInstanceFactoryUnsafe(rubyClass, factory);
    Layouts.MODULE.setFields(rubyClass, model);
    model.name = model.givenBaseName;

    assert RubyGuards.isRubyModule(rubyClass);
    assert RubyGuards.isRubyClass(rubyClass);
    assert Layouts.MODULE.getFields(rubyClass) == model;
    assert Layouts.BASIC_OBJECT.getLogicalClass(rubyClass) == rubyClass;

    return rubyClass;
  }
  @Override
  public Object isDefined(VirtualFrame frame) {
    final RubyConstant constant;
    try {
      constant = lookupConstantNode.executeLookupConstant(frame);
    } catch (RaiseException e) {
      if (Layouts.BASIC_OBJECT.getLogicalClass(((DynamicObject) e.getRubyException()))
          == getContext().getCoreLibrary().getNameErrorClass()) {
        // private constant
        return nil();
      }
      throw e;
    }

    if (constant == null) {
      return nil();
    } else {
      return Layouts.STRING.createString(
          getContext().getCoreLibrary().getStringFactory(),
          RubyString.encodeBytelist("constant", UTF8Encoding.INSTANCE),
          StringSupport.CR_7BIT,
          null);
    }
  }
예제 #12
0
  private DynamicObject translate(UnsupportedSpecializationException exception) {
    if (getContext().getOptions().EXCEPTIONS_PRINT_JAVA) {
      exception.printStackTrace();
    }

    final StringBuilder builder = new StringBuilder();
    builder.append("Truffle doesn't have a case for the ");
    builder.append(exception.getNode().getClass().getName());
    builder.append(" node with values of type ");

    for (Object value : exception.getSuppliedValues()) {
      builder.append(" ");

      if (value == null) {
        builder.append("null");
      } else if (value instanceof DynamicObject) {
        builder.append(
            Layouts.MODULE
                .getFields(Layouts.BASIC_OBJECT.getLogicalClass(((DynamicObject) value)))
                .getName());
        builder.append("(");
        builder.append(value.getClass().getName());
        builder.append(")");

        if (RubyGuards.isRubyArray(value)) {
          final DynamicObject array = (DynamicObject) value;
          builder.append("[");

          if (Layouts.ARRAY.getStore(array) == null) {
            builder.append("null");
          } else {
            builder.append(Layouts.ARRAY.getStore(array).getClass().getName());
          }

          builder.append(",");
          builder.append(Layouts.ARRAY.getSize(array));
          builder.append("]");
        } else if (RubyGuards.isRubyHash(value)) {
          final Object store = Layouts.HASH.getStore((DynamicObject) value);

          if (store == null) {
            builder.append("[null]");
          } else {
            builder.append("[");
            builder.append(store.getClass().getName());
            builder.append("]");
          }
        }
      } else {
        builder.append(value.getClass().getName());
      }

      if (value instanceof Number || value instanceof Boolean) {
        builder.append("=");
        builder.append(value.toString());
      }
    }

    switch (unsupportedOperationBehavior) {
      case TYPE_ERROR:
        return getContext().getCoreLibrary().typeError(builder.toString(), this);
      case ARGUMENT_ERROR:
        return getContext().getCoreLibrary().argumentError(builder.toString(), this);
      default:
        throw new UnsupportedOperationException();
    }
  }
예제 #13
0
 public DynamicObject getLogicalClass() {
   return Layouts.BASIC_OBJECT.getLogicalClass(rubyModuleObject);
 }