001: /*
002: * Spoon - http://spoon.gforge.inria.fr/
003: * Copyright (C) 2006 INRIA Futurs <renaud.pawlak@inria.fr>
004: *
005: * This software is governed by the CeCILL-C License under French law and
006: * abiding by the rules of distribution of free software. You can use, modify
007: * and/or redistribute the software under the terms of the CeCILL-C license as
008: * circulated by CEA, CNRS and INRIA at http://www.cecill.info.
009: *
010: * This program is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details.
013: *
014: * The fact that you are presently reading this means that you have had
015: * knowledge of the CeCILL-C license and that you accept its terms.
016: */
017:
018: package spoon.reflect.eval;
019:
020: import java.util.List;
021: import java.util.Map;
022: import java.util.Stack;
023:
024: import spoon.reflect.code.CtAbstractInvocation;
025: import spoon.reflect.reference.CtExecutableReference;
026: import spoon.reflect.reference.CtVariableReference;
027:
028: /**
029: * This class defines a symbolic evaluation stack for
030: * {@link spoon.reflect.eval.SymbolicEvaluator}.
031: */
032: public class SymbolicEvaluationStack {
033:
034: /**
035: * Tests the equality with another stack.
036: */
037: @Override
038: public boolean equals(Object obj) {
039: SymbolicEvaluationStack c = (SymbolicEvaluationStack) obj;
040: return frameStack.equals(c.frameStack);
041: }
042:
043: private Stack<SymbolicStackFrame> frameStack = new Stack<SymbolicStackFrame>();
044:
045: /**
046: * Constructs and returns the calling stack for this evaluation stack.
047: */
048: public Stack<CtAbstractInvocation<?>> getCallingStack() {
049: Stack<CtAbstractInvocation<?>> s = new Stack<CtAbstractInvocation<?>>();
050: for (SymbolicStackFrame f : frameStack) {
051: s.add(f.getInvocation());
052: }
053: return s;
054: }
055:
056: /**
057: * Enters and creates a new {@link SymbolicStackFrame}, which is pushed on
058: * the top of the stack.
059: *
060: * @param caller
061: * the invocation that starts this new frame
062: * @param target
063: * the target of the invocation (to be <code>this</code>, see
064: * {@link #getThis()})
065: * @param executable
066: * the entered executable
067: * @param variables
068: * the variables accessible from the frame (invocation's
069: * parameters)
070: */
071: public void enterFrame(CtAbstractInvocation<?> caller,
072: SymbolicInstance<?> target,
073: CtExecutableReference<?> executable,
074: List<SymbolicInstance<?>> arguments,
075: Map<CtVariableReference<?>, SymbolicInstance<?>> variables) {
076: frameStack.push(new SymbolicStackFrame(caller, frameStack
077: .isEmpty() ? null : frameStack.peek().getThis(),
078: target, executable, arguments, variables));
079: }
080:
081: /**
082: * Pops the top frame in order to leave it.
083: */
084: public void exitFrame() {
085: frameStack.pop();
086: }
087:
088: /**
089: * Gets the this value of the top frame.
090: */
091: public SymbolicInstance<?> getThis() {
092: return frameStack.peek().getThis();
093: }
094:
095: /**
096: * Gets the symbolic value of a variable within the top frame.
097: */
098: public SymbolicInstance<?> getVariableValue(
099: CtVariableReference<?> vref) {
100: if (frameStack.peek().getVariables().containsKey(vref)) {
101: return frameStack.peek().getVariables().get(vref);
102: }
103: throw new RuntimeException("unknown variable '" + vref + "'");
104: }
105:
106: /**
107: * Sets the symbolic value of a variable within the top frame.
108: */
109: public void setVariableValue(CtVariableReference<?> vref,
110: SymbolicInstance<?> value) {
111: if (frameStack.peek().getVariables().containsKey(vref)) {
112: frameStack.peek().getVariables().put(vref, value);
113: } else {
114: throw new RuntimeException("unknown variable '" + vref
115: + "'");
116: }
117: }
118:
119: /**
120: * Creates a copy of the given stack.
121: */
122: public SymbolicEvaluationStack(SymbolicEvaluationStack stack) {
123: for (SymbolicStackFrame f : stack.frameStack) {
124: frameStack.add(new SymbolicStackFrame(f));
125: }
126: }
127:
128: /**
129: * Creates an empty evaluation stack.
130: */
131: public SymbolicEvaluationStack() {
132: }
133:
134: /**
135: * A string representation.
136: */
137: @Override
138: public String toString() {
139: return "" + frameStack;
140: }
141:
142: /**
143: * Dumps the stack on the screen.
144: */
145: public void dump() {
146: System.out.println("Stack:");
147: int i = 1;
148: for (SymbolicStackFrame f : frameStack) {
149: System.out.print(" " + (i++) + "\t");
150: System.out.println(f.toString());
151: }
152: }
153:
154: /**
155: * Gets the current result (returned value) for the top stack frame of this
156: * stack.
157: */
158: public SymbolicInstance<?> getResult() {
159: return frameStack.peek().getResult();
160: }
161:
162: /**
163: * Sets the current result (returned value) for the top stack frame of this
164: * stack.
165: */
166: public void setResult(SymbolicInstance<?> result) {
167: frameStack.peek().setResult(result);
168: }
169:
170: /**
171: * Gets the frames as a stack.
172: */
173: public Stack<SymbolicStackFrame> getFrameStack() {
174: return frameStack;
175: }
176:
177: }
|