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) {
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();
+ 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(); ) {
+ 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) {
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;
}
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;
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);
}
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);
//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();
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");
ParseNode epn=vardecl.getChild("initializer");
ExpressionNode en=null;
+
if (epn!=null) {
en=parseExpression(epn.getFirstChild());
en.setNumLine(epn.getFirstChild().getLine());
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")||
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));
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);
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++) {
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());
-
- FieldAccessNode fan=new FieldAccessNode(nn,"this$parent");
+ //because inner classes pass right thru......
+ FieldAccessNode fan=new FieldAccessNode(nn,"this");
fan.setNumLine(pn.getLine());
return fan;
} else if (isNode(pn,"isavailable")) {
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());