Пример #1
0
 @CompilerDirectives.TruffleBoundary
 public RubyConstant removeConstant(Node currentNode, String name) {
   checkFrozen(currentNode);
   RubyConstant oldConstant = constants.remove(name);
   newLexicalVersion();
   return oldConstant;
 }
Пример #2
0
  @CompilerDirectives.TruffleBoundary
  public void addMethod(Node currentNode, InternalMethod method) {
    assert method != null;

    if (getContext().getCoreLibrary().isLoadingRubyCore()) {
      final InternalMethod currentMethod = methods.get(method.getName());

      if (currentMethod != null
          && currentMethod.getSharedMethodInfo().getSourceSection() instanceof CoreSourceSection) {
        return;
      }
    }

    checkFrozen(currentNode);
    methods.put(method.getName(), method.withDeclaringModule(rubyModuleObject));
    newVersion();

    if (context.getCoreLibrary().isLoaded() && !method.isUndefined()) {
      context.send(
          rubyModuleObject,
          "method_added",
          null,
          context.getSymbolTable().getSymbol(method.getName()));
    }
  }
Пример #3
0
  @CompilerDirectives.TruffleBoundary
  public void prepend(Node currentNode, DynamicObject module) {
    assert RubyGuards.isRubyModule(module);

    checkFrozen(currentNode);

    // If the module we want to prepend already includes us, it is cyclic
    if (ModuleOperations.includesModule(module, rubyModuleObject)) {
      throw new RaiseException(
          getContext().getCoreLibrary().argumentError("cyclic prepend detected", currentNode));
    }

    ModuleChain mod = Layouts.MODULE.getFields(module).start;
    ModuleChain cur = start;
    while (mod != null
        && !(RubyGuards.isRubyModule(mod)
            && RubyGuards.isRubyClass(((ModuleFields) mod).rubyModuleObject))) {
      if (!(mod instanceof PrependMarker)) {
        if (!ModuleOperations.includesModule(rubyModuleObject, mod.getActualModule())) {
          cur.insertAfter(mod.getActualModule());
          Layouts.MODULE.getFields(mod.getActualModule()).addDependent(rubyModuleObject);
          cur = cur.getParentModule();
        }
      }
      mod = mod.getParentModule();
    }

    newVersion();
  }
Пример #4
0
  @CompilerDirectives.TruffleBoundary
  public Object removeClassVariable(Node currentNode, String name) {
    checkFrozen(currentNode);

    final Object found = classVariables.remove(name);
    if (found == null) {
      CompilerDirectives.transferToInterpreter();
      throw new RaiseException(
          context
              .getCoreLibrary()
              .nameErrorClassVariableNotDefined(name, rubyModuleObject, currentNode));
    }
    return found;
  }
Пример #5
0
  @CompilerDirectives.TruffleBoundary
  public void changeConstantVisibility(Node currentNode, String name, boolean isPrivate) {
    checkFrozen(currentNode);
    RubyConstant rubyConstant = constants.get(name);

    if (rubyConstant != null) {
      rubyConstant.setPrivate(isPrivate);
      newLexicalVersion();
    } else {
      throw new RaiseException(
          context
              .getCoreLibrary()
              .nameErrorUninitializedConstant(rubyModuleObject, name, currentNode));
    }
  }
Пример #6
0
  public void setConstantInternal(Node currentNode, String name, Object value, boolean autoload) {
    checkFrozen(currentNode);

    RubyConstant previous = constants.get(name);
    if (previous == null) {
      constants.put(name, new RubyConstant(rubyModuleObject, value, false, autoload));
    } else {
      // TODO(CS): warn when redefining a constant
      // TODO (nirvdrum 18-Feb-15): But don't warn when redefining an autoloaded constant.
      constants.put(
          name, new RubyConstant(rubyModuleObject, value, previous.isPrivate(), autoload));
    }

    newLexicalVersion();
  }
Пример #7
0
  @CompilerDirectives.TruffleBoundary
  public void include(Node currentNode, DynamicObject module) {
    assert RubyGuards.isRubyModule(module);

    checkFrozen(currentNode);

    // If the module we want to include already includes us, it is cyclic
    if (ModuleOperations.includesModule(module, rubyModuleObject)) {
      throw new RaiseException(
          getContext().getCoreLibrary().argumentError("cyclic include detected", currentNode));
    }

    // We need to include the module ancestors in reverse order for a given inclusionPoint
    ModuleChain inclusionPoint = this;
    Deque<DynamicObject> modulesToInclude = new ArrayDeque<>();
    for (DynamicObject ancestor : Layouts.MODULE.getFields(module).ancestors()) {
      if (ModuleOperations.includesModule(rubyModuleObject, ancestor)) {
        if (isIncludedModuleBeforeSuperClass(ancestor)) {
          // Include the modules at the appropriate inclusionPoint
          performIncludes(inclusionPoint, modulesToInclude);
          assert modulesToInclude.isEmpty();

          // We need to include the others after that module
          inclusionPoint = parentModule;
          while (inclusionPoint.getActualModule() != ancestor) {
            inclusionPoint = inclusionPoint.getParentModule();
          }
        } else {
          // Just ignore this module, as it is included above the superclass
        }
      } else {
        modulesToInclude.push(ancestor);
      }
    }

    performIncludes(inclusionPoint, modulesToInclude);

    newVersion();
  }
Пример #8
0
  @CompilerDirectives.TruffleBoundary
  public void setClassVariable(Node currentNode, String variableName, Object value) {
    checkFrozen(currentNode);

    classVariables.put(variableName, value);
  }