@TruffleBoundary public static Object lookupClassVariable(RubyModule module, String name) { CompilerAsserts.neverPartOfCompilation(); Object value; // Look in the current module value = module.getClassVariables().get(name); if (value != null) { return value; } // Look in ancestors for (RubyModule ancestor : module.parentAncestors()) { value = ancestor.getClassVariables().get(name); if (value != null) { return value; } } // Nothing found return null; }
@TruffleBoundary public static InternalMethod lookupMethod(RubyModule module, String name) { CompilerAsserts.neverPartOfCompilation(); InternalMethod method; // Look in the current module method = module.getMethods().get(name); if (method != null) { return method; } // Look in ancestors for (RubyModule ancestor : module.parentAncestors()) { method = ancestor.getMethods().get(name); if (method != null) { return method; } } // Nothing found return null; }
@Override public RubySymbol execute(VirtualFrame frame) { notDesignedForCompilation(); final Object receiverObject = receiver.execute(frame); final RubyMethod methodObject = (RubyMethod) method.execute(frame); RubyModule module; if (receiverObject instanceof RubyModule) { module = (RubyModule) receiverObject; } else { module = ((RubyBasicObject) receiverObject).getSingletonClass(this); } final RubyMethod methodWithDeclaringModule = methodObject.withDeclaringModule(module); if (moduleFunctionFlag(frame)) { module.addMethod(this, methodWithDeclaringModule.withVisibility(Visibility.PRIVATE)); module .getSingletonClass(this) .addMethod(this, methodWithDeclaringModule.withVisibility(Visibility.PUBLIC)); } else { module.addMethod(this, methodWithDeclaringModule); } return getContext().newSymbol(method.getName()); }
@Override public Object execute(VirtualFrame frame) { // TODO(cs): can module ever not evaluate to a RubyModule? final RubyModule moduleObject = (RubyModule) module.execute(frame); final Object rhsValue = rhs.execute(frame); assert rhsValue != null; assert !(rhsValue instanceof String); moduleObject.setModuleConstant(name, rhsValue); return rhsValue; }
public boolean isVisibleTo(RubyContext context, LexicalScope lexicalScope, RubyModule module) { CompilerAsserts.neverPartOfCompilation(); assert lexicalScope == null || lexicalScope.getLiveModule() == module; if (!isPrivate) { return true; } // Look in lexical scope if (lexicalScope != null) { while (lexicalScope != context.getRootLexicalScope()) { if (lexicalScope.getLiveModule() == declaringModule) { return true; } lexicalScope = lexicalScope.getParent(); } } // Look in ancestors if (module instanceof RubyClass) { for (RubyModule included : module.parentAncestors()) { if (included == declaringModule) { return true; } } } // Allow Object constants if looking with lexical scope. if (lexicalScope != null && context.getCoreLibrary().getObjectClass() == declaringModule) { return true; } return false; }
@TruffleBoundary public static void setClassVariable( RubyModule module, String name, Object value, RubyNode currentNode) { CompilerAsserts.neverPartOfCompilation(); // Look in the current module if (module.getClassVariables().containsKey(name)) { module.setClassVariable(currentNode, name, value); return; } // Look in ancestors for (RubyModule ancestor : module.parentAncestors()) { if (ancestor.getClassVariables().containsKey(name)) { ancestor.setClassVariable(currentNode, name, value); return; } } // Not existing class variable - set in the current module module.setClassVariable(currentNode, name, value); }
public static boolean includesModule(RubyModule module, RubyModule other) { for (RubyModule ancestor : module.ancestors()) { if (ancestor == other) { return true; } } return false; }
@TruffleBoundary public static Map<String, Object> getAllClassVariables(RubyModule module) { CompilerAsserts.neverPartOfCompilation(); final Map<String, Object> classVariables = new HashMap<>(); // Look in the current module classVariables.putAll(module.getClassVariables()); // Look in ancestors for (RubyModule ancestor : module.parentAncestors()) { for (Map.Entry<String, Object> classVariable : ancestor.getClassVariables().entrySet()) { if (!classVariables.containsKey(classVariable.getKey())) { classVariables.put(classVariable.getKey(), classVariable.getValue()); } } } return classVariables; }
@TruffleBoundary public static Map<String, InternalMethod> getAllMethods(RubyModule module) { CompilerAsserts.neverPartOfCompilation(); final Map<String, InternalMethod> methods = new HashMap<>(); // Look in the current module methods.putAll(module.getMethods()); // Look in ancestors for (RubyModule ancestor : module.parentAncestors()) { for (Map.Entry<String, InternalMethod> method : ancestor.getMethods().entrySet()) { if (!methods.containsKey(method.getKey())) { methods.put(method.getKey(), method.getValue()); } } } return methods; }
@TruffleBoundary public static Map<String, RubyConstant> getAllConstants(RubyModule module) { CompilerAsserts.neverPartOfCompilation(); final Map<String, RubyConstant> constants = new HashMap<>(); // Look in the current module constants.putAll(module.getConstants()); // TODO(eregon): Look in lexical scope? // Look in ancestors for (RubyModule ancestor : module.parentAncestors()) { for (Map.Entry<String, RubyConstant> constant : ancestor.getConstants().entrySet()) { if (!constants.containsKey(constant.getKey())) { constants.put(constant.getKey(), constant.getValue()); } } } return constants; }
@TruffleBoundary public static InternalMethod lookupSuperMethod( RubyModule declaringModule, String name, RubyClass objectMetaClass) { CompilerAsserts.neverPartOfCompilation(); boolean foundDeclaringModule = false; for (RubyModule module : objectMetaClass.ancestors()) { if (module == declaringModule) { foundDeclaringModule = true; } else if (foundDeclaringModule) { InternalMethod method = module.getMethods().get(name); if (method != null) { return method; } } } assert foundDeclaringModule : "Did not find the declaring module in " + objectMetaClass.getName() + " ancestors"; return null; }
public boolean isVisibleTo(Node currentNode, RubyClass callerClass) { switch (visibility) { case PUBLIC: return true; case PROTECTED: for (RubyModule ancestor : callerClass.ancestors()) { if (ancestor == declaringModule || ancestor.getMetaClass() == declaringModule) { return true; } } return false; case PRIVATE: // A private method may only be called with an implicit receiver, // in which case the visibility must not be checked. return false; default: return false; } }
/** * @param lexicalScope The surrounding LexicalScope (as in Constant), or null if it is ignored (as * in Mod::Constant or ::Constant) * @param module The receiver of the constant lookup. Must be identical to * lexicalScope.getLiveModule() if lexicalScope != null. */ @TruffleBoundary public static RubyConstant lookupConstant( RubyContext context, LexicalScope lexicalScope, RubyModule module, String name) { CompilerAsserts.neverPartOfCompilation(); assert lexicalScope == null || lexicalScope.getLiveModule() == module; RubyConstant constant; // Look in the current module constant = module.getConstants().get(name); if (constant != null) { return constant; } // Look in lexical scope if (lexicalScope != null) { if (lexicalScope != context.getRootLexicalScope()) { // Already looked in the top lexical scope, which is module. lexicalScope = lexicalScope.getParent(); } while (lexicalScope != context.getRootLexicalScope()) { constant = lexicalScope.getLiveModule().getConstants().get(name); if (constant != null) { return constant; } lexicalScope = lexicalScope.getParent(); } } // Look in ancestors for (RubyModule ancestor : module.parentAncestors()) { constant = ancestor.getConstants().get(name); if (constant != null) { return constant; } } // Look in Object and its included modules if (module.isOnlyAModule()) { final RubyClass objectClass = context.getCoreLibrary().getObjectClass(); constant = objectClass.getConstants().get(name); if (constant != null) { return constant; } for (RubyModule ancestor : objectClass.includedModules()) { constant = ancestor.getConstants().get(name); if (constant != null) { return constant; } } } // Nothing found return null; }