@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(); }