package com.hpctoday.fada.c2fada;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import com.hpctoday.fada.Condition;
import com.hpctoday.fada.Expression;
import com.hpctoday.fada.Inequation;
public class ExprVisitor extends ASTVisitor {
Expression finalExpr;
Condition finalCond;
boolean isCondition;
ExprVisitor() {
this.shouldVisitExpressions=true;
finalExpr = null;
finalCond = null;
}
public Expression getExpr() {
if(finalExpr == null){
throw new RuntimeException("Expression is null");
}
return finalExpr;
}
public Condition getCond() {
if(finalCond == null){
throw new RuntimeException("Condition is null");
}
return finalCond;
}
private boolean checkIsCondition (IASTBinaryExpression bexpr) {
int op = bexpr.getOperator();
if (op == IASTBinaryExpression.op_greaterThan ||
op == IASTBinaryExpression.op_lessThan ||
op == IASTBinaryExpression.op_greaterEqual ||
op == IASTBinaryExpression.op_lessEqual ||
op == IASTBinaryExpression.op_logicalAnd ||
op == IASTBinaryExpression.op_logicalOr ||
op == IASTBinaryExpression.op_notequals ||
op == IASTBinaryExpression.op_equals)
return true;
return false;
}
private int visit_condition_expression(IASTBinaryExpression bexpr) {
ExprVisitor lhs = new ExprVisitor();
ExprVisitor rhs = new ExprVisitor();
bexpr.getOperand1().accept(lhs);
bexpr.getOperand2().accept(rhs);
switch (bexpr.getOperator()) {
case IASTBinaryExpression.op_logicalAnd:
finalCond = new Condition(lhs.getCond(), Condition.Logical_Operator.FADA_AND, rhs.getCond());
break;
case IASTBinaryExpression.op_logicalOr:
finalCond = new Condition(lhs.getCond(), Condition.Logical_Operator.FADA_OR, rhs.getCond());
break;
case IASTBinaryExpression.op_equals:
finalCond = new Condition(new Inequation(lhs.getExpr(), Inequation.Predicate.FADA_EQ, rhs.getExpr()));
break;
case IASTBinaryExpression.op_notequals:
finalCond = new Condition(new Inequation(lhs.getExpr(), Inequation.Predicate.FADA_NEQ, rhs.getExpr()));
break;
case IASTBinaryExpression.op_lessThan:
finalCond = new Condition(new Inequation(lhs.getExpr(), Inequation.Predicate.FADA_LESS, rhs.getExpr()));
break;
case IASTBinaryExpression.op_lessEqual:
finalCond = new Condition(new Inequation(lhs.getExpr(), Inequation.Predicate.FADA_LESS_EQ, rhs.getExpr()));
break;
case IASTBinaryExpression.op_greaterThan:
finalCond = new Condition(new Inequation(lhs.getExpr(), Inequation.Predicate.FADA_GREATER, rhs.getExpr()));
break;
case IASTBinaryExpression.op_greaterEqual:
finalCond = new Condition(new Inequation(lhs.getExpr(), Inequation.Predicate.FADA_GREATER_EQ, rhs.getExpr()));
break;
default:
System.err.println("COND OP NOT HANDLED: " + bexpr.getOperator() + " -> " + bexpr.getRawSignature());
}
return PROCESS_SKIP;
}
private int visit(IASTUnaryExpression expr){
ExprVisitor operandVisitor = new ExprVisitor();
ExprVisitor opr;
switch (expr.getOperator()){
case IASTUnaryExpression.op_bracketedPrimary:
return visit(expr.getOperand());
case IASTUnaryExpression.op_not:
expr.getOperand().accept(operandVisitor);
finalCond = operandVisitor.getCond().Negate();
break;
case IASTUnaryExpression.op_prefixIncr:
opr = new ExprVisitor();
expr.getOperand().accept(opr);
finalExpr = opr.getExpr().add(new Expression(1));
break;
case IASTUnaryExpression.op_minus:
opr = new ExprVisitor();
expr.getOperand().accept(opr);
//FIXME what if operand is floating number
finalExpr = opr.getExpr().mul(new Expression(-1));
break;
case IASTUnaryExpression.op_plus:
opr = new ExprVisitor();
expr.getOperand().accept(opr);
finalExpr = opr.getExpr();
break;
default:
System.err.println ("UNARY OP NOT HANDLED: " + expr.getOperator() + " -> " + expr.getRawSignature());
}
return PROCESS_SKIP;
}
private int visit_binary_expression(IASTBinaryExpression bexpr) {
ExprVisitor lhs = new ExprVisitor();
ExprVisitor rhs = new ExprVisitor();
bexpr.getOperand1().accept(lhs);
bexpr.getOperand2().accept(rhs);
switch (bexpr.getOperator()) {
case IASTBinaryExpression.op_plus:
case IASTBinaryExpression.op_modulo:
finalExpr = lhs.getExpr().add(rhs.getExpr());
break;
case IASTBinaryExpression.op_minus:
finalExpr = lhs.getExpr().sub(rhs.getExpr());
break;
case IASTBinaryExpression.op_divide:
finalExpr = lhs.getExpr().div(rhs.getExpr());
break;
case IASTBinaryExpression.op_multiply:
finalExpr = lhs.getExpr().mul(rhs.getExpr());
break;
default:
System.err.println("BINARY OP NOT HANDLED:" + bexpr.getOperator() + " -> " + bexpr.getRawSignature());
}
return PROCESS_SKIP;
}
public int visit(IASTExpression expr) {
if (expr instanceof IASTBinaryExpression) {
IASTBinaryExpression bexpr = (IASTBinaryExpression)expr;
boolean isCondition = checkIsCondition(bexpr);
if (isCondition) {
return visit_condition_expression(bexpr);
} else {
return visit_binary_expression(bexpr);
}
}else if (expr instanceof IASTIdExpression){
//IASTIdExpression id = (IASTIdExpression) expr;
//System.err.println(id.getName().getBinding());
finalExpr = new Expression(expr.getRawSignature());
return PROCESS_SKIP;
} else if (expr instanceof IASTLiteralExpression) {
IASTLiteralExpression literal = (IASTLiteralExpression) expr;
try {
int value = Integer.parseInt(literal.getRawSignature());
finalExpr = new Expression(value);
} catch (NumberFormatException ex){
//finalExpr = new Expression(expr.getRawSignature());
finalExpr = new Expression(1000);
}
return PROCESS_SKIP;
} else if (expr instanceof IASTArraySubscriptExpression){
ArrayAccessVisitor aVisitor = new ArrayAccessVisitor();
expr.accept(aVisitor);
finalExpr = new Expression(aVisitor.id);
for (int i = aVisitor.indices.size()-1; i >=0; i--) {
finalExpr.AddIndex(aVisitor.indices.get(i));
}
finalCond = new Condition(new Inequation(finalExpr, Inequation.Predicate.FADA_NEQ, new Expression(0)));
return PROCESS_SKIP;
} else if (expr instanceof IASTUnaryExpression){
return visit ((IASTUnaryExpression)expr);
} else if (expr instanceof IASTFunctionCallExpression){
IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression)expr;
List<Expression> arguments = new ArrayList<Expression>();
for(IASTInitializerClause argument: funcExpr.getArguments()){
ExprVisitor visitor = new ExprVisitor();
argument.accept(visitor);
arguments.add(visitor.getExpr());
}
finalExpr = new Expression(Expression.Leaf.FADA_function, funcExpr.getFunctionNameExpression().getRawSignature(), arguments);
finalCond = new Condition(new Inequation(finalExpr, Inequation.Predicate.FADA_NEQ, new Expression(0)));
return PROCESS_SKIP;
} else {
System.err.println("ExprVisitor.visit: " + expr.getRawSignature() + " " + expr.getClass());
return PROCESS_ABORT;
}
}
}