001: // This file is part of KeY - Integrated Deductive Software Design
002: // Copyright (C) 2001-2007 Universitaet Karlsruhe, Germany
003: // Universitaet Koblenz-Landau, Germany
004: // Chalmers University of Technology, Sweden
005: //
006: // The KeY system is protected by the GNU General Public License.
007: // See LICENSE.TXT for details.
008: //
009: //
010:
011: package de.uka.ilkd.key.java.recoderext;
012:
013: import recoder.java.*;
014: import recoder.java.statement.JavaStatement;
015:
016: /**
017: * The statement inserted by KeY if a method call is executed.
018: */
019:
020: public class MethodCallStatement extends JavaStatement implements
021: StatementContainer, ExpressionContainer {
022:
023: /**
024: * resultVar (should be a VariableReference, but the parser can't enforce this)
025: */
026:
027: protected Expression resultVar;
028:
029: protected ExecutionContext ec;
030:
031: /**
032: * Body.
033: */
034: protected Statement body;
035:
036: /**
037: * MethodCallStatement.
038: * @param resultVar the ProgramVariable the return value is assigned to
039: * @param body a Statement containing the method body of
040: * the called method
041: */
042:
043: public MethodCallStatement(Expression resultVar,
044: ExecutionContext ec, StatementBlock body) {
045: this .resultVar = resultVar;
046: this .ec = ec;
047: this .body = body;
048: makeParentRoleValid();
049: }
050:
051: /**
052: * MethodCallStatement.
053: * @param proto a MethodCallStatement
054: */
055:
056: protected MethodCallStatement(MethodCallStatement proto) {
057: super (proto);
058: if (proto.resultVar != null) {
059: resultVar = (Expression) proto.resultVar.deepClone();
060: }
061: if (proto.ec != null) {
062: ec = (ExecutionContext) proto.ec.deepClone();
063: }
064: if (proto.body != null) {
065: body = (Statement) proto.body.deepClone();
066: }
067: makeParentRoleValid();
068: }
069:
070: /**
071: * Set the result variable.
072: * @param resultVar the result variable
073: */
074:
075: public void setResultVariable(Expression resultVar) {
076: this .resultVar = resultVar;
077: }
078:
079: /**
080: * Get the result variable.
081: * @return the VariableReference
082: */
083:
084: public Expression getResultVariable() {
085: return resultVar;
086: }
087:
088: /**
089: * Set body.
090: * @param body the Statement
091: */
092:
093: public void setBody(Statement body) {
094: this .body = body;
095: }
096:
097: /**
098: * Get body.
099: * @return the Statement
100: */
101:
102: public Statement getBody() {
103: return body;
104: }
105:
106: /**
107: * Finds the source element that occurs first in the source.
108: * Returns the first element of the first child.
109: * @return the last source element in the syntactical representation of
110: * this element, may be equals to this element.
111: */
112:
113: public SourceElement getFirstElement() {
114: return getChildAt(0).getFirstElement();
115: }
116:
117: /**
118: * Finds the source element that occurs last in the source.
119: * Returns the last element of the body.
120: * @return the last source element in the syntactical representation of
121: * this element, may be equals to this element.
122: */
123:
124: public SourceElement getLastElement() {
125: return body.getLastElement();
126: }
127:
128: /**
129: * returns the execution context
130: */
131: public ExecutionContext getExecutionContext() {
132: return ec;
133: }
134:
135: /**
136: * Returns the number of children of this node.
137: * @return an int giving the number of children of this node
138: */
139:
140: public int getChildCount() {
141: int result = 0;
142: if (resultVar != null)
143: result++;
144: if (ec != null)
145: result++;
146: if (body != null)
147: result++;
148: return result;
149: }
150:
151: /**
152: * Returns the child at the specified index in this node's "virtual"
153: * child array
154: * @param index an index into this node's "virtual" child array
155: * @return the program element at the given position
156: * @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
157: * of bounds
158: */
159:
160: public ProgramElement getChildAt(int index) {
161: if (resultVar != null) {
162: if (index == 0)
163: return resultVar;
164: index--;
165: }
166: if (ec != null) {
167: if (index == 0)
168: return ec;
169: index--;
170: }
171: if (body != null) {
172: if (index == 0)
173: return body;
174: index--;
175: }
176: throw new ArrayIndexOutOfBoundsException();
177: }
178:
179: public int getChildPositionCode(ProgramElement child) {
180: // role -/0: resultVar
181: // role 1/2: ec
182: // role 2/1: body
183: if (resultVar == child) {
184: return 0;
185: }
186: if (ec == child) {
187: return (resultVar != null) ? 1 : 0;
188: }
189:
190: if (body == child) {
191: return (resultVar != null) ? 2 : 1;
192: }
193: return -1;
194: }
195:
196: /**
197: * Get the number of statements in this container.
198: * @return the number of statements.
199: */
200:
201: public int getStatementCount() {
202: int result = (body != null) ? 1 : 0;
203: return result;
204: }
205:
206: /**
207: * Return the statement at the specified index in this node's
208: * "virtual" statement array.
209: * @param index an index for a statement.
210: * @return the statement with the given index.
211: * @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
212: * of bounds.
213: */
214:
215: public Statement getStatementAt(int index) {
216: if (body != null && index == 0) {
217: return body;
218: }
219: throw new ArrayIndexOutOfBoundsException();
220: }
221:
222: /**
223: * Get the number of expressions in this container.
224: * @return the number of expressions.
225: */
226:
227: public int getExpressionCount() {
228: return (resultVar != null) ? 1 : 0;
229: }
230:
231: /**
232: * Return the expression at the specified index in this node's
233: * "virtual" expression array.
234: * @param index an index for a expression.
235: * @return the expression with the given index.
236: * @exception ArrayIndexOutOfBoundsException if <tt>index</tt> is out
237: * of bounds.
238: */
239:
240: public Expression getExpressionAt(int index) {
241: if (resultVar != null && index == 0) {
242: return resultVar;
243: }
244: throw new ArrayIndexOutOfBoundsException();
245: }
246:
247: /**
248: * Replace a single child in the current node.
249: * The child to replace is matched by identity and hence must be known
250: * exactly. The replacement element can be null - in that case, the child
251: * is effectively removed.
252: * The parent role of the new child is validated, while the
253: * parent link of the replaced child is left untouched.
254: * @param p the old child.
255: * @param q the new child.
256: * @return true if a replacement has occured, false otherwise.
257: * @exception ClassCastException if the new child cannot take over
258: * the role of the old one.
259: */
260:
261: public boolean replaceChild(ProgramElement p, ProgramElement q) {
262: if (resultVar == p) {
263: Expression r = (Expression) q;
264: resultVar = r;
265: if (r != null) {
266: r.setExpressionContainer(this );
267: }
268: return true;
269: } else if (ec == p) {
270: ec = (ExecutionContext) q;
271: if (ec != null) {
272: ec.setParent(this );
273: }
274: return true;
275: } else if (body == p) {
276: Statement r = (Statement) q;
277: body = r;
278: if (r != null) {
279: r.setStatementContainer(this );
280: }
281: return true;
282: }
283: return false;
284: }
285:
286: /**
287: * Ensures that each child has "this" as syntactical parent.
288: */
289: public void makeParentRoleValid() {
290: super .makeParentRoleValid();
291: if (resultVar != null) {
292: resultVar.setExpressionContainer(this );
293: }
294: if (ec != null) {
295: ec.setParent(this );
296: }
297: if (body != null) {
298: body.setStatementContainer(this );
299: }
300: }
301:
302: //don't think we need it
303: public void accept(SourceVisitor v) {
304: }
305:
306: /**
307: * Deep clone.
308: * @return the object
309: */
310: public Object deepClone() {
311: return new MethodCallStatement(this);
312: }
313:
314: }
|