Fix inner class implementation. Now code like inner.this.X/outer.this.X work correctl...
authorjzhou <jzhou>
Fri, 11 Nov 2011 00:18:09 +0000 (00:18 +0000)
committerjzhou <jzhou>
Fri, 11 Nov 2011 00:18:09 +0000 (00:18 +0000)
Robust/src/IR/Flat/BuildCode.java
Robust/src/IR/SymbolTable.java
Robust/src/IR/Tree/BuildIR.java
Robust/src/IR/Tree/FieldAccessNode.java
Robust/src/IR/Tree/SemanticCheck.java

index 9482735f03a93795ceeaf8af59c8b9a2a95775c8..59ee3e07d1e675f51941ea5753a56680ff11b987 100644 (file)
@@ -2805,7 +2805,22 @@ fldloop:
       output.println("}else{");
       output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+"->"+ ffn.getField().getSafeSymbol()+";");
       output.println("}");
-    }else {
+    }else if (ffn.getField().getSymbol().equals("this")) {
+       // an inner class refers to itself
+       if( state.CAPTURE_NULL_DEREFERENCES ) {
+           output.println("#ifdef CAPTURE_NULL_DEREFERENCES");
+           output.println("if (" + generateTemp(fm,ffn.getSrc()) + " == NULL) {");
+           output.println("printf(\" NULL ptr error: %s, %s, %d \\n\", __FILE__, __func__, __LINE__);");
+           if(state.MULTICOREGC||state.PMC) {
+               output.println("failednullptr(&___locals___);");
+           } else {
+               output.println("failednullptr(NULL);");
+           }
+           output.println("}");
+           output.println("#endif //CAPTURE_NULL_DEREFERENCES");
+       }
+       output.println(generateTemp(fm, ffn.getDst())+"="+ generateTemp(fm,ffn.getSrc())+";");
+    } else {
       if( state.CAPTURE_NULL_DEREFERENCES ) {
         output.println("#ifdef CAPTURE_NULL_DEREFERENCES");
         output.println("if (" + generateTemp(fm,ffn.getSrc()) + " == NULL) {");
index 3ada402962d337e5bcc5590360b9f56083643510..057e93be3b4d43927dba11342673ad6cdedf15a4 100644 (file)
@@ -9,15 +9,12 @@ public class SymbolTable {
   private HashSet valueset;
 
   private Vector<SymbolTable> parentIFs;
-  private SymbolTable surrounding;
-
 
   public SymbolTable() {
     table = new Hashtable();
     valueset = new HashSet();
     parent = null;
     parentIFs = null;
-    this.surrounding = null;
   }
 
   public SymbolTable(SymbolTable parent) {
@@ -49,9 +46,6 @@ public class SymbolTable {
        hs.addAll(parentIFs.elementAt(i).getPSet(name));
       }
     }
-    if(this.surrounding != null) {
-       hs.addAll(this.surrounding.getPSet(name));
-    }
     if (table.containsKey(name)) {
       hs.addAll((HashSet)table.get(name));
     }
@@ -90,13 +84,6 @@ public class SymbolTable {
       }
     }
     
-    if(this.surrounding != null) {
-       d = this.surrounding.get(name);
-       if(d != null) {
-           return d;
-       }
-    }
-    
     return null;
   }
 
@@ -136,9 +123,6 @@ public class SymbolTable {
         hs.addAll(parentIFs.elementAt(i).getAllValueSet());
       }
     }
-    if(this.surrounding != null) {
-       hs.addAll(this.surrounding.getAllValueSet());
-    }
 
     hs.addAll(valueset);
     return hs;
@@ -160,14 +144,6 @@ public class SymbolTable {
     this.parent = parent;
   }
   
-  public SymbolTable getSurrounding() {
-      return this.surrounding;
-  }
-  
-  public void setSurrounding(SymbolTable surrounding) {
-      this.surrounding = surrounding;
-  }
-
   public Vector<SymbolTable> getParentIFs() {
     return parentIFs;
   }
index 31f062e946508cdb8e74421ca04c33575773add8..a6005bd38f8c97a2762392652715aa02dceb289d 100644 (file)
@@ -1202,13 +1202,13 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       nn.setNumLine(pn.getLine());
       return nn;
     } else if (isNode(pn,"parentclass")) {
-      NameDescriptor nd=new NameDescriptor("this");
+      NameDescriptor nd=new NameDescriptor(pn.getChild("name").getFirstChild().getFirstChild().getTerminal());
       NameNode nn=new NameNode(nd);
       nn.setNumLine(pn.getLine());
        //because inner classes pass right thru......
-    /*  FieldAccessNode fan=new FieldAccessNode(nn,"this$0");
-      fan.setNumLine(pn.getLine());*/
-      return nn;
+      FieldAccessNode fan=new FieldAccessNode(nn,"this");
+      fan.setNumLine(pn.getLine());
+      return fan;
     } else if (isNode(pn,"isavailable")) {
       NameDescriptor nd=new NameDescriptor(pn.getTerminal());
       NameNode nn=new NameNode(nd);
index d7c28bda45b2a223b7201929e859b65cd6cf3b43..e764bb0d7dec71342e300bb4d892603000f8c55a 100644 (file)
@@ -19,6 +19,10 @@ public class FieldAccessNode extends ExpressionNode {
   public String getFieldName() {
     return fieldname;
   }
+  
+  public void setFieldName(String fieldname) {
+      this.fieldname = fieldname;
+  }
 
   public FieldDescriptor getField() {
     return field;
index b461accb958d703325c4881117da9855cb24603a..76443900cbc8d8d1dca25643cc58532d252c3911 100644 (file)
@@ -75,13 +75,6 @@ public class SemanticCheck {
              cd.getFieldTable().setParent(cd.getSuperDesc().getFieldTable());
              cd.getMethodTable().setParent(cd.getSuperDesc().getMethodTable());
              cd.getFlagTable().setParent(cd.getSuperDesc().getFlagTable());
-             // if this is an inner class, link together Field, Method and Flag
-             // tables from its surrounding class
-             if(cd.isInnerClass()) {
-                 cd.getFieldTable().setSurrounding(cd.getSurroundingDesc().getFieldTable());
-                 cd.getMethodTable().setSurrounding(cd.getSurroundingDesc().getMethodTable());
-                 cd.getFlagTable().setSurrounding(cd.getSurroundingDesc().getFlagTable());
-             }
            }
          }
         }
@@ -677,6 +670,26 @@ public class SemanticCheck {
     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")) {
+          ClassDescriptor icd = ((VarDescriptor)nametable.get("this")).getType().getClassDesc();
+          if(icd.isInnerClass()) {
+              NameNode nn = new NameNode(new NameDescriptor("this"));
+              nn.setVar((VarDescriptor)nametable.get("this"));
+              fan.setExpression(nn);
+              if(icd.getSurroundingDesc()==ltd.getClassDesc()) {
+                  // this is a surrounding class access inside an inner class
+                  fan.setExpression(nn);
+                  fan.setFieldName("this$0");
+                  fd = (FieldDescriptor)icd.getFieldTable().get("this$0");
+              } else if(icd==ltd.getClassDesc()) {
+                  // this is an inner class this operation 
+                  fd = new FieldDescriptor(new Modifiers(),new TypeDescriptor(icd),"this",null,false);
+              }
+              fan.setField(fd);
+              return;
+          }
+       }
        ClassDescriptor surroundingCls=ltd.getClassDesc().getSurroundingDesc();
        
        while(surroundingCls!=null) {
@@ -833,9 +846,23 @@ public class SemanticCheck {
       }
   }
 
+  FieldDescriptor recurseSurroundingClasses( ClassDescriptor icd, String varname ) {
+        if( null == icd || false == icd.isInnerClass() )
+           return null;
+      
+        ClassDescriptor surroundingDesc = icd.getSurroundingDesc();
+        if( null == surroundingDesc )
+           return null;
+      
+        SymbolTable fieldTable = surroundingDesc.getFieldTable();
+        FieldDescriptor fd = ( FieldDescriptor ) fieldTable.get( varname );
+        if( null != fd )
+           return fd;
+        return recurseSurroundingClasses( surroundingDesc, varname );
+  }
+  
   FieldAccessNode fieldAccessExpression( ClassDescriptor icd, String varname, int linenum ) {
-        // first check if the field is belong to the icd or its parent class
-       FieldDescriptor fd = (FieldDescriptor)icd.getFieldTable().get(varname);
+        FieldDescriptor fd = recurseSurroundingClasses( icd, varname );
        if( null == fd )
                return null;
 
@@ -1291,6 +1318,41 @@ NextMethod: for (Iterator methodit = methoddescriptorset.iterator(); methodit.ha
     }
   }
 
+  MethodDescriptor recurseSurroundingClassesM( ClassDescriptor icd, String varname ) {
+      if( null == icd || false == icd.isInnerClass() )
+           return null;
+    
+      ClassDescriptor surroundingDesc = icd.getSurroundingDesc();
+      if( null == surroundingDesc )
+           return null;
+    
+      SymbolTable methodTable = surroundingDesc.getMethodTable();
+      MethodDescriptor md = ( MethodDescriptor ) methodTable.get( varname );
+      if( null != md )
+           return md;
+      return recurseSurroundingClassesM( surroundingDesc, varname );
+  }
+
+  ExpressionNode methodInvocationExpression( ClassDescriptor icd, MethodDescriptor md, int linenum ) {
+       ClassDescriptor cd = md.getClassDesc();
+       int depth = 1;
+       int startingDepth = icd.getInnerDepth();
+
+       if( true == cd.isInnerClass() ) 
+               depth = cd.getInnerDepth();
+
+       String composed = "this";
+       NameDescriptor runningDesc = new NameDescriptor( "this" );;
+       
+       for ( int index = startingDepth; index > depth; --index ) {
+               composed = "this$" + String.valueOf( index - 1  );      
+               runningDesc = new NameDescriptor( runningDesc, composed );
+       }
+       if( false == cd.isInnerClass() )
+               runningDesc = new NameDescriptor( runningDesc, "this$" + String.valueOf(0) ); //all the way up.
+
+       return new NameNode(runningDesc);
+}
 
   void checkMethodInvokeNode(Descriptor md, SymbolTable nametable, MethodInvokeNode min, TypeDescriptor td) {
     /*Typecheck subexpressions
@@ -1393,8 +1455,18 @@ NextMethod:
         /* Is this more specific than bestmd */
       }
     }
-    if (bestmd==null)
-      throw new Error("No method found for :"+min.printNode(0)+" in class: " + classtolookin+" in "+md);
+    if (bestmd==null) {
+      // if this is an inner class, need to check the method table for the surrounding class
+      bestmd = recurseSurroundingClassesM(classtolookin, min.getMethodName());
+      if(bestmd == null)
+         throw new Error("No method found for :"+min.printNode(0)+" in class: " + classtolookin+" in "+md);
+      else {
+         // set the correct "this" expression here
+         ExpressionNode en=methodInvocationExpression(classtolookin, bestmd, min.getNumLine());
+         min.setExpression(en);
+         checkExpressionNode(md, nametable, min.getExpression(), null);
+      }
+    }
     min.setMethod(bestmd);
 
     if ((td!=null)&&(min.getType()!=null)&&!typeutil.isSuperorType(td,  min.getType()))