示例#1
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()));
    }
  }
示例#2
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();
  }
示例#3
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();
  }
示例#4
0
 public void newLexicalVersion() {
   newVersion(new HashSet<DynamicObject>(), true);
 }
示例#5
0
 public void newVersion() {
   newVersion(new HashSet<DynamicObject>(), false);
 }
示例#6
0
 @CompilerDirectives.TruffleBoundary
 public void removeMethod(String methodName) {
   methods.remove(methodName);
   newVersion();
 }