import jastaddmodules.*; aspect JAModuleLookupModule { //lookupModuleCUNoTransform : lookup the base module CU of a compilation unit. //Traverses the tree instead of just going up the parents, so use sparingly //The JastAddModules code should just use this prior to InserModuleCUs // //NOTE: Keep this non-lazy, as this is called both before and after //InsertModuleCUs syn ModuleCompilationUnit ASTNode.lookupModuleCUNoTransform(ModuleAccess access) { if (access == null) { return null; } ModuleCompilationUnit ret = null; for (int i = 0 ; i < getNumChild(); i++) { ret = getChild(i).lookupModuleCUNoTransform(access); if (ret != null) { return ret; } } return ret; } syn ModuleCompilationUnit CompilationUnit.lookupModuleCUNoTransform(ModuleAccess access) { return null; } syn ModuleCompilationUnit ModuleCompilationUnit.lookupModuleCUNoTransform(ModuleAccess access) { if (access == null) { return null; } ModuleCompilationUnit ret = null; for (int i = 0 ; i < getNumChild(); i++) { ret = getChild(i).lookupModuleCUNoTransform(access); if (ret != null) { return ret; } } return ret; } syn ModuleCompilationUnit ModuleDecl.lookupModuleCUNoTransform(ModuleAccess access) { if (getModuleAccess().getID().equals(access.getID())) { return getModuleCompilationUnit(); } else { return null; } } public ModuleCompilationUnit CompilationUnit.lookupModuleCUNoTransform() { if (this.getModuleDecl() == null) { return null; } return getHostProgram().lookupModuleCUNoTransform(this.getModuleDecl().getModuleAccess()); } public ModuleCompilationUnit Program.lookupModuleCUNoTransform(String moduleName) { return this.lookupModuleCUNoTransform(new ModuleAccess(moduleName)); } //module lookup after the ModuleCUs have been rearranged in the tree public ModuleCompilationUnit ModuleAccess.lookupModule() { ModuleCompilationUnit context = getModuleCompilationUnit(); if (context == null) { return null; } return context.getRealInstance().lookupModule(this.getID()); } //module lookup after the ModuleCUs have been rearranged in the tree public ModuleReference ModuleAccess.lookupModuleReference() { ModuleCompilationUnit context = getModuleCompilationUnit(); if (context == null) { return null; } return context.getRealInstance().lookupModuleReference(this.getID()); } public ModuleCompilationUnit ModuleCompilationUnit.lookupModule(String name) { return lookupModule(this, name); } public ModuleReference ModuleCompilationUnit.lookupModuleReference(String name) { return lookupModuleReference(this, name); } //non-lazy, since merges use lookup and still rely on up-to-date lookups //TODO: if too slow, add a wrapper method for when it's used in lookupType //TODO: this code is unnecessarily complicated since it once had to do //disambiguation when module separators where dots. Clean it up to reflect //the more simple syntax syn ModuleReference ModuleCompilationUnit.lookupModuleReference(ModuleCompilationUnit originalContext, String name) { //matching is greedy. Find the longest match first, try it and return if a match was found SortedSet localAliases = new TreeSet(new Comparator() { public int compare(String x, String y) { if (x.length() != y.length()) { return y.length() - x.length(); } return x.compareTo(y); } }); localAliases.addAll(getModuleReferenceMap().keySet()); //add self name to local aliases localAliases.add(getBaseCU().getModuleName()); for (String alias : localAliases) { //if alias cannot be a qualifier, proceed to next if (!name.startsWith(alias)) { continue; } //if equal match and is visible from the original context, return entry //it is visible from the original context iff: // the original context is the same as the current context (i.e. it is a direct import) or // the import was exported if (name.equals(alias)) { //special case for self reference if (alias.equals(getBaseCU().getModuleName())) { //self reference return new ModuleReference(alias, this, getBaseCU(), new AsTypeNone(), new ModuleImportTypeNorm(), this); } if (originalContext == this || getModuleReference(name).isExported()) { return getModuleReference(alias); } continue; } //check if alias is a qualifier, then lookup in the module String trimmedName = name.substring(alias.length()); if (!trimmedName.startsWith(Program.MODULE_SEPARATOR)) { continue; } trimmedName = trimmedName.substring(2); //go into imports only iff: // it is a direct import (this = originalContext) // or it is exported ModuleReference importedCU = null; if (alias.equals(getBaseCU().getModuleName())) { importedCU = new ModuleReference(alias, this, getBaseCU(), new AsTypeNone(), new ModuleImportTypeNorm(), this); //special case for self reference, not exported so that it only goes into the imports when it is in the originalContext } else { importedCU = getModuleReference(alias); } //the original context check will make sure that self references only work at //the front of a module qualified name (this is good, avoids stuff like m1::m2::m2::m2...) if (originalContext == this || importedCU.isExported()) { ModuleReference ret = importedCU.getModuleCU().lookupModuleReference(originalContext, trimmedName); if (ret != null) { return ret; } } } return null; } syn ModuleCompilationUnit ModuleCompilationUnit.lookupModule(ModuleCompilationUnit originalContext, String name) { ModuleReference reference = lookupModuleReference(originalContext, name); if (reference != null) { return reference.getModuleCU(); } return null; } }