Handling the case NAME DOT THIS for inner classes
[IRC.git] / Robust / src / IR / Tree / BuildIR.java
index 30440944e12ba848cfe29967e08b5b00dd2cc796..31f062e946508cdb8e74421ca04c33575773add8 100644 (file)
@@ -5,15 +5,17 @@ import Util.Pair;
 
 import java.io.File;
 import java.util.*;
-
+import java.io.*;
+import java.lang.Throwable;
 public class BuildIR {
   State state;
-
+  private boolean isRunningRecursiveInnerClass;
   private int m_taskexitnum;
 
   public BuildIR(State state) {
     this.state=state;
     this.m_taskexitnum = 0;
+    this.isRunningRecursiveInnerClass = false;
   }
 
   public void buildtree(ParseNode pn, Set toanalyze, String sourcefile) {
@@ -588,16 +590,106 @@ public class BuildIR {
       md.setDefaultConstructor();
       cn.addMethod(md);
     }
+
+
     popChainMaps();
 
     cn.setSourceFileName(currsourcefile);
+
+
+    
     if (analyzeset != null)
       analyzeset.add(cn);
     state.addClass(cn);
-
+//create this$n representing a final reference to the next surrounding class. each inner class should have whatever inner class
+//pointers the surrounding class has + a pointer to the surrounding class.
+   if( true )
+   {
+       this.isRunningRecursiveInnerClass = true; //fOR dEBUGGING PURPOSES IN ORDER TO DUMP STRINGS WHILE IN THIS CODE PATH
+       addOuterClassReferences( cn, 0 );
+       addOuterClassParam( cn, 0 );
+       this.isRunningRecursiveInnerClass = false;
+    }
     return cn;
   }
 
+private void initializeOuterMember( MethodDescriptor md, String fieldName, String formalParameter ) {
+        BlockNode obn = state.getMethodBody(md);
+         NameNode nn=new NameNode( new NameDescriptor( fieldName ) );
+        NameNode fn = new NameNode ( new NameDescriptor( formalParameter ) );
+          //nn.setNumLine(en.getNumLine())
+         AssignmentNode an=new AssignmentNode(nn,fn,new AssignOperation(1));
+         //an.setNumLine(pn.getLine());
+         obn.addFirstBlockStatement(new BlockExpressionNode(an));
+       // System.out.print( "The code inserted is : " + obn.printNode( 0 ) + "\n" );
+         state.addTreeCode(md, obn);
+}
+
+private void addOuterClassParam( ClassDescriptor cn, int depth )
+{
+       Iterator nullCheckItr = cn.getInnerClasses();
+       if( false == nullCheckItr.hasNext() )
+               return;
+
+       //create a typedescriptor of type cn
+       TypeDescriptor theTypeDesc = new TypeDescriptor( cn );
+       
+       for(Iterator it=cn.getInnerClasses(); it.hasNext(); ) {
+               ClassDescriptor icd=(ClassDescriptor)it.next();
+               
+               //iterate over all ctors of I.Cs and add a new param
+               for(Iterator method_it=icd.getMethods(); method_it.hasNext(); ) {
+                        MethodDescriptor md=(MethodDescriptor)method_it.next();
+                        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" );           
+                       }
+               }
+               addOuterClassParam( icd, depth + 1 );
+               
+       }
+       
+}
+private void addOuterClassReferences( ClassDescriptor cn, int depth )
+{
+       //SYMBOLTABLE does not have a length or empty method, hence could not define a hasInnerClasses method in classDescriptor
+       Iterator nullCheckItr = cn.getInnerClasses();
+       if( false == nullCheckItr.hasNext() )
+               return;
+
+       String tempCopy = cn.getClassName();
+       //MESSY HACK FOLLOWS
+       int i = 0;
+
+       ParseNode theNode = new ParseNode( "field_declaration" );
+       theNode.addChild("modifier").addChild( new ParseNode( "modifier_list" ) ).addChild("final");
+       ParseNode theTypeNode = new ParseNode("type");
+       ParseNode tempChildNode = theTypeNode.addChild("class").addChild( "name" );
+               //tempChildNode.addChild("base").addChild( new ParseNode("empty") );
+       tempChildNode.addChild("identifier").addChild ( tempCopy );
+       theNode.addChild("type").addChild( theTypeNode );
+       ParseNode variableDeclaratorID = new ParseNode("single");
+       String theStr = "this$" + String.valueOf( depth );
+       variableDeclaratorID.addChild( theStr );
+       ParseNode variableDeclarator = new ParseNode( "variable_declarator" );
+       variableDeclarator.addChild( variableDeclaratorID );
+       ParseNode variableDeclaratorList = new ParseNode("variable_declarators_list");
+       variableDeclaratorList.addChild( variableDeclarator );
+       theNode.addChild("variables").addChild( variableDeclaratorList );
+
+       for(Iterator it=cn.getInnerClasses(); it.hasNext(); ) {
+               ClassDescriptor icd=(ClassDescriptor)it.next();
+               parseFieldDecl( icd, theNode );         
+               /*if( true ) {
+                       SymbolTable fieldTable = icd.getFieldTable();
+                       //System.out.println( fieldTable.toString() );
+               }*/
+               icd.setInnerDepth( depth + 1 );
+               addOuterClassReferences( icd, depth + 1 );      
+       }
+}
+
   private void parseClassBody(ClassDescriptor cn, ParseNode pn) {
     ParseNode decls=pn.getChild("class_body_declaration_list");
     if (decls!=null) {
@@ -619,6 +711,7 @@ public class BuildIR {
   private void parseClassMember(ClassDescriptor cn, ParseNode pn) {
     ParseNode fieldnode=pn.getChild("field");
     if (fieldnode!=null) {
+      //System.out.println( pn.PPrint( 0, true ) );
       parseFieldDecl(cn,fieldnode.getChild("field_declaration"));
       return;
     }
@@ -657,6 +750,8 @@ public class BuildIR {
     throw new Error();
   }
 
+//10/9/2011 changed this function to enable creation of default constructor for inner classes.
+//the change was refactoring this function with the corresponding version for normal classes. sganapat
   private ClassDescriptor parseInnerClassDecl(ClassDescriptor cn, ParseNode pn) {
     String basename=pn.getChild("name").getTerminal();
     String classname=cn.getClassName()+"$"+basename;
@@ -669,11 +764,11 @@ public class BuildIR {
     ClassDescriptor icn=new ClassDescriptor(cn.getPackage(), classname, false);
     pushChainMaps();
     icn.setImports(mandatoryImports, multiimports);
-    icn.setAsInnerClass();
     icn.setSurroundingClass(cn.getSymbol());
     icn.setSurrounding(cn);
     cn.addInnerClass(icn);
-    if (!isEmpty(pn.getChild("super").getTerminal())) {
+
+     if (!isEmpty(pn.getChild("super").getTerminal())) {
       /* parse superclass name */
       ParseNode snn=pn.getChild("super").getChild("type").getChild("class").getChild("name");
       NameDescriptor nd=parseClassName(snn);
@@ -698,9 +793,29 @@ public class BuildIR {
     }
     icn.setModifiers(parseModifiersList(pn.getChild("modifiers")));
 
+   if (!icn.isStatic())
+     icn.setAsInnerClass();
+
     parseClassBody(icn, pn.getChild("classbody"));
+
+    boolean hasConstructor = false;
+    for(Iterator method_it=icn.getMethods(); method_it.hasNext(); ) {
+      MethodDescriptor md=(MethodDescriptor)method_it.next();
+      hasConstructor |= md.isConstructor();
+    }
+//sganapat adding change to allow proper construction of inner class objects
+    if((!hasConstructor) && (!icn.isEnum())) {
+      // add a default constructor for this class
+      MethodDescriptor md = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC),
+                                                 icn.getSymbol(), false);
+      BlockNode bn=new BlockNode();
+      state.addTreeCode(md,bn);
+      md.setDefaultConstructor();
+      icn.addMethod(md);
+   }
     popChainMaps();
-    if (analyzeset != null)
+
+     if (analyzeset != null)
       analyzeset.add(icn);
     icn.setSourceFileName(currsourcefile);
     state.addClass(icn);
@@ -747,6 +862,8 @@ public class BuildIR {
   //we do not want to apply our resolveName function (i.e. deal with imports)
   //otherwise, if base == null, we do just want to resolve name.
   private NameDescriptor parseClassName(ParseNode nn) {
+    
+
     ParseNode base=nn.getChild("base");
     ParseNode id=nn.getChild("identifier");
     String classname = id.getTerminal();
@@ -834,6 +951,11 @@ public class BuildIR {
       ParseNode vardecl=pnv.elementAt(i);
       ParseNode tmp=vardecl;
       TypeDescriptor arrayt=t;
+       if( this.isRunningRecursiveInnerClass && false )
+       {       
+               System.out.println( "the length of the list is " + String.valueOf( pnv.size() ) );
+               System.out.println( "\n the parse node is \n" + tmp.PPrint( 0, true ) );
+       }
       while (tmp.getChild("single")==null) {
         arrayt=arrayt.makeArray(state);
         tmp=tmp.getChild("array");
@@ -842,6 +964,7 @@ public class BuildIR {
       ParseNode epn=vardecl.getChild("initializer");
 
       ExpressionNode en=null;
+      
       if (epn!=null) {
         en=parseExpression(epn.getFirstChild());
         en.setNumLine(epn.getFirstChild().getLine());
@@ -901,7 +1024,10 @@ public class BuildIR {
 
   private ExpressionNode parseExpression(ParseNode pn) {
     if (isNode(pn,"assignment"))
+       {
+          //System.out.println( "parsing a field decl in my class that has assignment in initialization " + pn.PPrint( 0, true ) + "\n");
       return parseAssignmentExpression(pn);
+       }
     else if (isNode(pn,"logical_or")||isNode(pn,"logical_and")||
              isNode(pn,"bitwise_or")||isNode(pn,"bitwise_xor")||
              isNode(pn,"bitwise_and")||isNode(pn,"equal")||
@@ -960,7 +1086,24 @@ public class BuildIR {
       if (pn.getChild("disjoint") != null) {
         disjointId = pn.getChild("disjoint").getTerminal();
       }
+      ParseNode idChild = (pn.getChild( "id" ));
+      ParseNode baseChild = (pn.getChild( "base" ));
+      
       CreateObjectNode con = new CreateObjectNode(td, isglobal, disjointId);
+      if( null != idChild && null != idChild.getFirstChild() ) {
+       idChild = idChild.getFirstChild();
+       //System.out.println( "\nThe object passed has this expression " + idChild.PPrint( 0, true ) );
+       ExpressionNode en = parseExpression( idChild ); 
+       //System.out.println( "\nThe object passed has this expression " + en.printNode( 0 ) );
+       con.setSurroundingExpression( en );
+      }
+      else if( null != baseChild  && null != baseChild.getFirstChild()  ) {
+       baseChild = baseChild.getFirstChild();
+       //System.out.println( "\nThe object passed has this expression " + baseChild.PPrint( 0, true ) );
+       ExpressionNode en = parseExpression( baseChild ); 
+       //System.out.println( "\nThe object passed has this expression " + en.printNode( 0 ) );
+       con.setSurroundingExpression( en );     
+      }
       con.setNumLine(pn.getLine());
       for (int i = 0; i < args.size(); i++) {
         con.addArgument((ExpressionNode) args.get(i));
@@ -979,6 +1122,7 @@ public class BuildIR {
       return con;
     } else if (isNode(pn,"createobjectcls")) {
       //TODO:::  FIX BUG!!!  static fields in caller context need to become parameters
+      //TODO::: caller context need to be passed in here
       TypeDescriptor td=parseTypeDescriptor(pn);
       innerCount++;
       ClassDescriptor cnnew=new ClassDescriptor(packageName,td.getSymbol()+"$"+innerCount, false);
@@ -990,7 +1134,13 @@ public class BuildIR {
       TypeDescriptor tdnew=state.getTypeDescriptor(cnnew.getSymbol());
 
       Vector args=parseArgumentList(pn);
-
+      ParseNode idChild = pn.getChild( "id" );
+      ParseNode baseChild = pn.getChild( "base" );
+      //System.out.println("\n to print idchild and basechild for ");
+      /*if( null != idChild )
+       System.out.println( "\n trying to create an inner class and the id child passed is "  + idChild.PPrint( 0, true ) );
+      if( null != baseChild )
+       System.out.println( "\n trying to create an inner class and the base child passed is "  + baseChild.PPrint( 0, true ) );*/
       CreateObjectNode con=new CreateObjectNode(tdnew, false, null);
       con.setNumLine(pn.getLine());
       for(int i=0; i<args.size(); i++) {
@@ -1055,10 +1205,10 @@ public class BuildIR {
       NameDescriptor nd=new NameDescriptor("this");
       NameNode nn=new NameNode(nd);
       nn.setNumLine(pn.getLine());
-
-      FieldAccessNode fan=new FieldAccessNode(nn,"this$parent");
-      fan.setNumLine(pn.getLine());
-      return fan;
+       //because inner classes pass right thru......
+    /*  FieldAccessNode fan=new FieldAccessNode(nn,"this$0");
+      fan.setNumLine(pn.getLine());*/
+      return nn;
     } else if (isNode(pn,"isavailable")) {
       NameDescriptor nd=new NameDescriptor(pn.getTerminal());
       NameNode nn=new NameNode(nd);
@@ -1341,15 +1491,19 @@ public class BuildIR {
     return bn;
   }
 
-  public BlockNode parseSingleBlock(ParseNode pn{
+  public BlockNode parseSingleBlock(ParseNode pn, String label){
     BlockNode bn=new BlockNode();
-    Vector bsv=parseBlockStatement(pn);
+    Vector bsv=parseBlockStatement(pn,label);
     for(int j=0; j<bsv.size(); j++) {
       bn.addBlockStatement((BlockStatementNode)bsv.get(j));
     }
     bn.setStyle(BlockNode.NOBRACES);
     return bn;
   }
+  
+  public BlockNode parseSingleBlock(ParseNode pn) {
+    return parseSingleBlock(pn,null);
+  }
 
   public Vector parseSESEBlock(Vector parentbs, ParseNode pn) {
     ParseNodeVector pnv=pn.getChildren();
@@ -1359,8 +1513,12 @@ public class BuildIR {
     }
     return bv;
   }
+  
+  public Vector parseBlockStatement(ParseNode pn){
+    return parseBlockStatement(pn,null);
+  }
 
-  public Vector parseBlockStatement(ParseNode pn) {
+  public Vector parseBlockStatement(ParseNode pn, String label) {
     Vector blockstatements=new Vector();
     if (isNode(pn,"tag_declaration")) {
       String name=pn.getChild("single").getTerminal();
@@ -1526,7 +1684,7 @@ public class BuildIR {
         // no condition clause, make a 'true' expression as the condition
         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
       }
-      LoopNode ln=new LoopNode(init,condition,update,body);
+      LoopNode ln=new LoopNode(init,condition,update,body,label);
       ln.setNumLine(pn.getLine());
       blockstatements.add(ln);
     } else if (isNode(pn,"whilestatement")) {
@@ -1536,7 +1694,7 @@ public class BuildIR {
         // no condition clause, make a 'true' expression as the condition
         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
       }
-      blockstatements.add(new LoopNode(condition,body,LoopNode.WHILELOOP));
+      blockstatements.add(new LoopNode(condition,body,LoopNode.WHILELOOP,label));
     } else if (isNode(pn,"dowhilestatement")) {
       ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
       BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
@@ -1544,7 +1702,7 @@ public class BuildIR {
         // no condition clause, make a 'true' expression as the condition
         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
       }
-      blockstatements.add(new LoopNode(condition,body,LoopNode.DOWHILELOOP));
+      blockstatements.add(new LoopNode(condition,body,LoopNode.DOWHILELOOP,label));
     } else if (isNode(pn,"sese")) {
       ParseNode pnID=pn.getChild("identifier");
       String stID=null;
@@ -1570,14 +1728,18 @@ public class BuildIR {
       ParseNode idopt_pn=pn.getChild("identifier_opt");
       ParseNode name_pn=idopt_pn.getChild("name");
       // name_pn.getTerminal() gives you the label
+
     } else if (isNode(pn,"genreach")) {
       String graphName = pn.getChild("graphName").getTerminal();
       blockstatements.add(new GenReachNode(graphName) );
 
+    } else if (isNode(pn,"gen_def_reach")) {
+      String outputName = pn.getChild("outputName").getTerminal();
+      blockstatements.add(new GenDefReachNode(outputName) );
+
     } else if(isNode(pn,"labeledstatement")) {
-      String label = pn.getChild("name").getTerminal();
-      BlockNode bn=parseSingleBlock(pn.getChild("statement").getFirstChild());
-      bn.setLabel(label);
+      String labeledstatement = pn.getChild("name").getTerminal();
+      BlockNode bn=parseSingleBlock(pn.getChild("statement").getFirstChild(),labeledstatement);
       blockstatements.add(new SubBlockNode(bn));
     } else {
       System.out.println("---------------");
@@ -1632,8 +1794,8 @@ public class BuildIR {
 
         md.addParameter(type, paramname);
         if(isNode(paramn, "annotation_parameter")) {
-          ParseNode bodynode=paramn.getChild("annotation_body");
-          parseParameterAnnotation(bodynode,type);
+          ParseNode listnode=paramn.getChild("annotation_list");
+          parseParameterAnnotation(listnode,type);
         }
 
       }
@@ -1697,15 +1859,21 @@ public class BuildIR {
     }
   }
 
-  private void parseParameterAnnotation(ParseNode body_list,TypeDescriptor type) {
-    ParseNode body_node = body_list.getFirstChild();
-    if (isNode(body_node, "marker_annotation")) {
-      type.addAnnotationMarker(new AnnotationDescriptor(body_node.getChild("name").getTerminal()));
-    } else if (isNode(body_node, "single_annotation")) {
-      type.addAnnotationMarker(new AnnotationDescriptor(body_node.getChild("name").getTerminal(),
-                                                        body_node.getChild("element_value").getTerminal()));
-    } else if (isNode(body_node, "normal_annotation")) {
-      throw new Error("Annotation with multiple data members is not supported yet.");
+  private void parseParameterAnnotation(ParseNode pn,TypeDescriptor type) {
+    ParseNodeVector pnv = pn.getChildren();
+    for (int i = 0; i < pnv.size(); i++) {
+      ParseNode body_list = pnv.elementAt(i);
+      if (isNode(body_list, "annotation_body")) {
+        ParseNode body_node = body_list.getFirstChild();
+        if (isNode(body_node, "marker_annotation")) {
+          type.addAnnotationMarker(new AnnotationDescriptor(body_node.getChild("name").getTerminal()));
+        } else if (isNode(body_node, "single_annotation")) {
+          type.addAnnotationMarker(new AnnotationDescriptor(body_node.getChild("name").getTerminal(),
+                                                   body_node.getChild("element_value").getTerminal()));
+        } else if (isNode(body_node, "normal_annotation")) {
+          throw new Error("Annotation with multiple data members is not supported yet.");
+        }
+      }
     }
   }