From 10832818dfeb5482be4982182418cf7f497a4a7d Mon Sep 17 00:00:00 2001 From: jzhou Date: Fri, 11 Nov 2011 21:08:41 +0000 Subject: [PATCH] Make the compiler to support super.X/L.super.X which access super class' fields. We might still not be able to correctly support access to super class' methods like super.foo(). Also fix another nested class bug. Previously the unit test StaticInnerClassTest was broken because of newly added inner class support. Note that nested class (static inner class) should NOT have reference to its surrounding class in its constructor as it is static and can be created without any outer class instance. --- Robust/src/IR/Tree/BuildIR.java | 19 +++++++++++++++++++ Robust/src/IR/Tree/FieldAccessNode.java | 10 ++++++++++ Robust/src/IR/Tree/NameNode.java | 10 ++++++++++ Robust/src/IR/Tree/SemanticCheck.java | 17 +++++++++++++---- Robust/src/Parse/java14.cup | 13 +++++++++++-- Robust/src/Tests/DoTests | 1 + Robust/src/Tests/inner.java | 3 +++ Robust/src/Tests/output/inner.output.goal | 12 ++++++++++++ 8 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 Robust/src/Tests/output/inner.output.goal diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index a6005bd3..6f3ed520 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -636,6 +636,9 @@ private void addOuterClassParam( ClassDescriptor cn, int depth ) for(Iterator it=cn.getInnerClasses(); it.hasNext(); ) { ClassDescriptor icd=(ClassDescriptor)it.next(); + if(icd.isStatic()) { + continue; + } //iterate over all ctors of I.Cs and add a new param for(Iterator method_it=icd.getMethods(); method_it.hasNext(); ) { @@ -1240,6 +1243,22 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth ) FieldAccessNode fan=new FieldAccessNode(en,fieldname); fan.setNumLine(pn.getLine()); return fan; + } else if (isNode(pn,"superfieldaccess")) { + ExpressionNode en=new NameNode(new NameDescriptor("super")); + String fieldname=pn.getChild("field").getTerminal(); + + FieldAccessNode fan=new FieldAccessNode(en,fieldname); + fan.setNumLine(pn.getLine()); + return fan; + } else if (isNode(pn,"supernamefieldaccess")) { + ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild()); + ExpressionNode exp = new FieldAccessNode(en, "super"); + exp.setNumLine(pn.getLine()); + String fieldname=pn.getChild("field").getTerminal(); + + FieldAccessNode fan=new FieldAccessNode(exp,fieldname); + fan.setNumLine(pn.getLine()); + return fan; } else if (isNode(pn,"arrayaccess")) { ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild()); ExpressionNode index=parseExpression(pn.getChild("index").getFirstChild()); diff --git a/Robust/src/IR/Tree/FieldAccessNode.java b/Robust/src/IR/Tree/FieldAccessNode.java index e764bb0d..66c7238d 100644 --- a/Robust/src/IR/Tree/FieldAccessNode.java +++ b/Robust/src/IR/Tree/FieldAccessNode.java @@ -6,10 +6,12 @@ public class FieldAccessNode extends ExpressionNode { ExpressionNode left; String fieldname; FieldDescriptor field; + boolean issuper; public FieldAccessNode(ExpressionNode l, String field) { fieldname=field; left=l; + this.issuper = false; } public void setField(FieldDescriptor fd) { @@ -44,6 +46,14 @@ public class FieldAccessNode extends ExpressionNode { public TypeDescriptor getType() { return getField().getType(); } + + public void setIsSuper() { + this.issuper = true; + } + + public boolean isSuper() { + return issuper; + } public Long evaluate() { // if the field is a constant value then OK diff --git a/Robust/src/IR/Tree/NameNode.java b/Robust/src/IR/Tree/NameNode.java index 77cdbcde..bad7b7b6 100644 --- a/Robust/src/IR/Tree/NameNode.java +++ b/Robust/src/IR/Tree/NameNode.java @@ -13,12 +13,22 @@ public class NameNode extends ExpressionNode { FieldDescriptor fd; ExpressionNode en; ClassDescriptor cd; + boolean issuper; public NameNode(NameDescriptor nd) { this.name=nd; this.vd=null; this.fd=null; this.cd = null; + this.issuper= false; + } + + public boolean isSuper() { + return this.issuper; + } + + public void setIsSuper() { + this.issuper = true; } public ExpressionNode getExpression() { diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java index 76443900..22f9546f 100644 --- a/Robust/src/IR/Tree/SemanticCheck.java +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -664,14 +664,17 @@ public class SemanticCheck { FieldDescriptor fd=null; if (ltd.isArray()&&fieldname.equals("length")) fd=FieldDescriptor.arrayLength; - else { + else if(((left instanceof NameNode) && ((NameNode)left).isSuper()) + ||((left instanceof FieldAccessNode) && ((FieldAccessNode)left).isSuper())){ + fd = (FieldDescriptor) ltd.getClassDesc().getSuperDesc().getFieldTable().get(fieldname); + } else { fd=(FieldDescriptor) ltd.getClassDesc().getFieldTable().get(fieldname); } if(ltd.isClassNameRef()) { // the field access is using a class name directly if (fd==null) { // check if it is to access a surrounding class in an inner class - if(fieldname.equals("this")) { + if(fieldname.equals("this") || fieldname.equals("super")) { ClassDescriptor icd = ((VarDescriptor)nametable.get("this")).getType().getClassDesc(); if(icd.isInnerClass()) { NameNode nn = new NameNode(new NameDescriptor("this")); @@ -686,10 +689,13 @@ public class SemanticCheck { // this is an inner class this operation fd = new FieldDescriptor(new Modifiers(),new TypeDescriptor(icd),"this",null,false); } + if(fieldname.equals("super")) { + fan.setIsSuper(); + } fan.setField(fd); return; } - } + } ClassDescriptor surroundingCls=ltd.getClassDesc().getSurroundingDesc(); while(surroundingCls!=null) { @@ -899,9 +905,12 @@ public class SemanticCheck { checkExpressionNode(md,nametable,en,td); } else { String varname=nd.toString(); - if(varname.equals("this")) { + if(varname.equals("this") || varname.equals("super")) { // "this" nn.setVar((VarDescriptor)nametable.get("this")); + if(varname.equals("super")) { + nn.setIsSuper(); + } return; } Descriptor d=(Descriptor)nametable.get(varname); diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup index 9416a94b..762cf794 100644 --- a/Robust/src/Parse/java14.cup +++ b/Robust/src/Parse/java14.cup @@ -2204,8 +2204,17 @@ field_access ::= pn.addChild("field").addChild(id); RESULT=pn; :} -// | SUPER DOT IDENTIFIER -// | name DOT SUPER DOT IDENTIFIER + | SUPER DOT IDENTIFIER:id {: + ParseNode pn=new ParseNode("superfieldaccess",parser.lexer.line_num); + pn.addChild("field").addChild(id); + RESULT=pn; + :} + | name:name DOT SUPER DOT IDENTIFIER:id {: + ParseNode pn=new ParseNode("supernamefieldaccess",parser.lexer.line_num); + pn.addChild("base").addChild(name); + pn.addChild("field").addChild(id); + RESULT=pn; + :} ; method_invocation ::= name:name LPAREN argument_list_opt:args RPAREN {: diff --git a/Robust/src/Tests/DoTests b/Robust/src/Tests/DoTests index 37a4aff4..0cfd99df 100755 --- a/Robust/src/Tests/DoTests +++ b/Robust/src/Tests/DoTests @@ -24,3 +24,4 @@ dotest StaticInnerClassTest StaticInnerClassTest.java dotest StaticTest StaticTest.java dotest SwitchCaseTest SwitchCaseTest.java dotest TryCatchTest TryCatchTest.java +dotest inner inner.java innerp.java innerpt.java diff --git a/Robust/src/Tests/inner.java b/Robust/src/Tests/inner.java index ca5b94e8..6000c3e3 100644 --- a/Robust/src/Tests/inner.java +++ b/Robust/src/Tests/inner.java @@ -38,6 +38,9 @@ public class inner extends innerp { System.out.println("\t Inner class print: "); System.out.println(outer); System.out.println(super.outer); + t.super.outer = 1; + System.out.println(outer); + System.out.println(t.super.outer); System.out.println(inner.this.outer); System.out.println(inner.super.outer); System.out.println(f1); diff --git a/Robust/src/Tests/output/inner.output.goal b/Robust/src/Tests/output/inner.output.goal new file mode 100644 index 00000000..31735e74 --- /dev/null +++ b/Robust/src/Tests/output/inner.output.goal @@ -0,0 +1,12 @@ +Outer class print: 35; 0 + Inner class print: +4 +0 +4 +1 +35 +31 +2 +3 +4 +Outer class print: 35; 3 -- 2.34.1