From fb5e6c9a3b75668af62e9d6a3f16d27107aee110 Mon Sep 17 00:00:00 2001 From: bdemsky <bdemsky> Date: Wed, 22 Feb 2006 19:36:20 +0000 Subject: [PATCH] checking in changes --- Robust/src/IR/AssignOperation.java | 28 ++++ Robust/src/IR/ClassDescriptor.java | 44 ++++-- Robust/src/IR/FieldDescriptor.java | 4 + Robust/src/IR/Flat/BuildFlat.java | 109 +++++++++++-- Robust/src/IR/Flat/FlatCall.java | 26 ++++ Robust/src/IR/Flat/FlatCastNode.java | 18 +++ Robust/src/IR/Flat/FlatCondBranch.java | 10 ++ Robust/src/IR/Flat/FlatFieldNode.java | 22 +++ Robust/src/IR/Flat/FlatLiteralNode.java | 40 +++++ Robust/src/IR/Flat/FlatMethod.java | 70 ++++++++- Robust/src/IR/Flat/FlatNew.java | 16 ++ Robust/src/IR/Flat/FlatNode.java | 22 ++- Robust/src/IR/MethodDescriptor.java | 26 ++++ Robust/src/IR/State.java | 15 +- Robust/src/IR/SymbolTable.java | 15 +- Robust/src/IR/Tree/AssignmentNode.java | 12 ++ Robust/src/IR/Tree/BlockNode.java | 8 + Robust/src/IR/Tree/BuildIR.java | 14 +- Robust/src/IR/Tree/CastNode.java | 8 + Robust/src/IR/Tree/CreateObjectNode.java | 22 +++ Robust/src/IR/Tree/ExpressionNode.java | 4 + Robust/src/IR/Tree/FieldAccessNode.java | 14 ++ Robust/src/IR/Tree/LiteralNode.java | 7 +- Robust/src/IR/Tree/MethodInvokeNode.java | 24 +++ Robust/src/IR/Tree/SemanticCheck.java | 189 +++++++++++++++++++++++ Robust/src/IR/TypeDescriptor.java | 26 +++- Robust/src/IR/VarDescriptor.java | 4 + Robust/src/Main/Main.java | 5 + Robust/src/Parse/java14.cup | 15 +- Robust/src/t.test | 5 + 30 files changed, 771 insertions(+), 51 deletions(-) create mode 100644 Robust/src/IR/Flat/FlatCall.java create mode 100644 Robust/src/IR/Flat/FlatCastNode.java create mode 100644 Robust/src/IR/Flat/FlatFieldNode.java create mode 100644 Robust/src/IR/Flat/FlatLiteralNode.java create mode 100644 Robust/src/IR/Flat/FlatNew.java create mode 100644 Robust/src/IR/Tree/SemanticCheck.java diff --git a/Robust/src/IR/AssignOperation.java b/Robust/src/IR/AssignOperation.java index e8dce7de..2abd7c8e 100644 --- a/Robust/src/IR/AssignOperation.java +++ b/Robust/src/IR/AssignOperation.java @@ -23,6 +23,34 @@ public class AssignOperation { this.operation=parseOp(op); } + public Operation getBaseOp() { + switch(operation) { + case EQ: + return null; + case MULTEQ: + return new Operation(Operation.MULT); + case DIVEQ: + return new Operation(Operation.DIV); + case MODEQ: + return new Operation(Operation.MOD); + case PLUSEQ: + return new Operation(Operation.ADD); + case MINUSEQ: + return new Operation(Operation.SUB); + case LSHIFTEQ: + return new Operation(Operation.LEFTSHIFT); + case RSHIFTEQ: + return new Operation(Operation.RIGHTSHIFT); + case ANDEQ: + return new Operation(Operation.BIT_AND); + case XOREQ: + return new Operation(Operation.BIT_XOR); + case OREQ: + return new Operation(Operation.BIT_OR); + } + throw new Error(); + } + public static int parseOp(String st) { if (st.equals("eq")) return EQ; diff --git a/Robust/src/IR/ClassDescriptor.java b/Robust/src/IR/ClassDescriptor.java index 353ab00f..72b0802a 100644 --- a/Robust/src/IR/ClassDescriptor.java +++ b/Robust/src/IR/ClassDescriptor.java @@ -1,27 +1,40 @@ package IR; import java.util.*; import IR.Tree.*; +import IR.SymbolTable; import IR.FieldDescriptor; import IR.MethodDescriptor; import IR.NameDescriptor; -public class ClassDescriptor { - public ClassDescriptor() { - classname=null; +public class ClassDescriptor extends Descriptor { + public ClassDescriptor(String classname) { + super(classname); + this.classname=classname; superclass=null; - fields=new Vector(); - methods=new Vector(); + fields=new SymbolTable(); + methods=new SymbolTable(); } + String classname; - NameDescriptor superclass; + String superclass; Modifiers modifiers; - Vector fields; - Vector methods; + + SymbolTable fields; + SymbolTable methods; + public Iterator getMethods() { - return methods.iterator(); + return methods.getDescriptorsIterator(); + } + + public Iterator getFields() { + return fields.getDescriptorsIterator(); } + public SymbolTable getFieldTable() { + return fields; + } + public String printTree(State state) { int indent; String st=modifiers.toString()+"class "+classname; @@ -29,15 +42,16 @@ public class ClassDescriptor { st+="extends "+superclass.toString(); st+=" {\n"; indent=TreeNode.INDENT; - for(int i=0;i<fields.size();i++) { - FieldDescriptor fd=(FieldDescriptor)fields.get(i); + + for(Iterator it=getFields();it.hasNext();) { + FieldDescriptor fd=(FieldDescriptor)it.next(); st+=TreeNode.printSpace(indent)+fd.toString()+"\n"; } if (fields.size()>0) st+="\n"; - for(int i=0;i<methods.size();i++) { - MethodDescriptor md=(MethodDescriptor)methods.get(i); + for(Iterator it=getMethods();it.hasNext();) { + MethodDescriptor md=(MethodDescriptor)it.next(); st+=TreeNode.printSpace(indent)+md.toString()+" "; BlockNode bn=state.getMethodBody(md); st+=bn.printNode(indent)+"\n\n"; @@ -47,6 +61,8 @@ public class ClassDescriptor { } public void addField(FieldDescriptor fd) { + if (fields.contains(fd.getSymbol())) + throw new Error(fd.getSymbol()+" already defined"); fields.add(fd); } @@ -62,7 +78,7 @@ public class ClassDescriptor { classname=name; } - public void setSuper(NameDescriptor superclass) { + public void setSuper(String superclass) { this.superclass=superclass; } } diff --git a/Robust/src/IR/FieldDescriptor.java b/Robust/src/IR/FieldDescriptor.java index a0469d8f..ce57b627 100644 --- a/Robust/src/IR/FieldDescriptor.java +++ b/Robust/src/IR/FieldDescriptor.java @@ -25,6 +25,10 @@ public class FieldDescriptor extends Descriptor { this.uniqueid=count++; } + public TypeDescriptor getType() { + return td; + } + public String toString() { if (en==null) return modifier.toString()+td.toString()+" "+identifier+";"; diff --git a/Robust/src/IR/Flat/BuildFlat.java b/Robust/src/IR/Flat/BuildFlat.java index d14bc6a3..13735871 100644 --- a/Robust/src/IR/Flat/BuildFlat.java +++ b/Robust/src/IR/Flat/BuildFlat.java @@ -13,7 +13,7 @@ public class BuildFlat { } public void buildFlat() { - Iterator it=state.classset.iterator(); + Iterator it=state.getClassSymbolTable().getDescriptorsIterator(); while(it.hasNext()) { ClassDescriptor cn=(ClassDescriptor)it.next(); flattenClass(cn); @@ -56,27 +56,114 @@ public class BuildFlat { return flattenExpressionNode(en.getExpression(),tmp); } - private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) { - throw new Error(); + private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) { + TempDescriptor tmp=TempDescriptor.tempFactory("tocast"); + NodePair np=flattenExpressionNode(cn.getExpression(), tmp); + FlatCastNode fcn=new FlatCastNode(cn.getType(), tmp, out_temp); + np.getEnd().addNext(fcn); + return new NodePair(np.getBegin(),fcn); } - private NodePair flattenCastNode(CastNode cn,TempDescriptor out_temp) { - throw new Error(); + private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) { + FlatLiteralNode fln=new FlatLiteralNode(ln.getType(), ln.getValue(), out_temp); + return new NodePair(fln,fln); } + private NodePair flattenCreateObjectNode(CreateObjectNode con,TempDescriptor out_temp) { - throw new Error(); + TypeDescriptor td=con.getType(); + FlatNew fn=new FlatNew(td, out_temp); + TempDescriptor[] temps=new TempDescriptor[con.numArgs()]; + FlatNode last=fn; + //Build arguments + for(int i=0;i<con.numArgs();i++) { + ExpressionNode en=con.getArg(i); + TempDescriptor tmp=TempDescriptor.tempFactory("arg"); + temps[i]=tmp; + NodePair np=flattenExpressionNode(en, tmp); + last.addNext(np.getBegin()); + last=np.getEnd(); + } + MethodDescriptor md=con.getConstructor(); + //Call to constructor + FlatCall fc=new FlatCall(md, null, out_temp, temps); + last.addNext(fc); + return new NodePair(fn,fc); } - private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) { - throw new Error(); + private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) { + TempDescriptor[] temps=new TempDescriptor[min.numArgs()]; + FlatNode first=null; + FlatNode last=null; + TempDescriptor thisarg=null; + + if (min.getExpression()==null) { + thisarg=TempDescriptor.tempFactory("thisarg"); + NodePair np=flattenExpressionNode(min.getExpression(),temps[0]); + first=np.getBegin(); + last=np.getEnd(); + } + + //Build arguments + for(int i=0;i<min.numArgs();i++) { + ExpressionNode en=min.getArg(i); + TempDescriptor td=TempDescriptor.tempFactory("arg"); + temps[i]=td; + NodePair np=flattenExpressionNode(en, td); + if (first==null) + first=np.getBegin(); + else + last.addNext(np.getBegin()); + last=np.getEnd(); + } + + MethodDescriptor md=min.getMethod(); + + //Call to constructor + FlatCall fc=new FlatCall(md, out_temp, thisarg, temps); + if (first==null) { + first=fc; + } else + last.addNext(fc); + return new NodePair(first,fc); } - private NodePair flattenLiteralNode(LiteralNode ln,TempDescriptor out_temp) { - throw new Error(); + private NodePair flattenFieldAccessNode(FieldAccessNode fan,TempDescriptor out_temp) { + TempDescriptor tmp=TempDescriptor.tempFactory("temp"); + NodePair npe=flattenExpressionNode(fan.getExpression(),tmp); + FlatFieldNode fn=new FlatFieldNode(fan.getField(),tmp,out_temp); + npe.getEnd().addNext(fn); + return new NodePair(npe.getBegin(),fn); } - private NodePair flattenMethodInvokeNode(MethodInvokeNode min,TempDescriptor out_temp) { + private NodePair flattenAssignmentNode(AssignmentNode an,TempDescriptor out_temp) { + // Two cases: + // left side is variable + // left side is field + + Operation base=an.getOperation().getBaseOp(); + TempDescriptor src_tmp=TempDescriptor.tempFactory("src"); + NodePair np_src=flattenExpressionNode(an.getSrc(),src_tmp); + FlatNode last=np_src.getEnd(); + if (base!=null) { + TempDescriptor src_tmp2=TempDescriptor.tempFactory("tmp"); + NodePair np_dst_init=flattenExpressionNode(an.getDest(),src_tmp2); + last.addNext(np_dst_init.getBegin()); + TempDescriptor dst_tmp=TempDescriptor.tempFactory("dst_tmp"); + FlatOpNode fon=new FlatOpNode(dst_tmp, src_tmp,src_tmp2, base); + np_dst_init.getEnd().addNext(fon); + last=fon; + src_tmp=dst_tmp; + } + + if (an.getDest().kind()==Kind.FieldAccessNode) { + FieldAccessNode fan=(FieldAccessNode)an.getDest(); + + + // Need to assign field + } else if (an.getDest().kind()==Kind.NameNode) { + + } throw new Error(); } diff --git a/Robust/src/IR/Flat/FlatCall.java b/Robust/src/IR/Flat/FlatCall.java new file mode 100644 index 00000000..057cb3c2 --- /dev/null +++ b/Robust/src/IR/Flat/FlatCall.java @@ -0,0 +1,26 @@ +package IR.Flat; +import IR.MethodDescriptor; + +public class FlatCall extends FlatNode { + TempDescriptor args[]; + TempDescriptor this_temp; + TempDescriptor dst; + MethodDescriptor method; + + public FlatCall(MethodDescriptor md, TempDescriptor dst, TempDescriptor this_temp, TempDescriptor[] args) { + this.method=md; + this.dst=dst; + this.this_temp=this_temp; + this.args=args; + } + + public String toString() { + String st=dst+"="+method.toString()+"("+this_temp; + for(int i=0;i<args.length;i++) { + st+=args[i].toString(); + if ((i+1)<args.length) + st+=", "; + } + return st+")"; + } +} diff --git a/Robust/src/IR/Flat/FlatCastNode.java b/Robust/src/IR/Flat/FlatCastNode.java new file mode 100644 index 00000000..2b3e45a7 --- /dev/null +++ b/Robust/src/IR/Flat/FlatCastNode.java @@ -0,0 +1,18 @@ +package IR.Flat; +import IR.TypeDescriptor; + +public class FlatCastNode extends FlatNode { + TempDescriptor src; + TempDescriptor dst; + TypeDescriptor type; + + public FlatCastNode(TypeDescriptor type, TempDescriptor src, TempDescriptor dst) { + this.type=type; + this.src=src; + this.dst=dst; + } + + public String toString() { + return dst.toString()+"=("+type.toString()+")"+src.toString(); + } +} diff --git a/Robust/src/IR/Flat/FlatCondBranch.java b/Robust/src/IR/Flat/FlatCondBranch.java index fa0f9817..9ebee1ee 100644 --- a/Robust/src/IR/Flat/FlatCondBranch.java +++ b/Robust/src/IR/Flat/FlatCondBranch.java @@ -10,10 +10,20 @@ public class FlatCondBranch extends FlatNode { public void addTrueNext(FlatNode n) { next.setElementAt(n,0); + n.addPrev(this); } public void addFalseNext(FlatNode n) { next.setElementAt(n,1); + n.addPrev(this); + } + + public String toString() { + return "conditional branch"; + } + + public String toString(String negjump) { + return "if (!"+test_cond.toString()+") goto "+negjump; } public void addNext(FlatNode n) { diff --git a/Robust/src/IR/Flat/FlatFieldNode.java b/Robust/src/IR/Flat/FlatFieldNode.java new file mode 100644 index 00000000..79d7f6a4 --- /dev/null +++ b/Robust/src/IR/Flat/FlatFieldNode.java @@ -0,0 +1,22 @@ +package IR.Flat; +import IR.FieldDescriptor; + +public class FlatFieldNode extends FlatNode { + TempDescriptor src; + TempDescriptor dst; + FieldDescriptor field; + + public FlatFieldNode(FieldDescriptor field, TempDescriptor src, TempDescriptor dst) { + this.field=field; + this.src=src; + this.dst=dst; + } + + public FieldDescriptor getField() { + return field; + } + + public String toString() { + return dst.toString()+"="+src.toString()+"."+field.toString(); + } +} diff --git a/Robust/src/IR/Flat/FlatLiteralNode.java b/Robust/src/IR/Flat/FlatLiteralNode.java new file mode 100644 index 00000000..b7aa9a91 --- /dev/null +++ b/Robust/src/IR/Flat/FlatLiteralNode.java @@ -0,0 +1,40 @@ +package IR.Flat; +import IR.TypeDescriptor; + +public class FlatLiteralNode extends FlatNode { + Object value; + TypeDescriptor type; + TempDescriptor dst; + + public FlatLiteralNode(TypeDescriptor type, Object o, TempDescriptor dst) { + this.type=type; + value=o; + this.dst=dst; + } + + public Object getValue() { + return value; + } + + public String printNode(int indent) { + /* if (type==NULL) + return dst+"=null"; + if (type==STRING) { + return dst+"="+'"'+escapeString(value.toString())+'"'; + }*/ + //return dst+"="+"/*"+getType()+ "*/"+value.toString(); + return ""; + } + private static String escapeString(String st) { + String new_st=""; + for(int i=0;i<st.length();i++) { + char x=st.charAt(i); + if (x=='\n') + new_st+="\\n"; + else if (x=='"') + new_st+="'"+'"'+"'"; + else new_st+=x; + } + return new_st; + } +} diff --git a/Robust/src/IR/Flat/FlatMethod.java b/Robust/src/IR/Flat/FlatMethod.java index 53c4e6c9..7845df9f 100644 --- a/Robust/src/IR/Flat/FlatMethod.java +++ b/Robust/src/IR/Flat/FlatMethod.java @@ -1,5 +1,6 @@ package IR.Flat; import IR.MethodDescriptor; +import java.util.*; public class FlatMethod extends FlatNode { FlatNode method_entry; @@ -11,6 +12,73 @@ public class FlatMethod extends FlatNode { } public String toString() { - return method.toString()+"\n"+method_entry.toString(); + return method.toString(); } + + public String printMethod() { + String st=""; + HashSet tovisit=new HashSet(); + HashSet visited=new HashSet(); + int labelindex=0; + Hashtable nodetolabel=new Hashtable(); + tovisit.add(method_entry); + FlatNode current_node=null; + //Assign labels 1st + //Node needs a label if it is + while(!tovisit.isEmpty()) { + FlatNode fn=(FlatNode)tovisit.iterator().next(); + tovisit.remove(fn); + visited.add(fn); + for(int i=0;i<fn.numNext();i++) { + FlatNode nn=fn.getNext(i); + if(i>0) { + //1) Edge >1 of node + nodetolabel.put(nn,new Integer(labelindex++)); + } + if (!visited.contains(nn)) { + tovisit.add(nn); + } else { + //2) Join point + nodetolabel.put(nn,new Integer(labelindex++)); + } + } + } + + //Do the actual printing + tovisit=new HashSet(); + visited=new HashSet(); + tovisit.add(method_entry); + while(!tovisit.isEmpty()) { + if (current_node==null) { + current_node=(FlatNode)tovisit.iterator().next(); + tovisit.remove(current_node); + } + visited.add(current_node); + if (nodetolabel.containsKey(current_node)) + st+="L"+nodetolabel.get(current_node)+":\n"; + st+=current_node.toString(); + if (current_node.numNext()==0) { + current_node=null; + } else if(current_node.numNext()==1) { + FlatNode nextnode=current_node.getNext(0); + if (visited.contains(nextnode)) { + st+="goto L"+nodetolabel.get(nextnode)+"\n"; + current_node=null; + } else + current_node=nextnode; + } else if (current_node.numNext()==2) { + /* Branch */ + st+=((FlatCondBranch)current_node).toString("L"+nodetolabel.get(current_node.getNext(1))); + if (visited.contains(current_node.getNext(0))) { + st+="goto L"+nodetolabel.get(current_node.getNext(0))+"\n"; + current_node=null; + } else + current_node=current_node.getNext(0); + if (!visited.contains(current_node.getNext(1))) + tovisit.add(current_node.getNext(1)); + } else throw new Error(); + } + return st; + } + } diff --git a/Robust/src/IR/Flat/FlatNew.java b/Robust/src/IR/Flat/FlatNew.java new file mode 100644 index 00000000..e8aeaa63 --- /dev/null +++ b/Robust/src/IR/Flat/FlatNew.java @@ -0,0 +1,16 @@ +package IR.Flat; +import IR.TypeDescriptor; + +public class FlatNew extends FlatNode { + TempDescriptor dst; + TypeDescriptor type; + + public FlatNew(TypeDescriptor type, TempDescriptor dst) { + this.type=type; + this.dst=dst; + } + + public String toString() { + return dst.toString()+"= NEW "+type.toString(); + } +} diff --git a/Robust/src/IR/Flat/FlatNode.java b/Robust/src/IR/Flat/FlatNode.java index b53eb433..4824875a 100644 --- a/Robust/src/IR/Flat/FlatNode.java +++ b/Robust/src/IR/Flat/FlatNode.java @@ -2,13 +2,31 @@ package IR.Flat; import java.util.Vector; public class FlatNode { - Vector next; - + protected Vector next; + protected Vector prev; public String toString() { throw new Error(); } + public int numNext() { + return next.size(); + } + public FlatNode getNext(int i) { + return (FlatNode) next.get(i); + } + + public int numPrev() { + return prev.size(); + } + public FlatNode getPrev(int i) { + return (FlatNode) prev.get(i); + } + public void addNext(FlatNode n) { next.add(n); + n.addPrev(this); + } + protected void addPrev(FlatNode p) { + prev.add(p); } } diff --git a/Robust/src/IR/MethodDescriptor.java b/Robust/src/IR/MethodDescriptor.java index a7df7866..28eb9724 100644 --- a/Robust/src/IR/MethodDescriptor.java +++ b/Robust/src/IR/MethodDescriptor.java @@ -16,6 +16,7 @@ public class MethodDescriptor extends Descriptor { protected String identifier; protected Vector param_name; protected Vector param_type; + protected SymbolTable paramtable; public MethodDescriptor(Modifiers m, TypeDescriptor rt, String identifier) { super(identifier); @@ -26,10 +27,35 @@ public class MethodDescriptor extends Descriptor { this.uniqueid=count++; param_name=new Vector(); param_type=new Vector(); + paramtable=new SymbolTable(); } + public TypeDescriptor getReturnType() { + return returntype; + } + + public SymbolTable getParameterTable() { + return paramtable; + } + public void addParameter(TypeDescriptor type, String paramname) { param_name.add(paramname); param_type.add(type); + if (paramtable.getFromSameScope(paramname)!=null) { + throw new Error("Parameter "+paramname+" already defined"); + } + paramtable.add(paramname,type); + } + + public int numParameters() { + return param_name.size(); + } + + public String getParamName(int i) { + return (String) param_name.get(i); + } + + public TypeDescriptor getParamType(int i) { + return (TypeDescriptor) param_type.get(i); } public String toString() { diff --git a/Robust/src/IR/State.java b/Robust/src/IR/State.java index 1bd8067e..a83b1af7 100644 --- a/Robust/src/IR/State.java +++ b/Robust/src/IR/State.java @@ -6,16 +6,14 @@ import java.util.*; public class State { public State(ParseNode parsetree) { - globals=new SymbolTable(); this.parsetree=parsetree; - this.classset=new HashSet(); + this.classes=new SymbolTable(); this.treemethodmap=new Hashtable(); this.flatmethodmap=new Hashtable(); } - public SymbolTable globals; + public SymbolTable classes; public ParseNode parsetree; - public HashSet classset; public Hashtable treemethodmap; public Hashtable flatmethodmap; @@ -30,12 +28,17 @@ public class State { } public void addClass(ClassDescriptor tdn) { - classset.add(tdn); + if (classes.contains(tdn.getSymbol())) + throw new Error("Class "+tdn.getSymbol()+" defined twice"); + classes.add(tdn); } public BlockNode getMethodBody(MethodDescriptor md) { return (BlockNode)treemethodmap.get(md); - + } + + public SymbolTable getClassSymbolTable() { + return classes; } public FlatMethod getMethodFlat(MethodDescriptor md) { diff --git a/Robust/src/IR/SymbolTable.java b/Robust/src/IR/SymbolTable.java index 7203183e..a7218ffd 100644 --- a/Robust/src/IR/SymbolTable.java +++ b/Robust/src/IR/SymbolTable.java @@ -17,17 +17,12 @@ public class SymbolTable { this.parent = parent; } - //public void add(String name, Descriptor d) { - //table.put(name, d); - //} - public void add(Descriptor d) { - table.put(d.getSymbol(), d); + add(d.getSymbol(), d); } public void add(String name, Descriptor d) { table.put(name, d); - } public void dump() { @@ -59,10 +54,18 @@ public class SymbolTable { return table.keys(); } + public Iterator getNamesIterator() { + return table.keySet().iterator(); + } + public Enumeration getDescriptors() { return table.elements(); } + public Iterator getDescriptorsIterator() { + return table.values().iterator(); + } + public Iterator descriptors() { return table.values().iterator(); } diff --git a/Robust/src/IR/Tree/AssignmentNode.java b/Robust/src/IR/Tree/AssignmentNode.java index f30ccb56..31f5b4fa 100644 --- a/Robust/src/IR/Tree/AssignmentNode.java +++ b/Robust/src/IR/Tree/AssignmentNode.java @@ -11,6 +11,18 @@ public class AssignmentNode extends ExpressionNode { right=r; this.op=op; } + + public ExpressionNode getDest() { + return left; + } + + public ExpressionNode getSrc() { + return right; + } + + public AssignOperation getOperation() { + return op; + } public String printNode(int indent) { return left.printNode(indent)+" "+op.toString()+" "+right.printNode(indent); diff --git a/Robust/src/IR/Tree/BlockNode.java b/Robust/src/IR/Tree/BlockNode.java index 94179eea..62b3b67d 100644 --- a/Robust/src/IR/Tree/BlockNode.java +++ b/Robust/src/IR/Tree/BlockNode.java @@ -1,15 +1,23 @@ package IR.Tree; import java.util.Vector; +import IR.*; public class BlockNode extends TreeNode { Vector blockstatements; int printStyle=0; + protected SymbolTable table; + public final static int NORMAL=0; public final static int NOBRACES=1; public final static int EXPRLIST=2; public BlockNode() { blockstatements=new Vector(); + table=new SymbolTable(); + } + + public SymbolTable getVarTable() { + return table; } public void addBlockStatement(BlockStatementNode bsn) { diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index 0dafcc9d..0995b447 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -29,10 +29,12 @@ public class BuildIR { public ClassDescriptor parseTypeDecl(ParseNode pn) { if (isNode(pn, "class_declaration")) { - ClassDescriptor cn=new ClassDescriptor(); - cn.setName(pn.getChild("name").getTerminal()); + ClassDescriptor cn=new ClassDescriptor(pn.getChild("name").getTerminal()); if (!isEmpty(pn.getChild("super").getTerminal())) { /* parse superclass name */ + ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name"); + NameDescriptor nd=parseName(snn); + cn.setSuper(nd.toString()); } cn.setModifiers(parseModifiersList(pn.getChild("modifiers"))); parseClassBody(cn, pn.getChild("classbody")); @@ -315,6 +317,14 @@ public class BuildIR { ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild()); BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild()); blockstatements.add(new LoopNode(init,condition,update,body)); + } else if (isNode(pn,"whilestatement")) { + ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild()); + BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild()); + blockstatements.add(new LoopNode(condition,body,LoopNode.WHILELOOP)); + } else if (isNode(pn,"dowhilestatement")) { + ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild()); + BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild()); + blockstatements.add(new LoopNode(condition,body,LoopNode.DOWHILELOOP)); } else { System.out.println("---------------"); System.out.println(pn.PPrint(3,true)); diff --git a/Robust/src/IR/Tree/CastNode.java b/Robust/src/IR/Tree/CastNode.java index e4f82ec4..4e7dd8dd 100644 --- a/Robust/src/IR/Tree/CastNode.java +++ b/Robust/src/IR/Tree/CastNode.java @@ -18,6 +18,14 @@ public class CastNode extends ExpressionNode { this.etd=type; } + public TypeDescriptor getType() { + return td; + } + + public ExpressionNode getExpression() { + return exp; + } + public String printNode(int indentlevel) { if (etd==null) return "("+td.toString()+")"+exp.printNode(indentlevel); diff --git a/Robust/src/IR/Tree/CreateObjectNode.java b/Robust/src/IR/Tree/CreateObjectNode.java index 99b6783b..1d28efcf 100644 --- a/Robust/src/IR/Tree/CreateObjectNode.java +++ b/Robust/src/IR/Tree/CreateObjectNode.java @@ -1,10 +1,12 @@ package IR.Tree; import java.util.Vector; import IR.TypeDescriptor; +import IR.MethodDescriptor; public class CreateObjectNode extends ExpressionNode { TypeDescriptor td; Vector argumentlist; + MethodDescriptor md; public CreateObjectNode(TypeDescriptor type) { td=type; @@ -14,6 +16,26 @@ public class CreateObjectNode extends ExpressionNode { argumentlist.add(en); } + public void setConstructor(MethodDescriptor md) { + this.md=md; + } + + public MethodDescriptor getConstructor() { + return md; + } + + public TypeDescriptor getType() { + return td; + } + + public int numArgs() { + return argumentlist.size(); + } + + public ExpressionNode getArg(int i) { + return (ExpressionNode) argumentlist.get(i); + } + public String printNode(int indent) { String st="new "+td.toString()+"("; for(int i=0;i<argumentlist.size();i++) { diff --git a/Robust/src/IR/Tree/ExpressionNode.java b/Robust/src/IR/Tree/ExpressionNode.java index 058d6294..a2cab155 100644 --- a/Robust/src/IR/Tree/ExpressionNode.java +++ b/Robust/src/IR/Tree/ExpressionNode.java @@ -1,6 +1,10 @@ package IR.Tree; +import IR.TypeDescriptor; public class ExpressionNode extends TreeNode { + public TypeDescriptor getType() { + throw new Error(); + } public String printNode(int indentlevel) { return null; diff --git a/Robust/src/IR/Tree/FieldAccessNode.java b/Robust/src/IR/Tree/FieldAccessNode.java index a2284d19..eee8ffb4 100644 --- a/Robust/src/IR/Tree/FieldAccessNode.java +++ b/Robust/src/IR/Tree/FieldAccessNode.java @@ -1,14 +1,28 @@ package IR.Tree; +import IR.FieldDescriptor; public class FieldAccessNode extends ExpressionNode { ExpressionNode left; String fieldname; + FieldDescriptor field; public FieldAccessNode(ExpressionNode l, String field) { fieldname=field; left=l; } + public void setField(FieldDescriptor fd) { + field=fd; + } + + public FieldDescriptor getField() { + return field; + } + + public ExpressionNode getExpression() { + return left; + } + public String printNode(int indent) { return left.printNode(indent)+"."+fieldname; } diff --git a/Robust/src/IR/Tree/LiteralNode.java b/Robust/src/IR/Tree/LiteralNode.java index 4f273fde..db1f90cb 100644 --- a/Robust/src/IR/Tree/LiteralNode.java +++ b/Robust/src/IR/Tree/LiteralNode.java @@ -8,7 +8,6 @@ public class LiteralNode extends ExpressionNode { public final static int STRING=5; public final static int NULL=6; - Object value; int type; @@ -17,6 +16,10 @@ public class LiteralNode extends ExpressionNode { value=o; } + public Object getValue() { + return value; + } + private static int parseType(String type) { if (type.equals("integer")) return INTEGER; @@ -33,7 +36,7 @@ public class LiteralNode extends ExpressionNode { else throw new Error(); } - private String getType() { + private String getStringType() { if (type==INTEGER) return "integer"; else if (type==FLOAT) diff --git a/Robust/src/IR/Tree/MethodInvokeNode.java b/Robust/src/IR/Tree/MethodInvokeNode.java index 705b316c..08ad56f9 100644 --- a/Robust/src/IR/Tree/MethodInvokeNode.java +++ b/Robust/src/IR/Tree/MethodInvokeNode.java @@ -1,18 +1,21 @@ package IR.Tree; import java.util.Vector; import IR.NameDescriptor; +import IR.MethodDescriptor; public class MethodInvokeNode extends ExpressionNode { NameDescriptor nd; Vector argumentlist; String methodid; ExpressionNode en; + MethodDescriptor md; public MethodInvokeNode(NameDescriptor name) { nd=name; argumentlist=new Vector(); methodid=null; en=null; + md=null; } public MethodInvokeNode(String methodid, ExpressionNode exp) { @@ -20,12 +23,33 @@ public class MethodInvokeNode extends ExpressionNode { this.en=exp; nd=null; argumentlist=new Vector(); + md=null; + } + + public ExpressionNode getExpression() { + return en; + } + + public void setMethod(MethodDescriptor md) { + this.md=md; + } + + public MethodDescriptor getMethod() { + return md; } public void addArgument(ExpressionNode en) { argumentlist.add(en); } + public int numArgs() { + return argumentlist.size(); + } + + public ExpressionNode getArg(int i) { + return (ExpressionNode) argumentlist.get(i); + } + public String printNode(int indent) { String st; if (nd==null) { diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java new file mode 100644 index 00000000..9c8294b7 --- /dev/null +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -0,0 +1,189 @@ +package IR.Tree; + +import java.util.*; +import IR.*; + +public class SemanticCheck { + State state; + + public SemanticCheck(State state) { + this.state=state; + } + + public void semanticCheck() { + SymbolTable classtable=state.getClassSymbolTable(); + Iterator it=classtable.getDescriptorsIterator(); + while(it.hasNext()) { + ClassDescriptor cd=(ClassDescriptor)it.next(); + System.out.println("Checking class: "+cd); + for(Iterator field_it=cd.getFields();field_it.hasNext();) { + FieldDescriptor fd=(FieldDescriptor)field_it.next(); + System.out.println("Checking field: "+fd); + checkField(cd,fd); + } + + for(Iterator method_it=cd.getMethods();method_it.hasNext();) { + MethodDescriptor md=(MethodDescriptor)method_it.next(); + checkMethod(cd,md); + } + } + } + + public void checkTypeDescriptor(TypeDescriptor td) { + if (td.isPrimitive()) + return; /* Done */ + if (td.isClass()) { + String name=td.toString(); + ClassDescriptor field_cd=(ClassDescriptor)state.getClassSymbolTable().get(name); + if (field_cd==null) + throw new Error("Undefined class "+name); + td.setClassDescriptor(field_cd); + return; + } + throw new Error(); + } + + public void checkField(ClassDescriptor cd, FieldDescriptor fd) { + checkTypeDescriptor(fd.getType()); + } + + public void checkMethod(ClassDescriptor cd, MethodDescriptor md) { + /* Check return type */ + if (!md.getReturnType().isVoid()) + checkTypeDescriptor(md.getReturnType()); + for(int i=0;i<md.numParameters();i++) { + TypeDescriptor param_type=md.getParamType(i); + checkTypeDescriptor(param_type); + } + BlockNode bn=state.getMethodBody(md); + /* Link the naming environments */ + md.getParameterTable().setParent(cd.getFieldTable()); + checkBlockNode(md, md.getParameterTable(),bn); + } + + public void checkBlockNode(MethodDescriptor md, SymbolTable nametable, BlockNode bn) { + /* Link in the naming environment */ + bn.getVarTable().setParent(nametable); + for(int i=0;i<bn.size();i++) { + BlockStatementNode bsn=bn.get(i); + checkBlockStatementNode(md, bn.getVarTable(),bsn); + } + } + + public void checkBlockStatementNode(MethodDescriptor md, SymbolTable nametable, BlockStatementNode bsn) { + switch(bsn.kind()) { + case Kind.BlockExpressionNode: + checkBlockExpressionNode(md, nametable,(BlockExpressionNode)bsn); + return; + + case Kind.DeclarationNode: + checkDeclarationNode(md, nametable, (DeclarationNode)bsn); + return; + + case Kind.IfStatementNode: + checkIfStatementNode(md, nametable, (IfStatementNode)bsn); + return; + + case Kind.LoopNode: + checkLoopNode(md, nametable, (LoopNode)bsn); + return; + + case Kind.ReturnNode: + checkReturnNode(md, nametable, (ReturnNode)bsn); + return; + + case Kind.SubBlockNode: + checkSubBlockNode(md, nametable, (SubBlockNode)bsn); + return; + } + throw new Error(); + } + + void checkBlockExpressionNode(MethodDescriptor md, SymbolTable nametable, BlockExpressionNode ben) { + checkExpressionNode(md, nametable, ben.getExpression(), null); + } + + void checkDeclarationNode(MethodDescriptor md, SymbolTable nametable, DeclarationNode dn) { + VarDescriptor vd=dn.getVarDescriptor(); + checkTypeDescriptor(vd.getType()); + Descriptor d=nametable.get(vd.getSymbol()); + if ((d==null)|| + (d instanceof FieldDescriptor)) { + nametable.add(vd); + } else + throw new Error(vd.getSymbol()+" defined a second time"); + checkExpressionNode(md, nametable, dn.getExpression(), vd.getType()); + } + + void checkSubBlockNode(MethodDescriptor md, SymbolTable nametable, SubBlockNode sbn) { + checkBlockNode(md, nametable, sbn.getBlockNode()); + } + + void checkReturnNode(MethodDescriptor md, SymbolTable nametable, ReturnNode rn) { + checkExpressionNode(md, nametable, rn.getReturnExpression(), md.getReturnType()); + } + + void checkIfStatementNode(MethodDescriptor md, SymbolTable nametable, IfStatementNode isn) { + checkExpressionNode(md, nametable, isn.getCondition(), new TypeDescriptor(TypeDescriptor.BOOLEAN)); + checkBlockNode(md, nametable, isn.getTrueBlock()); + checkBlockNode(md, nametable, isn.getFalseBlock()); + } + + void checkExpressionNode(MethodDescriptor md, SymbolTable nametable, ExpressionNode en, TypeDescriptor td) { + switch(en.kind()) { + case Kind.AssignmentNode: + checkAssignmentNode(md,nametable,(AssignmentNode)en,td); + return; + case Kind.CastNode: + checkCastNode(md,nametable,(CastNode)en,td); + return; + case Kind.CreateObjectNode: + checkCreateObjectNode(md,nametable,(CreateObjectNode)en,td); + return; + case Kind.FieldAccessNode: + checkFieldAccessNode(md,nametable,(FieldAccessNode)en,td); + return; + case Kind.LiteralNode: + checkLiteralNode(md,nametable,(LiteralNode)en,td); + return; + case Kind.MethodInvokeNode: + checkMethodInvokeNode(md,nametable,(MethodInvokeNode)en,td); + return; + case Kind.NameNode: + checkNameNode(md,nametable,(NameNode)en,td); + return; + case Kind.OpNode: + checkOpNode(md,nametable,(OpNode)en,td); + return; + } + throw new Error(); + } + + void checkAssignmentNode(MethodDescriptor md, SymbolTable nametable, AssignmentNode an, TypeDescriptor td) { + + } + + void checkCastNode(MethodDescriptor md, SymbolTable nametable, CastNode cn, TypeDescriptor td) { + } + + void checkCreateObjectNode(MethodDescriptor md, SymbolTable nametable, CreateObjectNode con, TypeDescriptor td) { + } + + void checkFieldAccessNode(MethodDescriptor md, SymbolTable nametable, FieldAccessNode fan, TypeDescriptor td) { + } + + void checkLiteralNode(MethodDescriptor md, SymbolTable nametable, LiteralNode ln, TypeDescriptor td) { + } + + void checkMethodInvokeNode(MethodDescriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) { + } + + void checkNameNode(MethodDescriptor md, SymbolTable nametable, NameNode nn, TypeDescriptor td) { + } + + void checkOpNode(MethodDescriptor md, SymbolTable nametable, OpNode on,TypeDescriptor td) { + } + + void checkLoopNode(MethodDescriptor md, SymbolTable nametable, LoopNode ln) { + } +} diff --git a/Robust/src/IR/TypeDescriptor.java b/Robust/src/IR/TypeDescriptor.java index e7a79eef..1832c571 100644 --- a/Robust/src/IR/TypeDescriptor.java +++ b/Robust/src/IR/TypeDescriptor.java @@ -16,16 +16,36 @@ public class TypeDescriptor extends Descriptor { public static final int FLOAT=7; public static final int DOUBLE=8; public static final int VOID=9; - public static final int CLASS=10; + public static final int NULL=10; + public static final int CLASS=11; + int type; NameDescriptor name_desc; - + ClassDescriptor class_desc; + + public void setClassDescriptor(ClassDescriptor cd) { + class_desc=cd; + } + + public boolean isVoid() { + return type==VOID; + } + + public boolean isPrimitive() { + return ((type>=BYTE)&&(type<=DOUBLE)); + } + + public boolean isClass() { + return type==CLASS; + } + public TypeDescriptor(NameDescriptor name) { super(name.toString()); this.type=CLASS; this.name_desc=name; + this.class_desc=null; } public TypeDescriptor(int t) { @@ -59,6 +79,8 @@ public class TypeDescriptor extends Descriptor { return "double"; else if (type==VOID) return "void"; + else if (type==NULL) + return "null"; else throw new Error(); } } diff --git a/Robust/src/IR/VarDescriptor.java b/Robust/src/IR/VarDescriptor.java index d8726f28..42038b2a 100644 --- a/Robust/src/IR/VarDescriptor.java +++ b/Robust/src/IR/VarDescriptor.java @@ -25,6 +25,10 @@ public class VarDescriptor extends Descriptor { return identifier; } + public TypeDescriptor getType() { + return td; + } + public String toString() { return td.toString()+" "+identifier; } diff --git a/Robust/src/Main/Main.java b/Robust/src/Main/Main.java index 8eebe0a1..e9d89b96 100644 --- a/Robust/src/Main/Main.java +++ b/Robust/src/Main/Main.java @@ -5,6 +5,7 @@ import java.io.BufferedReader; import java.io.FileReader; import IR.Tree.ParseNode; import IR.Tree.BuildIR; +import IR.Tree.SemanticCheck; import IR.Flat.BuildFlat; import IR.State; @@ -21,8 +22,12 @@ public class Main { ParseNode p=(ParseNode) g./*debug_*/parse().value; // System.out.println(p.PPrint(2,true)); State state=new State(p); + BuildIR bir=new BuildIR(state); bir.buildtree(); + + SemanticCheck sc=new SemanticCheck(state); + sc.semanticCheck(); BuildFlat bf=new BuildFlat(state); bf.buildFlat(); diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup index 74945097..761df786 100644 --- a/Robust/src/Parse/java14.cup +++ b/Robust/src/Parse/java14.cup @@ -178,7 +178,7 @@ non terminal ParseNode if_then_else_statement, if_then_else_statement_no_short_i //non terminal ParseNode switch_block_statement_group; //non terminal ParseNode switch_labels, switch_label; non terminal ParseNode while_statement, while_statement_no_short_if; -//non terminal ParseNode do_statement; +non terminal ParseNode do_statement; non terminal ParseNode for_statement, for_statement_no_short_if; non terminal ParseNode for_init_opt, for_init; non terminal ParseNode for_update_opt, for_update; @@ -774,7 +774,7 @@ statement_without_trailing_substatement ::= | empty_statement:st {: RESULT=st; :} | expression_statement:st {: RESULT=st; :} // | switch_statement -// | do_statement + | do_statement | break_statement:st {: RESULT=st; :} | continue_statement:st {: RESULT=st; :} | return_statement:st {: RESULT=st; :} @@ -876,9 +876,14 @@ while_statement_no_short_if ::= RESULT=pn; :} ; -//do_statement ::= -// DO statement WHILE LPAREN expression RPAREN SEMICOLON -// ; +do_statement ::= + DO statement:st WHILE LPAREN expression:exp RPAREN SEMICOLON {: + ParseNode pn=new ParseNode("dowhilestatement"); + pn.addChild("condition").addChild(exp); + pn.addChild("statement").addChild(st); + RESULT=pn; + :} + ; for_statement ::= FOR LPAREN for_init_opt:init SEMICOLON expression_opt:exp SEMICOLON for_update_opt:update RPAREN statement:st {: diff --git a/Robust/src/t.test b/Robust/src/t.test index 9e40fa59..1e99ef98 100644 --- a/Robust/src/t.test +++ b/Robust/src/t.test @@ -216,3 +216,8 @@ public class ParseNode { } +public class String {} + +public class ParseNodeVector {} + +public class Object {} -- 2.34.1