X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=Robust%2Fsrc%2FIR%2FTree%2FBuildIR.java;h=c8efb8e7bc29898770e26fdbb7b1bb8a90733140;hb=d396c42d2a86460c7e220d21e5219049c177c5cf;hp=deb48958b54ee370040eea360b02bdb385a9fabe;hpb=21fb3a46af7ff94815d3dd49a3c91e730429473f;p=IRC.git diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index deb48958..c8efb8e7 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -1,71 +1,412 @@ package IR.Tree; import IR.*; -import java.util.*; - +import Util.Lattice; +import Util.Pair; +import java.io.File; +import java.util.*; +import java.io.*; +import java.lang.Throwable; public class BuildIR { State state; - + private boolean isRunningRecursiveInnerClass; private int m_taskexitnum; public BuildIR(State state) { this.state=state; this.m_taskexitnum = 0; + this.isRunningRecursiveInnerClass = false; } - public void buildtree() { - for(Iterator it=state.parsetrees.iterator(); it.hasNext();) { - ParseNode pn=(ParseNode)it.next(); - parseFile(pn); + public void buildtree(ParseNode pn, Set toanalyze, String sourcefile) { + parseFile(pn, toanalyze, sourcefile); + + // numering the interfaces + int if_num = 0; + Iterator it_classes = state.getClassSymbolTable().getValueSet().iterator(); + while(it_classes.hasNext()) { + ClassDescriptor cd = (ClassDescriptor)it_classes.next(); + if(cd.isInterface()) { + cd.setInterfaceId(if_num++); + } } } + //This is all single imports and a subset of the + //multi imports that have been resolved. + ChainHashMap mandatoryImports; + //maps class names in file to full name + //Note may map a name to an ERROR. + ChainHashMap multiimports; + String packageName; + + String currsourcefile; + Set analyzeset; + + void pushChainMaps() { + mandatoryImports=mandatoryImports.makeChild(); + multiimports=multiimports.makeChild(); + } + + void popChainMaps() { + mandatoryImports=mandatoryImports.getParent(); + multiimports=multiimports.getParent(); + } + /** Parse the classes in this file */ - public void parseFile(ParseNode pn) { - NameDescriptor packages; - Vector singleimports=new Vector(); - Vector multiimports=new Vector(); - - ParseNode ipn=pn.getChild("imports").getChild("import_decls_list"); - if (ipn!=null) { - ParseNodeVector pnv=ipn.getChildren(); - for(int i=0; i import the package directory as a multi-import and it'll + //automatically recognize files in the same directory. + addMultiImport(sourcefile, packageName, true); } + ParseNode tpn=pn.getChild("type_declaration_list"); - if (tpn!=null) { - ParseNodeVector pnv=tpn.getChildren(); + if (tpn != null) { + ParseNodeVector pnv = tpn.getChildren(); + for (int i = 0; i < pnv.size(); i++) { + ParseNode type_pn = pnv.elementAt(i); + if (isEmpty(type_pn)) /* Skip the semicolon */ + continue; + if (isNode(type_pn, "class_declaration")) { + ClassDescriptor cn = parseTypeDecl(type_pn); + parseInitializers(cn); + + // for inner classes/enum + HashSet tovisit = new HashSet(); + Iterator it_icds = cn.getInnerClasses(); + while (it_icds.hasNext()) { + tovisit.add(it_icds.next()); + } + + while (!tovisit.isEmpty()) { + ClassDescriptor cd = (ClassDescriptor) tovisit.iterator().next(); + tovisit.remove(cd); + parseInitializers(cd); + + Iterator it_ics = cd.getInnerClasses(); + while (it_ics.hasNext()) { + tovisit.add(it_ics.next()); + } + } + } else if (isNode(type_pn, "task_declaration")) { + TaskDescriptor td = parseTaskDecl(type_pn); + if (toanalyze != null) + toanalyze.add(td); + state.addTask(td); + } else if (isNode(type_pn, "interface_declaration")) { + // TODO add version for normal Java later + ClassDescriptor cn = parseInterfaceDecl(type_pn, null); + } else if (isNode(type_pn, "enum_declaration")) { + // TODO add version for normal Java later + ClassDescriptor cn = parseEnumDecl(null, type_pn); + + } else if(isNode(type_pn,"annotation_type_declaration")) { + ClassDescriptor cn=parseAnnotationTypeDecl(type_pn); + } else { + throw new Error(type_pn.getLabel()); + } + } + } + } + + + //This kind of breaks away from tradition a little bit by doing the file checks here + // instead of in Semantic check, but doing it here is easier because we have a mapping early on + // if I wait until semantic check, I have to change ALL the type descriptors to match the new + // mapping and that's both ugly and tedious. + private void addMultiImport(String currentSource, String importPath, boolean isPackageDirectory) { + boolean found = false; + for (int j = 0; j < state.classpath.size(); j++) { + String path = (String) state.classpath.get(j); + File folder = new File(path, importPath.replace('.', '/')); + if (folder.exists()) { + found = true; + for (String file : folder.list()) { + // if the file is of type *.java add to multiImport list. + if (file.lastIndexOf('.') != -1 && file.substring(file.lastIndexOf('.')).equalsIgnoreCase(".java")) { + String classname = file.substring(0, file.length() - 5); + // single imports have precedence over multi-imports + if (!mandatoryImports.containsKey(classname)) { + //package files have precedence over multi-imports. + if (multiimports.containsKey(classname) && !isPackageDirectory) { + // put error in for later, in case we try to import + multiimports.put(classname, new Error("Error: class " + classname + " is defined more than once in a multi-import in " + currentSource)); + } else { + multiimports.put(classname, importPath + "." + classname); + } + } + } + } + } + } + + if(!found) { + throw new Error("Import package " + importPath + " in " + currentSource + + " cannot be resolved."); + } + } + + public void parseInitializers(ClassDescriptor cn) { + Vector fv=cn.getFieldVec(); + Iterator methodit = cn.getMethods(); + HashMap md2pos = new HashMap(); + while(methodit.hasNext()) { + MethodDescriptor currmd=(MethodDescriptor)methodit.next(); + if(currmd.isConstructor()) { + BlockNode bn=state.getMethodBody(currmd); + // if there are super(...) invokation, the initializers should be invoked after that + int i = 0; + for(; i < bn.size(); i++) { + if(Kind.BlockExpressionNode==bn.get(i).kind() + &&(((BlockExpressionNode)bn.get(i)).getExpression() instanceof MethodInvokeNode) + &&((MethodInvokeNode)(((BlockExpressionNode)bn.get(i)).getExpression())).getMethodName().equals("super")) { + break; + } + } + if(i==bn.size()) { + md2pos.put(currmd, 0); + } else { + md2pos.put(currmd, i+1); + } + } + } + int pos = 0; + for(int i=0; i annotations=modifiers.getAnnotations(); + for(int i=0; i slv = new Vector(); + for(int j=0; j