From 69c5f0df3cb1cd34d074a111ae526332564fc35e Mon Sep 17 00:00:00 2001 From: jzhou Date: Wed, 27 Oct 2010 22:07:37 +0000 Subject: [PATCH] Enable interface for mgc version. --- Robust/src/IR/ClassDescriptor.java | 46 +++++++ Robust/src/IR/Flat/BuildCode.java | 12 +- Robust/src/IR/Flat/BuildCodeMGC.java | 18 +-- Robust/src/IR/SymbolTable.java | 20 +++ Robust/src/IR/Tree/BuildIR.java | 108 +++++++++++++++- Robust/src/IR/Tree/SemanticCheck.java | 16 ++- Robust/src/IR/TypeUtil.java | 136 +++++++++++++++++++- Robust/src/IR/Virtual.java | 29 +++++ Robust/src/Lex/Keyword.java | 3 + Robust/src/Lex/Lexer.java | 4 +- Robust/src/Parse/java14.cup | 174 +++++++++++++++++--------- Robust/src/Tests/InterfaceTest.java | 78 ++++++++++++ 12 files changed, 564 insertions(+), 80 deletions(-) create mode 100644 Robust/src/Tests/InterfaceTest.java diff --git a/Robust/src/IR/ClassDescriptor.java b/Robust/src/IR/ClassDescriptor.java index f9d19595..6c3735b2 100644 --- a/Robust/src/IR/ClassDescriptor.java +++ b/Robust/src/IR/ClassDescriptor.java @@ -19,6 +19,11 @@ public class ClassDescriptor extends Descriptor { int numstaticblocks = 0; int numstaticfields = 0; + + // for interfaces + boolean isInterface=false; + Vector superinterfaces; + SymbolTable superIFdesc; public ClassDescriptor(String classname) { this("", classname); @@ -33,6 +38,8 @@ public class ClassDescriptor extends Descriptor { methods=new SymbolTable(); classid=UIDCount++; this.packagename=packagename; + superinterfaces = new Vector(); + superIFdesc = new SymbolTable(); } public int getId() { @@ -50,6 +57,10 @@ public class ClassDescriptor extends Descriptor { public Iterator getFlags() { return flags.getDescriptorsIterator(); } + + public Iterator getSuperInterfaces() { + return this.superIFdesc.getDescriptorsIterator(); + } public SymbolTable getFieldTable() { return fields; @@ -66,6 +77,10 @@ public class ClassDescriptor extends Descriptor { public SymbolTable getMethodTable() { return methods; } + + public SymbolTable getSuperInterfaceTable() { + return this.superIFdesc; + } public String getSafeDescriptor() { return "L"+safename.replace('.','/'); @@ -76,6 +91,17 @@ public class ClassDescriptor extends Descriptor { String st=modifiers.toString()+"class "+getSymbol(); if (superclass!=null) st+="extends "+superclass.toString(); + if(this.superinterfaces != null) { + st += "implements "; + boolean needcomma = false; + for(int i = 0; i < this.superinterfaces.size(); i++) { + if(needcomma) { + st += ", "; + } + st += this.superinterfaces.elementAt(i); + needcomma = true; + } + } st+=" {\n"; indent=TreeNode.INDENT; boolean printcr=false; @@ -153,6 +179,18 @@ public class ClassDescriptor extends Descriptor { return superclass; } + public void addSuperInterface(String superif) { + this.superinterfaces.addElement(superif); + } + + public Vector getSuperInterface() { + return this.superinterfaces; + } + + public void addSuperInterfaces(ClassDescriptor sif) { + this.superIFdesc.add(sif); + } + public void incStaticBlocks() { this.numstaticblocks++; } @@ -172,4 +210,12 @@ public class ClassDescriptor extends Descriptor { public boolean isAbstract() { return this.modifiers.isAbstract(); } + + public boolean isInterface() { + return this.isInterface; + } + + public void setAsInterface() { + this.isInterface = true; + } } diff --git a/Robust/src/IR/Flat/BuildCode.java b/Robust/src/IR/Flat/BuildCode.java index 35ce9bcc..52108168 100644 --- a/Robust/src/IR/Flat/BuildCode.java +++ b/Robust/src/IR/Flat/BuildCode.java @@ -394,7 +394,9 @@ public class BuildCode { while(it_sclasses.hasNext()) { ClassDescriptor cd = (ClassDescriptor)it_sclasses.next(); MethodDescriptor md = (MethodDescriptor)cd.getMethodTable().get("staticblocks"); - tovisit.add(md); + if(md != null) { + tovisit.add(md); + } } while(!tovisit.isEmpty()) { @@ -1191,6 +1193,14 @@ public class BuildCode { /* Get inherited methods */ if (cd.getSuperDesc()!=null) fillinRow(cd.getSuperDesc(), virtualtable, rownum); + if(state.MGC) { + // TODO add version for normal Java later + Iterator it_sifs = cd.getSuperInterfaces(); + while(it_sifs.hasNext()) { + ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); + fillinRow(superif, virtualtable, rownum); + } + } /* Override them with our methods */ for(Iterator it=cd.getMethods(); it.hasNext();) { MethodDescriptor md=(MethodDescriptor)it.next(); diff --git a/Robust/src/IR/Flat/BuildCodeMGC.java b/Robust/src/IR/Flat/BuildCodeMGC.java index 52dc69c8..2e1211d8 100644 --- a/Robust/src/IR/Flat/BuildCodeMGC.java +++ b/Robust/src/IR/Flat/BuildCodeMGC.java @@ -189,15 +189,17 @@ public class BuildCodeMGC extends BuildCode { // TODO may need to invoke static field initialization here } MethodDescriptor t_md = (MethodDescriptor)t_cd.getMethodTable().get("staticblocks"); - outmethod.println(" {"); - if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) { - outmethod.print(" struct "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"_params __parameterlist__={"); - outmethod.println("1, NULL};"); - outmethod.println(" "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"(& __parameterlist__);"); - } else { - outmethod.println(" "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"();"); + if(t_md != null) { + outmethod.println(" {"); + if ((GENERATEPRECISEGC) || (this.state.MULTICOREGC)) { + outmethod.print(" struct "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"_params __parameterlist__={"); + outmethod.println("1, NULL};"); + outmethod.println(" "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"(& __parameterlist__);"); + } else { + outmethod.println(" "+t_cd.getSafeSymbol()+t_md.getSafeSymbol()+"_"+t_md.getSafeMethodDescriptor()+"();"); + } + outmethod.println(" }"); } - outmethod.println(" }"); } outmethod.println("#undef MGC_STATIC_INIT_CHECK"); } diff --git a/Robust/src/IR/SymbolTable.java b/Robust/src/IR/SymbolTable.java index ed1d1337..6532671f 100644 --- a/Robust/src/IR/SymbolTable.java +++ b/Robust/src/IR/SymbolTable.java @@ -7,11 +7,14 @@ public class SymbolTable { private Hashtable table; private SymbolTable parent; private HashSet valueset; + + private Vector parentIFs; public SymbolTable() { table = new Hashtable(); valueset = new HashSet(); this.parent = null; + this.parentIFs = null; } public SymbolTable(SymbolTable parent) { @@ -99,6 +102,11 @@ public class SymbolTable { hs=(HashSet) parent.getAllValueSet(); else hs=new HashSet(); + if (this.parentIFs != null) { + for(int i = 0; i < this.parentIFs.size(); i++) { + hs.addAll(this.parentIFs.elementAt(i).getAllValueSet()); + } + } hs.addAll(valueset); return hs; } @@ -118,6 +126,18 @@ public class SymbolTable { public void setParent(SymbolTable parent) { this.parent = parent; } + + public Vector getParentIFs() { + return this.parentIFs; + } + + public void addParentIF(SymbolTable parentif) { + if(this.parentIFs == null) { + this.parentIFs = new Vector(); + } + this.parentIFs.addElement(parentif); + } + public String toString() { return "ST: " + table.toString(); diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index 5cef8cc2..ddae6ac0 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -60,12 +60,94 @@ public class BuildIR { if (toanalyze!=null) toanalyze.add(td); state.addTask(td); - } else { + } else if ((state.MGC) && isNode(type_pn,"interface_declaration")) { + // TODO add version for normal Java later + ClassDescriptor cn = parseInterfaceDecl(type_pn); + if (toanalyze!=null) + toanalyze.add(cn); + state.addClass(cn); + } else { throw new Error(type_pn.getLabel()); } } } } + + public ClassDescriptor parseInterfaceDecl(ParseNode pn) { + ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal()); + cn.setAsInterface(); + if (!isEmpty(pn.getChild("superIF").getTerminal())) { + /* parse inherited interface name */ + ParseNode snlist=pn.getChild("superIF").getChild("extend_interface_list"); + ParseNodeVector pnv=snlist.getChildren(); + for(int i=0; i sifv = cd.getSuperInterface(); + for(int i = 0; i < sifv.size(); i++) { + ClassDescriptor superif = getClass(sifv.elementAt(i)); + cd.addSuperInterfaces(superif); + cd.getFieldTable().addParentIF(superif.getFieldTable()); + cd.getMethodTable().addParentIF(superif.getMethodTable()); + } + } } /* Check to see that fields are well typed */ @@ -218,8 +230,8 @@ public class SemanticCheck { // TODO add version for normal Java later /* Check for abstract methods */ if(md.isAbstract()) { - if(!cd.isAbstract()) { - throw new Error("Error! The non-abstract Class " + cd.getSymbol() + "contains an abstract method " + md.getSymbol()); + if(!cd.isAbstract() && !cd.isInterface()) { + throw new Error("Error! The non-abstract Class " + cd.getSymbol() + " contains an abstract method " + md.getSymbol()); } } } diff --git a/Robust/src/IR/TypeUtil.java b/Robust/src/IR/TypeUtil.java index d289a953..72d84051 100644 --- a/Robust/src/IR/TypeUtil.java +++ b/Robust/src/IR/TypeUtil.java @@ -1,5 +1,7 @@ package IR; import java.util.*; + +import IR.Flat.FlatNode; import IR.Tree.*; import java.io.File; import Main.Main; @@ -15,6 +17,9 @@ public class TypeUtil { Hashtable supertable; Hashtable subclasstable; BuildIR bir; + + // for interfaces + Hashtable superIFtbl; public TypeUtil(State state, BuildIR bir) { this.state=state; @@ -63,11 +68,23 @@ public class TypeUtil { supertable.put(cd,cd_super); } } + if (!this.superIFtbl.containsKey(cd)) { + // add inherited interfaces + superIFtbl.put(cd,new HashSet()); + HashSet hs=(HashSet)superIFtbl.get(cd); + Vector superifv = cd.getSuperInterface(); + for(int i = 0; i < superifv.size(); i++) { + String superif = superifv.elementAt(i); + ClassDescriptor if_super = getClass(superif, todo); + hs.add(if_super); + } + } return cd; } private void createTables() { supertable=new Hashtable(); + superIFtbl = new Hashtable(); } public ClassDescriptor getMainClass() { @@ -181,18 +198,69 @@ NextMethod: public void createFullTable() { subclasstable=new Hashtable(); + //subIFclasstable = new Hashtable(); + HashSet tovisit=new HashSet(); + HashSet visited=new HashSet(); Iterator classit=state.getClassSymbolTable().getDescriptorsIterator(); while(classit.hasNext()) { ClassDescriptor cd=(ClassDescriptor)classit.next(); ClassDescriptor tmp=cd.getSuperDesc(); + + if(state.MGC) { + // TODO add version for normal Java later + // check tmp's interface ancestors + Iterator it_sifs = cd.getSuperInterfaces(); + while(it_sifs.hasNext()) { + ClassDescriptor cdt = (ClassDescriptor)it_sifs.next(); + if(!tovisit.contains(cdt)){ + tovisit.add(cdt); + } + } + } while(tmp!=null) { - if (!subclasstable.containsKey(tmp)) - subclasstable.put(tmp,new HashSet()); - HashSet hs=(HashSet)subclasstable.get(tmp); - hs.add(cd); - tmp=tmp.getSuperDesc(); + if (!subclasstable.containsKey(tmp)) + subclasstable.put(tmp,new HashSet()); + HashSet hs=(HashSet)subclasstable.get(tmp); + hs.add(cd); + if(state.MGC) { + // TODO add version for normal Java later + // check tmp's interface ancestors + Iterator it_sifs = tmp.getSuperInterfaces(); + while(it_sifs.hasNext()) { + ClassDescriptor cdt = (ClassDescriptor)it_sifs.next(); + if(!tovisit.contains(cdt)){ + tovisit.add(cdt); + } + } + } + tmp=tmp.getSuperDesc(); + } + + if(state.MGC) { + // TODO add version for normal Java later + while(!tovisit.isEmpty()) { + ClassDescriptor sif = (ClassDescriptor)tovisit.iterator().next(); + tovisit.remove(sif); + + if(!visited.contains(sif)) { + if(!this.subclasstable.containsKey(sif)) { + this.subclasstable.put(sif, new HashSet()); + } + HashSet hs = (HashSet)this.subclasstable/*subIFclasstable*/.get(sif); + hs.add(cd); + + Iterator it_sifs = sif.getSuperInterfaces(); + while(it_sifs.hasNext()) { + ClassDescriptor siftmp = (ClassDescriptor)it_sifs.next(); + if(!tovisit.contains(siftmp)){ + tovisit.add(siftmp); + } + } + visited.add(sif); + } + } } } } @@ -204,6 +272,10 @@ NextMethod: public ClassDescriptor getSuper(ClassDescriptor cd) { return (ClassDescriptor)supertable.get(cd); } + + public Set getSuperIFs(ClassDescriptor cd) { + return (Set)this.superIFtbl.get(cd); + } public boolean isCastable(TypeDescriptor original, TypeDescriptor casttype) { if (original.isChar()&& @@ -327,11 +399,65 @@ NextMethod: } private boolean isSuper(ClassDescriptor possiblesuper, ClassDescriptor cd2) { + HashSet tovisit=new HashSet(); + HashSet visited=new HashSet(); + + if(state.MGC) { + // TODO add version for normal Java later + // check cd2's interface ancestors + Iterator it_sifs = getSuperIFs(cd2).iterator(); + while(it_sifs.hasNext()) { + ClassDescriptor cd = (ClassDescriptor)it_sifs.next(); + if(cd == possiblesuper) { + return true; + } else if(!tovisit.contains(cd)){ + tovisit.add(cd); + } + } + } while(cd2!=null) { cd2=getSuper(cd2); if (cd2==possiblesuper) return true; + + if(state.MGC) { + // TODO add version for normal Java later + // check cd2's interface ancestors + if(cd2 != null) { + Iterator it_sifs = getSuperIFs(cd2).iterator(); + while(it_sifs.hasNext()) { + ClassDescriptor cd = (ClassDescriptor)it_sifs.next(); + if(cd == possiblesuper) { + return true; + } else if(!tovisit.contains(cd)){ + tovisit.add(cd); + } + } + } + } + } + + if(state.MGC) { + // TODO add version for normal Java later + while(!tovisit.isEmpty()) { + ClassDescriptor cd = (ClassDescriptor)tovisit.iterator().next(); + tovisit.remove(cd); + + if(!visited.contains(cd)) { + Iterator it_sifs = getSuperIFs(cd).iterator(); + while(it_sifs.hasNext()) { + ClassDescriptor cdt = (ClassDescriptor)it_sifs.next(); + if(cdt == possiblesuper) { + return true; + } else if(!tovisit.contains(cdt)){ + tovisit.add(cdt); + } + } + visited.add(cd); + } + } + } return false; } diff --git a/Robust/src/IR/Virtual.java b/Robust/src/IR/Virtual.java index aea9ac7f..907ce865 100644 --- a/Robust/src/IR/Virtual.java +++ b/Robust/src/IR/Virtual.java @@ -97,6 +97,15 @@ public class Virtual { int start=0; if (superdesc!=null) start=numberMethods(superdesc); + if(state.MGC) { + // TODO add version for normal Java later + // check the inherited interfaces + Iterator it_sifs = cd.getSuperInterfaces(); + while(it_sifs.hasNext()) { + ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); + start += numberMethods(superif); // TODO Can there be duplicated methods from multiple ancestors? + } + } for(Iterator it=cd.getMethods(); it.hasNext();) { MethodDescriptor md=(MethodDescriptor)it.next(); if (md.isStatic()||md.getReturnType()==null) @@ -113,6 +122,26 @@ public class Virtual { break; } } + if(state.MGC) { + // TODO add version for normal Java later + if(!foundmatch) { + // check if there is a matched method in inherited interfaces + Iterator it_sifs = cd.getSuperInterfaces(); + while(it_sifs.hasNext() && !foundmatch) { + ClassDescriptor superif = (ClassDescriptor)it_sifs.next(); + Set possiblematches_if=superif.getMethodTable().getSet(md.getSymbol()); + for(Iterator matchit=possiblematches_if.iterator(); matchit.hasNext();) { + MethodDescriptor matchmd=(MethodDescriptor)matchit.next(); + if (md.matches(matchmd)) { + int num=((Integer)methodnumber.get(matchmd)).intValue(); + methodnumber.put(md, new Integer(num)); + foundmatch=true; + break; + } + } + } + } + } if (!foundmatch) methodnumber.put(md, new Integer(start++)); } else { diff --git a/Robust/src/Lex/Keyword.java b/Robust/src/Lex/Keyword.java index 3b830c8d..b10d949c 100644 --- a/Robust/src/Lex/Keyword.java +++ b/Robust/src/Lex/Keyword.java @@ -88,5 +88,8 @@ class Keyword extends Token { //Keywords for coarse-grain parallelization key_table.put("sese", new Integer(Sym.SESE)); key_table.put("rblock", new Integer(Sym.RBLOCK)); + // Keywords for interface of mgc + key_table.put("interface", new Integer(Sym.INTERFACE)); + key_table.put("implements", new Integer(Sym.IMPLEMENTS)); } } diff --git a/Robust/src/Lex/Lexer.java b/Robust/src/Lex/Lexer.java index 34f24fde..14a25697 100644 --- a/Robust/src/Lex/Lexer.java +++ b/Robust/src/Lex/Lexer.java @@ -262,9 +262,9 @@ public class Lexer { "extends", "external", "final", "finally", "flag", //keyword for failure aware computation "float", "for", "genreach", "getoffset", "global", "goto", "if", - //"implements", + "implements", "import", "instanceof", "int", - //"interface", + "interface", "isavailable", "long", "native", "new", "optional", "package", "private", "protected", "public", diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup index 718ef76d..c1b5470a 100644 --- a/Robust/src/Parse/java14.cup +++ b/Robust/src/Parse/java14.cup @@ -52,11 +52,11 @@ terminal STATIC; // modifier terminal ABSTRACT, FINAL, NATIVE, SYNCHRONIZED, TRANSIENT, VOLATILE; terminal CLASS; // class_declaration terminal EXTENDS; // super -//terminal IMPLEMENTS; // interfaces +terminal IMPLEMENTS; // interfaces terminal VOID; // method_header terminal THROWS; // throws terminal THIS, SUPER; // explicit_constructor_invocation -//terminal INTERFACE; // interface_declaration +terminal INTERFACE; // interface_declaration terminal IF, ELSE; // if_then_statement, if_then_else_statement terminal SWITCH; // switch_statement terminal CASE, DEFAULT; // switch_label @@ -117,7 +117,7 @@ non terminal ParseNode integral_type, floating_point_type; non terminal ParseNode reference_type; non terminal ParseNode class_or_interface_type; non terminal ParseNode class_type; -//non terminal ParseNode interface_type; +non terminal ParseNode interface_type; non terminal ParseNode array_type; // 19.5) Names non terminal ParseNode name, simple_name, qualified_name; @@ -134,7 +134,7 @@ non terminal ParseNode type_declaration; non terminal ParseNode modifiers_opt, modifiers, modifier; // 19.8.1) Class Declaration non terminal ParseNode class_declaration, super, super_opt; -//non terminal interfaces, interfaces_opt, interface_type_list; +non terminal ParseNode interfaces, interfaces_opt, interface_type_list; non terminal ParseNode class_body; non terminal ParseNode class_body_declarations, class_body_declarations_opt; non terminal ParseNode class_body_declaration, class_member_declaration; @@ -157,12 +157,12 @@ non terminal ParseNode constructor_declaration, constructor_declarator; non terminal ParseNode constructor_body; non terminal ParseNode explicit_constructor_invocation; // 19.9.1) Interface Declarations -//non terminal ParseNode interface_declaration; -//non terminal ParseNode extends_interfaces_opt, extends_interfaces; -//non terminal ParseNode interface_body; -//non terminal ParseNode interface_member_declarations_opt, interface_member_declarations; -//non terminal ParseNode interface_member_declaration, constant_declaration; -//non terminal ParseNode abstract_method_declaration; +non terminal ParseNode interface_declaration; +non terminal ParseNode extends_interfaces_opt, extends_interfaces; +non terminal ParseNode interface_body; +non terminal ParseNode interface_member_declarations_opt, interface_member_declarations; +non terminal ParseNode interface_member_declaration, constant_declaration; +non terminal ParseNode abstract_method_declaration; // 19.10) Arrays non terminal ParseNode array_initializer; non terminal ParseNode variable_initializers; @@ -569,7 +569,7 @@ class_or_interface_type ::= name:name {: :}; class_type ::= class_or_interface_type:type {: RESULT=type; :}; -//interface_type ::= class_or_interface_type; +interface_type ::= class_or_interface_type:type {: RESULT=type; :}; array_type ::= primitive_type:prim dims:dims {: ParseNode pn=(new ParseNode("type")).addChild("array"); @@ -689,7 +689,10 @@ type_declaration ::= {: RESULT=td; :} -// | interface_declaration + | interface_declaration:in + {: + RESULT=in; + :} | SEMICOLON {: RESULT=new ParseNode("empty"); :} ; @@ -730,13 +733,14 @@ modifier ::= // 19.8.1) Class Declaration: class_declaration ::= - modifiers_opt:mo CLASS IDENTIFIER:id super_opt:so //interfaces_opt -class_body:body + modifiers_opt:mo CLASS IDENTIFIER:id super_opt:so interfaces_opt:ifo + class_body:body {: ParseNode pn=new ParseNode("class_declaration"); pn.addChild("modifiers").addChild(mo); pn.addChild("name").addChild(id); pn.addChild("super").addChild(so); + pn.addChild("superIF").addChild(ifo); pn.addChild("classbody").addChild(body); RESULT=pn; :} @@ -752,15 +756,23 @@ super_opt ::= :} ; -//interfaces ::= IMPLEMENTS interface_type_list -// ; -//interfaces_opt::= -// | interfaces -// ; -//interface_type_list ::= -// interface_type -// | interface_type_list COMMA interface_type -// ; +interfaces ::= IMPLEMENTS interface_type_list:iftl {: RESULT=iftl; :} + ; +interfaces_opt ::= + {: RESULT=new ParseNode("empty"); :} + | interfaces:ifs {: RESULT=ifs; :} + ; +interface_type_list ::= + interface_type:ift {: + ParseNode pn=new ParseNode("interface_type_list"); + pn.addChild(ift); + RESULT=pn; + :} + | interface_type_list:iftl COMMA interface_type:ift {: + iftl.addChild(ift); + RESULT=iftl; + :} + ; class_body ::= LBRACE class_body_declarations_opt:cbdo RBRACE {: RESULT=cbdo; :} ; @@ -809,7 +821,9 @@ class_member_declaration ::= :} /* repeat the prod for 'class_declaration' here: */ // | modifiers_opt CLASS IDENTIFIER super_opt class_body -// | interface_declaration + | interface_declaration:interfaced {: + RESULT=(new ParseNode("interface")).addChild(interfaced).getRoot(); + :} | SEMICOLON {: RESULT=new ParseNode("empty"); :} ; @@ -1048,43 +1062,81 @@ SUPER LPAREN argument_list_opt:alo RPAREN SEMICOLON {: // 19.9) Interfaces // 19.9.1) Interface Declarations -//interface_declaration ::= -// modifiers_opt INTERFACE IDENTIFIER extends_interfaces_opt -// interface_body -// ; -//extends_interfaces_opt ::= -// | extends_interfaces -// ; -//extends_interfaces ::= -// EXTENDS interface_type -// | extends_interfaces COMMA interface_type -// ; -//interface_body ::= -// LBRACE interface_member_declarations_opt RBRACE -// ; -//interface_member_declarations_opt ::= -// | interface_member_declarations -// ; -//interface_member_declarations ::= -// interface_member_declaration -// | interface_member_declarations interface_member_declaration -// ; -//interface_member_declaration ::= -// constant_declaration -// | abstract_method_declaration -// | class_declaration -// | interface_declaration -// | SEMICOLON -// ; -//constant_declaration ::= -// field_declaration -// // need to semantically check that modifiers of field declaration -// // include only PUBLIC, STATIC, or FINAL. Other modifiers are -// // disallowed. -// ; -//abstract_method_declaration ::= -// method_header SEMICOLON -// ; +interface_declaration ::= + modifiers_opt:mo INTERFACE IDENTIFIER:id extends_interfaces_opt:io + interface_body:body + {: + ParseNode pn=new ParseNode("interface_declaration"); + pn.addChild("modifiers").addChild(mo); + pn.addChild("name").addChild(id); + pn.addChild("superIF").addChild(io); + pn.addChild("interfacebody").addChild(body); + RESULT=pn; + :} + ; +extends_interfaces_opt ::= + {: RESULT=new ParseNode("empty"); :} + | extends_interfaces:eifs {: RESULT=eifs; :} + ; +extends_interfaces ::= + EXTENDS interface_type:ift + {: + ParseNode pn=new ParseNode("extend_interface_list"); + pn.addChild(ift); + RESULT=pn; + :} + | extends_interfaces:eifs COMMA interface_type:ift + {: + eifs.addChild(ift); + RESULT=eifs; + :} + ; +interface_body ::= + LBRACE interface_member_declarations_opt:imdo RBRACE + {: RESULT=imdo; :} + ; +interface_member_declarations_opt ::= + {: RESULT=new ParseNode("empty"); :} + | interface_member_declarations:imd {: RESULT=imd; :} + ; +interface_member_declarations ::= + interface_member_declaration:imd {: + ParseNode pn=new ParseNode("interface_member_declaration_list"); + pn.addChild(imd); + RESULT=pn; + :} + | interface_member_declarations:imds interface_member_declaration:imd {: + imds.addChild(imd); + RESULT=imds; + :} + ; +interface_member_declaration ::= + constant_declaration:constant {: + RESULT=(new ParseNode("constant")).addChild(constant).getRoot(); + :} + | abstract_method_declaration:method {: + RESULT=(new ParseNode("method")).addChild(method).getRoot(); + :} +// | class_declaration:class +// | interface_declaration:interface + | SEMICOLON {: + RESULT=new ParseNode("empty"); + :} + ; +constant_declaration ::= + field_declaration:fd {: RESULT=fd; :} + // need to semantically check that modifiers of field declaration + // include only PUBLIC, STATIC, or FINAL. Other modifiers are + // disallowed. + ; +abstract_method_declaration ::= + method_header:header SEMICOLON {: + ParseNode pn=new ParseNode("method_declaration"); + pn.addChild("header").addChild(header); + pn.addChild("body").addChild(new ParseNode("empty")); + RESULT=pn; + :} + ; // 19.10) Arrays diff --git a/Robust/src/Tests/InterfaceTest.java b/Robust/src/Tests/InterfaceTest.java new file mode 100644 index 00000000..80eec8f8 --- /dev/null +++ b/Robust/src/Tests/InterfaceTest.java @@ -0,0 +1,78 @@ +public interface Instrument { + // Compile-time constant: + int VALUE;// = 5; // static & final + // Cannot have method definitions: + void play(int n); // Automatically public + void adjust(); +} + +class Wind implements Instrument { + public Wind(){} + public void play(int n) { + System.out.println("Wind.play() " + n); + } + public String what() { return "Wind"; } + public void adjust() { System.out.println("Wind.adjust()"); } +} + +class Percussion implements Instrument { + public Percussion(){} + public void play(int n) { + System.out.println("Percussion.play() " + n); + } + public String what() { return "Percussion"; } + public void adjust() { System.out.println("Percussion.adjust()"); } +} + +class Stringed implements Instrument { + public Stringed(){} + public void play(int n) { + System.out.println("Stringed.play() " + n); + } + public String what() { return "Stringed"; } + public void adjust() { System.out.println("Stringed.adjust()"); } +} + +class Brass extends Wind { + public Brass(){} + public String what() { return "Brass"; } +} + +class Woodwind extends Wind { + public Woodwind(){} + public String what() { return "Woodwind"; } +} + +public class InterfaceTest { + public InterfaceTest(){} + + // Doesn’t care about type, so new types + // added to the system still work right: + static void tune(Instrument i) { + // ... + i.play(9); + } + static void tuneAll(Instrument[] e) { + for(int k = 0; k < e.length; k++) { + Instrument i = e[k]; + tune(i); + } + } + public static void main(String[] args) { + // Upcasting during addition to the array: + Instrument.VALUE=5; + Instrument[] orchestra = new Instrument[5]; + orchestra[0] = new Wind(); + orchestra[1] = new Percussion(); + orchestra[2] = new Stringed(); + orchestra[3] = new Brass(); + orchestra[4] = new Woodwind(); + tuneAll(orchestra); + } +} /* Output: +Wind.play() MIDDLE_C +Percussion.play() MIDDLE_C +Stringed.play() MIDDLE_C +Wind.play() MIDDLE_C //Brass.play() MIDDLE_C +Wind.play() MIDDLE_C //Woodwind.play() MIDDLE_C +*///:~ -- 2.34.1