Fix another inner class bug: every inner class along the inherited chain has a pointe...
authorjzhou <jzhou>
Sat, 3 Dec 2011 01:42:41 +0000 (01:42 +0000)
committerjzhou <jzhou>
Sat, 3 Dec 2011 01:42:41 +0000 (01:42 +0000)
Robust/src/IR/Tree/BuildIR.java
Robust/src/IR/Tree/SemanticCheck.java
Robust/src/Tests/DoTests
Robust/src/Tests/inner.java
Robust/src/Tests/output/inner.output.goal

index a12dcf0a36aa0595d9c70d0598a4969b12f15c0b..7b14d103ae23a3b77740012cd5399cba77eeb99e 100644 (file)
@@ -184,18 +184,41 @@ public class BuildIR {
 
   public void parseInitializers(ClassDescriptor cn) {
     Vector fv=cn.getFieldVec();
+    Iterator methodit = cn.getMethods();
+    HashMap<MethodDescriptor, Integer> md2pos = new HashMap<MethodDescriptor, Integer>();
+    while(methodit.hasNext()) {
+      MethodDescriptor currmd=(MethodDescriptor)methodit.next();
+      if(currmd.isConstructor()) {
+        BlockNode bn=state.getMethodBody(currmd);
+        // if there are super(...) invokation, the initializers should be invoked after that
+        int i = 0;
+        for(; i < bn.size(); i++) {
+          if(Kind.BlockExpressionNode==bn.get(i).kind()
+                 &&(((BlockExpressionNode)bn.get(i)).getExpression() instanceof MethodInvokeNode)
+                 &&((MethodInvokeNode)(((BlockExpressionNode)bn.get(i)).getExpression())).getMethodName().equals("super")) {
+            break;
+          }
+        }
+        if(i==bn.size()) {
+          md2pos.put(currmd, 0);
+        } else {
+          md2pos.put(currmd, i+1);
+        }
+      }
+    }
     int pos = 0;
     for(int i=0; i<fv.size(); i++) {
       FieldDescriptor fd=(FieldDescriptor)fv.get(i);
       if(fd.getExpressionNode()!=null) {
-        Iterator methodit = cn.getMethods();
+        methodit = cn.getMethods();
         while(methodit.hasNext()) {
           MethodDescriptor currmd=(MethodDescriptor)methodit.next();
           if(currmd.isConstructor()) {
+            int offset = md2pos.get(currmd);
             BlockNode bn=state.getMethodBody(currmd);
             NameNode nn=new NameNode(new NameDescriptor(fd.getSymbol()));
             AssignmentNode an=new AssignmentNode(nn,fd.getExpressionNode(),new AssignOperation(1));
-            bn.addBlockStatementAt(new BlockExpressionNode(an), pos);
+            bn.addBlockStatementAt(new BlockExpressionNode(an), pos+offset);
           }
         }
         pos++;
@@ -646,7 +669,7 @@ private void addOuterClassParam( ClassDescriptor cn, int depth )
                         if( md.isConstructor() ){
                                md.addParameter( theTypeDesc, "surrounding$" + String.valueOf(depth) ); 
                                initializeOuterMember( md, "this$" + String.valueOf( depth ), "surrounding$" + String.valueOf(depth) );
-                               //System.out.println( "The added param is " + md.toString() + "\n" );           
+                               //System.out.println( "The added param is " + md.toString() + "\n" );
                        }
                }
                addOuterClassParam( icd, depth + 1 );
index 42a37f30c8184136716b0b187714cc3f2a045e52..95042d31b38833a1f307fb118bc1b04a5cdb5379 100644 (file)
@@ -1257,11 +1257,11 @@ public class SemanticCheck {
     // for an inline class, need to first add the original parameters of the CreatObjectNode
     // into its anonymous constructor and insert a super(...) into the anonymous constructor
     // if its super class is not null
-    MethodDescriptor cd_construtor = null;
+    MethodDescriptor cd_constructor = null;
     for(Iterator it_methods = cd.getMethods(); it_methods.hasNext();) {
       MethodDescriptor imd = (MethodDescriptor)it_methods.next();
       if(imd.isConstructor()) {
-        cd_construtor = imd; // an inline class should only have one anonymous constructor
+         cd_constructor = imd; // an inline class should only have one anonymous constructor
       }
     }
     MethodInvokeNode min = null;
@@ -1270,13 +1270,18 @@ public class SemanticCheck {
       NameDescriptor nd=new NameDescriptor("super");
       min=new MethodInvokeNode(nd);
       BlockExpressionNode ben=new BlockExpressionNode(min);
-      BlockNode bn = state.getMethodBody(cd_construtor);
+      BlockNode bn = state.getMethodBody(cd_constructor);
       bn.addFirstBlockStatement(ben);
+      if(cd.getSuperDesc().isInnerClass()&&!cd.getSuperDesc().isStatic()&&!cd.getSuperDesc().getInStaticContext()) {
+       // for a super class that is also an inner class with surrounding reference, add the surrounding 
+       // instance of the child instance as the parent instance's surrounding instance
+       min.addArgument(new NameNode(new NameDescriptor("surrounding$0")));
+      }
     }
     for(int i = 0 ; i < tdarray.length; i++) {
       assert(null!=min);
       TypeDescriptor itd = tdarray[i];
-      cd_construtor.addParameter(itd, itd.getSymbol()+"_from_con_node_"+i);
+      cd_constructor.addParameter(itd, itd.getSymbol()+"_from_con_node_"+i);
       min.addArgument(new NameNode(new NameDescriptor(itd.getSymbol()+"_from_con_node_"+i)));
     }
     
@@ -1293,14 +1298,14 @@ public class SemanticCheck {
       if(d instanceof VarDescriptor && !d.getSymbol().equals("this")) {
         con.addArgument(new NameNode(new NameDescriptor(d.getSymbol())));
         cd.addField(new FieldDescriptor(new Modifiers(Modifiers.PUBLIC), ((VarDescriptor)d).getType(), d.getSymbol(), null, false));
-        cd_construtor.addParameter(((VarDescriptor)d).getType(), d.getSymbol()+"_p");
+        cd_constructor.addParameter(((VarDescriptor)d).getType(), d.getSymbol()+"_p");
         // add the initialize statement into this constructor
-        BlockNode obn = state.getMethodBody(cd_construtor);
+        BlockNode obn = state.getMethodBody(cd_constructor);
         NameNode nn=new NameNode(new NameDescriptor(d.getSymbol()));
         NameNode fn = new NameNode (new NameDescriptor(d.getSymbol()+"_p"));
         AssignmentNode an=new AssignmentNode(nn,fn,new AssignOperation(1));
         obn.addFirstBlockStatement(new BlockExpressionNode(an));
-        state.addTreeCode(cd_construtor, obn);
+        state.addTreeCode(cd_constructor, obn);
       }
     }
   }
@@ -1559,6 +1564,25 @@ NextMethod: for (Iterator methodit = methoddescriptorset.iterator(); methodit.ha
       ClassDescriptor supercd=((MethodDescriptor)md).getClassDesc().getSuperDesc();
       min.methodid=supercd.getSymbol();
       typetolookin=new TypeDescriptor(supercd);
+      if(supercd.isInnerClass()&&!supercd.isStatic()&&!supercd.getInStaticContext()) {
+       // for a super class that is also an inner class with surrounding reference, add the surrounding 
+       // instance of the child instance as the parent instance's surrounding instance
+       if(((MethodDescriptor)md).isConstructor()) {
+         min.addArgument(new NameNode(new NameDescriptor("surrounding$0")));
+       } else if(((MethodDescriptor)md).getClassDesc().isInnerClass()&&!((MethodDescriptor)md).getClassDesc().isStatic()&&!((MethodDescriptor)md).getClassDesc().getInStaticContext()) {
+         min.addArgument(new NameNode(new NameDescriptor("this$0")));
+       }
+      }
+      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();
+
+        if(en.getType().isClass() && en.getType().getClassDesc().isEnum()) {
+          tdarray[i] = new TypeDescriptor(TypeDescriptor.INT);
+        }
+      }
     } else if (md instanceof MethodDescriptor) {
       typetolookin=new TypeDescriptor(((MethodDescriptor)md).getClassDesc());
     } else {
@@ -1592,8 +1616,14 @@ NextMethod:
       else {
         if (typeutil.isMoreSpecific(currmd,bestmd, false)) {
           bestmd=currmd;
-        } else if (!typeutil.isMoreSpecific(bestmd, currmd, false))
-          throw new Error("No method is most specific:"+bestmd+" and "+currmd);
+        } else if (!typeutil.isMoreSpecific(bestmd, currmd, false)) {
+          // if the two methods are inherited from super class/interface, use the super class' as first priority
+          if(bestmd.getClassDesc().isInterface()&&!currmd.getClassDesc().isInterface()) {
+            bestmd = currmd;
+          } else {
+            throw new Error("No method is most specific:"+bestmd+" and "+currmd);
+          }
+        }
 
         /* Is this more specific than bestmd */
       }
index 1f27017129c9b3f02d930f646a84ead01aa437ec..2f7457eed258452a485c48645469b8367742e946 100755 (executable)
@@ -25,4 +25,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 innerCallback.java
+dotest inner inner.java innerp.java innerpt.java innerCallback.java innerEgg2.java innerBigEgg2.java
index 89e42a473a082c9acb1f536c0634e06e1e4bcb28..5558f8ec48de23319c6421b21ef7b8a9f8c38c58 100644 (file)
@@ -10,6 +10,8 @@ public class inner extends innerp {
     inner i=new inner();
     i.dotest();
     outerAnonymousInnerStatic(20, 30);
+    innerEgg2 e2 = new innerBigEgg2();
+    e2.g();
   }
 
   public void dotest() {
index 4f3672e49e780218295452518ed4eb9e9e20e94c..a07b91a2185aa32bede5179cea88baf62950960b 100644 (file)
@@ -12,3 +12,8 @@ Outer class print: 35; 0
 Outer class print: 35; 3
 innerCallback: 100
 innerCallbackStatic: 20, 30
+innerEgg2.Yolk() : getValue() = 0 value = -1
+New innerEgg2()
+innerEgg2.Yolk() : getValue() = 2 value = 1
+innerBigEgg2.Yolk() getValue() = 2 value = 2
+innerBigEgg2.Yolk.f()