st+="extends "+superclass.toString();
st+=" {\n";
indent=TreeNode.INDENT;
-
+ boolean printcr=false;
+
for(Iterator it=getFields();it.hasNext();) {
FieldDescriptor fd=(FieldDescriptor)it.next();
st+=TreeNode.printSpace(indent)+fd.toString()+"\n";
+ printcr=true;
}
- if (fields.size()>0)
+ if (printcr)
st+="\n";
for(Iterator it=getMethods();it.hasNext();) {
protected Modifiers modifier;
protected TypeDescriptor returntype;
protected String identifier;
- protected Vector param_name;
- protected Vector param_type;
+ protected Vector params;
protected SymbolTable paramtable;
-
+ protected ClassDescriptor cd;
+ protected VarDescriptor thisvd;
+
+
public MethodDescriptor(Modifiers m, TypeDescriptor rt, String identifier) {
super(identifier);
this.modifier=m;
this.identifier=identifier;
this.safename = "__" + name + "__";
this.uniqueid=count++;
- param_name=new Vector();
- param_type=new Vector();
+ params=new Vector();
paramtable=new SymbolTable();
+ thisvd=null;
+ }
+
+ public MethodDescriptor(Modifiers m, String identifier) {
+ super(identifier);
+ this.modifier=m;
+ this.returntype=null;
+ this.identifier=identifier;
+ this.safename = "__" + name + "__";
+ this.uniqueid=count++;
+ params=new Vector();
+ paramtable=new SymbolTable();
+ thisvd=null;
+ }
+
+ public void setThis(VarDescriptor vd) {
+ thisvd=vd;
+ paramtable.add(vd);
+ }
+
+ public boolean isStatic() {
+ return modifier.isStatic();
}
+
+ public boolean isConstructor() {
+ return (returntype==null);
+ }
+
public TypeDescriptor getReturnType() {
return returntype;
}
+ public void setClassDesc(ClassDescriptor cd) {
+ this.cd=cd;
+ }
+
+ public ClassDescriptor getClassDesc() {
+ return cd;
+ }
+
public SymbolTable getParameterTable() {
return paramtable;
}
public void addParameter(TypeDescriptor type, String paramname) {
- param_name.add(paramname);
- param_type.add(type);
+ if (paramname.equals("this"))
+ throw new Error("Can't have parameter named this");
+ VarDescriptor vd=new VarDescriptor(type, paramname);
+
+ params.add(vd);
if (paramtable.getFromSameScope(paramname)!=null) {
throw new Error("Parameter "+paramname+" already defined");
}
- paramtable.add(paramname,type);
+ paramtable.add(vd);
}
public int numParameters() {
- return param_name.size();
+ return params.size();
}
public String getParamName(int i) {
- return (String) param_name.get(i);
+ return ((VarDescriptor)params.get(i)).getName();
}
public TypeDescriptor getParamType(int i) {
- return (TypeDescriptor) param_type.get(i);
+ return ((VarDescriptor)params.get(i)).getType();
}
public String toString() {
- String st=modifier.toString()+returntype.toString()+" "+identifier+"(";
- for(int i=0;i<param_type.size();i++) {
- st+=param_type.get(i).toString()+" "+param_name.get(i).toString();
- if ((i+1)!=param_type.size())
+ String st="";
+ if (returntype!=null)
+ st=modifier.toString()+returntype.toString()+" "+identifier+"(";
+ else
+ st=modifier.toString()+" "+identifier+"(";
+ for(int i=0;i<params.size();i++) {
+ st+=getParamName(i)+" "+getParamType(i);
+ if ((i+1)!=params.size())
st+=", ";
}
st+=")";
nd=null;
}
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ public NameDescriptor getBase() {
+ return nd;
+ }
+
+ public String getRoot() {
+ if (nd==null)
+ return identifier;
+ else
+ return nd.getRoot();
+ }
+
public String toString() {
if (nd==null)
return identifier;
private Hashtable table;
private SymbolTable parent;
+ private HashSet valueset;
public SymbolTable() {
table = new Hashtable();
+ valueset = new HashSet();
this.parent = null;
}
}
public void add(String name, Descriptor d) {
- table.put(name, d);
+ if (!table.containsKey(name))
+ table.put(name, new HashSet());
+ HashSet hs=(HashSet)table.get(name);
+ hs.add(d);
+ valueset.add(d);
}
- public void dump() {
- Enumeration e = getDescriptors();
- while (e.hasMoreElements()) {
- Descriptor d = (Descriptor) e.nextElement();
- System.out.println(d.getSymbol());
- }
- if (parent != null) {
- System.out.println("parent:");
- parent.dump();
+ public Set getSet(String name) {
+ return getPSet(name);
+ }
+
+ private HashSet getPSet(String name) {
+ HashSet hs=null;
+ if (parent!=null)
+ hs=parent.getPSet(name);
+ else
+ hs=new HashSet();
+ if (table.containsKey(name)) {
+ hs.addAll((HashSet)table.get(name));
}
+ return hs;
}
-
+
+ public Set getSetFromSameScope(String name) {
+ return getPSetFromSameScope(name);
+ }
+
+ private HashSet getPSetFromSameScope(String name) {
+ if (table.containsKey(name)) {
+ HashSet hs=(HashSet)table.get(name);
+ return hs;
+ } else
+ return new HashSet();
+ }
+
public Descriptor get(String name) {
- Descriptor d = (Descriptor) table.get(name);
+ Descriptor d = getFromSameScope(name);
if (d == null && parent != null) {
return parent.get(name);
} else {
}
public Descriptor getFromSameScope(String name) {
- return (Descriptor)table.get(name);
+ if (table.containsKey(name)) {
+ HashSet hs=(HashSet) table.get(name);
+ return (Descriptor) hs.iterator().next();
+ } else
+ return null;
+
}
public Enumeration getNames() {
return table.keySet().iterator();
}
- public Enumeration getDescriptors() {
- return table.elements();
+ public Set getValueSet() {
+ return valueset;
}
public Iterator getDescriptorsIterator() {
- return table.values().iterator();
+ return getValueSet().iterator();
}
- public Iterator descriptors() {
- return table.values().iterator();
+ public Set getAllValueSet() {
+ HashSet hs=null;
+ if (parent!=null)
+ hs=(HashSet) parent.getAllValueSet();
+ else
+ hs=new HashSet();
+ hs.addAll(valueset);
+ return hs;
}
- public Vector getAllDescriptors() {
- Vector d;
- if (parent == null) {
- d = new Vector();
- } else {
- d = parent.getAllDescriptors();
- }
-
- Enumeration e = getDescriptors();
- while(e.hasMoreElements()) {
- d.addElement(e.nextElement());
- }
-
- return d;
+ public Iterator getAllDescriptorsIterator() {
+ return getAllValueSet().iterator();
}
public boolean contains(String name) {
return (get(name) != null);
}
-
- public int size() {
- return table.size();
- }
-
- public int sizeAll() {
- if (parent != null) {
- return parent.sizeAll() + table.size();
- } else {
- return table.size();
- }
- }
-
public SymbolTable getParent() {
return parent;
}
this.parent = parent;
}
- /**
- * Adds contents of st2.table to this.table and returns a
- * Vector of shared names, unless there are no shared names,
- * in which case returns null.
- */
- public Vector merge(SymbolTable st2) {
- Vector v = new Vector();
- Enumeration names = st2.table.keys();
-
- while (names.hasMoreElements()) {
- Object o = names.nextElement();
-
- if (table.containsKey(o)) {
- v.addElement(o);
- } else {
- table.put(o, st2.table.get(o));
- }
- }
-
- if (v.size() == 0) {
- return null;
- } else {
- return v;
- }
- }
-
public String toString() {
return "ST: " + table.toString();
}
if (isNode(decl,"member")) {
parseClassMember(cn,decl);
} else if (isNode(decl,"constructor")) {
+ parseConstructorDecl(cn,decl.getChild("constructor_declaration"));
} else if (isNode(decl,"block")) {
} else throw new Error();
}
state.addTreeCode(md,bn);
}
+ private void parseConstructorDecl(ClassDescriptor cn, ParseNode pn) {
+ ParseNode mn=pn.getChild("modifiers");
+ Modifiers m=parseModifiersList(mn);
+ ParseNode cdecl=pn.getChild("constructor_declarator");
+ String name=cdecl.getChild("name").getChild("identifier").getTerminal();
+ MethodDescriptor md=new MethodDescriptor(m, name);
+ ParseNode paramnode=cdecl.getChild("parameters");
+ parseParameterList(md,paramnode);
+ ParseNode bodyn0=pn.getChild("body");
+ ParseNode bodyn=bodyn0.getChild("constructor_body");
+ cn.addMethod(md);
+ if (bodyn!=null) {
+ BlockNode bn=parseBlock(bodyn);
+ state.addTreeCode(md,bn);
+ }
+ }
+
public BlockNode parseBlock(ParseNode pn) {
if (isEmpty(pn.getTerminal()))
return new BlockNode();
import IR.MethodDescriptor;
public class MethodInvokeNode extends ExpressionNode {
- NameDescriptor nd;
Vector argumentlist;
String methodid;
+ NameDescriptor basename;
ExpressionNode en;
MethodDescriptor md;
public MethodInvokeNode(NameDescriptor name) {
- nd=name;
+ methodid=name.getIdentifier();
+ if (name.getBase()!=null) {
+ basename=name.getBase();
+ }
argumentlist=new Vector();
- methodid=null;
en=null;
md=null;
}
public MethodInvokeNode(String methodid, ExpressionNode exp) {
this.methodid=methodid;
this.en=exp;
- nd=null;
argumentlist=new Vector();
md=null;
+ this.basename=null;
+ }
+
+ public NameDescriptor getBaseName() {
+ return basename;
+ }
+
+ public String getMethodName() {
+ return methodid;
}
public ExpressionNode getExpression() {
return en;
}
+ public void setExpression(ExpressionNode en) {
+ this.en=en;
+ }
+
public void setMethod(MethodDescriptor md) {
this.md=md;
}
public String printNode(int indent) {
String st;
- if (nd==null) {
- st=en.printNode(indent)+"."+methodid+"(";
- } else {
- st=nd.toString()+"(";
- }
+ st=en.printNode(indent)+"."+methodid+"(";
+
for(int i=0;i<argumentlist.size();i++) {
ExpressionNode en=(ExpressionNode)argumentlist.get(i);
st+=en.printNode(indent);
value|=mod;
}
+ public boolean isStatic() {
+ return ((value&STATIC)!=0);
+ }
+
public String toString() {
String st="";
if ((value&PUBLIC)!=0)
import IR.NameDescriptor;
import IR.VarDescriptor;
import IR.TypeDescriptor;
+import IR.FieldDescriptor;
public class NameNode extends ExpressionNode {
NameDescriptor name;
VarDescriptor vd;
+ FieldDescriptor fd;
public NameNode(NameDescriptor nd) {
this.name=nd;
+ this.vd=null;
+ this.fd=null;
}
public void setVar(VarDescriptor vd) {
this.vd=vd;
}
+ public void setField(FieldDescriptor fd) {
+ this.fd=fd;
+ }
+
public TypeDescriptor getType() {
- return vd.getType();
+ if (vd!=null)
+ return vd.getType();
+ else
+ return fd.getType();
}
NameDescriptor getName() {
package IR.Tree;
import IR.Operation;
+import IR.TypeDescriptor;
public class OpNode extends ExpressionNode {
ExpressionNode left;
ExpressionNode right;
Operation op;
+ TypeDescriptor td;
public OpNode(ExpressionNode l, ExpressionNode r, Operation o) {
left=l;
else
return left.printNode(indent)+" "+op.toString()+" "+right.printNode(indent);
}
+
+ public TypeDescriptor getType() {
+ return td;
+ }
+
+ public void setType(TypeDescriptor td) {
+ this.td=td;
+ }
+
public int kind() {
return Kind.OpNode;
}
public void checkMethod(ClassDescriptor cd, MethodDescriptor md) {
/* Check return type */
- if (!md.getReturnType().isVoid())
- checkTypeDescriptor(md.getReturnType());
+ if (!md.isConstructor())
+ if (!md.getReturnType().isVoid())
+ checkTypeDescriptor(md.getReturnType());
+
for(int i=0;i<md.numParameters();i++) {
TypeDescriptor param_type=md.getParamType(i);
checkTypeDescriptor(param_type);
}
/* Link the naming environments */
md.getParameterTable().setParent(cd.getFieldTable());
+ md.setClassDesc(cd);
+ if (!md.isStatic()) {
+ VarDescriptor thisvd=new VarDescriptor(new TypeDescriptor(cd),"this");
+ md.setThis(thisvd);
+ }
}
public void checkMethodBody(ClassDescriptor cd, MethodDescriptor md) {
void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) {
NameDescriptor nd=nn.getName();
String varname=nd.toString();
- VarDescriptor vd=(VarDescriptor)nametable.get(varname);
- if (vd==null) {
- throw new Error("Variable "+varname+" undefined");
+ Descriptor d=(Descriptor)nametable.get(varname);
+ if (d==null) {
+ throw new Error("Name "+varname+" undefined");
+ }
+ if (d instanceof VarDescriptor) {
+ nn.setVar((VarDescriptor)d);
+ } else if (d instanceof FieldDescriptor) {
+ nn.setField((FieldDescriptor)d);
}
- nn.setVar(vd);
if (td!=null)
if (!typeutil.isSuperorType(td,nn.getType()))
throw new Error("Field node returns "+nn.getType()+", but need "+td);
void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) {
+ TypeDescriptor[] tdarray=new TypeDescriptor[con.numArgs()];
+ for(int i=0;i<con.numArgs();i++) {
+ ExpressionNode en=con.getArg(i);
+ checkExpressionNode(md,nametable,en,null);
+ tdarray[i]=en.getType();
+ }
+
+ TypeDescriptor typetolookin=con.getType();
+ checkTypeDescriptor(typetolookin);
+ if (!typetolookin.isClass())
+ throw new Error();
+
+ ClassDescriptor classtolookin=typetolookin.getClassDesc();
+ System.out.println("Looking for "+typetolookin.getSymbol());
+ System.out.println(classtolookin.getMethodTable());
+
+ Set methoddescriptorset=classtolookin.getMethodTable().getSet(typetolookin.getSymbol());
+ MethodDescriptor bestmd=null;
+ NextMethod:
+ for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
+ MethodDescriptor currmd=(MethodDescriptor)methodit.next();
+ /* Need correct number of parameters */
+ System.out.println("Examining: "+currmd);
+ if (con.numArgs()!=currmd.numParameters())
+ continue;
+ for(int i=0;i<con.numArgs();i++) {
+ if (!typeutil.isSuperorType(currmd.getParamType(i),tdarray[i]))
+ continue NextMethod;
+ }
+ /* Method okay so far */
+ if (bestmd==null)
+ bestmd=currmd;
+ else {
+ if (isMoreSpecific(currmd,bestmd)) {
+ bestmd=currmd;
+ } else if (!isMoreSpecific(bestmd, currmd))
+ throw new Error("No method is most specific");
+
+ /* Is this more specific than bestmd */
+ }
+ }
+ if (bestmd==null)
+ throw new Error("No method found for "+con.printNode(0));
+ con.setConstructor(bestmd);
+
}
- void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
+ /** Check to see if md1 is more specific than md2... Informally
+ if md2 could always be called given the arguments passed into
+ md1 */
+
+ boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
+ /* Checks if md1 is more specific than md2 */
+ if (md1.numParameters()!=md2.numParameters())
+ throw new Error();
+ for(int i=0;i<md1.numParameters();i++) {
+ if (!typeutil.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
+ return false;
+ }
+ if (!typeutil.isSuperorType(md2.getReturnType(), md1.getReturnType()))
+ return false;
+ return true;
+ }
+ ExpressionNode translateNameDescriptorintoExpression(NameDescriptor nd) {
+ String id=nd.getIdentifier();
+ NameDescriptor base=nd.getBase();
+ if (base==null)
+ return new NameNode(nd);
+ else
+ return new FieldAccessNode(translateNameDescriptorintoExpression(base),id);
+ }
+
+
+ void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
+ /*Typecheck subexpressions
+ and get types for expressions*/
+
+ TypeDescriptor[] tdarray=new TypeDescriptor[min.numArgs()];
+ for(int i=0;i<min.numArgs();i++) {
+ ExpressionNode en=min.getArg(i);
+ checkExpressionNode(md,nametable,en,null);
+ tdarray[i]=en.getType();
+ }
+ TypeDescriptor typetolookin=null;
+ if (min.getExpression()!=null) {
+ checkExpressionNode(md,nametable,min.getExpression(),null);
+ typetolookin=min.getExpression().getType();
+ } else if (min.getBaseName()!=null) {
+ String rootname=min.getBaseName().getRoot();
+ if (nametable.get(rootname)!=null) {
+ //we have an expression
+ min.setExpression(translateNameDescriptorintoExpression(min.getBaseName()));
+ checkExpressionNode(md, nametable, min.getExpression(), null);
+ typetolookin=min.getExpression().getType();
+ } else {
+ //we have a type
+ ClassDescriptor cd=typeutil.getClass(min.getBaseName().getSymbol());
+ if (cd==null)
+ throw new Error(min.getBaseName()+" undefined");
+ typetolookin=new TypeDescriptor(cd);
+ }
+ } else {
+ typetolookin=new TypeDescriptor(md.getClassDesc());
+ }
+ if (!typetolookin.isClass())
+ throw new Error();
+ ClassDescriptor classtolookin=typetolookin.getClassDesc();
+ System.out.println("Method name="+min.getMethodName());
+ Set methoddescriptorset=classtolookin.getMethodTable().getSet(min.getMethodName());
+ MethodDescriptor bestmd=null;
+ NextMethod:
+ for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
+ MethodDescriptor currmd=(MethodDescriptor)methodit.next();
+ /* Need correct number of parameters */
+ if (min.numArgs()!=currmd.numParameters())
+ continue;
+ for(int i=0;i<min.numArgs();i++) {
+ if (!typeutil.isSuperorType(currmd.getParamType(i),tdarray[i]))
+ continue NextMethod;
+ }
+ /* Method okay so far */
+ if (bestmd==null)
+ bestmd=currmd;
+ else {
+ if (isMoreSpecific(currmd,bestmd)) {
+ bestmd=currmd;
+ } else if (!isMoreSpecific(bestmd, currmd))
+ throw new Error("No method is most specific");
+
+ /* Is this more specific than bestmd */
+ }
+ }
+ if (bestmd==null)
+ throw new Error("No method found for :"+min.printNode(0));
+ min.setMethod(bestmd);
}
thistype=ltd;
}
on.setType(thistype);
- if (!typeutil.isSuperorType(td, thistype))
- throw new Error("Type of rside not compatible with type of lside"+on.printNode(0));
+ if (td!=null)
+ if (!typeutil.isSuperorType(td, thistype))
+ throw new Error("Type of rside not compatible with type of lside"+on.printNode(0));
}
return type==DOUBLE;
}
-
public void setClassDescriptor(ClassDescriptor cd) {
class_desc=cd;
}
//throws_opt
constructor_body:body {:
ParseNode pn=new ParseNode("constructor_declaration");
- pn.addChild("modifier").addChild(mo);
- pn.addChild("declarator").addChild(cd);
+ pn.addChild("modifiers").addChild(mo);
+ pn.addChild(cd);
pn.addChild("body").addChild(body);
RESULT=pn;
:}
constructor_declarator ::=
simple_name:name LPAREN formal_parameter_list_opt:fplo RPAREN {:
ParseNode pn=new ParseNode("constructor_declarator");
- pn.addChild("name").addChild(name);
+ pn.addChild(name);
pn.addChild("parameters").addChild(fplo);
RESULT=pn;
:}
// LBRACE explicit_constructor_invocation RBRACE |
LBRACE block_statements:block RBRACE {:
ParseNode pn=new ParseNode("constructor_body");
- pn.addChild("block").addChild(block);
+ pn.addChild(block);
RESULT=pn;
:}
| LBRACE RBRACE {: RESULT=new ParseNode("empty"); :}