blob: 6b0d3fe7db91ad8f64d051921e8b7207042df060 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 Nokia and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Nokia - Initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.debug.edc.internal.eval.ast.engine;
import java.util.Stack;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTComment;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTFieldReference;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.IASTProblem;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTEnumerationSpecifier.IASTEnumerator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.EDCTrace;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.ArraySubscript;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.CompoundInstruction;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.EvaluateID;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.FieldReference;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.Instruction;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.InstructionSequence;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.NoOp;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorAddrOf;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorBinaryAnd;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorBinaryOr;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorBinaryXor;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorBitwiseNot;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorCast;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorCastValue;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorDivide;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorEquals;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorGreaterEqual;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorGreaterThan;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorIndirection;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorLessEqual;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorLessThan;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorLogicalAnd;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorLogicalNot;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorLogicalOr;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorMinus;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorModulo;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorMultiply;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorNotEquals;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorPlus;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorShiftLeft;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorShiftRight;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorUnaryMinus;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.OperatorUnaryPlus;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.PushBoolean;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.PushChar;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.PushDouble;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.PushFloat;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.PushLongOrBigInteger;
import org.eclipse.cdt.debug.edc.internal.eval.ast.engine.instructions.PushString;
import org.eclipse.cdt.debug.edc.symbols.TypeEngine;
import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode;
@SuppressWarnings("restriction")
public class ASTInstructionCompiler extends ASTVisitor {
private final Stack<Instruction> stack;
private final InstructionSequence instructions;
private int counter;
private String errorMessage;
private boolean active = true;
public ASTInstructionCompiler( String snippet) {
super(true);
stack = new Stack<Instruction>();
instructions = new InstructionSequence(snippet);
}
private void push(Instruction i) {
stack.push(i);
}
private Instruction pop() {
return stack.pop();
}
/**
* Returns the instruction sequence generated by this AST instruction
* compiler
*/
public InstructionSequence getInstructions() {
return instructions;
}
public boolean hasErrors() {
return errorMessage != null;
}
public String getErrorMessage() {
return errorMessage;
}
private boolean isActive() {
return active;
}
private void storeInstruction() {
Instruction instruction = pop();
counter++;
if (instruction instanceof CompoundInstruction) {
((CompoundInstruction) instruction).setEnd(counter);
}
instructions.add(instruction);
}
@Override
public int leave(IASTArrayModifier arrayModifier) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(arrayModifier)); }
return super.leave(arrayModifier);
}
@SuppressWarnings("deprecation") // we're simply wrapping a deprecated method
@Override
public int leave(IASTComment comment) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(comment)); }
return super.leave(comment);
}
@Override
public int leave(IASTDeclaration declaration) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(declaration)); }
return super.leave(declaration);
}
@Override
public int leave(IASTDeclarator declarator) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(declarator)); }
return super.leave(declarator);
}
@Override
public int leave(IASTDeclSpecifier declSpec) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(declSpec)); }
return super.leave(declSpec);
}
@Override
public int leave(IASTEnumerator enumerator) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(enumerator)); }
return super.leave(enumerator);
}
@Override
public int leave(IASTExpression expression) {
if (!isActive() || hasErrors())
return PROCESS_CONTINUE;
storeInstruction();
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(expression)); }
return super.leave(expression);
}
@Override
public int leave(IASTInitializer initializer) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(initializer)); }
return super.leave(initializer);
}
@Override
public int leave(IASTName name) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(name)); }
return super.leave(name);
}
@Override
public int leave(IASTParameterDeclaration parameterDeclaration) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(parameterDeclaration)); }
return super.leave(parameterDeclaration);
}
@Override
public int leave(IASTPointerOperator ptrOperator) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(ptrOperator)); }
return super.leave(ptrOperator);
}
@Override
public int leave(IASTProblem problem) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(problem)); }
return super.leave(problem);
}
@Override
public int leave(IASTStatement statement) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(statement)); }
return super.leave(statement);
}
@Override
public int leave(IASTTranslationUnit tu) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(tu)); }
return super.leave(tu);
}
@Override
public int leave(IASTTypeId typeId) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(typeId)); }
return super.leave(typeId);
}
@Override
public int visit(IASTArrayModifier arrayModifier) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(arrayModifier)); }
return super.visit(arrayModifier);
}
@SuppressWarnings("deprecation") // we're simply wrapping a deprecated method
@Override
public int visit(IASTComment comment) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(comment)); }
return super.visit(comment);
}
@Override
public int visit(IASTDeclaration declaration) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(declaration)); }
return super.visit(declaration);
}
@Override
public int visit(IASTDeclarator declarator) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(declarator)); }
return super.visit(declarator);
}
@Override
public int visit(IASTDeclSpecifier declSpec) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(declSpec)); }
return super.visit(declSpec);
}
@Override
public int visit(IASTEnumerator enumerator) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(enumerator)); }
return super.visit(enumerator);
}
@Override
public int visit(IASTInitializer initializer) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(initializer)); }
return super.visit(initializer);
}
@Override
public int visit(IASTParameterDeclaration parameterDeclaration) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg("visit: " + parameterDeclaration.getClass().getSimpleName())); } //$NON-NLS-1$
return super.visit(parameterDeclaration);
}
@Override
public int visit(IASTPointerOperator ptrOperator) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(ptrOperator)); }
return super.visit(ptrOperator);
}
@Override
public int visit(IASTStatement statement) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(statement)); }
return super.visit(statement);
}
@Override
public int visit(IASTTranslationUnit tu) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(tu)); }
return super.visit(tu);
}
@Override
public int visit(IASTTypeId typeId) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(typeId)); }
return super.visit(typeId);
}
@Override
public int visit(ASTAmbiguousNode astAmbiguousNode) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(astAmbiguousNode)); }
return super.visit(astAmbiguousNode);
}
@Override
public int visit(IASTName name) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(name)); }
return super.visit(name);
}
@Override
public int visit(IASTProblem problem) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(problem)); }
return super.visit(problem);
}
@Override
public int visit(IASTExpression expression) {
if (EDCTrace.EXPRESSION_PARSE_TRACE_ON) { EDCTrace.getTrace().traceEntry(null, EDCTrace.fixArg(expression)); }
if (expression instanceof IASTLiteralExpression) {
visitLiteralExpression((IASTLiteralExpression) expression);
} else if (expression instanceof IASTBinaryExpression) {
visitBinaryExpression((IASTBinaryExpression) expression);
} else if (expression instanceof IASTUnaryExpression) {
visitUnaryExpression((IASTUnaryExpression) expression);
} else if (expression instanceof IASTIdExpression) {
visitIDExpression((IASTIdExpression) expression);
} else if (expression instanceof IASTArraySubscriptExpression) {
visitArraySubscriptExpression((IASTArraySubscriptExpression) expression);
} else if (expression instanceof IASTFieldReference) {
visitFieldReference((IASTFieldReference) expression);
} else if (expression instanceof IASTCastExpression) {
visitCastExpression((IASTCastExpression) expression);
} else
push(new NoOp(counter));
return super.visit(expression);
}
private void visitIDExpression(IASTIdExpression expression) {
push(new EvaluateID(expression));
}
private void visitArraySubscriptExpression(IASTArraySubscriptExpression expression) {
push(new ArraySubscript(counter));
}
private void visitFieldReference(IASTFieldReference expression) {
push(new FieldReference(expression, counter));
}
private void visitCastExpression(IASTCastExpression expression) {
if (expression.getOperator() == ICPPASTCastExpression.op_reinterpret_cast)
push(new OperatorCastValue(counter, expression));
else
push(new OperatorCast(counter, expression));
}
private void visitLiteralExpression(IASTLiteralExpression expression) {
int kind = expression.getKind();
String value = new String(expression.getValue());
switch (kind) {
case IASTLiteralExpression.lk_integer_constant:
try {
push(new PushLongOrBigInteger(value));
} catch (NumberFormatException nfe) {
errorMessage = ASTEvalMessages.ASTInstructionCompiler_InvalidNumber;
}
break;
case IASTLiteralExpression.lk_float_constant:
// check for explicitly float constant
try {
if (value.toUpperCase().endsWith("F")) //$NON-NLS-1$
push(new PushFloat(value));
else
push(new PushDouble(value));
} catch (NumberFormatException nfe) {
errorMessage = ASTEvalMessages.ASTInstructionCompiler_InvalidNumber;
}
break;
case IASTLiteralExpression.lk_char_constant:
try {
push(new PushChar(value));
} catch (NumberFormatException nfe) {
errorMessage = ASTEvalMessages.ASTInstructionCompiler_InvalidNumber;
}
break;
case IASTLiteralExpression.lk_string_literal:
push(new PushString(value));
break;
case IASTLiteralExpression.lk_false:
push(new PushBoolean(false));
break;
case IASTLiteralExpression.lk_true:
push(new PushBoolean(true));
break;
case IASTLiteralExpression.lk_this:
push(new EvaluateID("this")); //$NON-NLS-1$
break;
default:
push(new NoOp(counter));
}
}
private void visitBinaryExpression(IASTBinaryExpression expression) {
int op = expression.getOperator();
switch (op) {
case IASTBinaryExpression.op_binaryAnd:
push(new OperatorBinaryAnd(counter));
break;
case IASTBinaryExpression.op_binaryOr:
push(new OperatorBinaryOr(counter));
break;
case IASTBinaryExpression.op_binaryXor:
push(new OperatorBinaryXor(counter));
break;
case IASTBinaryExpression.op_plus:
push(new OperatorPlus(counter));
break;
case IASTBinaryExpression.op_minus:
push(new OperatorMinus(counter));
break;
case IASTBinaryExpression.op_multiply:
push(new OperatorMultiply(counter));
break;
case IASTBinaryExpression.op_divide:
push(new OperatorDivide(counter));
break;
case IASTBinaryExpression.op_modulo:
push(new OperatorModulo(counter));
break;
case IASTBinaryExpression.op_shiftLeft:
push(new OperatorShiftLeft(counter));
break;
case IASTBinaryExpression.op_shiftRight:
push(new OperatorShiftRight(counter));
break;
case IASTBinaryExpression.op_equals:
push(new OperatorEquals(counter));
break;
case IASTBinaryExpression.op_notequals:
push(new OperatorNotEquals(counter));
break;
case IASTBinaryExpression.op_greaterEqual:
push(new OperatorGreaterEqual(counter));
break;
case IASTBinaryExpression.op_greaterThan:
push(new OperatorGreaterThan(counter));
break;
case IASTBinaryExpression.op_lessEqual:
push(new OperatorLessEqual(counter));
break;
case IASTBinaryExpression.op_lessThan:
push(new OperatorLessThan(counter));
break;
case IASTBinaryExpression.op_logicalAnd:
push(new OperatorLogicalAnd(counter));
break;
case IASTBinaryExpression.op_logicalOr:
push(new OperatorLogicalOr(counter));
break;
default:
push(new NoOp(counter));
}
}
private void visitUnaryExpression(IASTUnaryExpression expression) {
int op = expression.getOperator();
switch (op) {
case IASTUnaryExpression.op_minus:
push(new OperatorUnaryMinus(counter));
break;
case IASTUnaryExpression.op_not:
push(new OperatorLogicalNot(counter));
break;
case IASTUnaryExpression.op_plus:
push(new OperatorUnaryPlus(counter));
break;
case IASTUnaryExpression.op_tilde:
push(new OperatorBitwiseNot(counter));
break;
case IASTUnaryExpression.op_star:
push(new OperatorIndirection(counter));
break;
case IASTUnaryExpression.op_amper:
push(new OperatorAddrOf(counter));
break;
default:
push(new NoOp(counter));
}
}
}