package com.hpctoday.fada.c2fada;
import java.util.Stack;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTForStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTIfStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTWhileStatement;
import com.hpctoday.fada.*;
/*
* This class creates the FADA Control structure node
* (for loop, while loop, if/else and body)
*/
public class ControlVisitor extends ASTVisitor {
Stack <Statement> stmtStack;
Stack <Boolean> elseFlagStack;
Statement parent;
ControlVisitor(Statement _parent) {
stmtStack = new Stack <Statement>();
elseFlagStack = new Stack<Boolean> ();
parent = _parent;
this.shouldVisitStatements=true;
}
@Override
public int visit(IASTStatement stmt) {
if (stmt instanceof IASTCompoundStatement) {
IASTStatement[] mystmts = ((IASTCompoundStatement) stmt).getStatements();
for (int i = 0; i < mystmts.length; i++) {
visit(mystmts[i]);
}
} else if (stmt instanceof IASTForStatement) {
IASTForStatement fstmt = (IASTForStatement) stmt;
IASTStatement initializer = fstmt.getInitializerStatement();
String initVar;
ExprVisitor initExpr = new ExprVisitor();
ExprVisitor finalExpr = new ExprVisitor();
if (initializer instanceof IASTDeclarationStatement) {
IASTDeclarationStatement declaration = (IASTDeclarationStatement) initializer;
IASTSimpleDeclaration simple = (IASTSimpleDeclaration) (declaration.getDeclaration());
IASTDeclarator[] declarators = simple.getDeclarators();
initVar = declarators[0].getName().getRawSignature();
((IASTEqualsInitializer) (declarators[0].getInitializer())).getInitializerClause().accept(initExpr);
} else {
initVar = ((IASTBinaryExpression) (((IASTExpressionStatement) initializer)
.getExpression())).getOperand1().getRawSignature();
((IASTBinaryExpression) (((IASTExpressionStatement) initializer).getExpression())).getOperand2().accept(initExpr);
}
int forOperator = ((IASTBinaryExpression) (fstmt.getConditionExpression())).getOperator();
Expression LBExpr, UBExpr;
int stride = 1; //FIXME: ACTUALLY COMPUTE STRIDE
((IASTBinaryExpression) (fstmt.getConditionExpression())).getOperand2().accept(finalExpr);
//condition is <=
if (forOperator == IASTBinaryExpression.op_lessEqual){
LBExpr = initExpr.getExpr();
UBExpr = finalExpr.getExpr();
}
else if (forOperator == IASTBinaryExpression.op_lessThan){
LBExpr = initExpr.getExpr();
UBExpr = finalExpr.getExpr();;
UBExpr = UBExpr.sub(new Expression(stride));
}
else if (forOperator == IASTBinaryExpression.op_greaterEqual){
LBExpr = finalExpr.getExpr();
UBExpr = initExpr.getExpr();
}
else if (forOperator == IASTBinaryExpression.op_greaterThan){
LBExpr = finalExpr.getExpr();
LBExpr = LBExpr.add(new Expression(stride));
UBExpr = initExpr.getExpr();
}
else {
//CRASH HERE
throw new RuntimeException ("PARSER CAN'T HANDLE EXCEPTION");
}
//_iterList.add(initVar);
IASTExpression condition = ((IASTBinaryExpression) (fstmt.getConditionExpression())).getOperand2();
//if (condition instanceof IASTIdExpression){
// _paramList.add(condition.getRawSignature());
//}
Control forControl = new Control(initVar, LBExpr, UBExpr);
Statement forStmt = new Statement(forControl); //factory.create(fstmt, forControl);
if (!stmtStack.empty()) stmtStack.peek().Enclose(forStmt, elseFlagStack.peek());
stmtStack.push(forStmt); elseFlagStack.push(false);
visit(fstmt.getBody());
if (stmtStack.size() == 1) parent.Enclose(stmtStack.peek(), elseFlagStack.peek());
stmtStack.pop(); elseFlagStack.pop();
return PROCESS_SKIP;
} else if (stmt instanceof IASTIfStatement) {
ExprVisitor condVisitor = new ExprVisitor();
((IASTIfStatement) stmt).getConditionExpression().accept(condVisitor);
Control ifControl = new Control(condVisitor.getCond());
Statement ifStmt = new Statement(ifControl); //factory.create(stmt, ifControl);
if (!stmtStack.empty()) stmtStack.peek().Enclose(ifStmt, elseFlagStack.peek());
stmtStack.push(ifStmt); elseFlagStack.push(false);
visit(((IASTIfStatement) stmt).getThenClause());
/* ExprVisitor elseCondVisitor = new ExprVisitor();
((IASTIfStatement) stmt).getElseClause().accept(elseCondVisitor);
Control elseControl = new Control((FadaCondition) (condVisitor.finalExpr)); */
if (((IASTIfStatement) stmt).getElseClause() != null) {
//factory creates dummy node for else statement, since FADA does not have a proper else node
//Statement emptyStmt = factory.create(((IASTIfStatement) stmt).getElseClause());
//if (lparent >=0) stmts[lparent].enclose(emptyStmt, stmtParentEncloseElse[lparent]);
elseFlagStack.set(elseFlagStack.size() - 1, true);
visit(((IASTIfStatement) stmt).getElseClause());
elseFlagStack.set(elseFlagStack.size() - 1, false);
}
if (stmtStack.size() == 1) parent.Enclose(stmtStack.peek(), elseFlagStack.peek());
stmtStack.pop(); elseFlagStack.pop();
return PROCESS_SKIP;
} else if (stmt instanceof IASTWhileStatement) {
IASTWhileStatement whileStmt = (IASTWhileStatement) stmt;
WhileCounterVisitor whileCounter = new WhileCounterVisitor();
whileStmt.getBody().accept(whileCounter);
ExprVisitor condVisitor = new ExprVisitor();
whileStmt.getCondition().accept(condVisitor);
//IASTExpression lc = ((IASTBinaryExpression) whileStmt.getCondition()).getOperand1();
Control whileControl = new Control("W_" + whileCounter.getCounter(), condVisitor.getCond());
Statement fadaWhileStmt = new Statement(whileControl); //factory.create(whileStmt, whileControl);
if (!stmtStack.empty()) stmtStack.peek().Enclose(fadaWhileStmt, elseFlagStack.peek());
stmtStack.push(fadaWhileStmt); elseFlagStack.push(false);
visit(whileStmt.getBody());
if (stmtStack.size() == 1) parent.Enclose(stmtStack.peek(), elseFlagStack.peek());
stmtStack.pop(); elseFlagStack.pop();
return PROCESS_SKIP;
}
else {
stmt.accept(new StmtVisitor(stmtStack.peek(), stmt, elseFlagStack.peek()));
return PROCESS_SKIP;
}
return PROCESS_SKIP;
}
}