From d56ced93c269c5840dc396bc4d9faa02ffb3280b Mon Sep 17 00:00:00 2001
From: jzhou <jzhou>
Date: Tue, 15 Nov 2011 00:41:04 +0000
Subject: [PATCH] Add a new feature for inner class: an anonymous inner class
 can now refer to the local variables in its defintion context. The fix is not
 completely apply to Java specification in that we do not check if the local
 variables are final. According to the Java spec, only final variables can be
 referred to by the snonymous inner class

---
 Robust/src/IR/Tree/BuildIR.java           | 196 ++++++++++++----------
 Robust/src/IR/Tree/SemanticCheck.java     |  98 +++++++----
 Robust/src/Tests/DoTests                  |   2 +-
 Robust/src/Tests/output/inner.output.goal |   1 +
 4 files changed, 171 insertions(+), 126 deletions(-)

diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java
index 6f3ed520..5d2b689b 100644
--- a/Robust/src/IR/Tree/BuildIR.java
+++ b/Robust/src/IR/Tree/BuildIR.java
@@ -375,7 +375,7 @@ public class BuildIR {
     md.getModifiers().addModifier(Modifiers.PUBLIC);
     md.getModifiers().addModifier(Modifiers.ABSTRACT);
     try {
-      BlockNode bn=parseBlock(bodyn);
+      BlockNode bn=parseBlock(cn, bodyn);
       cn.addMethod(md);
       state.addTreeCode(md,bn);
     } catch (Exception e) {
@@ -392,7 +392,7 @@ public class BuildIR {
   public TaskDescriptor parseTaskDecl(ParseNode pn) {
     TaskDescriptor td=new TaskDescriptor(pn.getChild("name").getTerminal());
     ParseNode bodyn=pn.getChild("body");
-    BlockNode bn=parseBlock(bodyn);
+    BlockNode bn=parseBlock(null, bodyn);
     parseParameterList(td, pn);
     state.addTreeCode(td,bn);
     if (pn.getChild("flag_effects_list")!=null)
@@ -969,7 +969,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       ExpressionNode en=null;
       
       if (epn!=null) {
-        en=parseExpression(epn.getFirstChild());
+        en=parseExpression(cn, epn.getFirstChild());
         en.setNumLine(epn.getFirstChild().getLine());
         if(m.isStatic()) {
           // for static field, the initializer should be considered as a
@@ -1025,11 +1025,11 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
 
   int innerCount=0;
 
-  private ExpressionNode parseExpression(ParseNode pn) {
+  private ExpressionNode parseExpression(ClassDescriptor cn, 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);
+      return parseAssignmentExpression(cn, pn);
 	}
     else if (isNode(pn,"logical_or")||isNode(pn,"logical_and")||
              isNode(pn,"bitwise_or")||isNode(pn,"bitwise_xor")||
@@ -1045,7 +1045,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       ParseNode left=pnv.elementAt(0);
       ParseNode right=pnv.elementAt(1);
       Operation op=new Operation(pn.getLabel());
-      OpNode on=new OpNode(parseExpression(left),parseExpression(right),op);
+      OpNode on=new OpNode(parseExpression(cn, left),parseExpression(cn, right),op);
       on.setNumLine(pn.getLine());
       return on;
     } else if (isNode(pn,"unaryplus")||
@@ -1054,14 +1054,14 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
                isNode(pn,"comp")) {
       ParseNode left=pn.getFirstChild();
       Operation op=new Operation(pn.getLabel());
-      OpNode on=new OpNode(parseExpression(left),op);
+      OpNode on=new OpNode(parseExpression(cn, left),op);
       on.setNumLine(pn.getLine());
       return on;
     } else if (isNode(pn,"postinc")||
                isNode(pn,"postdec")) {
       ParseNode left=pn.getFirstChild();
       AssignOperation op=new AssignOperation(pn.getLabel());
-      AssignmentNode an=new AssignmentNode(parseExpression(left),null,op);
+      AssignmentNode an=new AssignmentNode(parseExpression(cn, left),null,op);
       an.setNumLine(pn.getLine());
       return an;
 
@@ -1069,7 +1069,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
                isNode(pn,"predec")) {
       ParseNode left=pn.getFirstChild();
       AssignOperation op=isNode(pn,"preinc")?new AssignOperation(AssignOperation.PLUSEQ):new AssignOperation(AssignOperation.MINUSEQ);
-      AssignmentNode an=new AssignmentNode(parseExpression(left),
+      AssignmentNode an=new AssignmentNode(parseExpression(cn, left),
                                            new LiteralNode("integer",new Integer(1)),op);
       an.setNumLine(pn.getLine());
       return an;
@@ -1083,7 +1083,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     } else if (isNode(pn, "createobject")) {
       TypeDescriptor td = parseTypeDescriptor(pn);
 
-      Vector args = parseArgumentList(pn);
+      Vector args = parseArgumentList(cn, pn);
       boolean isglobal = pn.getChild("global") != null || pn.getChild("scratch") != null;
       String disjointId = null;
       if (pn.getChild("disjoint") != null) {
@@ -1096,14 +1096,14 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       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 ); 
+	ExpressionNode en = parseExpression(cn, 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 ); 
+	ExpressionNode en = parseExpression(cn, baseChild ); 
 	//System.out.println( "\nThe object passed has this expression " + en.printNode( 0 ) );
 	con.setSurroundingExpression( en );     
       }
@@ -1124,8 +1124,6 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
 
       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);
@@ -1133,10 +1131,30 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       cnnew.setImports(mandatoryImports, multiimports);
       cnnew.setSuper(td.getSymbol());
       cnnew.setInline();
+      // the inline anonymous class does not have modifiers, it cannot be static 
+      // TODO: need to check the Java specification
+      cnnew.setModifiers(new Modifiers(Modifiers.PUBLIC));
+      cnnew.setAsInnerClass();
+      cnnew.setSurroundingClass(cn.getSymbol());
+      cnnew.setSurrounding(cn);
+      cn.addInnerClass(cnnew);
       parseClassBody(cnnew, pn.getChild("decl").getChild("classbody"));
+      boolean hasConstructor = false;
+      for(Iterator method_it=cnnew.getMethods(); method_it.hasNext(); ) {
+	  MethodDescriptor md=(MethodDescriptor)method_it.next();
+	  hasConstructor |= md.isConstructor();
+      }
+      if((!hasConstructor) && (!cnnew.isEnum())) {
+	  // add a default constructor for this class
+	  MethodDescriptor md = new MethodDescriptor(new Modifiers(Modifiers.PUBLIC),cnnew.getSymbol(), false);
+	  BlockNode bn=new BlockNode();
+	  state.addTreeCode(md,bn);
+	  md.setDefaultConstructor();
+	  cnnew.addMethod(md);
+      }
       TypeDescriptor tdnew=state.getTypeDescriptor(cnnew.getSymbol());
 
-      Vector args=parseArgumentList(pn);
+      Vector args=parseArgumentList(cn, pn);
       ParseNode idChild = pn.getChild( "id" );
       ParseNode baseChild = pn.getChild( "base" );
       //System.out.println("\n to print idchild and basechild for ");
@@ -1166,7 +1184,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
         disjointId = pn.getChild("disjoint").getTerminal();
       }
       TypeDescriptor td=parseTypeDescriptor(pn);
-      Vector args=parseDimExprs(pn);
+      Vector args=parseDimExprs(cn, pn);
       int num=0;
       if (pn.getChild("dims_opt").getLiteral()!=null)
         num=((Integer)pn.getChild("dims_opt").getLiteral()).intValue();
@@ -1189,7 +1207,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       CreateObjectNode con=new CreateObjectNode(td, false, null);
       con.setNumLine(pn.getLine());
       ParseNode ipn = pn.getChild("initializer");
-      Vector initializers=parseVariableInitializerList(ipn);
+      Vector initializers=parseVariableInitializerList(cn, ipn);
       ArrayInitializerNode ain = new ArrayInitializerNode(initializers);
       ain.setNumLine(pn.getLine());
       con.addArrayInitializer(ain);
@@ -1219,7 +1237,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       return new OpNode(nn,null,new Operation(Operation.ISAVAILABLE));
     } else if (isNode(pn,"methodinvoke1")) {
       NameDescriptor nd=parseName(pn.getChild("name"));
-      Vector args=parseArgumentList(pn);
+      Vector args=parseArgumentList(cn, pn);
       MethodInvokeNode min=new MethodInvokeNode(nd);
       min.setNumLine(pn.getLine());
       for(int i=0; i<args.size(); i++) {
@@ -1228,8 +1246,8 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       return min;
     } else if (isNode(pn,"methodinvoke2")) {
       String methodid=pn.getChild("id").getTerminal();
-      ExpressionNode exp=parseExpression(pn.getChild("base").getFirstChild());
-      Vector args=parseArgumentList(pn);
+      ExpressionNode exp=parseExpression(cn, pn.getChild("base").getFirstChild());
+      Vector args=parseArgumentList(cn, pn);
       MethodInvokeNode min=new MethodInvokeNode(methodid,exp);
       min.setNumLine(pn.getLine());
       for(int i=0; i<args.size(); i++) {
@@ -1237,7 +1255,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       }
       return min;
     } else if (isNode(pn,"fieldaccess")) {
-      ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild());
+      ExpressionNode en=parseExpression(cn, pn.getChild("base").getFirstChild());
       String fieldname=pn.getChild("field").getTerminal();
 
       FieldAccessNode fan=new FieldAccessNode(en,fieldname);
@@ -1251,7 +1269,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
 	fan.setNumLine(pn.getLine());
 	return fan;
     } else if (isNode(pn,"supernamefieldaccess")) {
-	ExpressionNode en=parseExpression(pn.getChild("base").getFirstChild());
+	ExpressionNode en=parseExpression(cn, pn.getChild("base").getFirstChild());
 	ExpressionNode exp = new FieldAccessNode(en, "super");
 	exp.setNumLine(pn.getLine());
 	String fieldname=pn.getChild("field").getTerminal();
@@ -1260,25 +1278,25 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
 	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());
+      ExpressionNode en=parseExpression(cn, pn.getChild("base").getFirstChild());
+      ExpressionNode index=parseExpression(cn, pn.getChild("index").getFirstChild());
       ArrayAccessNode aan=new ArrayAccessNode(en,index);
       aan.setNumLine(pn.getLine());
       return aan;
     } else if (isNode(pn,"cast1")) {
       try {
-        CastNode cn=new CastNode(parseTypeDescriptor(pn.getChild("type")),parseExpression(pn.getChild("exp").getFirstChild()));
-        cn.setNumLine(pn.getLine());
-        return cn;
+        CastNode castn=new CastNode(parseTypeDescriptor(pn.getChild("type")),parseExpression(cn, pn.getChild("exp").getFirstChild()));
+        castn.setNumLine(pn.getLine());
+        return castn;
       } catch (Exception e) {
         System.out.println(pn.PPrint(1,true));
         e.printStackTrace();
         throw new Error();
       }
     } else if (isNode(pn,"cast2")) {
-      CastNode cn=new CastNode(parseExpression(pn.getChild("type").getFirstChild()),parseExpression(pn.getChild("exp").getFirstChild()));
-      cn.setNumLine(pn.getLine());
-      return cn;
+      CastNode castn=new CastNode(parseExpression(cn, pn.getChild("type").getFirstChild()),parseExpression(cn, pn.getChild("exp").getFirstChild()));
+      castn.setNumLine(pn.getLine());
+      return castn;
     } else if (isNode(pn, "getoffset")) {
       TypeDescriptor td=parseTypeDescriptor(pn);
       String fieldname = pn.getChild("field").getTerminal();
@@ -1286,20 +1304,20 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       return new OffsetNode(td, fieldname);
     } else if (isNode(pn, "tert")) {
 
-      TertiaryNode tn=new TertiaryNode(parseExpression(pn.getChild("cond").getFirstChild()),
-                                       parseExpression(pn.getChild("trueexpr").getFirstChild()),
-                                       parseExpression(pn.getChild("falseexpr").getFirstChild()) );
+      TertiaryNode tn=new TertiaryNode(parseExpression(cn, pn.getChild("cond").getFirstChild()),
+                                       parseExpression(cn, pn.getChild("trueexpr").getFirstChild()),
+                                       parseExpression(cn, pn.getChild("falseexpr").getFirstChild()) );
       tn.setNumLine(pn.getLine());
 
       return tn;
     } else if (isNode(pn, "instanceof")) {
-      ExpressionNode exp=parseExpression(pn.getChild("exp").getFirstChild());
+      ExpressionNode exp=parseExpression(cn, pn.getChild("exp").getFirstChild());
       TypeDescriptor t=parseTypeDescriptor(pn);
       InstanceOfNode ion=new InstanceOfNode(exp,t);
       ion.setNumLine(pn.getLine());
       return ion;
     } else if (isNode(pn, "array_initializer")) {
-      Vector initializers=parseVariableInitializerList(pn);
+      Vector initializers=parseVariableInitializerList(cn, pn);
       return new ArrayInitializerNode(initializers);
     } else if (isNode(pn, "class_type")) {
       TypeDescriptor td=parseTypeDescriptor(pn);
@@ -1315,26 +1333,26 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     }
   }
 
-  private Vector parseDimExprs(ParseNode pn) {
+  private Vector parseDimExprs(ClassDescriptor cn, ParseNode pn) {
     Vector arglist=new Vector();
     ParseNode an=pn.getChild("dim_exprs");
     if (an==null)       /* No argument list */
       return arglist;
     ParseNodeVector anv=an.getChildren();
     for(int i=0; i<anv.size(); i++) {
-      arglist.add(parseExpression(anv.elementAt(i)));
+      arglist.add(parseExpression(cn, anv.elementAt(i)));
     }
     return arglist;
   }
 
-  private Vector parseArgumentList(ParseNode pn) {
+  private Vector parseArgumentList(ClassDescriptor cn, ParseNode pn) {
     Vector arglist=new Vector();
     ParseNode an=pn.getChild("argument_list");
     if (an==null)       /* No argument list */
       return arglist;
     ParseNodeVector anv=an.getChildren();
     for(int i=0; i<anv.size(); i++) {
-      arglist.add(parseExpression(anv.elementAt(i)));
+      arglist.add(parseExpression(cn, anv.elementAt(i)));
     }
     return arglist;
   }
@@ -1351,28 +1369,28 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       ParseNode var=cpn.getChild("var");
       ParseNode exp=cpn.getChild("exp").getFirstChild();
       varlist.add(var.getTerminal());
-      arglist.add(parseExpression(exp));
+      arglist.add(parseExpression(null, exp));
     }
     return new Vector[] {varlist, arglist};
   }
 
-  private Vector parseVariableInitializerList(ParseNode pn) {
+  private Vector parseVariableInitializerList(ClassDescriptor cn, ParseNode pn) {
     Vector varInitList=new Vector();
     ParseNode vin=pn.getChild("var_init_list");
     if (vin==null)       /* No argument list */
       return varInitList;
     ParseNodeVector vinv=vin.getChildren();
     for(int i=0; i<vinv.size(); i++) {
-      varInitList.add(parseExpression(vinv.elementAt(i)));
+      varInitList.add(parseExpression(cn, vinv.elementAt(i)));
     }
     return varInitList;
   }
 
-  private ExpressionNode parseAssignmentExpression(ParseNode pn) {
+  private ExpressionNode parseAssignmentExpression(ClassDescriptor cn, ParseNode pn) {
     AssignOperation ao=new AssignOperation(pn.getChild("op").getTerminal());
     ParseNodeVector pnv=pn.getChild("args").getChildren();
 
-    AssignmentNode an=new AssignmentNode(parseExpression(pnv.elementAt(0)),parseExpression(pnv.elementAt(1)),ao);
+    AssignmentNode an=new AssignmentNode(parseExpression(cn, pnv.elementAt(0)),parseExpression(cn, pnv.elementAt(1)),ao);
     an.setNumLine(pn.getLine());
     return an;
   }
@@ -1383,7 +1401,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     ParseNode bodyn=pn.getChild("body");
     MethodDescriptor md=parseMethodHeader(headern);
     try {
-      BlockNode bn=parseBlock(bodyn);
+      BlockNode bn=parseBlock(cn, bodyn);
       bn.setNumLine(pn.getLine()); // assume that method header is located at the beginning of method body
       cn.addMethod(md);
       state.addTreeCode(md,bn);
@@ -1423,13 +1441,13 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     cn.addMethod(md);
     BlockNode bn=null;
     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
-      bn=parseBlock(bodyn);
+      bn=parseBlock(cn, bodyn);
     else
       bn=new BlockNode();
     if (bodyn!=null&&bodyn.getChild("superinvoke")!=null) {
       ParseNode sin=bodyn.getChild("superinvoke");
       NameDescriptor nd=new NameDescriptor("super");
-      Vector args=parseArgumentList(sin);
+      Vector args=parseArgumentList(cn, sin);
       MethodInvokeNode min=new MethodInvokeNode(nd);
       min.setNumLine(sin.getLine());
       for(int i=0; i<args.size(); i++) {
@@ -1441,7 +1459,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     } else if (bodyn!=null&&bodyn.getChild("explconstrinv")!=null) {
       ParseNode eci=bodyn.getChild("explconstrinv");
       NameDescriptor nd=new NameDescriptor(cn.getSymbol());
-      Vector args=parseArgumentList(eci);
+      Vector args=parseArgumentList(cn, eci);
       MethodInvokeNode min=new MethodInvokeNode(nd);
       min.setNumLine(eci.getLine());
       for(int i=0; i<args.size(); i++) {
@@ -1474,7 +1492,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     cn.incStaticBlocks();
     BlockNode bn=null;
     if (bodyn!=null&&bodyn.getChild("block_statement_list")!=null)
-      bn=parseBlock(bodyn);
+      bn=parseBlock(cn, bodyn);
     else
       bn=new BlockNode();
     if(isfirst) {
@@ -1490,19 +1508,19 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     }
   }
 
-  public BlockNode parseBlock(ParseNode pn) {
+  public BlockNode parseBlock(ClassDescriptor cn, ParseNode pn) {
     this.m_taskexitnum = 0;
     if (pn==null||isEmpty(pn.getTerminal()))
       return new BlockNode();
     ParseNode bsn=pn.getChild("block_statement_list");
-    return parseBlockHelper(bsn);
+    return parseBlockHelper(cn, bsn);
   }
 
-  private BlockNode parseBlockHelper(ParseNode pn) {
+  private BlockNode parseBlockHelper(ClassDescriptor cn, ParseNode pn) {
     ParseNodeVector pnv=pn.getChildren();
     BlockNode bn=new BlockNode();
     for(int i=0; i<pnv.size(); i++) {
-      Vector bsv=parseBlockStatement(pnv.elementAt(i));
+      Vector bsv=parseBlockStatement(cn, pnv.elementAt(i));
       for(int j=0; j<bsv.size(); j++) {
         bn.addBlockStatement((BlockStatementNode)bsv.get(j));
       }
@@ -1510,9 +1528,9 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     return bn;
   }
 
-  public BlockNode parseSingleBlock(ParseNode pn, String label){
+  public BlockNode parseSingleBlock(ClassDescriptor cn, ParseNode pn, String label){
     BlockNode bn=new BlockNode();
-    Vector bsv=parseBlockStatement(pn,label);
+    Vector bsv=parseBlockStatement(cn, pn,label);
     for(int j=0; j<bsv.size(); j++) {
       bn.addBlockStatement((BlockStatementNode)bsv.get(j));
     }
@@ -1520,24 +1538,24 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     return bn;
   }
   
-  public BlockNode parseSingleBlock(ParseNode pn) {
-    return parseSingleBlock(pn,null);
+  public BlockNode parseSingleBlock(ClassDescriptor cn, ParseNode pn) {
+    return parseSingleBlock(cn, pn,null);
   }
 
-  public Vector parseSESEBlock(Vector parentbs, ParseNode pn) {
+  public Vector parseSESEBlock(ClassDescriptor cn, Vector parentbs, ParseNode pn) {
     ParseNodeVector pnv=pn.getChildren();
     Vector bv=new Vector();
     for(int i=0; i<pnv.size(); i++) {
-      bv.addAll(parseBlockStatement(pnv.elementAt(i)));
+      bv.addAll(parseBlockStatement(cn, pnv.elementAt(i)));
     }
     return bv;
   }
   
-  public Vector parseBlockStatement(ParseNode pn){
-    return parseBlockStatement(pn,null);
+  public Vector parseBlockStatement(ClassDescriptor cn, ParseNode pn){
+    return parseBlockStatement(cn, pn,null);
   }
 
-  public Vector parseBlockStatement(ParseNode pn, String label) {
+  public Vector parseBlockStatement(ClassDescriptor cn, ParseNode pn, String label) {
     Vector blockstatements=new Vector();
     if (isNode(pn,"tag_declaration")) {
       String name=pn.getChild("single").getTerminal();
@@ -1570,7 +1588,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
 
         ExpressionNode en=null;
         if (epn!=null)
-          en=parseExpression(epn.getFirstChild());
+          en=parseExpression(cn, epn.getFirstChild());
 
         DeclarationNode dn=new DeclarationNode(new VarDescriptor(arrayt, identifier),en);
         dn.setNumLine(tmp.getLine());
@@ -1587,20 +1605,20 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
     } else if (isNode(pn,"nop")) {
       /* Do Nothing */
     } else if (isNode(pn,"expression")) {
-      BlockExpressionNode ben=new BlockExpressionNode(parseExpression(pn.getFirstChild()));
+      BlockExpressionNode ben=new BlockExpressionNode(parseExpression(cn, pn.getFirstChild()));
       ben.setNumLine(pn.getLine());
       blockstatements.add(ben);
     } else if (isNode(pn,"ifstatement")) {
-      IfStatementNode isn=new IfStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
-                                              parseSingleBlock(pn.getChild("statement").getFirstChild()),
-                                              pn.getChild("else_statement")!=null?parseSingleBlock(pn.getChild("else_statement").getFirstChild()):null);
+      IfStatementNode isn=new IfStatementNode(parseExpression(cn, pn.getChild("condition").getFirstChild()),
+                                              parseSingleBlock(cn, pn.getChild("statement").getFirstChild()),
+                                              pn.getChild("else_statement")!=null?parseSingleBlock(cn, pn.getChild("else_statement").getFirstChild()):null);
       isn.setNumLine(pn.getLine());
 
       blockstatements.add(isn);
     } else if (isNode(pn,"switch_statement")) {
       // TODO add version for normal Java later
-      SwitchStatementNode ssn=new SwitchStatementNode(parseExpression(pn.getChild("condition").getFirstChild()),
-                                                      parseSingleBlock(pn.getChild("statement").getFirstChild()));
+      SwitchStatementNode ssn=new SwitchStatementNode(parseExpression(cn, pn.getChild("condition").getFirstChild()),
+                                                      parseSingleBlock(cn, pn.getChild("statement").getFirstChild()));
       ssn.setNumLine(pn.getLine());
       blockstatements.add(ssn);
     } else if (isNode(pn,"switch_block_list")) {
@@ -1616,7 +1634,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
           for(int j=0; j<labelv.size(); j++) {
             ParseNode labeldecl=labelv.elementAt(j);
             if(isNode(labeldecl, "switch_label")) {
-              SwitchLabelNode sln=new SwitchLabelNode(parseExpression(labeldecl.getChild("constant_expression").getFirstChild()), false);
+              SwitchLabelNode sln=new SwitchLabelNode(parseExpression(cn, labeldecl.getChild("constant_expression").getFirstChild()), false);
               sln.setNumLine(labeldecl.getLine());
               slv.addElement(sln);
             } else if(isNode(labeldecl, "default_switch_label")) {
@@ -1627,7 +1645,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
           }
 
           SwitchBlockNode sbn=new SwitchBlockNode(slv,
-                                                  parseSingleBlock(sblockdecl.getChild("switch_statements").getFirstChild()));
+                                                  parseSingleBlock(cn, sblockdecl.getChild("switch_statements").getFirstChild()));
           sbn.setNumLine(sblockdecl.getLine());
 
           blockstatements.add(sbn);
@@ -1639,13 +1657,13 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       // Do not fully support exceptions now. Only make sure that if there are no
       // exceptions thrown, the execution is right
       ParseNode tpn = pn.getChild("tryblock").getFirstChild();
-      BlockNode bn=parseBlockHelper(tpn);
+      BlockNode bn=parseBlockHelper(cn, tpn);
       blockstatements.add(new SubBlockNode(bn));
 
       ParseNode fbk = pn.getChild("finallyblock");
       if(fbk != null) {
         ParseNode fpn = fbk.getFirstChild();
-        BlockNode fbn=parseBlockHelper(fpn);
+        BlockNode fbn=parseBlockHelper(cn, fpn);
         blockstatements.add(new SubBlockNode(fbn));
       }
     } else if (isNode(pn, "throwstatement")) {
@@ -1662,13 +1680,13 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       ten.setNumLine(pn.getLine());
       blockstatements.add(ten);
     } else if (isNode(pn,"atomic")) {
-      BlockNode bn=parseBlockHelper(pn);
+      BlockNode bn=parseBlockHelper(cn, pn);
       AtomicNode an=new AtomicNode(bn);
       an.setNumLine(pn.getLine());
       blockstatements.add(an);
     } else if (isNode(pn,"synchronized")) {
-      BlockNode bn=parseBlockHelper(pn.getChild("block"));
-      ExpressionNode en=parseExpression(pn.getChild("expr").getFirstChild());
+      BlockNode bn=parseBlockHelper(cn, pn.getChild("block"));
+      ExpressionNode en=parseExpression(cn, pn.getChild("expr").getFirstChild());
       SynchronizedNode sn=new SynchronizedNode(en, bn);
       sn.setNumLine(pn.getLine());
       blockstatements.add(sn);
@@ -1676,13 +1694,13 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       if (isEmpty(pn.getTerminal()))
         blockstatements.add(new ReturnNode());
       else {
-        ExpressionNode en=parseExpression(pn.getFirstChild());
+        ExpressionNode en=parseExpression(cn, pn.getFirstChild());
         ReturnNode rn=new ReturnNode(en);
         rn.setNumLine(pn.getLine());
         blockstatements.add(rn);
       }
     } else if (isNode(pn,"block_statement_list")) {
-      BlockNode bn=parseBlockHelper(pn);
+      BlockNode bn=parseBlockHelper(cn, pn);
       blockstatements.add(new SubBlockNode(bn));
     } else if (isNode(pn,"empty")) {
       /* nop */
@@ -1690,15 +1708,15 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       ParseNodeVector pnv=pn.getChildren();
       BlockNode bn=new BlockNode();
       for(int i=0; i<pnv.size(); i++) {
-        ExpressionNode en=parseExpression(pnv.elementAt(i));
+        ExpressionNode en=parseExpression(cn, pnv.elementAt(i));
         blockstatements.add(new BlockExpressionNode(en));
       }
       bn.setStyle(BlockNode.EXPRLIST);
     } else if (isNode(pn,"forstatement")) {
-      BlockNode init=parseSingleBlock(pn.getChild("initializer").getFirstChild());
-      BlockNode update=parseSingleBlock(pn.getChild("update").getFirstChild());
-      ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
-      BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
+      BlockNode init=parseSingleBlock(cn, pn.getChild("initializer").getFirstChild());
+      BlockNode update=parseSingleBlock(cn, pn.getChild("update").getFirstChild());
+      ExpressionNode condition=parseExpression(cn, pn.getChild("condition").getFirstChild());
+      BlockNode body=parseSingleBlock(cn, pn.getChild("statement").getFirstChild());
       if(condition == null) {
         // no condition clause, make a 'true' expression as the condition
         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
@@ -1707,16 +1725,16 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       ln.setNumLine(pn.getLine());
       blockstatements.add(ln);
     } else if (isNode(pn,"whilestatement")) {
-      ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
-      BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
+      ExpressionNode condition=parseExpression(cn, pn.getChild("condition").getFirstChild());
+      BlockNode body=parseSingleBlock(cn, pn.getChild("statement").getFirstChild());
       if(condition == null) {
         // 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,label));
     } else if (isNode(pn,"dowhilestatement")) {
-      ExpressionNode condition=parseExpression(pn.getChild("condition").getFirstChild());
-      BlockNode body=parseSingleBlock(pn.getChild("statement").getFirstChild());
+      ExpressionNode condition=parseExpression(cn, pn.getChild("condition").getFirstChild());
+      BlockNode body=parseSingleBlock(cn, pn.getChild("statement").getFirstChild());
       if(condition == null) {
         // no condition clause, make a 'true' expression as the condition
         condition = (ExpressionNode) new LiteralNode("boolean", new Boolean(true));
@@ -1734,7 +1752,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
       start.setEnd(end);
       end.setStart(start);
       blockstatements.add(start);
-      blockstatements.addAll(parseSESEBlock(blockstatements,pn.getChild("body").getFirstChild()));
+      blockstatements.addAll(parseSESEBlock(cn, blockstatements,pn.getChild("body").getFirstChild()));
       blockstatements.add(end);
     } else if (isNode(pn,"continue")) {
       ContinueBreakNode cbn=new ContinueBreakNode(false);
@@ -1758,7 +1776,7 @@ private void addOuterClassReferences( ClassDescriptor cn, int depth )
 
     } else if(isNode(pn,"labeledstatement")) {
       String labeledstatement = pn.getChild("name").getTerminal();
-      BlockNode bn=parseSingleBlock(pn.getChild("statement").getFirstChild(),labeledstatement);
+      BlockNode bn=parseSingleBlock(cn, pn.getChild("statement").getFirstChild(),labeledstatement);
       blockstatements.add(new SubBlockNode(bn));
     } else {
       System.out.println("---------------");
diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java
index ece917d7..55b6f77e 100644
--- a/Robust/src/IR/Tree/SemanticCheck.java
+++ b/Robust/src/IR/Tree/SemanticCheck.java
@@ -94,12 +94,6 @@ public class SemanticCheck {
         }
       }
       if (oldstatus<INIT&&fullcheck>=INIT) {
-       /*if (cd.isInnerClass()) {
-          Modifiers fdmodifiers=new Modifiers();
-         FieldDescriptor enclosingfd=new FieldDescriptor(fdmodifiers,new TypeDescriptor(cd.getSurroundingDesc()),"this___enclosing",null,false);
-         cd.addField(enclosingfd);
-       }*/
-
         /* Check to see that fields are well typed */
         for(Iterator field_it=cd.getFields(); field_it.hasNext(); ) {
           FieldDescriptor fd=(FieldDescriptor)field_it.next();
@@ -143,10 +137,30 @@ public class SemanticCheck {
       } else {
         ClassDescriptor cd = (ClassDescriptor) obj;
         toanalyze.remove(cd);
-
-        // need to initialize typeutil object here...only place we can
-        // get class descriptors without first calling getclass
-        getClass(cd, cd.getSymbol());
+        if(cd.getInline()) {
+          getClass(cd, cd.getSymbol());
+          // for inline defined anonymous classes, we need to check its 
+          // surrounding class first to get its surrounding context
+          ClassDescriptor surroundingcd = cd.getSurroundingDesc();
+          if(toanalyze.contains(surroundingcd)) {
+            toanalyze.remove(surroundingcd);
+            getClass(surroundingcd, surroundingcd.getSymbol());
+            for (Iterator method_it = surroundingcd.getMethods(); method_it.hasNext(); ) {
+              MethodDescriptor md = (MethodDescriptor) method_it.next();
+              try {
+                checkMethodBody(surroundingcd, md);
+              } catch (Error e) {
+                System.out.println("Error in " + md);
+                throw e;
+              }
+            }
+          }
+        } else {
+          // need to initialize typeutil object here...only place we can
+          // get class descriptors without first calling getclass
+          getClass(cd, cd.getSymbol());
+        }
+        
         for (Iterator method_it = cd.getMethods(); method_it.hasNext(); ) {
           MethodDescriptor md = (MethodDescriptor) method_it.next();
           try {
@@ -745,31 +759,6 @@ public class SemanticCheck {
 	}
 	throw new Error("Unknown field "+fieldname + " in "+fan.printNode(0)+" in "+md);
     }
-    /*if (fd==null) {
-      ClassDescriptor surroundingCls=ltd.getClassDesc().getSurroundingDesc();
-      int numencloses=1;
-      while(surroundingCls!=null) {
-       fd=(FieldDescriptor)surroundingCls.getFieldTable().get(fieldname);
-       if (fd!=null) {
-         surroundingCls=ltd.getClassDesc().getSurroundingDesc();
-         FieldAccessNode ftmp=fan;
-         for(;numencloses>0;numencloses--) {
-           FieldAccessNode fnew=new FieldAccessNode(ftmp.left, "this___enclosing");
-           fnew.setField((FieldDescriptor)surroundingCls.getFieldTable().get("this___enclosing"));
-           ftmp.left=fnew;
-           ftmp=fnew;
-           surroundingCls=surroundingCls.getSurroundingDesc();
-         }
-         break;
-       }
-       surroundingCls=surroundingCls.getSurroundingDesc();
-       numencloses++;
-      }
-
-      if (fd==null)
-       throw new Error("Unknown field "+fieldname + " in "+fan.printNode(0)+" in "+md);
-    }*/
-
 
     if (fd.getType().iswrapper()) {
       FieldAccessNode fan2=new FieldAccessNode(left, fieldname);
@@ -924,7 +913,7 @@ public class SemanticCheck {
 			nn.setExpression(( ExpressionNode )theFieldNode);
       			checkExpressionNode(md,nametable,( ExpressionNode )theFieldNode,td);
 			return;		
-		}		
+		}
 	}
         if((md instanceof MethodDescriptor) && ((MethodDescriptor)md).isStaticBlock()) {
           // this is a static block, all the accessed fields should be static field
@@ -976,6 +965,7 @@ public class SemanticCheck {
           }
         }
       }
+
       if (d instanceof VarDescriptor) {
         nn.setVar(d);
       } else if (d instanceof FieldDescriptor) {
@@ -1186,6 +1176,37 @@ public class SemanticCheck {
 	}
 	//System.out.println( " the modified createObjectNode is " + con.printNode( 0 ) + "\n" );
 }
+  
+  // add all the vars in the surrounding context of the inline class into the inline 
+  // classes field table and pass them to the inline class' constructors
+  // TODO: BUGFIX. There need not add all the local vars of the surrounding context 
+  // into the inline class. Should only add those that are referred to inside the inline
+  // class. Also these local vars should be final. But currently we've lost those 
+  // information, so we cannot have that checked.
+  void InlineClassAddParamToCtor(MethodDescriptor md, ClassDescriptor cd , SymbolTable nametable, CreateObjectNode con, TypeDescriptor td ) {
+      Iterator it_values = nametable.getAllValueSet().iterator();
+      while(it_values.hasNext()) {
+	  Descriptor d = (Descriptor)it_values.next();
+	  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));
+	      for(Iterator it_methods = cd.getMethods(); it_methods.hasNext();) {
+		  MethodDescriptor imd = (MethodDescriptor)it_methods.next();
+		  if(imd.isConstructor()) {
+		      imd.addParameter(((VarDescriptor)d).getType(), d.getSymbol()+"_p");
+		      // add the initialize statement into this constructor
+		      BlockNode obn = state.getMethodBody(imd);
+		      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(imd, obn);
+		  }
+	      }
+	  }
+      }
+  }
+  
   void checkCreateObjectNode(Descriptor md, SymbolTable nametable, CreateObjectNode con,
                              TypeDescriptor td) {
     TypeDescriptor[] tdarray = new TypeDescriptor[con.numArgs()];
@@ -1244,6 +1265,11 @@ public class SemanticCheck {
       checkClass(classtolookin, INIT);
       if( classtolookin.isInnerClass() ) {
       	InnerClassAddParamToCtor( (MethodDescriptor)md, ((MethodDescriptor)md).getClassDesc() , nametable, con, td );
+      	if(classtolookin.getInline()) {
+    	  // for an inline anonymous inner class, all the local variables are passed as
+      	  // parameters of the constructors of the inline class
+      	  InlineClassAddParamToCtor( (MethodDescriptor)md, classtolookin, nametable, con, td );
+      	}
 	tdarray = new TypeDescriptor[con.numArgs()];
     	for (int i = 0; i < con.numArgs(); i++) {
       		ExpressionNode en = con.getArg(i);
diff --git a/Robust/src/Tests/DoTests b/Robust/src/Tests/DoTests
index bddaa4ee..687668f1 100755
--- a/Robust/src/Tests/DoTests
+++ b/Robust/src/Tests/DoTests
@@ -24,4 +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 innerCallback.java
+dotest inner inner.java innerp.java innerpt.java innerCallback.java
diff --git a/Robust/src/Tests/output/inner.output.goal b/Robust/src/Tests/output/inner.output.goal
index 31735e74..79d81794 100644
--- a/Robust/src/Tests/output/inner.output.goal
+++ b/Robust/src/Tests/output/inner.output.goal
@@ -10,3 +10,4 @@ Outer class print: 35; 0
 3
 4
 Outer class print: 35; 3
+innerCallback: 100
-- 
2.34.1