From 8f6aa78dcdd81cda0742a0a0b34cfba815a710cf Mon Sep 17 00:00:00 2001 From: bdemsky Date: Fri, 3 Jun 2011 23:16:48 +0000 Subject: [PATCH] file changes --- Robust/src/IR/ClassDescriptor.java | 24 ++- Robust/src/IR/Descriptor.java | 3 +- Robust/src/IR/Flat/BuildCode.java | 2 +- Robust/src/IR/MethodDescriptor.java | 4 + Robust/src/IR/Tree/BuildIR.java | 225 ++++++++++++++------------ Robust/src/IR/Tree/ChainHashMap.java | 50 ++++++ Robust/src/IR/Tree/JavaBuilder.java | 4 +- Robust/src/IR/Tree/SemanticCheck.java | 11 +- Robust/src/Parse/java14.cup | 16 +- 9 files changed, 213 insertions(+), 126 deletions(-) create mode 100644 Robust/src/IR/Tree/ChainHashMap.java diff --git a/Robust/src/IR/ClassDescriptor.java b/Robust/src/IR/ClassDescriptor.java index 221c878c..faa72242 100644 --- a/Robust/src/IR/ClassDescriptor.java +++ b/Robust/src/IR/ClassDescriptor.java @@ -10,6 +10,7 @@ public class ClassDescriptor extends Descriptor { ClassDescriptor superdesc; boolean hasFlags=false; String packagename; + String classname; Modifiers modifiers; @@ -18,8 +19,8 @@ public class ClassDescriptor extends Descriptor { SymbolTable flags; SymbolTable methods; - Hashtable mandatoryImports; - Hashtable multiImports; + ChainHashMap mandatoryImports; + ChainHashMap multiImports; int numstaticblocks = 0; int numstaticfields = 0; @@ -51,7 +52,8 @@ public class ClassDescriptor extends Descriptor { public ClassDescriptor(String packagename, String classname, boolean isInterface) { //make the name canonical by class file path (i.e. package) - super(classname); + super(packagename!=null?packagename+"."+classname:classname); + this.classname=classname; superclass=null; flags=new SymbolTable(); fields=new SymbolTable(); @@ -101,6 +103,10 @@ public class ClassDescriptor extends Descriptor { return fieldvec; } + public String getClassName() { + return classname; + } + public String getPackage() { return packagename; } @@ -118,7 +124,11 @@ public class ClassDescriptor extends Descriptor { } public String getSafeDescriptor() { - return "L"+safename.replace('.','/'); + return "L"+safename.replace(".","___________"); + } + + public String getSafeSymbol() { + return safename.replace(".","___________"); } public String printTree(State state) { @@ -403,7 +413,7 @@ public class ClassDescriptor extends Descriptor { this.sourceFileName=sourceFileName; } - public void setImports(Hashtable singleImports, Hashtable multiImports) { + public void setImports(ChainHashMap singleImports, ChainHashMap multiImports) { this.mandatoryImports = singleImports; this.multiImports = multiImports; } @@ -412,11 +422,11 @@ public class ClassDescriptor extends Descriptor { return this.sourceFileName; } - public Hashtable getSingleImportMappings() { + public ChainHashMap getSingleImportMappings() { return this.mandatoryImports; } - public Hashtable getMultiImportMappings() { + public ChainHashMap getMultiImportMappings() { return this.multiImports; } diff --git a/Robust/src/IR/Descriptor.java b/Robust/src/IR/Descriptor.java index 4439b198..1691b9e4 100644 --- a/Robust/src/IR/Descriptor.java +++ b/Robust/src/IR/Descriptor.java @@ -36,8 +36,9 @@ public abstract class Descriptor { //the text replacement is done here because SOMEWHERE someone //modifies safename without going through the constructor... public String getSafeSymbol() { - return safename.replaceAll("\\.", "___________"); + return safename; } + public int getNum() { return uniqueid; } diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index b87e6e63..60ba556c 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -992,7 +992,7 @@ public class BuildCode { cdarray=new ClassDescriptor[state.numClasses()]; ifarray = new ClassDescriptor[state.numInterfaces()]; cdarray[0] = null; - int interfaceid = 0; + while(it.hasNext()) { ClassDescriptor cd=(ClassDescriptor)it.next(); if(cd.isInterface()) { diff --git a/Robust/src/IR/MethodDescriptor.java b/Robust/src/IR/MethodDescriptor.java index 724983c4..167b7f42 100644 --- a/Robust/src/IR/MethodDescriptor.java +++ b/Robust/src/IR/MethodDescriptor.java @@ -195,6 +195,10 @@ public class MethodDescriptor extends Descriptor { else throw new Error(); } + public String getSafeSymbol() { + return safename.replace(".","___________"); + } + public String toString() { String st=""; String type=""; diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index f42d7d82..6b94d45d 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -32,16 +32,31 @@ public class BuildIR { //This is all single imports and a subset of the //multi imports that have been resolved. - Hashtable mandatoryImports; + ChainHashMap mandatoryImports; //maps class names in file to full name //Note may map a name to an ERROR. - Hashtable multiimports; - NameDescriptor packages; + 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, Set toanalyze, String sourcefile) { - mandatoryImports = new Hashtable(); - multiimports = new Hashtable(); + mandatoryImports = new ChainHashMap(); + multiimports = new ChainHashMap(); + currsourcefile=sourcefile; + analyzeset=toanalyze; if(state.JNI) { //add java.lang as our default multi-import @@ -70,7 +85,7 @@ public class BuildIR { } ParseNode ppn=pn.getChild("packages").getChild("package"); - String packageName = null; + packageName = null; if ((ppn!=null) && !state.MGC){ NameDescriptor nd = parseClassName(ppn.getChild("name")); packageName = nd.getPathFromRootToHere(); @@ -87,12 +102,9 @@ public class BuildIR { if (isEmpty(type_pn)) /* Skip the semicolon */ continue; if (isNode(type_pn, "class_declaration")) { - ClassDescriptor cn = parseTypeDecl(type_pn, packageName); - cn.setSourceFileName(sourcefile); + ClassDescriptor cn = parseTypeDecl(type_pn); parseInitializers(cn); - if (toanalyze != null) - toanalyze.add(cn); - state.addClass(cn); + // for inner classes/enum HashSet tovisit = new HashSet(); Iterator it_icds = cn.getInnerClasses(); @@ -104,36 +116,11 @@ public class BuildIR { ClassDescriptor cd = (ClassDescriptor) tovisit.iterator().next(); tovisit.remove(cd); parseInitializers(cd); - if (toanalyze != null) { - toanalyze.add(cd); - } - cd.setSourceFileName(sourcefile); - state.addClass(cd); Iterator it_ics = cd.getInnerClasses(); while (it_ics.hasNext()) { tovisit.add(it_ics.next()); } - - Iterator it_ienums = cd.getEnum(); - while (it_ienums.hasNext()) { - ClassDescriptor iecd = (ClassDescriptor) it_ienums.next(); - if (toanalyze != null) { - toanalyze.add(iecd); - } - iecd.setSourceFileName(sourcefile); - state.addClass(iecd); - } - } - - Iterator it_enums = cn.getEnum(); - while (it_enums.hasNext()) { - ClassDescriptor ecd = (ClassDescriptor) it_enums.next(); - if (toanalyze != null) { - toanalyze.add(ecd); - } - ecd.setSourceFileName(sourcefile); - state.addClass(ecd); } } else if (isNode(type_pn, "task_declaration")) { TaskDescriptor td = parseTaskDecl(type_pn); @@ -142,35 +129,13 @@ public class BuildIR { state.addTask(td); } else if (isNode(type_pn, "interface_declaration")) { // TODO add version for normal Java later - ClassDescriptor cn = parseInterfaceDecl(type_pn, packageName); - if (toanalyze != null) - toanalyze.add(cn); - cn.setSourceFileName(sourcefile); - state.addClass(cn); - - // for enum - Iterator it_enums = cn.getEnum(); - while (it_enums.hasNext()) { - ClassDescriptor ecd = (ClassDescriptor) it_enums.next(); - if (toanalyze != null) { - toanalyze.add(ecd); - } - ecd.setSourceFileName(sourcefile); - state.addClass(ecd); - } + 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); - if (toanalyze != null) - toanalyze.add(cn); - cn.setSourceFileName(sourcefile); - state.addClass(cn); + } else if(isNode(type_pn,"annotation_type_declaration")) { ClassDescriptor cn=parseAnnotationTypeDecl(type_pn); - if (toanalyze != null) - toanalyze.add(cn); - cn.setSourceFileName(sourcefile); - state.addClass(cn); } else { throw new Error(type_pn.getLabel()); } @@ -179,7 +144,6 @@ public class BuildIR { } - //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 @@ -210,7 +174,6 @@ public class BuildIR { } } - if(!found) { throw new Error("Import package " + importPath + " in " + currentSource + " cannot be resolved."); @@ -237,9 +200,20 @@ public class BuildIR { } } } + + private ClassDescriptor parseEnumDecl(ClassDescriptor cn, ParseNode pn) { + String basename=pn.getChild("name").getTerminal(); + String classname=(cn!=null)?cn.getClassName()+"$"+basename:basename; + ClassDescriptor ecd=new ClassDescriptor(cn!=null?cn.getPackage():null, classname, false); + + if (cn!=null) { + if (packageName==null) + cn.getSingleImportMappings().put(basename,classname); + else + cn.getSingleImportMappings().put(basename,packageName+"."+classname); + } - private ClassDescriptor parseEnumDecl(ClassDescriptor cn, ParseNode pn) { - ClassDescriptor ecd=new ClassDescriptor(pn.getChild("name").getTerminal(), false); + pushChainMaps(); ecd.setImports(mandatoryImports, multiimports); ecd.setAsEnum(); if(cn != null) { @@ -253,6 +227,13 @@ public class BuildIR { } ecd.setModifiers(parseModifiersList(pn.getChild("modifiers"))); parseEnumBody(ecd, pn.getChild("enumbody")); + + if (analyzeset != null) + analyzeset.add(ecd); + ecd.setSourceFileName(currsourcefile); + state.addClass(ecd); + + popChainMaps(); return ecd; } @@ -275,12 +256,20 @@ public class BuildIR { private ClassDescriptor parseAnnotationTypeDecl(ParseNode pn) { ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal(), true); + pushChainMaps(); cn.setImports(mandatoryImports, multiimports); ParseNode modifiers=pn.getChild("modifiers"); if(modifiers!=null) { cn.setModifiers(parseModifiersList(modifiers)); } parseAnnotationTypeBody(cn,pn.getChild("body")); + popChainMaps(); + + if (analyzeset != null) + analyzeset.add(cn); + cn.setSourceFileName(currsourcefile); + state.addClass(cn); + return cn; } @@ -311,15 +300,18 @@ public class BuildIR { } } - public ClassDescriptor parseInterfaceDecl(ParseNode pn, String packageName) { - ClassDescriptor cn; - if(packageName == null) { - cn=new ClassDescriptor(pn.getChild("name").getTerminal(), true); - } else { - String newClassname = packageName + "." + pn.getChild("name").getTerminal(); - cn= new ClassDescriptor(packageName, newClassname, true); + public ClassDescriptor parseInterfaceDecl(ParseNode pn, ClassDescriptor outerclass) { + String basename=pn.getChild("name").getTerminal(); + String classname=((outerclass==null)?"":(outerclass.getClassName()+"$"))+basename; + if (outerclass!=null) { + if (packageName==null) + outerclass.getSingleImportMappings().put(basename,classname); + else + outerclass.getSingleImportMappings().put(basename,packageName+"."+classname); } + ClassDescriptor cn= new ClassDescriptor(packageName, classname, true); + pushChainMaps(); cn.setImports(mandatoryImports, multiimports); //cn.setAsInterface(); if (!isEmpty(pn.getChild("superIF").getTerminal())) { @@ -331,11 +323,18 @@ public class BuildIR { if (isNode(decl,"type")) { NameDescriptor nd=parseClassName(decl.getChild("class").getChild("name")); cn.addSuperInterface(nd.toString()); - } + } else if (isNode(decl, "interface_declaration")) { + ClassDescriptor innercn = parseInterfaceDecl(decl, cn); + } else throw new Error(); } } cn.setModifiers(parseModifiersList(pn.getChild("modifiers"))); parseInterfaceBody(cn, pn.getChild("interfacebody")); + if (analyzeset != null) + analyzeset.add(cn); + cn.setSourceFileName(currsourcefile); + state.addClass(cn); + popChainMaps(); return cn; } @@ -350,7 +349,9 @@ public class BuildIR { parseInterfaceConstant(cn,decl); } else if (isNode(decl,"method")) { parseInterfaceMethod(cn,decl.getChild("method_declaration")); - } else throw new Error(); + } else if (isNode(decl, "interface_declaration")) { + parseInterfaceDecl(decl, cn); + } else throw new Error(decl.PPrint(2, true)); } } } @@ -375,17 +376,6 @@ public class BuildIR { BlockNode bn=parseBlock(bodyn); cn.addMethod(md); state.addTreeCode(md,bn); - - // this is a hack for investigating new language features - // at the AST level, someday should evolve into a nice compiler - // option *wink* - //if( cn.getSymbol().equals( ***put a class in here like: "Test" ) && - // md.getSymbol().equals( ***put your method in here like: "main" ) - //) { - // bn.setStyle( BlockNode.NORMAL ); - // System.out.println( bn.printNode( 0 ) ); - //} - } catch (Exception e) { System.out.println("Error with method:"+md.getSymbol()); e.printStackTrace(); @@ -554,16 +544,9 @@ public class BuildIR { return tel; } - public ClassDescriptor parseTypeDecl(ParseNode pn, String packageName) { - ClassDescriptor cn; - // if is in no package, then create a class descriptor with just the name. - // else add the package on - if(packageName == null) { - cn=new ClassDescriptor(pn.getChild("name").getTerminal(), false); - } else { - String newClassname = packageName + "." + pn.getChild("name").getTerminal(); - cn= new ClassDescriptor(packageName, newClassname, false); - } + public ClassDescriptor parseTypeDecl(ParseNode pn) { + ClassDescriptor cn=new ClassDescriptor(packageName, pn.getChild("name").getTerminal(), false); + pushChainMaps(); cn.setImports(mandatoryImports, multiimports); if (!isEmpty(pn.getChild("super").getTerminal())) { /* parse superclass name */ @@ -605,6 +588,13 @@ public class BuildIR { md.setDefaultConstructor(); cn.addMethod(md); } + popChainMaps(); + + cn.setSourceFileName(currsourcefile); + if (analyzeset != null) + analyzeset.add(cn); + state.addClass(cn); + return cn; } @@ -642,9 +632,15 @@ public class BuildIR { parseInnerClassDecl(cn,innerclassnode); return; } + + ParseNode innerinterfacenode=pn.getChild("interface_declaration"); + if (innerinterfacenode!=null) { + parseInterfaceDecl(innerinterfacenode, cn); + } + ParseNode enumnode=pn.getChild("enum_declaration"); if (enumnode!=null) { - parseEnumDecl(cn,enumnode); + ClassDescriptor ecn=parseEnumDecl(cn,enumnode); return; } ParseNode flagnode=pn.getChild("flag"); @@ -661,7 +657,16 @@ public class BuildIR { } private ClassDescriptor parseInnerClassDecl(ClassDescriptor cn, ParseNode pn) { - ClassDescriptor icn=new ClassDescriptor(pn.getChild("name").getTerminal(), false); + String basename=pn.getChild("name").getTerminal(); + String classname=cn.getClassName()+"$"+basename; + + if (cn.getPackage()==null) + cn.getSingleImportMappings().put(basename,classname); + else + cn.getSingleImportMappings().put(basename,cn.getPackage()+"."+classname); + + ClassDescriptor icn=new ClassDescriptor(cn.getPackage(), classname, false); + pushChainMaps(); icn.setImports(mandatoryImports, multiimports); icn.setAsInnerClass(); icn.setSurroundingClass(cn.getSymbol()); @@ -691,11 +696,14 @@ public class BuildIR { } } icn.setModifiers(parseModifiersList(pn.getChild("modifiers"))); - if(!icn.isStatic()) { - throw new Error("Error: inner class " + icn.getSymbol() + " in Class " + - cn.getSymbol() + " is not a nested class and is not supported yet!"); - } + parseClassBody(icn, pn.getChild("classbody")); + popChainMaps(); + if (analyzeset != null) + analyzeset.add(icn); + icn.setSourceFileName(currsourcefile); + state.addClass(icn); + return icn; } @@ -972,7 +980,8 @@ public class BuildIR { //TODO::: FIX BUG!!! static fields in caller context need to become parameters TypeDescriptor td=parseTypeDescriptor(pn); innerCount++; - ClassDescriptor cnnew=new ClassDescriptor(td.getSymbol()+"$"+innerCount, false); + ClassDescriptor cnnew=new ClassDescriptor(packageName,td.getSymbol()+"$"+innerCount, false); + pushChainMaps(); cnnew.setImports(mandatoryImports, multiimports); cnnew.setSuper(td.getSymbol()); parseClassBody(cnnew, pn.getChild("decl").getChild("classbody")); @@ -983,6 +992,12 @@ public class BuildIR { for(int i=0; i extends AbstractMap { + private ChainHashMap parent; + private HashMap table; + + public ChainHashMap() { + table=new HashMap(); + } + + public ChainHashMap makeChild() { + ChainHashMap chm=new ChainHashMap(); + chm.parent=this; + return chm; + } + + public ChainHashMap getParent() { + return parent; + } + + public V put(K key, V value) { + return table.put(key, value); + } + + public V get(Object o) { + K key=(K) o; + if (table.containsKey(key)) + return table.get(key); + else if (parent!=null) + return parent.get(key); + else + return null; + } + + public boolean containsKey(Object o) { + K key=(K)o; + if (table.containsKey(key)) + return true; + else if (parent!=null) + return parent.containsKey(key); + else + return false; + } + + public Set> entrySet() { + throw new Error("ChainHashMap does not support entrySet"); + } +} \ No newline at end of file diff --git a/Robust/src/IR/Tree/JavaBuilder.java b/Robust/src/IR/Tree/JavaBuilder.java index a60b294f..eea8b016 100644 --- a/Robust/src/IR/Tree/JavaBuilder.java +++ b/Robust/src/IR/Tree/JavaBuilder.java @@ -76,8 +76,10 @@ public class JavaBuilder implements CallGraph { return set; } + /* Returns whether there is a reachable call to this method descriptor...Not whether the implementation is called */ + public boolean isCalled(MethodDescriptor md) { - return !getMethods(md).isEmpty(); + return canCall.containsKey(md); } public boolean isCallable(MethodDescriptor md) { diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java index b5a92a93..29f36b33 100644 --- a/Robust/src/IR/Tree/SemanticCheck.java +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -40,7 +40,6 @@ public class SemanticCheck { public ClassDescriptor getClass(ClassDescriptor context, String classnameIn, int fullcheck) { String classname = classnameIn; if (context!=null) { -// System.out.println(context.getSymbol() + " is looking for " + classname); classname = context.getCannonicalImportMapName(classnameIn); } ClassDescriptor cd=typeutil.getClass(classname, toanalyze); @@ -1202,7 +1201,7 @@ NextMethod: for (Iterator methodit = methoddescriptorset.iterator(); methodit.ha checkExpressionNode(md, nametable, min.getExpression(), null); typetolookin=min.getExpression().getType(); } else { - if(!min.getBaseName().getSymbol().equals("System.out")) { + if(!min.getBaseName().getSymbol().equals("System.out")||state.JNI) { ExpressionNode nn = translateNameDescriptorintoExpression(min.getBaseName(),min.getNumLine()); checkExpressionNode(md, nametable, nn, null); typetolookin = nn.getType(); @@ -1213,12 +1212,8 @@ NextMethod: for (Iterator methodit = methoddescriptorset.iterator(); methodit.ha } } else { //we have a type - ClassDescriptor cd = null; - //if (min.getBaseName().getSymbol().equals("System.out")) - cd=getClass(null, "System"); - /*else { - cd=getClass(min.getBaseName().getSymbol()); - }*/ + ClassDescriptor cd = getClass(null, "System"); + if (cd==null) throw new Error("md = "+ md.toString()+ " "+min.getBaseName()+" undefined"); typetolookin=new TypeDescriptor(cd); diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup index 16d229f3..b6287157 100644 --- a/Robust/src/Parse/java14.cup +++ b/Robust/src/Parse/java14.cup @@ -983,9 +983,7 @@ class_member_declaration ::= {: RESULT=ed; :} -// | interface_declaration:interfaced {: -// RESULT=(new ParseNode("interface",parser.lexer.line_num)).addChild(interfaced).getRoot(); -// :} + | interface_declaration:interfaced {: RESULT=interfaced; :} | SEMICOLON {: RESULT=new ParseNode("empty",parser.lexer.line_num); :} ; @@ -1287,8 +1285,8 @@ SUPER LPAREN argument_list_opt:alo RPAREN SEMICOLON {: pn.addChild(alo); RESULT=pn; :} -// | primary DOT THIS LPAREN argument_list_opt RPAREN SEMICOLON -// | primary DOT SUPER LPAREN argument_list_opt RPAREN SEMICOLON + | primary DOT THIS LPAREN argument_list_opt RPAREN SEMICOLON + | primary DOT SUPER LPAREN argument_list_opt RPAREN SEMICOLON ; // 19.9) Interfaces @@ -1356,7 +1354,7 @@ interface_member_declaration ::= RESULT=(new ParseNode("enum_declaration",parser.lexer.line_num)).addChild(ed).getRoot(); :} // | class_declaration:class -// | interface_declaration:interface + | interface_declaration:interfaced {: RESULT=interfaced; :} | SEMICOLON {: RESULT=new ParseNode("empty",parser.lexer.line_num); :} @@ -1954,7 +1952,11 @@ primary_no_new_array ::= pn.addChild("type").addChild("class").addChild(name); RESULT=pn; :} -// | name DOT THIS + | name:name DOT THIS {: + ParseNode pn=new ParseNode("parentclass",parser.lexer.line_num); + pn.addChild("name").addChild(name); + RESULT=pn; + :} ; class_instance_creation_expression ::= NEWFLAG class_or_interface_type:type LPAREN argument_list_opt:args RPAREN flag_list_opt:feo {: -- 2.34.1