int numstaticblocks = 0;
int numstaticfields = 0;
+
+ // for interfaces
+ boolean isInterface=false;
+ Vector<String> superinterfaces;
+ SymbolTable superIFdesc;
public ClassDescriptor(String classname) {
this("", classname);
methods=new SymbolTable();
classid=UIDCount++;
this.packagename=packagename;
+ superinterfaces = new Vector<String>();
+ superIFdesc = new SymbolTable();
}
public int getId() {
public Iterator getFlags() {
return flags.getDescriptorsIterator();
}
+
+ public Iterator getSuperInterfaces() {
+ return this.superIFdesc.getDescriptorsIterator();
+ }
public SymbolTable getFieldTable() {
return fields;
public SymbolTable getMethodTable() {
return methods;
}
+
+ public SymbolTable getSuperInterfaceTable() {
+ return this.superIFdesc;
+ }
public String getSafeDescriptor() {
return "L"+safename.replace('.','/');
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;
return superclass;
}
+ public void addSuperInterface(String superif) {
+ this.superinterfaces.addElement(superif);
+ }
+
+ public Vector<String> getSuperInterface() {
+ return this.superinterfaces;
+ }
+
+ public void addSuperInterfaces(ClassDescriptor sif) {
+ this.superIFdesc.add(sif);
+ }
+
public void incStaticBlocks() {
this.numstaticblocks++;
}
public boolean isAbstract() {
return this.modifiers.isAbstract();
}
+
+ public boolean isInterface() {
+ return this.isInterface;
+ }
+
+ public void setAsInterface() {
+ this.isInterface = true;
+ }
}
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()) {
/* 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();
// 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");
}
private Hashtable table;
private SymbolTable parent;
private HashSet valueset;
+
+ private Vector<SymbolTable> parentIFs;
public SymbolTable() {
table = new Hashtable();
valueset = new HashSet();
this.parent = null;
+ this.parentIFs = null;
}
public SymbolTable(SymbolTable parent) {
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;
}
public void setParent(SymbolTable parent) {
this.parent = parent;
}
+
+ public Vector<SymbolTable> getParentIFs() {
+ return this.parentIFs;
+ }
+
+ public void addParentIF(SymbolTable parentif) {
+ if(this.parentIFs == null) {
+ this.parentIFs = new Vector<SymbolTable>();
+ }
+ this.parentIFs.addElement(parentif);
+ }
+
public String toString() {
return "ST: " + table.toString();
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<pnv.size(); i++) {
+ ParseNode decl=pnv.elementAt(i);
+ if (isNode(decl,"type")) {
+ NameDescriptor nd=parseName(decl.getChild("class").getChild("name"));
+ cn.addSuperInterface(nd.toString());
+ }
+ }
+ }
+ cn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
+ parseInterfaceBody(cn, pn.getChild("interfacebody"));
+ return cn;
+ }
+
+ private void parseInterfaceBody(ClassDescriptor cn, ParseNode pn) {
+ assert(cn.isInterface());
+ ParseNode decls=pn.getChild("interface_member_declaration_list");
+ if (decls!=null) {
+ ParseNodeVector pnv=decls.getChildren();
+ for(int i=0; i<pnv.size(); i++) {
+ ParseNode decl=pnv.elementAt(i);
+ if (isNode(decl,"constant")) {
+ parseInterfaceConstant(cn,decl);
+ } else if (isNode(decl,"method")) {
+ parseInterfaceMethod(cn,decl.getChild("method_declaration"));
+ } else throw new Error();
+ }
+ }
+ }
+
+ private void parseInterfaceConstant(ClassDescriptor cn, ParseNode pn) {
+ if (pn!=null) {
+ parseFieldDecl(cn,pn.getChild("field_declaration"));
+ return;
+ }
+ throw new Error();
+ }
+
+ private void parseInterfaceMethod(ClassDescriptor cn, ParseNode pn) {
+ ParseNode headern=pn.getChild("header");
+ ParseNode bodyn=pn.getChild("body");
+ MethodDescriptor md=parseMethodHeader(headern.getChild("method_header"));
+ md.getModifiers().addModifier(Modifiers.PUBLIC);
+ md.getModifiers().addModifier(Modifiers.ABSTRACT);
+ try {
+ 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();
+ throw new Error();
+ } catch (Error e) {
+ System.out.println("Error with method:"+md.getSymbol());
+ e.printStackTrace();
+ throw new Error();
+ }
+ }
public TaskDescriptor parseTaskDecl(ParseNode pn) {
TaskDescriptor td=new TaskDescriptor(pn.getChild("name").getTerminal());
cn.getSymbol().equals(TypeUtil.TagClass)))
cn.setSuper(TypeUtil.ObjectClass);
}
+ // check inherited interfaces
+ if (!isEmpty(pn.getChild("superIF").getTerminal())) {
+ /* parse inherited interface name */
+ ParseNode snlist=pn.getChild("superIF").getChild("interface_type_list");
+ ParseNodeVector pnv=snlist.getChildren();
+ for(int i=0; i<pnv.size(); i++) {
+ ParseNode decl=pnv.elementAt(i);
+ if (isNode(decl,"type")) {
+ NameDescriptor nd=parseName(decl.getChild("class").getChild("name"));
+ cn.addSuperInterface(nd.toString());
+ }
+ }
+ }
cn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
parseClassBody(cn, pn.getChild("classbody"));
return cn;
private void parseFieldDecl(ClassDescriptor cn,ParseNode pn) {
ParseNode mn=pn.getChild("modifier");
Modifiers m=parseModifiersList(mn);
+ if((state.MGC) && cn.isInterface()) {
+ // TODO add version for normal Java later
+ // Can only be PUBLIC or STATIC or FINAL
+ if((m.isAbstract()) || (m.isAtomic()) || (m.isNative())
+ || (m.isSynchronized())) {
+ throw new Error("Error: field in Interface " + cn.getSymbol() + "can only be PUBLIC or STATIC or FINAL");
+ }
+ m.addModifier(Modifiers.PUBLIC);
+ m.addModifier(Modifiers.STATIC);
+ m.addModifier(Modifiers.FINAL);
+ }
ParseNode tn=pn.getChild("type");
TypeDescriptor t=parseTypeDescriptor(tn);
cd.getFieldTable().setParent(cd.getSuperDesc().getFieldTable());
cd.getMethodTable().setParent(cd.getSuperDesc().getMethodTable());
cd.getFlagTable().setParent(cd.getSuperDesc().getFlagTable());
+ if(state.MGC) {
+ // TODO add version for normal Java later
+ // Link together Field, Method tables do classes inherit these from
+ // their ancestor interfaces
+ Vector<String> 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 */
// 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());
}
}
}
package IR;
import java.util.*;
+
+import IR.Flat.FlatNode;
import IR.Tree.*;
import java.io.File;
import Main.Main;
Hashtable supertable;
Hashtable subclasstable;
BuildIR bir;
+
+ // for interfaces
+ Hashtable superIFtbl;
public TypeUtil(State state, BuildIR bir) {
this.state=state;
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<String> 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() {
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);
+ }
+ }
}
}
}
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()&&
}
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;
}
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)
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 {
//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));
}
}
"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",
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
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;
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;
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;
:};
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");
{:
RESULT=td;
:}
-// | interface_declaration
+ | interface_declaration:in
+ {:
+ RESULT=in;
+ :}
| SEMICOLON {: RESULT=new ParseNode("empty"); :}
;
// 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;
:}
:}
;
-//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; :}
;
:}
/* 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"); :}
;
// 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
--- /dev/null
+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
+*///:~