//STANDING NOTE: Make VERY sure that all JAModule passes before the java //errorcheck DO NOT TOUCH any AST nodes below CompilationUnit to avoid //the REWRITES import jastaddmodules.ModuleReference; aspect ModuleCompilationUnit { //adapted from ASTGrammar.jrag refine ASTGrammar public void Program.addSourceFile(String name) { if(name.endsWith(".module")) { loadModuleFile(name); } else { ASTGrammar.Program.addSourceFile(name); } } public void Program.loadModuleFile(String name) { try { File inFile = new File(name); FileInputStream is = new FileInputStream(inFile); scanner.JavaScanner scanner = new scanner.JavaScanner(new scanner.Unicode(is)); scanner.enterJastAddModule(); CompilationUnit cu = (CompilationUnit)new parser.JavaParser().parse(scanner, parser.JavaParser.AltGoals.jamodule_compilation_unit); scanner.previousState(); is.close(); cu.setFromSource(true); cu.setRelativeName(name); cu.setPathName(inFile.getAbsolutePath()); ((ModuleCompilationUnit)cu).setBaseCU((ModuleCompilationUnit)cu); //set base to itself addCompilationUnit(cu); } catch (Exception e) { throw new Error(e.getMessage()); } } //TODO: Would be better if ModuleDecl was a subtype of a PackageDecl //(except PackageDecl has no AST type). See if worth changing. //TODO: This is broken, since non-list ast nodes don't do addChild as expected ModuleDecl CompilationUnit.moduleDecl; public ModuleDecl CompilationUnit.getModuleDecl() { return this.moduleDecl; } public void CompilationUnit.setModuleDecl(ModuleDecl decl) { this.moduleDecl = decl; } syn lazy boolean CompilationUnit.isInJAModule() { return (this.lookupModuleCUNoTransform() != null); } eq Program.getChild(int index).getModuleCompilationUnit() = null; syn ModuleCompilationUnit ModuleCompilationUnit.getModuleCompilationUnit() = this; eq ModuleCompilationUnit.getChild(int index).getModuleCompilationUnit() = this; inh ModuleCompilationUnit ModuleDecl.getModuleCompilationUnit(); inh ModuleCompilationUnit ModuleAccess.getModuleCompilationUnit(); inh ModuleCompilationUnit CompilationUnit.getModuleCompilationUnit(); inh ModuleCompilationUnit ModuleExpr.getModuleCompilationUnit(); inh ModuleCompilationUnit ModuleMemberDecl.getModuleCompilationUnit(); //TODO: check if cached result remains consistent (don't call before all CUs have been parsed syn lazy boolean Program.hasJAModules() { for (Iterator iter = compilationUnitIterator(); iter.hasNext();) { if (iter.next() instanceof ModuleCompilationUnit) { return true; } } return false; } protected ModuleCompilationUnit ModuleCompilationUnit.baseCU = null; public void ModuleCompilationUnit.setBaseCU(ModuleCompilationUnit baseCU) { this.baseCU = baseCU; } public ModuleCompilationUnit ModuleCompilationUnit.getBaseCU() { return this.baseCU; } public void ModuleCompilationUnit.setModuleName(String name) { getModuleDecl().getModuleAccess().setID(name); } public String ModuleCompilationUnit.getModuleName() { return getModuleDecl().getModuleAccess().getID(); } //String is the local alias of the imported CU protected HashMap ModuleCompilationUnit.importedModules = new HashMap(); public void ModuleCompilationUnit.setModuleReferences(HashMap modules) { this.importedModules = modules; } public void ModuleCompilationUnit.addModuleReference(String alias, ModuleCompilationUnit cu, ModuleCompilationUnit staticType, AsType asType, ModuleImportType importType) { importedModules.put(alias, new ModuleReference(alias, cu, staticType, asType, importType, this)); } public ModuleReference ModuleCompilationUnit.removeModuleReference(String alias) { return importedModules.remove(alias); } public ModuleCompilationUnit ModuleCompilationUnit.removeModuleReference(ModuleCompilationUnit cu) { Set aliases = getModuleReferenceAliases(cu); for (String alias: aliases) { importedModules.remove(alias); } return cu; } public Set ModuleCompilationUnit.getModuleReferenceAliases(ModuleCompilationUnit cu) { Set ret = new HashSet(); for (String key : importedModules.keySet()) { if (cu == importedModules.get(key).getModuleCU()) { ret.add(key); } } return ret; } public Map ModuleCompilationUnit.getModuleReferenceMap() { return importedModules; } public ModuleReference ModuleCompilationUnit.getModuleReference(String name) { return importedModules.get(name); } //a module is an instance module if it was created from a base module //base modules are the ones directly generated by the parser public boolean ModuleCompilationUnit.isInstance() { return this.getBaseCU() != this; } //the context of the instance are the modules that can directly access the module protected HashSet ModuleCompilationUnit.instanceContext = new HashSet(); public void ModuleCompilationUnit.setInstanceContext(HashSet context) { this.instanceContext = context; } public void ModuleCompilationUnit.addInstanceContext(ModuleCompilationUnit context) { this.instanceContext.add(context); } public boolean ModuleCompilationUnit.removeInstanceContext(ModuleCompilationUnit context) { return this.instanceContext.remove(context); } public void ModuleCompilationUnit.isInInstanceContext(ModuleCompilationUnit context) { this.instanceContext.contains(context); } public HashSet ModuleCompilationUnit.getInstanceContext() { return this.instanceContext; } public void ModuleCompilationUnit.detachFromProgramList() { this.getInstanceContext().clear(); this.detachFromProgramList(null); } public void ModuleCompilationUnit.detachFromProgramList(ModuleCompilationUnit context) { assert (!(context == null) || getInstanceContext().size() == 0) : "Calls with a null context must have an empty instance context"; //dump the imported module cus into a hashset first to remove duplicates HashSet importedCUs = new HashSet(); for (ModuleReference cu : getModuleReferenceMap().values()) { importedCUs.add(cu.getModuleCU()); } for (ModuleCompilationUnit mcu : importedCUs) { if (mcu.isInstance()) { mcu.detachFromProgramList(this); } } if (context != null && context!= this) { //for self references, no need to remove as these references are generated and are not part of the import structures boolean result = removeInstanceContext(context); assert (result) : "Context not found in instance context"; } if (isInstance() && (context == null || getInstanceContext().size() == 0) ) { assert (getHostProgram() != null || getParent() != null) : "Unable to find host program in module " + getModuleName(); //remove the super instances from the Program CU list ModuleCompilationUnit superInstance = this.getSuperInstance(); while (superInstance != null) { int index = getHostProgram().getCompilationUnitList().getIndexOfChild(superInstance); getHostProgram().getCompilationUnitList().removeChild(index); superInstance = superInstance.getSuperInstance(); } //remove this from the Program CU list int index = getHostProgram().getCompilationUnitList().getIndexOfChild(this); getHostProgram().getCompilationUnitList().removeChild(index); } } //for synthetic CUs created by overrides protected boolean ModuleCompilationUnit.synthetic = false; protected boolean ModuleCompilationUnit.isSynthetic() { return this.synthetic; } protected void ModuleCompilationUnit.setSynthetic(boolean b) { this.synthetic = b; } }