@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())); } }
@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(); }
@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(); }
public void newLexicalVersion() { newVersion(new HashSet<DynamicObject>(), true); }
public void newVersion() { newVersion(new HashSet<DynamicObject>(), false); }
@CompilerDirectives.TruffleBoundary public void removeMethod(String methodName) { methods.remove(methodName); newVersion(); }