KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > eval > ast > engine > ASTInstructionCompiler


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.eval.ast.engine;
12
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Stack JavaDoc;
18
19 import org.eclipse.jdt.core.Flags;
20 import org.eclipse.jdt.core.Signature;
21 import org.eclipse.jdt.core.compiler.IProblem;
22 import org.eclipse.jdt.core.dom.ASTNode;
23 import org.eclipse.jdt.core.dom.ASTVisitor;
24 import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
25 import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
26 import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
27 import org.eclipse.jdt.core.dom.ArrayAccess;
28 import org.eclipse.jdt.core.dom.ArrayCreation;
29 import org.eclipse.jdt.core.dom.ArrayInitializer;
30 import org.eclipse.jdt.core.dom.ArrayType;
31 import org.eclipse.jdt.core.dom.AssertStatement;
32 import org.eclipse.jdt.core.dom.Assignment;
33 import org.eclipse.jdt.core.dom.Block;
34 import org.eclipse.jdt.core.dom.BlockComment;
35 import org.eclipse.jdt.core.dom.BooleanLiteral;
36 import org.eclipse.jdt.core.dom.BreakStatement;
37 import org.eclipse.jdt.core.dom.CastExpression;
38 import org.eclipse.jdt.core.dom.CatchClause;
39 import org.eclipse.jdt.core.dom.CharacterLiteral;
40 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
41 import org.eclipse.jdt.core.dom.CompilationUnit;
42 import org.eclipse.jdt.core.dom.ConditionalExpression;
43 import org.eclipse.jdt.core.dom.ConstructorInvocation;
44 import org.eclipse.jdt.core.dom.ContinueStatement;
45 import org.eclipse.jdt.core.dom.DoStatement;
46 import org.eclipse.jdt.core.dom.EmptyStatement;
47 import org.eclipse.jdt.core.dom.EnhancedForStatement;
48 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
49 import org.eclipse.jdt.core.dom.EnumDeclaration;
50 import org.eclipse.jdt.core.dom.Expression;
51 import org.eclipse.jdt.core.dom.ExpressionStatement;
52 import org.eclipse.jdt.core.dom.FieldAccess;
53 import org.eclipse.jdt.core.dom.FieldDeclaration;
54 import org.eclipse.jdt.core.dom.ForStatement;
55 import org.eclipse.jdt.core.dom.IBinding;
56 import org.eclipse.jdt.core.dom.IMethodBinding;
57 import org.eclipse.jdt.core.dom.IPackageBinding;
58 import org.eclipse.jdt.core.dom.ITypeBinding;
59 import org.eclipse.jdt.core.dom.IVariableBinding;
60 import org.eclipse.jdt.core.dom.IfStatement;
61 import org.eclipse.jdt.core.dom.ImportDeclaration;
62 import org.eclipse.jdt.core.dom.InfixExpression;
63 import org.eclipse.jdt.core.dom.Initializer;
64 import org.eclipse.jdt.core.dom.InstanceofExpression;
65 import org.eclipse.jdt.core.dom.Javadoc;
66 import org.eclipse.jdt.core.dom.LabeledStatement;
67 import org.eclipse.jdt.core.dom.LineComment;
68 import org.eclipse.jdt.core.dom.MarkerAnnotation;
69 import org.eclipse.jdt.core.dom.MemberRef;
70 import org.eclipse.jdt.core.dom.MemberValuePair;
71 import org.eclipse.jdt.core.dom.MethodDeclaration;
72 import org.eclipse.jdt.core.dom.MethodInvocation;
73 import org.eclipse.jdt.core.dom.MethodRef;
74 import org.eclipse.jdt.core.dom.MethodRefParameter;
75 import org.eclipse.jdt.core.dom.Modifier;
76 import org.eclipse.jdt.core.dom.Name;
77 import org.eclipse.jdt.core.dom.NormalAnnotation;
78 import org.eclipse.jdt.core.dom.NullLiteral;
79 import org.eclipse.jdt.core.dom.NumberLiteral;
80 import org.eclipse.jdt.core.dom.PackageDeclaration;
81 import org.eclipse.jdt.core.dom.ParameterizedType;
82 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
83 import org.eclipse.jdt.core.dom.PostfixExpression;
84 import org.eclipse.jdt.core.dom.PrefixExpression;
85 import org.eclipse.jdt.core.dom.PrimitiveType;
86 import org.eclipse.jdt.core.dom.QualifiedName;
87 import org.eclipse.jdt.core.dom.QualifiedType;
88 import org.eclipse.jdt.core.dom.ReturnStatement;
89 import org.eclipse.jdt.core.dom.SimpleName;
90 import org.eclipse.jdt.core.dom.SimpleType;
91 import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
92 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
93 import org.eclipse.jdt.core.dom.Statement;
94 import org.eclipse.jdt.core.dom.StringLiteral;
95 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
96 import org.eclipse.jdt.core.dom.SuperFieldAccess;
97 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
98 import org.eclipse.jdt.core.dom.SwitchCase;
99 import org.eclipse.jdt.core.dom.SwitchStatement;
100 import org.eclipse.jdt.core.dom.SynchronizedStatement;
101 import org.eclipse.jdt.core.dom.TagElement;
102 import org.eclipse.jdt.core.dom.TextElement;
103 import org.eclipse.jdt.core.dom.ThisExpression;
104 import org.eclipse.jdt.core.dom.ThrowStatement;
105 import org.eclipse.jdt.core.dom.TryStatement;
106 import org.eclipse.jdt.core.dom.Type;
107 import org.eclipse.jdt.core.dom.TypeDeclaration;
108 import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
109 import org.eclipse.jdt.core.dom.TypeLiteral;
110 import org.eclipse.jdt.core.dom.TypeParameter;
111 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
112 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
113 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
114 import org.eclipse.jdt.core.dom.WhileStatement;
115 import org.eclipse.jdt.core.dom.WildcardType;
116 import org.eclipse.jdt.internal.debug.eval.ast.instructions.AndAssignmentOperator;
117 import org.eclipse.jdt.internal.debug.eval.ast.instructions.AndOperator;
118 import org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAllocation;
119 import org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayInitializerInstruction;
120 import org.eclipse.jdt.internal.debug.eval.ast.instructions.AssignmentOperator;
121 import org.eclipse.jdt.internal.debug.eval.ast.instructions.Cast;
122 import org.eclipse.jdt.internal.debug.eval.ast.instructions.CompoundInstruction;
123 import org.eclipse.jdt.internal.debug.eval.ast.instructions.ConditionalJump;
124 import org.eclipse.jdt.internal.debug.eval.ast.instructions.Constructor;
125 import org.eclipse.jdt.internal.debug.eval.ast.instructions.DivideAssignmentOperator;
126 import org.eclipse.jdt.internal.debug.eval.ast.instructions.DivideOperator;
127 import org.eclipse.jdt.internal.debug.eval.ast.instructions.Dup;
128 import org.eclipse.jdt.internal.debug.eval.ast.instructions.DupX1;
129 import org.eclipse.jdt.internal.debug.eval.ast.instructions.EqualEqualOperator;
130 import org.eclipse.jdt.internal.debug.eval.ast.instructions.GreaterEqualOperator;
131 import org.eclipse.jdt.internal.debug.eval.ast.instructions.GreaterOperator;
132 import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstanceOfOperator;
133 import org.eclipse.jdt.internal.debug.eval.ast.instructions.Instruction;
134 import org.eclipse.jdt.internal.debug.eval.ast.instructions.InstructionSequence;
135 import org.eclipse.jdt.internal.debug.eval.ast.instructions.Jump;
136 import org.eclipse.jdt.internal.debug.eval.ast.instructions.LeftShiftAssignmentOperator;
137 import org.eclipse.jdt.internal.debug.eval.ast.instructions.LeftShiftOperator;
138 import org.eclipse.jdt.internal.debug.eval.ast.instructions.LessEqualOperator;
139 import org.eclipse.jdt.internal.debug.eval.ast.instructions.LessOperator;
140 import org.eclipse.jdt.internal.debug.eval.ast.instructions.LocalVariableCreation;
141 import org.eclipse.jdt.internal.debug.eval.ast.instructions.MinusAssignmentOperator;
142 import org.eclipse.jdt.internal.debug.eval.ast.instructions.MinusOperator;
143 import org.eclipse.jdt.internal.debug.eval.ast.instructions.MultiplyAssignmentOperator;
144 import org.eclipse.jdt.internal.debug.eval.ast.instructions.MultiplyOperator;
145 import org.eclipse.jdt.internal.debug.eval.ast.instructions.NoOp;
146 import org.eclipse.jdt.internal.debug.eval.ast.instructions.NotOperator;
147 import org.eclipse.jdt.internal.debug.eval.ast.instructions.OrAssignmentOperator;
148 import org.eclipse.jdt.internal.debug.eval.ast.instructions.OrOperator;
149 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PlusAssignmentOperator;
150 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PlusOperator;
151 import org.eclipse.jdt.internal.debug.eval.ast.instructions.Pop;
152 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PostfixMinusMinusOperator;
153 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PostfixPlusPlusOperator;
154 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PrefixMinusMinusOperator;
155 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PrefixPlusPlusOperator;
156 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushArrayLength;
157 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushArrayType;
158 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushBoolean;
159 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushChar;
160 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushClassLiteralValue;
161 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushDouble;
162 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushFieldVariable;
163 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushFloat;
164 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushInt;
165 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushLocalVariable;
166 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushLong;
167 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushNull;
168 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushStaticFieldVariable;
169 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushString;
170 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushThis;
171 import org.eclipse.jdt.internal.debug.eval.ast.instructions.PushType;
172 import org.eclipse.jdt.internal.debug.eval.ast.instructions.RemainderAssignmentOperator;
173 import org.eclipse.jdt.internal.debug.eval.ast.instructions.RemainderOperator;
174 import org.eclipse.jdt.internal.debug.eval.ast.instructions.ReturnInstruction;
175 import org.eclipse.jdt.internal.debug.eval.ast.instructions.RightShiftAssignmentOperator;
176 import org.eclipse.jdt.internal.debug.eval.ast.instructions.RightShiftOperator;
177 import org.eclipse.jdt.internal.debug.eval.ast.instructions.SendMessage;
178 import org.eclipse.jdt.internal.debug.eval.ast.instructions.SendStaticMessage;
179 import org.eclipse.jdt.internal.debug.eval.ast.instructions.ThrowInstruction;
180 import org.eclipse.jdt.internal.debug.eval.ast.instructions.TwiddleOperator;
181 import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnaryMinusOperator;
182 import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnaryPlusOperator;
183 import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnsignedRightShiftAssignmentOperator;
184 import org.eclipse.jdt.internal.debug.eval.ast.instructions.UnsignedRightShiftOperator;
185 import org.eclipse.jdt.internal.debug.eval.ast.instructions.Value;
186 import org.eclipse.jdt.internal.debug.eval.ast.instructions.XorAssignmentOperator;
187 import org.eclipse.jdt.internal.debug.eval.ast.instructions.XorOperator;
188
189 /**
190  * The AST instruction compiler generates a sequence
191  * of instructions (InstructionSequence) from a
192  * DOM AST.
193  */

194 public class ASTInstructionCompiler extends ASTVisitor {
195
196     /**
197      * Represent a break or a continue instruction.
198      * These instructions needs are stored and managed later by their
199      * related statement.
200      */

201     class CompleteInstruction {
202         Jump fInstruction;
203         String JavaDoc fLabel;
204         boolean fIsBreak;
205
206         public CompleteInstruction(Jump instruction, String JavaDoc label, boolean isBreak) {
207             fInstruction= instruction;
208             fLabel= label;
209             fIsBreak= isBreak;
210         }
211     }
212
213     /**
214      * Whether to print debug messages to the console
215      */

216     private static boolean VERBOSE = false;
217
218     private InstructionSequence fInstructions;
219
220     /**
221      * The list of pending break and continue instruction.
222      */

223     private List JavaDoc fCompleteInstructions;
224
225     private int fStartPosition;
226
227     private boolean fActive;
228
229     private boolean fHasErrors;
230
231     private Stack JavaDoc fStack;
232
233     private int fCounter;
234     
235     // internal index used to create unique variable name
236
private int fUniqueIdIndex= 0;
237
238
239     /**
240      * Create a new AST instruction compiler
241      */

242     public ASTInstructionCompiler(int startPosition, String JavaDoc snippet) {
243         fStartPosition = startPosition;
244         fInstructions = new InstructionSequence(snippet);
245         fStack = new Stack JavaDoc();
246         fCompleteInstructions= new ArrayList JavaDoc();
247     }
248
249     /**
250      * Returns the instruction sequence generated
251      * by this AST instruction compiler
252      */

253     public InstructionSequence getInstructions() {
254         return fInstructions;
255     }
256
257     /**
258      * Returns whether the generated instruction sequence
259      * has errors.
260      * Errors include:
261      * <ol>
262      * <li>AST contains unimplemented operations (features which will be supported,
263      * but aren't yet)</li>
264      * <li>AST contains unsupported operations (features which are not yet implemented
265      * and are likely NOT to be implemented)</li>
266      * </ol>
267      */

268     public boolean hasErrors() {
269         return fHasErrors;
270     }
271
272     private void setHasError(boolean value) {
273         fHasErrors= value;
274     }
275
276     private void addErrorMessage(String JavaDoc message) {
277         fInstructions.addError(message);
278     }
279
280     private boolean isActive() {
281         return fActive;
282     }
283
284     private void setActive(boolean active) {
285         fActive = active;
286     }
287
288
289     private void push(Instruction i) {
290         fStack.push(i);
291     }
292
293     private Instruction pop() {
294         return (Instruction)fStack.pop();
295     }
296
297     private void storeInstruction() {
298         Instruction instruction= pop();
299         fCounter++;
300         if (instruction instanceof CompoundInstruction) {
301             ((CompoundInstruction)instruction).setEnd(fCounter);
302         }
303         fInstructions.add(instruction);
304         verbose("Add " + instruction.toString()); //$NON-NLS-1$
305
}
306
307
308     /**
309      * Prints the given message to the console if verbose
310      * mode is on.
311      *
312      * @param message the message to display
313      */

314     private void verbose(String JavaDoc message) {
315         if (VERBOSE) {
316             System.out.println(message);
317         }
318     }
319
320     private String JavaDoc getTypeName(ITypeBinding typeBinding) {
321         if (typeBinding.isRawType()) {
322             typeBinding= typeBinding.getErasure();
323         }
324         if (typeBinding.isTypeVariable()) {
325             ITypeBinding[] typeBounds= typeBinding.getTypeBounds();
326             if (typeBounds.length > 0) {
327                 String JavaDoc name= getTypeName(typeBounds[0]);
328                 if (typeBounds.length > 1 && "java.lang.Object".equals(name)) { //$NON-NLS-1$
329
return getTypeName(typeBounds[1]);
330                 }
331                 return name;
332             }
333             return "java.lang.Object"; //$NON-NLS-1$
334
}
335         StringBuffer JavaDoc name;
336         if (typeBinding.isArray()) {
337             name= new StringBuffer JavaDoc(getTypeName(typeBinding.getElementType()));
338             int dimensions= typeBinding.getDimensions();
339             for (int i= 0; i < dimensions; i++) {
340                 name.append("[]"); //$NON-NLS-1$
341
}
342             return name.toString();
343         }
344         String JavaDoc typeName= typeBinding.getName();
345         int parameters= typeName.indexOf('<');
346         if (parameters >= 0) {
347             typeName= typeName.substring(0, parameters);
348         }
349         name= new StringBuffer JavaDoc(typeName);
350         IPackageBinding packageBinding= typeBinding.getPackage();
351         typeBinding= typeBinding.getDeclaringClass();
352         while(typeBinding != null) {
353             name.insert(0, '$').insert(0, typeBinding.getName());
354             typeBinding= typeBinding.getDeclaringClass();
355         }
356         if (packageBinding != null && !packageBinding.isUnnamed()) {
357             name.insert(0, '.').insert(0, packageBinding.getName());
358         }
359         return name.toString();
360     }
361
362     private String JavaDoc getTypeSignature(ITypeBinding typeBinding) {
363         return Signature.createTypeSignature(getTypeName(typeBinding), true).replace('.', '/');
364     }
365
366     private boolean isALocalType(ITypeBinding typeBinding) {
367         while(typeBinding != null) {
368             if (typeBinding.isLocal()) {
369                 return true;
370             }
371             typeBinding= typeBinding.getDeclaringClass();
372         }
373         return false;
374     }
375
376     private boolean containsALocalType(IMethodBinding methodBinding) {
377         ITypeBinding[] typeBindings= methodBinding.getParameterTypes();
378         for (int i= 0, length= typeBindings.length; i < length; i++) {
379             if (isALocalType(typeBindings[i])) {
380                 return true;
381             }
382         }
383         return false;
384     }
385
386     private int getEnclosingLevel(ASTNode node, ITypeBinding referenceTypeBinding) {
387         ASTNode parent= node;
388         do {
389             parent= parent.getParent();
390         } while (!(parent instanceof TypeDeclaration || parent instanceof EnumDeclaration || parent instanceof AnonymousClassDeclaration));
391         ITypeBinding parentBinding;
392         if (parent instanceof TypeDeclaration) {
393             parentBinding= ((TypeDeclaration)parent).resolveBinding();
394         } else if (parent instanceof EnumDeclaration) {
395             parentBinding= ((EnumDeclaration)parent).resolveBinding();
396         } else {
397             parentBinding= ((AnonymousClassDeclaration)parent).resolveBinding();
398         }
399         if (parentBinding.isCastCompatible(referenceTypeBinding)) {
400             return 0;
401         }
402         return getEnclosingLevel(parent, referenceTypeBinding) + 1;
403     }
404
405     private int getSuperLevel(ITypeBinding current, ITypeBinding reference) {
406         if (current.equals(reference)) {
407             return 0;
408         }
409         return getSuperLevel(current.getSuperclass(), reference);
410     }
411
412     /**
413      * Return the label associated with the given statement.
414      *
415      * @param statement the statement.
416      * @return the associated label, or <code>null</code> if there is none.
417      */

418     private String JavaDoc getLabel(Statement statement) {
419         ASTNode parent= statement.getParent();
420         if (parent instanceof LabeledStatement) {
421             return ((LabeledStatement)parent).getLabel().getIdentifier();
422         }
423         return null;
424     }
425
426     /**
427      * Append a pop instruction in the instruction list if needed.
428      * A pop instruction is added when the expression has a return value,
429      * i.e. all expressions expect method invocation expressions which
430      * have <code>void</code> as return type and variable declaration expression.
431      *
432      * @param expression the expressien to test.
433      */

434     private void addPopInstructionIfNeeded(Expression expression) {
435         boolean pop= true;
436
437         if (expression instanceof MethodInvocation) {
438             IMethodBinding methodBinding= (IMethodBinding)((MethodInvocation)expression).getName().resolveBinding();
439             if ("void".equals(methodBinding.getReturnType().getName())) { //$NON-NLS-1$
440
pop= false;
441             }
442         } else if (expression instanceof SuperMethodInvocation) {
443             IMethodBinding methodBinding= (IMethodBinding)((SuperMethodInvocation)expression).getName().resolveBinding();
444             if ("void".equals(methodBinding.getReturnType().getName())) { //$NON-NLS-1$
445
pop= false;
446             }
447         } else if (expression instanceof VariableDeclarationExpression) {
448             pop= false;
449         }
450
451         if (pop) {
452             addPopInstruction();
453         }
454     }
455
456     /**
457      *
458      */

459     private void addPopInstruction() {
460         Instruction lastInstruction= fInstructions.getInstruction(fInstructions.getEnd());
461         push(new Pop(lastInstruction.getSize() + 1));
462         storeInstruction();
463     }
464     
465     /**
466      * Check the current type of a value and the requested type to decide if boxing/unboxing is required.
467      * If needed, the correct instruction is added to the stack
468      * Returns true if a storeInstruction() is needed after visiting the expression
469      */

470     private boolean checkAutoBoxing(ITypeBinding valueBinding, ITypeBinding requestedBinding) {
471         if (valueBinding.isPrimitive() == requestedBinding.isPrimitive()) {
472             return false;
473         }
474         if (requestedBinding.isPrimitive()) {
475             unBoxing(valueBinding);
476         } else {
477             boxing(requestedBinding, valueBinding);
478         }
479         return true;
480     }
481
482     /**
483      * Add to the stack the instruction to box a primitive value.
484      */

485     private void boxing(ITypeBinding requestedBinding, ITypeBinding valueBinding) {
486         String JavaDoc requestedTypeName= requestedBinding.getQualifiedName();
487         if ("java.lang.Object".equals(requestedTypeName)) { //$NON-NLS-1$
488
switch (valueBinding.getBinaryName().charAt(0)) {
489                 case 'I':
490                     push(new SendStaticMessage("java.lang.Integer", "valueOf", "(I)Ljava/lang/Integer;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
491
break;
492                 case 'C':
493                     push(new SendStaticMessage("java.lang.Character", "valueOf", "(C)Ljava/lang/Character;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
494
break;
495                 case 'B':
496                     push(new SendStaticMessage("java.lang.Byte", "valueOf", "(B)Ljava/lang/Byte;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
497
break;
498                 case 'S':
499                     push(new SendStaticMessage("java.lang.Short", "valueOf", "(S)Ljava/lang/Short;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
500
break;
501                 case 'J':
502                     push(new SendStaticMessage("java.lang.Long", "valueOf", "(J)Ljava/lang/Long;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
503
break;
504                 case 'F':
505                     push(new SendStaticMessage("java.lang.Float", "valueOf", "(F)Ljava/lang/Float;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
506
break;
507                 case 'D':
508                     push(new SendStaticMessage("java.lang.Double", "valueOf", "(D)Ljava/lang/Double;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
509
break;
510                 case 'Z':
511                     push(new SendStaticMessage("java.lang.Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
512
break;
513             }
514         } else if ("java.lang.Integer".equals(requestedTypeName)) { //$NON-NLS-1$
515
push(new SendStaticMessage(requestedTypeName, "valueOf", "(I)Ljava/lang/Integer;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
516
} else if ("java.lang.Character".equals(requestedTypeName)) { //$NON-NLS-1$
517
push(new SendStaticMessage(requestedTypeName, "valueOf", "(C)Ljava/lang/Character;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
518
} else if ("java.lang.Byte".equals(requestedTypeName)) { //$NON-NLS-1$
519
push(new SendStaticMessage(requestedTypeName, "valueOf", "(B)Ljava/lang/Byte;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
520
} else if ("java.lang.Short".equals(requestedTypeName)) { //$NON-NLS-1$
521
push(new SendStaticMessage(requestedTypeName, "valueOf", "(S)Ljava/lang/Short;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
522
} else if ("java.lang.Long".equals(requestedTypeName)) { //$NON-NLS-1$
523
push(new SendStaticMessage(requestedTypeName, "valueOf", "(J)Ljava/lang/Long;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
524
} else if ("java.lang.Float".equals(requestedTypeName)) { //$NON-NLS-1$
525
push(new SendStaticMessage(requestedTypeName, "valueOf", "(F)Ljava/lang/Float;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
526
} else if ("java.lang.Double".equals(requestedTypeName)) { //$NON-NLS-1$
527
push(new SendStaticMessage(requestedTypeName, "valueOf", "(D)Ljava/lang/Double;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
528
} else if ("java.lang.Boolean".equals(requestedTypeName)) { //$NON-NLS-1$
529
push(new SendStaticMessage(requestedTypeName, "valueOf", "(Z)Ljava/lang/Boolean;", 1, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
530
}
531     }
532
533     /**
534      * Add the instruction to unbox a non-primitive value if needed.
535      * Returns true if a storeInstruction() is needed after visiting the expression
536      */

537     private boolean unBoxing(ITypeBinding valueBinding) {
538         String JavaDoc valueTypeName= valueBinding.getQualifiedName();
539         if ("java.lang.Integer".equals(valueTypeName)) { //$NON-NLS-1$
540
push(new SendMessage("intValue", "()I", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
541
} else if ("java.lang.Character".equals(valueTypeName)) { //$NON-NLS-1$
542
push(new SendMessage("charValue", "()C", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
543
} else if ("java.lang.Byte".equals(valueTypeName)) { //$NON-NLS-1$
544
push(new SendMessage("byteValue", "()B", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
545
} else if ("java.lang.Short".equals(valueTypeName)) { //$NON-NLS-1$
546
push(new SendMessage("shortValue", "()S", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
547
} else if ("java.lang.Long".equals(valueTypeName)) { //$NON-NLS-1$
548
push(new SendMessage("longValue", "()J", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
549
} else if ("java.lang.Float".equals(valueTypeName)) { //$NON-NLS-1$
550
push(new SendMessage("floatValue", "()F", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
551
} else if ("java.lang.Double".equals(valueTypeName)) { //$NON-NLS-1$
552
push(new SendMessage("doubleValue", "()D", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
553
} else if ("java.lang.Boolean".equals(valueTypeName)) { //$NON-NLS-1$
554
push(new SendMessage("booleanValue", "()Z", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
555
} else {
556             return false;
557         }
558         return true;
559     }
560
561     /**
562      * End visit methods
563      *
564      * There are two paths to ending a visit to a node:
565      * <ol>
566      * <li>For control statements, the necessary control
567      * instructions (jump, conditional jump) are inserted
568      * into the instruction sequence</li>
569      * <li>For other cases, we simply remove the node's
570      * instruction from the stack and add it to the
571      * instruction sequence.</li>
572      * </ol>
573      */

574
575     /**
576      * @see ASTVisitor#endVisit(AnonymousClassDeclaration)
577      */

578     public void endVisit(AnonymousClassDeclaration node) {
579
580     }
581
582     /**
583      * @see ASTVisitor#endVisit(ArrayAccess)
584      */

585     public void endVisit(ArrayAccess node) {
586         if (!isActive() || hasErrors())
587             return;
588         storeInstruction();
589     }
590
591     /**
592      * @see ASTVisitor#endVisit(ArrayCreation)
593      */

594     public void endVisit(ArrayCreation node) {
595         if (!isActive() || hasErrors())
596             return;
597         storeInstruction();
598     }
599
600     /**
601      * @see ASTVisitor#endVisit(ArrayInitializer)
602      */

603     public void endVisit(ArrayInitializer node) {
604         if (!isActive() || hasErrors())
605             return;
606         storeInstruction();
607     }
608
609     /**
610      * @see ASTVisitor#endVisit(ArrayType)
611      */

612     public void endVisit(ArrayType node) {
613         if (!isActive() || hasErrors())
614             return;
615         storeInstruction();
616     }
617
618     /**
619      * @see ASTVisitor#endVisit(AssertStatement)
620      */

621     public void endVisit(AssertStatement node) {
622
623     }
624
625     /**
626      * @see ASTVisitor#endVisit(Assignment)
627      */

628     public void endVisit(Assignment node) {
629         if (!isActive() || hasErrors())
630             return;
631         storeInstruction();
632     }
633
634     /**
635      * @see ASTVisitor#endVisit(Block)
636      */

637     public void endVisit(Block node) {
638         if (!isActive() || hasErrors())
639             return;
640         storeInstruction();
641     }
642
643     /**
644      * @see ASTVisitor#endVisit(BooleanLiteral)
645      */

646     public void endVisit(BooleanLiteral node) {
647         if (!isActive() || hasErrors())
648             return;
649         storeInstruction();
650     }
651
652     /**
653      * @see ASTVisitor#endVisit(BreakStatement)
654      */

655     public void endVisit(BreakStatement node) {
656         if (!isActive() || hasErrors())
657             return;
658         storeInstruction();
659     }
660
661     /**
662      * @see ASTVisitor#endVisit(CastExpression)
663      */

664     public void endVisit(CastExpression node) {
665         if (!isActive() || hasErrors())
666             return;
667         storeInstruction();
668     }
669
670     /**
671      * @see ASTVisitor#endVisit(CatchClause)
672      */

673     public void endVisit(CatchClause node) {
674
675     }
676
677     /**
678      * @see ASTVisitor#endVisit(CharacterLiteral)
679      */

680     public void endVisit(CharacterLiteral node) {
681         if (!isActive() || hasErrors())
682             return;
683         storeInstruction();
684     }
685
686     /**
687      * @see ASTVisitor#endVisit(ClassInstanceCreation)
688      */

689     public void endVisit(ClassInstanceCreation node) {
690         if (!isActive() || hasErrors())
691             return;
692         storeInstruction();
693     }
694
695     /**
696      * @see ASTVisitor#endVisit(CompilationUnit)
697      */

698     public void endVisit(CompilationUnit node) {
699
700     }
701
702     /**
703      * @see ASTVisitor#endVisit(ConditionalExpression)
704      */

705     public void endVisit(ConditionalExpression node) {
706         if (!isActive() || hasErrors())
707             return;
708
709         // Get the instructions
710
int ifFalseAddress= fInstructions.getEnd();
711         Instruction ifFalse= fInstructions.get(ifFalseAddress);
712         int ifTrueAddress= ifFalseAddress - ifFalse.getSize();
713         Instruction ifTrue= fInstructions.get(ifTrueAddress);
714         int conditionalAddress= ifTrueAddress - ifTrue.getSize();
715
716         // Insert the conditional jump
717
ConditionalJump conditionalJump= new ConditionalJump(false);
718         fInstructions.insert(conditionalJump, conditionalAddress + 1);
719
720         // Insert the jump
721
int jumpAddress= ifTrueAddress + 2;
722         Jump jump= new Jump();
723         fInstructions.insert(jump, jumpAddress);
724
725         // Set the jump offsets
726
conditionalJump.setOffset(ifTrue.getSize() + 1);
727         jump.setOffset(ifFalse.getSize() + 1);
728
729         fCounter += 2;
730         storeInstruction();
731
732     }
733
734     /**
735      * @see ASTVisitor#endVisit(ConstructorInvocation)
736      */

737     public void endVisit(ConstructorInvocation node) {
738
739     }
740
741     /**
742      * @see ASTVisitor#endVisit(ContinueStatement)
743      */

744     public void endVisit(ContinueStatement node) {
745         if (!isActive() || hasErrors())
746             return;
747         storeInstruction();
748     }
749
750     /**
751      * @see ASTVisitor#endVisit(DoStatement)
752      */

753     public void endVisit(DoStatement node) {
754         if (!isActive() || hasErrors())
755             return;
756
757         /* The structure of generated instructions is :
758          *
759          * --
760          * | body
761          * --
762          * --
763          * |condition
764          * --
765          * - jump to the first instruction of the body if the condition is true.
766          *
767          */

768
769         String JavaDoc label= getLabel(node);
770
771         // get adress of each part
772
int conditionAddress= fInstructions.getEnd();
773         Instruction condition= fInstructions.getInstruction(conditionAddress);
774         int bodyAddress= conditionAddress - condition.getSize();
775         Instruction body= fInstructions.getInstruction(bodyAddress);
776         int bodyStartAddress= bodyAddress - body.getSize();
777
778         // add the conditionnalJump
779
ConditionalJump conditionalJump= new ConditionalJump(true);
780         fInstructions.add(conditionalJump);
781         fCounter++;
782
783         // set jump offsets
784
conditionalJump.setOffset(-(condition.getSize() + body.getSize() + 1));
785
786         // for each pending break or continue instruction which are related to
787
// this loop, set the offset of the corresponding jump.
788
for (Iterator JavaDoc iter= fCompleteInstructions.iterator(); iter.hasNext();) {
789             CompleteInstruction instruction= (CompleteInstruction) iter.next();
790             Jump jumpInstruction= instruction.fInstruction;
791             int instructionAddress= fInstructions.indexOf(jumpInstruction);
792             if (instructionAddress > bodyStartAddress && (instruction.fLabel == null || instruction.fLabel.equals(label))) {
793                 iter.remove();
794                 if (instruction.fIsBreak) {
795                     // jump to the instruction after the last jump
796
jumpInstruction.setOffset((conditionAddress - instructionAddress) + 1);
797                 } else {
798                     // jump to the first instruction of the condition
799
jumpInstruction.setOffset(bodyAddress - instructionAddress);
800                 }
801             }
802         }
803
804         storeInstruction();
805     }
806
807     /**
808      * @see ASTVisitor#endVisit(EmptyStatement)
809      */

810     public void endVisit(EmptyStatement node) {
811         if (!isActive() || hasErrors())
812             return;
813         storeInstruction();
814     }
815     
816     /* (non-Javadoc)
817      * @see org.eclipse.jdt.core.dom.ASTVisitor#endVisit(org.eclipse.jdt.core.dom.EnhancedForStatement)
818      */

819     public void endVisit(EnhancedForStatement node) {
820         if (!isActive() || hasErrors())
821             return;
822
823         /* The structure of generated instructions is :
824          *
825          * For an array:
826          * --
827          * | <ParameterType>[] a= Expression
828          * | int i= 0
829          * | <ParameterType> <ParameterName>
830          * --
831          * --
832          * | i < a.length
833          * - jump to the instruction after the last jump if the condition is false.
834          * --
835          * --
836          * | s= a[i]
837          * | Body
838          * --
839          * --
840          * - jump to the first instruction of the condition.
841          *
842          * For an Iterable:
843          * --
844          * | Iterator i= Expression.iterator()
845          * | <ParameterType> <ParameterName>
846          * --
847          * --
848          * | i.hasNext()
849          * - jump to the instruction after the last jump if the condition is false.
850          * --
851          * --
852          * | s= i.next()
853          * | Body
854          * --
855          * --
856          * - jump to the first instruction of the condition.
857          *
858          */

859
860         int bodyAddress= fInstructions.getEnd();
861         Instruction body= fInstructions.getInstruction(bodyAddress);
862         int conditionAddress= bodyAddress - body.getSize();
863         Instruction condition= fInstructions.getInstruction(conditionAddress);
864         int initAddress= conditionAddress - condition.getSize();
865         
866         // add conditional jump
867
ConditionalJump condJump= new ConditionalJump(false);
868         fInstructions.insert(condJump, conditionAddress + 1);
869         bodyAddress++;
870         fCounter++;
871         condJump.setOffset(body.getSize() + 1);
872         
873         // add jump
874
Jump jump= new Jump();
875         fInstructions.add(jump);
876         fCounter++;
877         jump.setOffset(initAddress - (bodyAddress + 1));
878         
879
880         // for each pending break or continue instruction which are related to
881
// this loop, set the offset of the corresponding jump.
882
String JavaDoc label= getLabel(node);
883         for (Iterator JavaDoc iter= fCompleteInstructions.iterator(); iter.hasNext();) {
884             CompleteInstruction instruction= (CompleteInstruction) iter.next();
885             Jump jumpInstruction= instruction.fInstruction;
886             int instructionAddress= fInstructions.indexOf(jumpInstruction);
887             if (instructionAddress > conditionAddress && (instruction.fLabel == null || instruction.fLabel.equals(label))) {
888                 iter.remove();
889                 if (instruction.fIsBreak) {
890                     // jump to the instruction after the last jump
891
jumpInstruction.setOffset((bodyAddress - instructionAddress) + 1);
892                 } else {
893                     // jump to the first instruction of the condition
894
jumpInstruction.setOffset(initAddress - instructionAddress);
895                 }
896             }
897         }
898         
899         storeInstruction();
900     }
901
902     /**
903      * @see ASTVisitor#endVisit(ExpressionStatement)
904      */

905     public void endVisit(ExpressionStatement node) {
906         if (!isActive() || hasErrors())
907             return;
908
909         addPopInstructionIfNeeded(node.getExpression());
910     }
911
912     /**
913      * @see ASTVisitor#endVisit(FieldAccess)
914      */

915     public void endVisit(FieldAccess node) {
916         if (!isActive() || hasErrors())
917             return;
918         storeInstruction();
919     }
920
921     /**
922      * @see ASTVisitor#endVisit(FieldDeclaration)
923      */

924     public void endVisit(FieldDeclaration node) {
925
926     }
927
928     /**
929      * @see ASTVisitor#endVisit(ForStatement)
930      */

931     public void endVisit(ForStatement node) {
932         if (!isActive() || hasErrors())
933             return;
934
935         /* The structure of generated instructions is :
936          *
937          * --
938          * |initialization
939          * --
940          * --
941          * |condition
942          * --
943          * - jump to the instruction after the last jump if the condition is false.
944          * --
945          * | body
946          * --
947          * --
948          * | updaters
949          * --
950          * - jump to the first instruction of the condition.
951          *
952          */

953
954         String JavaDoc label= getLabel(node);
955         boolean hasCondition= node.getExpression() != null;
956
957         // get adress of each part
958
int updatersAddress= fInstructions.getEnd();
959         Instruction updaters= fInstructions.getInstruction(updatersAddress);
960         int bodyAddress= updatersAddress - updaters.getSize();
961         Instruction body= fInstructions.getInstruction(bodyAddress);
962         int bodyStartAddress= bodyAddress - body.getSize();
963
964         int conditionAddress;
965         Instruction condition;
966
967         if (hasCondition) {
968             conditionAddress= bodyStartAddress;
969             condition= fInstructions.getInstruction(conditionAddress);
970         } else {
971             conditionAddress= 0;
972             condition= null;
973         }
974
975         // add jump
976
Jump jump= new Jump();
977         fInstructions.add(jump);
978         fCounter++;
979
980         if (hasCondition) {
981             // add conditionnal jump
982
ConditionalJump condJump= new ConditionalJump(false);
983             fInstructions.insert(condJump, conditionAddress + 1);
984             bodyAddress++;
985             bodyStartAddress++;
986             updatersAddress++;
987             fCounter++;
988             // set conditionnal jump offset
989
condJump.setOffset(body.getSize() + updaters.getSize() + 1);
990         }
991
992         // set jump offset
993
jump.setOffset(-((hasCondition ? condition.getSize() : 0) + body.getSize() + updaters.getSize() + 2));
994
995         // for each pending break or continue instruction which are related to
996
// this loop, set the offset of the corresponding jump.
997
for (Iterator JavaDoc iter= fCompleteInstructions.iterator(); iter.hasNext();) {
998             CompleteInstruction instruction= (CompleteInstruction) iter.next();
999             Jump jumpInstruction= instruction.fInstruction;
1000            int instructionAddress= fInstructions.indexOf(jumpInstruction);
1001            if (instructionAddress > bodyStartAddress && (instruction.fLabel == null || instruction.fLabel.equals(label))) {
1002                iter.remove();
1003                if (instruction.fIsBreak) {
1004                    // jump to the instruction after the last jump
1005
jumpInstruction.setOffset((updatersAddress - instructionAddress) + 1);
1006                } else {
1007                    // jump to the first instruction of the condition
1008
jumpInstruction.setOffset(bodyAddress - instructionAddress);
1009                }
1010            }
1011        }
1012
1013        storeInstruction();
1014    }
1015
1016    /**
1017     * @see ASTVisitor#endVisit(IfStatement)
1018     */

1019    public void endVisit(IfStatement node) {
1020        if (!isActive() || hasErrors())
1021            return;
1022
1023        boolean hasElseStatement= node.getElseStatement() != null;
1024
1025        // Get the instructions
1026

1027        int ifFalseAddress= 0;
1028        Instruction ifFalse= null;
1029        int ifTrueAddress= 0;
1030        Instruction ifTrue= null;
1031
1032        if (hasElseStatement) {
1033            ifFalseAddress= fInstructions.getEnd();
1034            ifFalse= fInstructions.get(ifFalseAddress);
1035            ifTrueAddress= ifFalseAddress - ifFalse.getSize();
1036            ifTrue= fInstructions.get(ifTrueAddress);
1037        } else {
1038            ifTrueAddress= fInstructions.getEnd();
1039            ifTrue= fInstructions.get(ifTrueAddress);
1040        }
1041
1042        int conditionalAddress= ifTrueAddress - ifTrue.getSize();
1043
1044        // Insert the conditional jump
1045
ConditionalJump conditionalJump= new ConditionalJump(false);
1046        fInstructions.insert(conditionalJump, conditionalAddress + 1);
1047        // Set the jump offset
1048
conditionalJump.setOffset(ifTrue.getSize() + ((hasElseStatement)? 1 : 0));
1049        fCounter++;
1050
1051        if (hasElseStatement) {
1052            // Insert the jump
1053
int jumpAddress= ifTrueAddress + 2;
1054            Jump jump= new Jump();
1055            fInstructions.insert(jump, jumpAddress);
1056            // Set the jump offset
1057
jump.setOffset(ifFalse.getSize() + 1);
1058            fCounter++;
1059        }
1060
1061        storeInstruction();
1062
1063    }
1064
1065    /**
1066     * @see ASTVisitor#endVisit(ImportDeclaration)
1067     */

1068    public void endVisit(ImportDeclaration node) {
1069
1070    }
1071
1072    /**
1073     * @see ASTVisitor#endVisit(InfixExpression)
1074     */

1075    public void endVisit(InfixExpression node) {
1076    }
1077
1078    /**
1079     * @see ASTVisitor#endVisit(Initializer)
1080     */

1081    public void endVisit(Initializer node) {
1082
1083    }
1084
1085    /**
1086     * @see ASTVisitor#endVisit(InstanceofExpression)
1087     */

1088    public void endVisit(InstanceofExpression node) {
1089        if (!isActive() || hasErrors())
1090            return;
1091        storeInstruction();
1092    }
1093
1094    /**
1095     * @see ASTVisitor#endVisit(Javadoc)
1096     */

1097    public void endVisit(Javadoc node) {
1098
1099    }
1100
1101    /**
1102     * @see ASTVisitor#endVisit(LabeledStatement)
1103     */

1104    public void endVisit(LabeledStatement node) {
1105        if (!isActive() || hasErrors())
1106            return;
1107
1108        String JavaDoc label= node.getLabel().getIdentifier();
1109
1110        // for each pending continue instruction which are related to
1111
// this statement, set the offset of the corresponding jump.
1112
for (Iterator JavaDoc iter= fCompleteInstructions.iterator(); iter.hasNext();) {
1113            CompleteInstruction instruction= (CompleteInstruction) iter.next();
1114            if (instruction.fLabel != null && instruction.fLabel.equals(label)) {
1115                iter.remove();
1116                Jump jumpInstruction= instruction.fInstruction;
1117                int instructionAddress= fInstructions.indexOf(jumpInstruction);
1118                if (instruction.fIsBreak) {
1119                    // jump to the instruction after the statement
1120
jumpInstruction.setOffset(fInstructions.getEnd() - instructionAddress);
1121                }
1122            }
1123        }
1124    }
1125
1126    /**
1127     * @see ASTVisitor#endVisit(MethodDeclaration)
1128     */

1129    public void endVisit(MethodDeclaration node) {
1130        setActive(false);
1131    }
1132
1133    /**
1134     * @see ASTVisitor#endVisit(MethodInvocation)
1135     */

1136    public void endVisit(MethodInvocation node) {
1137        if (!isActive() || hasErrors())
1138            return;
1139        storeInstruction();
1140    }
1141
1142    /**
1143     * @see ASTVisitor#endVisit(NullLiteral)
1144     */

1145    public void endVisit(NullLiteral node) {
1146        if (!isActive() || hasErrors())
1147            return;
1148        storeInstruction();
1149    }
1150
1151    /**
1152     * @see ASTVisitor#endVisit(NumberLiteral)
1153     */

1154    public void endVisit(NumberLiteral node) {
1155        if (!isActive() || hasErrors())
1156            return;
1157        storeInstruction();
1158    }
1159
1160    /**
1161     * @see ASTVisitor#endVisit(PackageDeclaration)
1162     */

1163    public void endVisit(PackageDeclaration node) {
1164
1165    }
1166
1167    /**
1168     * @see ASTVisitor#endVisit(SimpleType)
1169     */

1170    public void endVisit(ParameterizedType node) {
1171        if (!isActive() || hasErrors())
1172            return;
1173        storeInstruction();
1174    }
1175
1176    /**
1177     * @see ASTVisitor#endVisit(ParenthesizedExpression)
1178     */

1179    public void endVisit(ParenthesizedExpression node) {
1180
1181    }
1182
1183    /**
1184     * @see ASTVisitor#endVisit(PostfixExpression)
1185     */

1186    public void endVisit(PostfixExpression node) {
1187        if (!isActive() || hasErrors())
1188            return;
1189        storeInstruction();
1190    }
1191
1192    /**
1193     * @see ASTVisitor#endVisit(PrefixExpression)
1194     */

1195    public void endVisit(PrefixExpression node) {
1196        if (!isActive() || hasErrors())
1197            return;
1198        storeInstruction();
1199    }
1200
1201    /**
1202     * @see ASTVisitor#endVisit(PrimitiveType)
1203     */

1204    public void endVisit(PrimitiveType node) {
1205    }
1206
1207    /**
1208     * @see ASTVisitor#endVisit(QualifiedName)
1209     */

1210    public void endVisit(QualifiedName node) {
1211    }
1212
1213    /**
1214     * @see ASTVisitor#endVisit(SimpleType)
1215     */

1216    public void endVisit(QualifiedType node) {
1217        if (!isActive() || hasErrors())
1218            return;
1219        storeInstruction();
1220    }
1221
1222    /**
1223     * @see ASTVisitor#endVisit(ReturnStatement)
1224     */

1225    public void endVisit(ReturnStatement node) {
1226        if (!isActive() || hasErrors())
1227            return;
1228        storeInstruction();
1229    }
1230
1231    /**
1232     * @see ASTVisitor#endVisit(SimpleName)
1233     */

1234    public void endVisit(SimpleName node) {
1235        if (!isActive() || hasErrors())
1236            return;
1237        storeInstruction();
1238    }
1239
1240    /**
1241     * @see ASTVisitor#endVisit(SimpleType)
1242     */

1243    public void endVisit(SimpleType node) {
1244        if (!isActive() || hasErrors())
1245            return;
1246        storeInstruction();
1247    }
1248
1249    /**
1250     * @see ASTVisitor#endVisit(SingleVariableDeclaration)
1251     */

1252    public void endVisit(SingleVariableDeclaration node) {
1253        if (!isActive() || hasErrors())
1254            return;
1255        storeInstruction();
1256    }
1257
1258    /**
1259     * @see ASTVisitor#endVisit(StringLiteral)
1260     */

1261    public void endVisit(StringLiteral node) {
1262        if (!isActive() || hasErrors())
1263            return;
1264        storeInstruction();
1265    }
1266
1267    /**
1268     * @see ASTVisitor#endVisit(SuperConstructorInvocation)
1269     */

1270    public void endVisit(SuperConstructorInvocation node) {
1271
1272    }
1273
1274    /**
1275     * @see ASTVisitor#endVisit(SuperFieldAccess)
1276     */

1277    public void endVisit(SuperFieldAccess node) {
1278        if (!isActive() || hasErrors())
1279            return;
1280        storeInstruction();
1281    }
1282
1283    /**
1284     * @see ASTVisitor#endVisit(SuperMethodInvocation)
1285     */

1286    public void endVisit(SuperMethodInvocation node) {
1287        if (!isActive() || hasErrors())
1288            return;
1289        storeInstruction();
1290    }
1291
1292    /**
1293     * @see ASTVisitor#endVisit(SwitchCase)
1294     */

1295    public void endVisit(SwitchCase node) {
1296        // never called
1297
}
1298
1299    /**
1300     * @see ASTVisitor#endVisit(SwitchStatement)
1301     */

1302    public void endVisit(SwitchStatement node) {
1303        // nothing to do
1304
}
1305
1306    /**
1307     * @see ASTVisitor#endVisit(SynchronizedStatement)
1308     */

1309    public void endVisit(SynchronizedStatement node) {
1310
1311    }
1312
1313    /**
1314     * @see ASTVisitor#endVisit(ThisExpression)
1315     */

1316    public void endVisit(ThisExpression node) {
1317        if (!isActive() || hasErrors())
1318            return;
1319        storeInstruction();
1320    }
1321
1322    /**
1323     * @see ASTVisitor#endVisit(ThrowStatement)
1324     */

1325    public void endVisit(ThrowStatement node) {
1326        if (!isActive() || hasErrors())
1327            return;
1328        storeInstruction();
1329    }
1330
1331    /**
1332     * @see ASTVisitor#endVisit(TryStatement)
1333     */

1334    public void endVisit(TryStatement node) {
1335
1336    }
1337
1338    /**
1339     * @see ASTVisitor#endVisit(TypeDeclaration)
1340     */

1341    public void endVisit(TypeDeclaration node) {
1342
1343    }
1344
1345    /**
1346     * @see ASTVisitor#endVisit(TypeDeclarationStatement)
1347     */

1348    public void endVisit(TypeDeclarationStatement node) {
1349
1350    }
1351
1352    /**
1353     * @see ASTVisitor#endVisit(TypeLiteral)
1354     */

1355    public void endVisit(TypeLiteral node) {
1356        if (!isActive() || hasErrors())
1357            return;
1358        storeInstruction();
1359    }
1360
1361    /**
1362     * @see ASTVisitor#endVisit(VariableDeclarationExpression)
1363     */

1364    public void endVisit(VariableDeclarationExpression node) {
1365
1366    }
1367
1368    /**
1369     * @see ASTVisitor#endVisit(VariableDeclarationFragment)
1370     */

1371    public void endVisit(VariableDeclarationFragment node) {
1372        if (!isActive() || hasErrors())
1373            return;
1374        storeInstruction();
1375    }
1376
1377    /**
1378     * @see ASTVisitor#endVisit(VariableDeclarationStatement)
1379     */

1380    public void endVisit(VariableDeclarationStatement node) {
1381
1382    }
1383
1384    /**
1385     * @see ASTVisitor#endVisit(WhileStatement)
1386     */

1387    public void endVisit(WhileStatement node) {
1388        if (!isActive() || hasErrors())
1389            return;
1390
1391        /* The structure of generated instructions is :
1392         *
1393         * --
1394         * |condition
1395         * --
1396         * - jump to the instruction after the last jump if the condition is false.
1397         * --
1398         * | body
1399         * --
1400         * - jump to the first instruction of the condition.
1401         *
1402         */

1403
1404        String JavaDoc label= getLabel(node);
1405
1406        // get adress of each part
1407
int bodyAddress= fInstructions.getEnd();
1408        Instruction body= fInstructions.getInstruction(bodyAddress);
1409        int conditionAddress= bodyAddress - body.getSize();
1410        Instruction condition= fInstructions.getInstruction(conditionAddress);
1411
1412        // add the conditionnalJump
1413
ConditionalJump conditionalJump= new ConditionalJump(false);
1414        fInstructions.insert(conditionalJump, conditionAddress + 1);
1415
1416        // add the jump
1417
Jump jump= new Jump();
1418        fInstructions.add(jump);
1419
1420        // set jump offsets
1421
conditionalJump.setOffset(body.getSize() + 1);
1422        jump.setOffset(-(condition.getSize() + body.getSize() + 2));
1423
1424        // for each pending break or continue instruction which are related to
1425
// this loop, set the offset of the corresponding jump.
1426
for (Iterator JavaDoc iter= fCompleteInstructions.iterator(); iter.hasNext();) {
1427            CompleteInstruction instruction= (CompleteInstruction) iter.next();
1428            Jump jumpInstruction= instruction.fInstruction;
1429            int instructionAddress= fInstructions.indexOf(jumpInstruction);
1430            if (instructionAddress > conditionAddress && (instruction.fLabel == null || instruction.fLabel.equals(label))) {
1431                iter.remove();
1432                if (instruction.fIsBreak) {
1433                    // jump to the instruction after the last jump
1434
jumpInstruction.setOffset((bodyAddress - instructionAddress) + 2);
1435                } else {
1436                    // jump to the first instruction of the condition
1437
jumpInstruction.setOffset((conditionAddress - condition.getSize()) - instructionAddress);
1438                }
1439            }
1440        }
1441
1442        fCounter+= 2;
1443        storeInstruction();
1444    }
1445
1446    /*
1447     * Visit methods
1448     *
1449     * There are two variations of node visiting:
1450     * <ol>
1451     * <li>Push the instruction corresponding to the node
1452     * onto the stack and return <code>true</code> to visit
1453     * the children of the node.</li>
1454     * <li>Push the instruction corresponding to the node
1455     * onto the stack and visit the children of the node
1456     * manually (return <code>false</code> to avoid the
1457     * default child visiting implementation).</li>
1458     * </ol>
1459     */

1460
1461    /* (non-Javadoc)
1462     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeDeclaration)
1463     */

1464    public boolean visit(AnnotationTypeDeclaration node) {
1465        return false;
1466    }
1467
1468    /* (non-Javadoc)
1469     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration)
1470     */

1471    public boolean visit(AnnotationTypeMemberDeclaration node) {
1472        return false;
1473    }
1474
1475    /**
1476     * @see ASTVisitor#visit(AnonymousClassDeclaration)
1477     */

1478    public boolean visit(AnonymousClassDeclaration node) {
1479        if (!isActive()) {
1480            return true;
1481        }
1482        setHasError(true);
1483        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Anonymous_type_declaration_cannot_be_used_in_an_evaluation_expression_2);
1484        return false;
1485    }
1486
1487    /**
1488     * @see ASTVisitor#visit(ArrayAccess)
1489     */

1490    public boolean visit(ArrayAccess node) {
1491        if (!isActive()) {
1492            return false;
1493        }
1494
1495        push(new org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAccess(fCounter));
1496
1497        return true;
1498    }
1499
1500    /**
1501     * @see ASTVisitor#visit(ArrayCreation)
1502     */

1503    public boolean visit(ArrayCreation node) {
1504        if (!isActive()) {
1505            return false;
1506        }
1507
1508        ArrayType arrayType= node.getType();
1509
1510        if (isALocalType(arrayType.resolveBinding().getElementType())) {
1511            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Local_type_array_instance_creation_cannot_be_used_in_an_evaluation_expression_29);
1512            setHasError(true);
1513            return true;
1514        }
1515
1516        push(new ArrayAllocation(arrayType.getDimensions(), node.dimensions().size(), node.getInitializer() != null, fCounter));
1517
1518        return true;
1519    }
1520
1521    /**
1522     * @see ASTVisitor#visit(ArrayInitializer)
1523     */

1524    public boolean visit(ArrayInitializer node) {
1525        if (!isActive()) {
1526            return false;
1527        }
1528
1529        ITypeBinding typeBinding= node.resolveTypeBinding();
1530        int dimension= typeBinding.getDimensions();
1531        String JavaDoc signature= getTypeSignature(typeBinding.getElementType());
1532
1533        push(new ArrayInitializerInstruction(signature, node.expressions().size(), dimension, fCounter));
1534
1535        return true;
1536    }
1537
1538    /**
1539     * @see ASTVisitor#visit(ArrayType)
1540     */

1541    public boolean visit(ArrayType node) {
1542        if (!isActive()) {
1543            return false;
1544        }
1545        ITypeBinding arrayTypeBinding= node.resolveBinding();
1546        int dimension= arrayTypeBinding.getDimensions();
1547        String JavaDoc signature= getTypeSignature(arrayTypeBinding.getElementType());
1548
1549        push(new PushArrayType(signature, dimension, fCounter));
1550
1551        return false;
1552    }
1553
1554    /**
1555     * @see ASTVisitor#visit(AssertStatement)
1556     */

1557    public boolean visit(AssertStatement node) {
1558        if (!isActive()) {
1559            return false;
1560        }
1561        setHasError(true);
1562        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Assert_statement_cannot_be_used_in_an_evaluation_expression_3);
1563        return true;
1564    }
1565
1566    /**
1567     * @see ASTVisitor#visit(Assignment)
1568     */

1569    public boolean visit(Assignment node) {
1570        if (!isActive()) {
1571            return false;
1572        }
1573        Expression leftHandSide= node.getLeftHandSide();
1574        Expression rightHandSide= node.getRightHandSide();
1575        int variableTypeId = getTypeId(leftHandSide);
1576        int valueTypeId = getTypeId(rightHandSide);
1577
1578        String JavaDoc opToken = node.getOperator().toString();
1579        int opTokenLength = opToken.length();
1580        char char0 = opToken.charAt(0);
1581        char char2 = '\0';
1582        if (opTokenLength > 2) {
1583            char2 = opToken.charAt(2);
1584        }
1585
1586        if (variableTypeId == Instruction.T_Object) {
1587            // If the variable is an object, the value may need to be boxed for
1588
// the simple assigment.
1589
// For the compound assigment operators, the value of the variable
1590
// have to be unboxed before the operation is done, then re-boxed to
1591
// to be stored in the variable.
1592

1593            int unboxedVariableTypeId= getUnBoxedTypeId(leftHandSide);
1594            int unboxedValueTypeId= getUnBoxedTypeId(rightHandSide);
1595            int unboxedResultTypeId= Instruction.getBinaryPromotionType(unboxedVariableTypeId, unboxedValueTypeId);
1596
1597            push(new AssignmentOperator(variableTypeId, variableTypeId, fCounter));
1598            
1599            leftHandSide.accept(this);
1600            
1601            if (char0 == '=') {
1602                
1603                boolean storeRequired= false;
1604                if (rightHandSide.resolveTypeBinding().isPrimitive()) {
1605                    boxing(leftHandSide.resolveTypeBinding(), rightHandSide.resolveTypeBinding());
1606                    storeRequired= true;
1607                }
1608                rightHandSide.accept(this);
1609                if (storeRequired) {
1610                    storeInstruction(); // boxing
1611
}
1612                
1613            } else {
1614                boolean unrecognized = false;
1615                
1616                
1617                boxing(leftHandSide.resolveTypeBinding(), rightHandSide.resolveTypeBinding());
1618                
1619                switch (char0) {
1620                    case '=': // equal
1621
break;
1622                    case '+': // plus equal
1623
push(new PlusOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1624                        break;
1625                    case '-': // minus equal
1626
push(new MinusOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1627                        break;
1628                    case '*': // multiply equal
1629
push(new MultiplyOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1630                        break;
1631                    case '/': // divide equal
1632
push(new DivideOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1633                        break;
1634                    case '%': // remainder equal
1635
push(new RemainderOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1636                        break;
1637                    case '^': // xor equal
1638
push(new XorOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1639                        break;
1640                    case '|': // or equal
1641
push(new OrOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1642                        break;
1643                    case '&': // and equal
1644
push(new AndOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1645                        break;
1646                    case '<': // left shift equal
1647
push(new LeftShiftOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1648                        break;
1649                    case '>': // right shift equal or unsigned right shift equal
1650
switch (char2) {
1651                            case '=': // right shift equal
1652
push(new RightShiftOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1653                                break;
1654                            case '>': // unsigned right shift equal
1655
push(new UnsignedRightShiftOperator(unboxedVariableTypeId, unboxedValueTypeId, unboxedResultTypeId, fCounter));
1656                                break;
1657                            default:
1658                                unrecognized = true;
1659                                break;
1660                        }
1661                        break;
1662                    default:
1663                        unrecognized = true;
1664                        break;
1665                }
1666
1667                if (unrecognized) {
1668                    setHasError(true);
1669                    addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_assignment_operator____4 + opToken);
1670                    return false;
1671                }
1672
1673                unBoxing(leftHandSide.resolveTypeBinding());
1674                push(new Dup());
1675                storeInstruction(); // dup
1676
storeInstruction(); // unboxing
1677

1678                boolean storeRequired= unBoxing(rightHandSide.resolveTypeBinding());
1679                rightHandSide.accept(this);
1680                if (storeRequired) {
1681                    storeInstruction(); // unboxing
1682
}
1683                
1684                storeInstruction(); // operation
1685
storeInstruction(); // boxing
1686

1687            }
1688            
1689        } else {
1690            boolean unrecognized = false;
1691            
1692            switch (char0) {
1693                case '=': // equal
1694
push(new AssignmentOperator(variableTypeId, valueTypeId, fCounter));
1695                    break;
1696                case '+': // plus equal
1697
push(new PlusAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1698                    break;
1699                case '-': // minus equal
1700
push(new MinusAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1701                    break;
1702                case '*': // multiply equal
1703
push(new MultiplyAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1704                    break;
1705                case '/': // divide equal
1706
push(new DivideAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1707                    break;
1708                case '%': // remainder equal
1709
push(new RemainderAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1710                    break;
1711                case '^': // xor equal
1712
push(new XorAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1713                    break;
1714                case '|': // or equal
1715
push(new OrAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1716                    break;
1717                case '&': // and equal
1718
push(new AndAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1719                    break;
1720                case '<': // left shift equal
1721
push(new LeftShiftAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1722                    break;
1723                case '>': // right shift equal or unsigned right shift equal
1724
switch (char2) {
1725                        case '=': // right shift equal
1726
push(new RightShiftAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1727                            break;
1728                        case '>': // unsigned right shift equal
1729
push(new UnsignedRightShiftAssignmentOperator(variableTypeId, valueTypeId, fCounter));
1730                            break;
1731                        default:
1732                            unrecognized = true;
1733                            break;
1734                    }
1735                    break;
1736                default:
1737                    unrecognized = true;
1738                    break;
1739            }
1740    
1741            if (unrecognized) {
1742                setHasError(true);
1743                addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_assignment_operator____4 + opToken);
1744                return false;
1745            }
1746            
1747            leftHandSide.accept(this);
1748            boolean storeRequired= unBoxing(rightHandSide.resolveTypeBinding());
1749            rightHandSide.accept(this);
1750            if (storeRequired) {
1751                storeInstruction();
1752            }
1753        }
1754    
1755        return false;
1756            
1757    }
1758
1759    /**
1760     * @see ASTVisitor#visit(Block)
1761     */

1762    public boolean visit(Block node) {
1763        int start= node.getStartPosition();
1764        if (start == fStartPosition || start == (fStartPosition + 1)) {
1765            setActive(true);
1766        }
1767        if (!isActive()) {
1768            return true;
1769        }
1770
1771        push(new NoOp(fCounter));
1772
1773        return true;
1774    }
1775
1776    /* (non-Javadoc)
1777     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.BlockComment)
1778     */

1779    public boolean visit(BlockComment node) {
1780        return false;
1781    }
1782    
1783    /**
1784     * @see ASTVisitor#visit(BooleanLiteral)
1785     */

1786    public boolean visit(BooleanLiteral node) {
1787        if (!isActive()) {
1788            return false;
1789        }
1790
1791        push(new PushBoolean(node.booleanValue()));
1792
1793        return true;
1794    }
1795
1796    /**
1797     * @see ASTVisitor#visit(BreakStatement)
1798     */

1799    public boolean visit(BreakStatement node) {
1800        if (!isActive()) {
1801            return false;
1802        }
1803        // create the equivalent jump instruction in the instruction
1804
// and add an element in the list of pending break and continue
1805
// instructions
1806
Jump instruction= new Jump();
1807        SimpleName labelName= node.getLabel();
1808        String JavaDoc label= null;
1809        if (labelName != null) {
1810            label= labelName.getIdentifier();
1811        }
1812        push(instruction);
1813        fCompleteInstructions.add(new CompleteInstruction(instruction, label, true));
1814
1815        return false;
1816    }
1817
1818    /**
1819     * @see ASTVisitor#visit(CastExpression)
1820     */

1821    public boolean visit(CastExpression node) {
1822        if (!isActive()) {
1823            return false;
1824        }
1825
1826        Type type= node.getType();
1827        int typeId= getTypeId(type);
1828        ITypeBinding typeBinding= type.resolveBinding();
1829
1830        String JavaDoc baseTypeSignature;
1831        int dimension= typeBinding.getDimensions();
1832
1833        if (typeBinding.isArray()) {
1834            typeBinding= typeBinding.getElementType();
1835        }
1836        
1837        baseTypeSignature= getTypeName(typeBinding);
1838
1839        push(new Cast(typeId, baseTypeSignature, dimension, fCounter));
1840
1841        node.getExpression().accept(this);
1842
1843        return false;
1844    }
1845
1846    /**
1847     * @see ASTVisitor#visit(CatchClause)
1848     */

1849    public boolean visit(CatchClause node) {
1850        if (!isActive()) {
1851            return false;
1852        }
1853        setHasError(true);
1854        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Catch_clause_cannot_be_used_in_an_evaluation_expression_6);
1855        return true;
1856    }
1857
1858    /**
1859     * @see ASTVisitor#visit(CharacterLiteral)
1860     */

1861    public boolean visit(CharacterLiteral node) {
1862        if (!isActive()) {
1863            return false;
1864        }
1865
1866        push(new PushChar(node.charValue()));
1867
1868        return true;
1869    }
1870
1871    /**
1872     * return false, visit expression, type name & arguments, don't visit body declaration
1873     * @see ASTVisitor#visit(ClassInstanceCreation)
1874     */

1875    public boolean visit(ClassInstanceCreation node) {
1876        if (!isActive()) {
1877            return true;
1878        }
1879
1880        if (node.getAnonymousClassDeclaration() != null) {
1881            setHasError(true);
1882            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Anonymous_type_declaration_cannot_be_used_in_an_evaluation_expression_7);
1883        }
1884
1885        IMethodBinding methodBinding= node.resolveConstructorBinding();
1886        ITypeBinding typeBinding= methodBinding.getDeclaringClass();
1887        ITypeBinding enclosingTypeBinding= typeBinding.getDeclaringClass();
1888
1889        boolean isInstanceMemberType= typeBinding.isMember() && ! Modifier.isStatic(typeBinding.getModifiers());
1890
1891        if (isALocalType(typeBinding)) {
1892            setHasError(true);
1893            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Constructor_of_a_local_type_cannot_be_used_in_an_evaluation_expression_8);
1894        }
1895
1896        if (containsALocalType(methodBinding)) {
1897            setHasError(true);
1898            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Constructor_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_30);
1899        }
1900
1901
1902        if (hasErrors()) {
1903            return true;
1904        }
1905
1906        int argCount= methodBinding.getParameterTypes().length;
1907
1908        String JavaDoc enclosingTypeSignature= null;
1909        if (isInstanceMemberType) {
1910            enclosingTypeSignature= getTypeSignature(enclosingTypeBinding);
1911            argCount++;
1912        }
1913
1914        String JavaDoc signature= getMethodSignature(methodBinding, enclosingTypeSignature).replace('.','/');
1915
1916        push(new Constructor(signature, argCount, fCounter));
1917
1918        push(new PushType(getTypeName(typeBinding)));
1919        storeInstruction();
1920
1921        if (isInstanceMemberType) {
1922            Expression optionalExpression= node.getExpression();
1923            if (optionalExpression != null) {
1924                optionalExpression.accept(this);
1925            } else {
1926                // for a non-static inner class, check if we are not in a static context (method)
1927
ASTNode parent= node;
1928                do {
1929                    parent= parent.getParent();
1930                } while (! (parent instanceof MethodDeclaration));
1931                if (Modifier.isStatic(((MethodDeclaration)parent).getModifiers())) {
1932                    setHasError(true);
1933                    addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Must_explicitly_qualify_the_allocation_with_an_instance_of_the_enclosing_type_33);
1934                    return true;
1935                }
1936
1937                push(new PushThis(getEnclosingLevel(node, enclosingTypeBinding)));
1938                storeInstruction();
1939            }
1940        }
1941
1942        Iterator JavaDoc iterator= node.arguments().iterator();
1943        while (iterator.hasNext()) {
1944            ((Expression) iterator.next()).accept(this);
1945        }
1946
1947        return false;
1948    }
1949
1950    /**
1951     * @see ASTVisitor#visit(CompilationUnit)
1952     */

1953    public boolean visit(CompilationUnit node) {
1954        return true;
1955    }
1956
1957    /**
1958     * @see ASTVisitor#visit(ConditionalExpression)
1959     */

1960    public boolean visit(ConditionalExpression node) {
1961        if (!isActive()) {
1962            return true;
1963        }
1964
1965        push(new NoOp(fCounter));
1966
1967        return true;
1968    }
1969
1970    /**
1971     * @see ASTVisitor#visit(ConstructorInvocation)
1972     */

1973    public boolean visit(ConstructorInvocation node) {
1974        if (!isActive()) {
1975            return false;
1976        }
1977        setHasError(true);
1978        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_this_constructor_invocation_cannot_be_used_in_an_evaluation_expression_9);
1979        return false;
1980    }
1981
1982    /**
1983     * @see ASTVisitor#visit(ContinueStatement)
1984     */

1985    public boolean visit(ContinueStatement node) {
1986        if (!isActive()) {
1987            return false;
1988        }
1989        // create the equivalent jump instruction in the instruction
1990
// and add an element in the list of pending break and continue
1991
// instructions
1992
Jump instruction= new Jump();
1993        SimpleName labelName= node.getLabel();
1994        String JavaDoc label= null;
1995        if (labelName != null) {
1996            label= labelName.getIdentifier();
1997        }
1998        push(instruction);
1999        fCompleteInstructions.add(new CompleteInstruction(instruction, label, false));
2000
2001        return false;
2002    }
2003
2004    /**
2005     * @see ASTVisitor#visit(DoStatement)
2006     */

2007    public boolean visit(DoStatement node) {
2008        if (!isActive()) {
2009            return false;
2010        }
2011
2012        push(new NoOp(fCounter));
2013        return true;
2014    }
2015
2016    /**
2017     * @see ASTVisitor#visit(EmptyStatement)
2018     */

2019    public boolean visit(EmptyStatement node) {
2020        if (!isActive()) {
2021            return false;
2022        }
2023        push(new NoOp(fCounter));
2024        return true;
2025    }
2026
2027    /* (non-Javadoc)
2028     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnhancedForStatement)
2029     */

2030    public boolean visit(EnhancedForStatement node) {
2031        if (!isActive()) {
2032            return false;
2033        }
2034        
2035        push(new NoOp(fCounter));
2036        
2037        
2038        ITypeBinding typeBinding= node.getExpression().resolveTypeBinding();
2039        Type paramType= node.getParameter().getType();
2040        ITypeBinding paramBinding = paramType.resolveBinding();
2041        String JavaDoc typeSignature= getTypeSignature(paramBinding);
2042        int paramTypeId= getTypeId(paramType);
2043        boolean isParamPrimitiveType= paramTypeId != Instruction.T_Object && paramTypeId != Instruction.T_String;
2044        String JavaDoc paramIdentifier= node.getParameter().getName().getIdentifier();
2045        
2046        if (typeBinding.isArray()) {
2047            // the expression returns an array
2048
int idIndex= fUniqueIdIndex++;
2049            String JavaDoc arrayIdentifier= "#a" + idIndex; //$NON-NLS-1$
2050
String JavaDoc varIdentifier= "#i" + idIndex; //$NON-NLS-1$
2051
push(new LocalVariableCreation(arrayIdentifier, typeSignature, 1, isParamPrimitiveType, true, fCounter));
2052                node.getExpression().accept(this);
2053            storeInstruction();
2054            push(new LocalVariableCreation(varIdentifier, "I", 0, true, true, fCounter)); //$NON-NLS-1$
2055
push(new PushInt(0));
2056                storeInstruction();
2057            storeInstruction();
2058            push(new LocalVariableCreation(paramIdentifier, typeSignature, 0, isParamPrimitiveType, false, fCounter));
2059            storeInstruction();
2060            
2061            push(new LessOperator(Instruction.T_int, Instruction.T_int, fCounter));
2062                push(new PushLocalVariable(varIdentifier));
2063                storeInstruction();
2064                push(new PushArrayLength(fCounter));
2065                    push(new PushLocalVariable(arrayIdentifier));
2066                    storeInstruction();
2067                storeInstruction();
2068            storeInstruction();
2069            
2070            // conditionnal jump will be added here
2071

2072            push(new NoOp(fCounter));
2073                push(new AssignmentOperator(paramTypeId, paramTypeId, fCounter));
2074                    push(new PushLocalVariable(paramIdentifier));
2075                    storeInstruction();
2076                    push(new org.eclipse.jdt.internal.debug.eval.ast.instructions.ArrayAccess(fCounter));
2077                        push(new PushLocalVariable(arrayIdentifier));
2078                        storeInstruction();
2079                        push(new PostfixPlusPlusOperator(Instruction.T_int, fCounter));
2080                            push(new PushLocalVariable(varIdentifier));
2081                            storeInstruction();
2082                        storeInstruction();
2083                    storeInstruction();
2084                    if (checkAutoBoxing(typeBinding.getElementType(), paramBinding)) {
2085                        storeInstruction();
2086                    }
2087                storeInstruction();
2088                addPopInstruction();
2089                node.getBody().accept(this);
2090            storeInstruction();
2091            
2092            // jump will be added here
2093

2094        } else {
2095            // the expression returns a collection
2096
String JavaDoc iteratorIdentifier= "#i" + fUniqueIdIndex++; //$NON-NLS-1$
2097
push(new LocalVariableCreation(iteratorIdentifier, "Ljava/util/Iterator;", 0, false, true, fCounter)); //$NON-NLS-1$
2098
push(new SendMessage("iterator", "()Ljava/util/Iterator;", 0, null, fCounter)); //$NON-NLS-1$//$NON-NLS-2$
2099
node.getExpression().accept(this);
2100                storeInstruction();
2101            storeInstruction();
2102            push(new LocalVariableCreation(paramIdentifier, typeSignature, 0, isParamPrimitiveType, false, fCounter));
2103            storeInstruction();
2104            
2105            push(new SendMessage("hasNext", "()Z", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
2106
push(new PushLocalVariable(iteratorIdentifier));
2107                storeInstruction();
2108            storeInstruction();
2109            
2110            // conditional jump will be added here
2111

2112            push(new NoOp(fCounter));
2113                push(new AssignmentOperator(paramTypeId, paramTypeId, fCounter));
2114                    push(new PushLocalVariable(paramIdentifier));
2115                    storeInstruction();
2116                    push(new SendMessage("next", "()Ljava/lang/Object;", 0, null, fCounter)); //$NON-NLS-1$ //$NON-NLS-2$
2117
push(new PushLocalVariable(iteratorIdentifier));
2118                        storeInstruction();
2119                    storeInstruction();
2120                    if (checkAutoBoxing(typeBinding.getTypeArguments()[0], paramBinding)) {
2121                        storeInstruction();
2122                    }
2123                storeInstruction();
2124                addPopInstruction();
2125                node.getBody().accept(this);
2126            storeInstruction();
2127            
2128            // jump will be added here
2129

2130        }
2131
2132        return false;
2133    }
2134
2135    /* (non-Javadoc)
2136     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumConstantDeclaration)
2137     */

2138    public boolean visit(EnumConstantDeclaration node) {
2139        if (!isActive()) {
2140            return true;
2141        }
2142
2143        // nothing to do, we shouldn't hit this node
2144
return false;
2145    }
2146
2147    /* (non-Javadoc)
2148     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.EnumDeclaration)
2149     */

2150    public boolean visit(EnumDeclaration node) {
2151        if (!isActive()) {
2152            return true;
2153        }
2154        setHasError(true);
2155        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_0);
2156        return false;
2157    }
2158
2159    /**
2160     * @see ASTVisitor#visit(ExpressionStatement)
2161     */

2162    public boolean visit(ExpressionStatement node) {
2163        return true;
2164    }
2165
2166    /**
2167     * return false, visit expression, don't visit name
2168     *
2169     * @see ASTVisitor#visit(FieldAccess)
2170     */

2171    public boolean visit(FieldAccess node) {
2172        if (!isActive()) {
2173            return false;
2174        }
2175
2176        SimpleName fieldName= node.getName();
2177        IVariableBinding fieldBinding= (IVariableBinding) fieldName.resolveBinding();
2178        ITypeBinding declaringTypeBinding= fieldBinding.getDeclaringClass();
2179        Expression expression = node.getExpression();
2180        String JavaDoc fieldId = fieldName.getIdentifier();
2181
2182        if (Modifier.isStatic(fieldBinding.getModifiers())) {
2183            push(new PushStaticFieldVariable(fieldId, getTypeName(declaringTypeBinding), fCounter));
2184            expression.accept(this);
2185            addPopInstruction();
2186        } else {
2187            if (declaringTypeBinding == null) { // it is a field without declaring type => it is the special length array field
2188
push(new PushArrayLength(fCounter));
2189            } else {
2190                if (isALocalType(declaringTypeBinding)) {
2191                    setHasError(true);
2192                    addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Qualified_local_type_field_access_cannot_be_used_in_an_evaluation_expression_31);
2193                    return false;
2194                }
2195                push(new PushFieldVariable(fieldId, getTypeSignature(declaringTypeBinding), fCounter));
2196            }
2197            expression.accept(this);
2198        }
2199
2200        return false;
2201    }
2202
2203    /**
2204     * @see ASTVisitor#visit(FieldDeclaration)
2205     */

2206    public boolean visit(FieldDeclaration node) {
2207        return true;
2208    }
2209
2210    /**
2211     * @see ASTVisitor#visit(ForStatement)
2212     * return <code>false</code>, don't use the standard accept order.
2213     * order used for visiting children :
2214     * initializers, condition, body, updaters
2215     */

2216    public boolean visit(ForStatement node) {
2217        if (!isActive()) {
2218            return false;
2219        }
2220
2221        push(new NoOp(fCounter));
2222
2223        push(new NoOp(fCounter));
2224        for (Iterator JavaDoc iter= node.initializers().iterator(); iter.hasNext();) {
2225            Expression expr= (Expression) iter.next();
2226            expr.accept(this);
2227            addPopInstructionIfNeeded(expr);
2228        }
2229        storeInstruction();
2230
2231        Expression condition= node.getExpression();
2232        if (condition != null) {
2233            condition.accept(this);
2234        }
2235
2236        node.getBody().accept(this);
2237
2238        push(new NoOp(fCounter));
2239        for (Iterator JavaDoc iter= node.updaters().iterator(); iter.hasNext();) {
2240            Expression expr= (Expression) iter.next();
2241            expr.accept(this);
2242            addPopInstructionIfNeeded(expr);
2243        }
2244        storeInstruction();
2245
2246        return false;
2247    }
2248
2249    /**
2250     * @see ASTVisitor#visit(IfStatement)
2251     */

2252    public boolean visit(IfStatement node) {
2253        if (!isActive()) {
2254            return false;
2255        }
2256
2257        push(new NoOp(fCounter));
2258
2259        return true;
2260    }
2261
2262    /**
2263     * @see ASTVisitor#visit(ImportDeclaration)
2264     */

2265    public boolean visit(ImportDeclaration node) {
2266        return false;
2267    }
2268
2269    /**
2270     * return <code>false</code>, don't use the standart accept order.
2271     *
2272     * @see ASTVisitor#visit(InfixExpression)
2273     */

2274    public boolean visit(InfixExpression node) {
2275        if (!isActive()) {
2276            return false;
2277        }
2278
2279        String JavaDoc opToken = node.getOperator().toString();
2280        int opTokenLength = opToken.length();
2281        char char0 = opToken.charAt(0);
2282        char char1 = '\0';
2283        char char2 = '\0';
2284        if (opTokenLength > 1) {
2285            char1 = opToken.charAt(1);
2286            if (opTokenLength > 2) {
2287                char2 = opToken.charAt(2);
2288            }
2289        }
2290
2291        List JavaDoc extendedOperands = node.extendedOperands();
2292
2293        int operatorNumber=extendedOperands.size() + 1;
2294
2295        int[][] types = new int[operatorNumber][3];
2296
2297        Iterator JavaDoc iterator = extendedOperands.iterator();
2298
2299        Expression leftOperand= node.getLeftOperand();
2300        Expression rightOperand= node.getRightOperand();
2301        int leftTypeId;
2302        int rightTypeId;
2303        // == case, do not unbox, if the two operands are objects
2304
boolean unbox= char0 != '=' || leftOperand.resolveTypeBinding().isPrimitive() || rightOperand.resolveTypeBinding().isPrimitive();
2305        if (unbox) {
2306            leftTypeId= getUnBoxedTypeId(leftOperand);
2307            rightTypeId = getUnBoxedTypeId(rightOperand);
2308        } else {
2309            leftTypeId= getTypeId(leftOperand);
2310            rightTypeId = getTypeId(rightOperand);
2311        }
2312        int resultTypeId = Instruction.getBinaryPromotionType(leftTypeId, rightTypeId);
2313
2314        types[0][0] = resultTypeId;
2315        types[0][1] = leftTypeId;
2316        types[0][2] = rightTypeId;
2317
2318        for (int i = 1; i < operatorNumber; i++) {
2319            Expression operand = (Expression) iterator.next();
2320            leftTypeId = resultTypeId;
2321            rightTypeId = getUnBoxedTypeId(operand);
2322            resultTypeId = Instruction.getBinaryPromotionType(leftTypeId, rightTypeId);
2323            types[i][0] = resultTypeId;
2324            types[i][1] = leftTypeId;
2325            types[i][2] = rightTypeId;
2326        }
2327
2328        boolean unrecognized= false;
2329
2330        switch (char0) {
2331            case '*': // multiply
2332
for (int i = operatorNumber - 1; i >= 0; i--) {
2333                    push(new MultiplyOperator(types[i][0], types[i][1], types[i][2], fCounter));
2334                }
2335                break;
2336            case '/': // divide
2337
for (int i = operatorNumber - 1; i >= 0; i--) {
2338                    push(new DivideOperator(types[i][0], types[i][1], types[i][2], fCounter));
2339                }
2340                break;
2341            case '%': // remainder
2342
for (int i = operatorNumber - 1; i >= 0; i--) {
2343                    push(new RemainderOperator(types[i][0], types[i][1], types[i][2], fCounter));
2344                }
2345                break;
2346            case '+': // plus
2347
for (int i = operatorNumber - 1; i >= 0; i--) {
2348                    push(new PlusOperator(types[i][0], types[i][1], types[i][2], fCounter));
2349                }
2350                break;
2351            case '-': // minus
2352
for (int i = operatorNumber - 1; i >= 0; i--) {
2353                    push(new MinusOperator(types[i][0], types[i][1], types[i][2], fCounter));
2354                }
2355                break;
2356            case '<': // left shift or less or less equal
2357
switch (char1) {
2358                    case '\0': // less
2359
for (int i = operatorNumber - 1; i >= 0; i--) {
2360                            push(new LessOperator(types[i][1], types[i][2], fCounter));
2361                        }
2362                        break;
2363                    case '<': // left shift
2364
for (int i = operatorNumber - 1; i >= 0; i--) {
2365                            push(new LeftShiftOperator(Instruction.getUnaryPromotionType(types[i][1]), types[i][1], types[i][2], fCounter));
2366                        }
2367                        break;
2368                    case '=': // less equal
2369
for (int i = operatorNumber - 1; i >= 0; i--) {
2370                            push(new LessEqualOperator(types[i][1], types[i][2], fCounter));
2371                        }
2372                        break;
2373                    default:
2374                        unrecognized= true;
2375                        break;
2376                }
2377                break;
2378            case '>': // right shift or unsigned right shift or greater or greater equal
2379
switch (char1) {
2380                    case '\0': // greater
2381
for (int i = operatorNumber - 1; i >= 0; i--) {
2382                            push(new GreaterOperator(types[i][1], types[i][2], fCounter));
2383                        }
2384                        break;
2385                    case '>': // right shift or unsigned right shift
2386
switch (char2) {
2387                            case '\0': // right shift
2388
for (int i = operatorNumber - 1; i >= 0; i--) {
2389                                    push(new RightShiftOperator(Instruction.getUnaryPromotionType(types[i][1]), types[i][1], types[i][2], fCounter));
2390                                }
2391                                break;
2392                            case '>': // unsigned right shift
2393
for (int i = operatorNumber - 1; i >= 0; i--) {
2394                                    push(new UnsignedRightShiftOperator(Instruction.getUnaryPromotionType(types[i][1]), types[i][1], types[i][2], fCounter));
2395                                }
2396                                break;
2397                        }
2398                        break;
2399                    case '=': // greater equal
2400
for (int i = operatorNumber - 1; i >= 0; i--) {
2401                            push(new GreaterEqualOperator(types[i][1], types[i][2], fCounter));
2402                        }
2403                        break;
2404                    default:
2405                        unrecognized= true;
2406                        break;
2407                }
2408                break;
2409            case '=': // equal equal
2410
for (int i = operatorNumber - 1; i >= 0; i--) {
2411                    push(new EqualEqualOperator(types[i][1], types[i][2], true, fCounter));
2412                }
2413                break;
2414            case '!': // not equal
2415
for (int i = operatorNumber - 1; i >= 0; i--) {
2416                    push(new EqualEqualOperator(types[i][1], types[i][2], false, fCounter));
2417                }
2418                break;
2419            case '^': // xor
2420
for (int i = operatorNumber - 1; i >= 0; i--) {
2421                    push(new XorOperator(types[i][0], types[i][1], types[i][2], fCounter));
2422                }
2423                break;
2424            case '|': // or or or or
2425
switch (char1) {
2426                    case '\0': // or
2427
for (int i = operatorNumber - 1; i >= 0; i--) {
2428                            push(new OrOperator(types[i][0], types[i][1], types[i][2], fCounter));
2429                        }
2430                        break;
2431                    case '|': // or or
2432
for (int i = operatorNumber - 1; i >= 0; i--) {
2433                            push(new NoOp(fCounter));
2434                        }
2435                        break;
2436                    default:
2437                        unrecognized= true;
2438                        break;
2439                }
2440                break;
2441            case '&': // and or and and
2442
switch (char1) {
2443                    case '\0': // and
2444
for (int i = operatorNumber - 1; i >= 0; i--) {
2445                            push(new AndOperator(types[i][0], types[i][1], types[i][2], fCounter));
2446                        }
2447                        break;
2448                    case '&': // and and
2449
for (int i = operatorNumber - 1; i >= 0; i--) {
2450                            push(new NoOp(fCounter));
2451                        }
2452                        break;
2453                    default:
2454                        unrecognized= true;
2455                        break;
2456                }
2457                break;
2458            default:
2459                unrecognized= true;
2460                break;
2461        }
2462
2463        if (unrecognized) {
2464            setHasError(true);
2465            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Unrecognized_infix_operator____13 + opToken);
2466        }
2467
2468        if (hasErrors()) {
2469            return true;
2470        }
2471
2472        iterator = extendedOperands.iterator();
2473
2474        if ((char0 == '&' && char1 == '&') || (char0 == '|' && char1 == '|')) { // and and operator
2475

2476            boolean isOrOr= char0 == '|';
2477
2478            ConditionalJump[] conditionalJumps= new ConditionalJump[operatorNumber];
2479            int[] conditionalJumpAddresses = new int[operatorNumber];
2480
2481            boolean storeRequired= unBoxing(leftOperand.resolveTypeBinding());
2482            leftOperand.accept(this);
2483            if (storeRequired) {
2484                storeInstruction();
2485            }
2486
2487            ConditionalJump conditionalJump= new ConditionalJump(isOrOr);
2488            conditionalJumps[0]= conditionalJump;
2489            conditionalJumpAddresses[0] = fCounter;
2490            push(conditionalJump);
2491            storeInstruction();
2492
2493            storeRequired= unBoxing(rightOperand.resolveTypeBinding());
2494            rightOperand.accept(this);
2495            if (storeRequired) {
2496                storeInstruction();
2497            }
2498
2499            for (int i= 1; i < operatorNumber; i ++) {
2500                conditionalJump= new ConditionalJump(isOrOr);
2501                conditionalJumps[i]= conditionalJump;
2502                conditionalJumpAddresses[i] = fCounter;
2503                push(conditionalJump);
2504                storeInstruction();
2505                Expression operand= (Expression) iterator.next();
2506                storeRequired= unBoxing(operand.resolveTypeBinding());
2507                operand.accept(this);
2508                if (storeRequired) {
2509                    storeInstruction();
2510                }
2511            }
2512
2513            Jump jump = new Jump();
2514            jump.setOffset(1);
2515            push(jump);
2516            storeInstruction();
2517
2518            for (int i= 0; i < operatorNumber; i ++) {
2519                conditionalJumps[i].setOffset(fCounter - conditionalJumpAddresses[i] - 1);
2520            }
2521
2522            push(new PushBoolean(isOrOr));
2523            storeInstruction();
2524
2525            // store the noop
2526
storeInstruction();
2527
2528        } else { // other operators
2529

2530            boolean storeRequired= false;
2531            if (unbox) {
2532                storeRequired= unBoxing(leftOperand.resolveTypeBinding());
2533            }
2534            leftOperand.accept(this);
2535            if (storeRequired) {
2536                storeInstruction();
2537            }
2538            if (unbox) {
2539                storeRequired= unBoxing(rightOperand.resolveTypeBinding());
2540            }
2541            rightOperand.accept(this);
2542            if (storeRequired) {
2543                storeInstruction();
2544            }
2545
2546            storeInstruction();
2547            for (int i= 1; i < operatorNumber; i ++) {
2548                Expression operand= (Expression) iterator.next();
2549                if (unbox) {
2550                    storeRequired= unBoxing(operand.resolveTypeBinding());
2551                }
2552                operand.accept(this);
2553                if (storeRequired) {
2554                    storeInstruction();
2555                }
2556                storeInstruction();
2557            }
2558        }
2559
2560
2561
2562        return false;
2563    }
2564
2565    /**
2566     * @see ASTVisitor#visit(Initializer)
2567     */

2568    public boolean visit(Initializer node) {
2569        return true;
2570    }
2571
2572    /**
2573     * @see ASTVisitor#visit(InstanceofExpression)
2574     */

2575    public boolean visit(InstanceofExpression node) {
2576        if (!isActive()) {
2577            return false;
2578        }
2579        push(new InstanceOfOperator(fCounter));
2580        return true;
2581    }
2582
2583    /**
2584     * @see ASTVisitor#visit(Javadoc)
2585     */

2586    public boolean visit(Javadoc node) {
2587        return false;
2588    }
2589
2590    /**
2591     * @see ASTVisitor#visit(LabeledStatement)
2592     * return <code>false</code>, don't use the standart accept order.
2593     */

2594    public boolean visit(LabeledStatement node) {
2595        node.getBody().accept(this);
2596        return false;
2597    }
2598
2599    /* (non-Javadoc)
2600     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LineComment)
2601     */

2602    public boolean visit(LineComment node) {
2603        return false;
2604    }
2605
2606
2607    /* (non-Javadoc)
2608     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MarkerAnnotation)
2609     */

2610    public boolean visit(MarkerAnnotation node) {
2611        return false;
2612    }
2613
2614    /* (non-Javadoc)
2615     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberRef)
2616     */

2617    public boolean visit(MemberRef node) {
2618        return false;
2619    }
2620    
2621    /* (non-Javadoc)
2622     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MemberValuePair)
2623     */

2624    public boolean visit(MemberValuePair node) {
2625        return false;
2626    }
2627    
2628    /**
2629     * @see ASTVisitor#visit(MethodDeclaration)
2630     */

2631    public boolean visit(MethodDeclaration node) {
2632        int start= node.getStartPosition();
2633        int end= start + node.getLength();
2634        if (start < fStartPosition && end > fStartPosition) {
2635            return true;
2636        }
2637        return false;
2638    }
2639
2640    /**
2641     * return false, don't visit name, visit expression & arguments
2642     *
2643     * @see ASTVisitor#visit(MethodInvocation)
2644     */

2645    public boolean visit(MethodInvocation node) {
2646        if (!isActive()) {
2647            return false;
2648        }
2649
2650        IMethodBinding methodBinding= (IMethodBinding) node.getName().resolveBinding();
2651        if (methodBinding == null) {
2652            // could be the receiver is not visible - for example a private field access from super class
2653
ASTNode root = node.getRoot();
2654            if (root instanceof CompilationUnit) {
2655                CompilationUnit cu = (CompilationUnit) root;
2656                IProblem[] problems = cu.getProblems();
2657                for (int i = 0; i < problems.length; i++) {
2658                    IProblem problem = problems[i];
2659                    setHasError(true);
2660                    addErrorMessage(problem.getMessage());
2661                }
2662            }
2663        }
2664        
2665        if (hasErrors()) {
2666            return true;
2667        }
2668
2669        if (containsALocalType(methodBinding)) {
2670            setHasError(true);
2671            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Method_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_32);
2672        }
2673
2674        if (hasErrors()) {
2675            return true;
2676        }
2677
2678        ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
2679        int paramCount= parameterTypes.length;
2680        String JavaDoc selector= methodBinding.getName();
2681
2682        String JavaDoc signature= getMethodSignature(methodBinding, null).replace('.','/');
2683
2684        boolean isStatic= Flags.isStatic(methodBinding.getModifiers());
2685        Expression expression= node.getExpression();
2686
2687        if (isStatic) {
2688            String JavaDoc typeName= getTypeName(methodBinding.getDeclaringClass());
2689            push(new SendStaticMessage(typeName, selector, signature, paramCount, fCounter));
2690            if (expression != null) {
2691                node.getExpression().accept(this);
2692                addPopInstruction();
2693            }
2694        } else {
2695            push(new SendMessage(selector, signature, paramCount, null, fCounter));
2696            if (expression == null) {
2697                push(new PushThis(getEnclosingLevel(node, methodBinding.getDeclaringClass())));
2698                storeInstruction();
2699            } else {
2700                node.getExpression().accept(this);
2701            }
2702        }
2703
2704        List JavaDoc arguments = node.arguments();
2705        int argCount = arguments.size();
2706        if (methodBinding.isVarargs() && !(paramCount == argCount && parameterTypes[paramCount - 1].getDimensions() == ((Expression)arguments.get(argCount - 1)).resolveTypeBinding().getDimensions())) {
2707            // if this method is a varargs, and if the method is invoked using the varargs syntax
2708
// (multiple arguments) and not an array
2709
Iterator JavaDoc iterator= arguments.iterator();
2710            // process the first arguments (no part of the var argument)
2711
for (int i= 0; i < paramCount - 1; i++) {
2712                Expression argument= (Expression)iterator.next();
2713                boolean storeRequired= checkAutoBoxing(argument.resolveTypeBinding(), parameterTypes[i]);
2714                argument.accept(this);
2715                if (storeRequired) {
2716                    storeInstruction();
2717                }
2718            }
2719            // create a array of the remainder arguments
2720
ITypeBinding varargsParameterType= parameterTypes[paramCount - 1];
2721            ITypeBinding varargsElementType= varargsParameterType.getElementType();
2722            push(new ArrayInitializerInstruction(getTypeSignature(varargsElementType), argCount - paramCount + 1, varargsParameterType.getDimensions(), fCounter));
2723            while (iterator.hasNext()) {
2724                Expression argument= (Expression) iterator.next();
2725                boolean storeRequired= checkAutoBoxing(argument.resolveTypeBinding(), varargsElementType);
2726                argument.accept(this);
2727                if (storeRequired) {
2728                    storeInstruction();
2729                }
2730            }
2731            storeInstruction();
2732        } else {
2733            Iterator JavaDoc iterator= arguments.iterator();
2734            int i= 0;
2735            while (iterator.hasNext()) {
2736                Expression argument= (Expression) iterator.next();
2737                boolean storeRequired= checkAutoBoxing(argument.resolveTypeBinding(), parameterTypes[i++]);
2738                argument.accept(this);
2739                if (storeRequired) {
2740                    storeInstruction();
2741                }
2742            }
2743        }
2744
2745        return false;
2746    }
2747    
2748    /* (non-Javadoc)
2749     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRef)
2750     */

2751    public boolean visit(MethodRef node) {
2752        return false;
2753    }
2754    
2755    /* (non-Javadoc)
2756     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodRefParameter)
2757     */

2758    public boolean visit(MethodRefParameter node) {
2759        return false;
2760    }
2761
2762    /* (non-Javadoc)
2763     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Modifier)
2764     */

2765    public boolean visit(Modifier node) {
2766        return false;
2767    }
2768
2769    /* (non-Javadoc)
2770     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.NormalAnnotation)
2771     */

2772    public boolean visit(NormalAnnotation node) {
2773        return false;
2774    }
2775
2776    /**
2777     * @see ASTVisitor#visit(NullLiteral)
2778     */

2779    public boolean visit(NullLiteral node) {
2780        if (!isActive()) {
2781            return false;
2782        }
2783
2784        push(new PushNull());
2785
2786        return true;
2787    }
2788
2789    /**
2790     * @see ASTVisitor#visit(NumberLiteral)
2791     */

2792    public boolean visit(NumberLiteral node) {
2793        if (!isActive()) {
2794            return false;
2795        }
2796
2797        int literalType= getTypeId(node);
2798        String JavaDoc token= node.getToken();
2799        int tokenLastCharOffset= token.length() - 1;
2800        char lastChar= token.charAt(tokenLastCharOffset);
2801        String JavaDoc subToken= token.substring(0, tokenLastCharOffset);
2802
2803
2804        switch (literalType) {
2805            case Instruction.T_int:
2806                push(new PushInt(parseIntValue(token)));
2807                break;
2808            case Instruction.T_long:
2809                push(new PushLong(parseLongValue(subToken)));
2810                break;
2811            case Instruction.T_float:
2812                push(new PushFloat(Float.parseFloat(subToken)));
2813                break;
2814            case Instruction.T_double:
2815                if (lastChar == 'D' || lastChar == 'd') {
2816                    push(new PushDouble(Double.parseDouble(subToken)));
2817                } else {
2818                    push(new PushDouble(Double.parseDouble(token)));
2819                }
2820                break;
2821        }
2822
2823        return true;
2824    }
2825
2826    /**
2827     * Method parseIntValue.
2828     * @param token
2829     */

2830    private int parseIntValue(String JavaDoc token) {
2831        int tokenLength= token.length();
2832        if (tokenLength < 10) {
2833            // Integer.decode can handle tokens with less than 10 digits
2834
return Integer.decode(token).intValue();
2835        }
2836        switch (getBase(token)) {
2837            case 8:
2838                return (Integer.decode(token.substring(0, tokenLength - 1)).intValue() << 3) | Integer.decode("0" + token.charAt(tokenLength - 1)).intValue(); //$NON-NLS-1$
2839
case 10:
2840                return Integer.decode(token).intValue();
2841            case 16:
2842                return (Integer.decode(token.substring(0, tokenLength - 1)).intValue() << 4) | Integer.decode("0x" + token.charAt(tokenLength - 1)).intValue(); //$NON-NLS-1$
2843
default:
2844                // getBase(String) only returns 8, 10, or 16. This code is unreachable
2845
return 0;
2846        }
2847    }
2848
2849
2850    /**
2851     * Method parseLongValue.
2852     * @param token
2853     */

2854    private long parseLongValue(String JavaDoc token) {
2855        int tokenLength= token.length();
2856        if (tokenLength < 18) {
2857            // Long.decode can handle tokens with less than 18 digits
2858
return Long.decode(token).longValue();
2859        }
2860        switch (getBase(token)) {
2861            case 8:
2862                return (Long.decode(token.substring(0, tokenLength - 1)).longValue() << 3) | Long.decode("0" + token.charAt(tokenLength - 1)).longValue(); //$NON-NLS-1$
2863
case 10:
2864                return Long.decode(token).longValue();
2865            case 16:
2866                return (Long.decode(token.substring(0, tokenLength - 1)).longValue() << 4) | Long.decode("0x" + token.charAt(tokenLength - 1)).longValue(); //$NON-NLS-1$
2867
default:
2868                // getBase(String) only returns 8, 10, or 16. This code is unreachable
2869
return 0;
2870        }
2871    }
2872
2873    /**
2874     * Returns the numeric base for the given token
2875     * according to the Java specification. Returns
2876     * 8, 10, or 16.
2877     */

2878    private int getBase(String JavaDoc token) {
2879        if (token.charAt(0) == '0') {
2880            if (token.charAt(1) == 'x') {
2881                return 16; // "0x" prefix: Hexadecimal
2882
}
2883            return 8; // "0" prefix: Octal
2884
}
2885        return 10; // No prefix: Decimal
2886
}
2887
2888    /**
2889     * @see ASTVisitor#visit(PackageDeclaration)
2890     */

2891    public boolean visit(PackageDeclaration node) {
2892        return false;
2893    }
2894
2895    /* (non-Javadoc)
2896     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ParameterizedType)
2897     */

2898    public boolean visit(ParameterizedType node) {
2899        if (!isActive()) {
2900            return false;
2901        }
2902        ITypeBinding typeBinding = node.resolveBinding();
2903        push(new PushType(getTypeName(typeBinding)));
2904        return false;
2905    }
2906
2907    /**
2908     * @see ASTVisitor#visit(ParenthesizedExpression)
2909     */

2910    public boolean visit(ParenthesizedExpression node) {
2911        if (!isActive()) {
2912            return false;
2913        }
2914        return true;
2915    }
2916
2917    /**
2918     * @see ASTVisitor#visit(PostfixExpression)
2919     */

2920    public boolean visit(PostfixExpression node) {
2921        if (!isActive()) {
2922            return false;
2923        }
2924
2925        Expression operand= node.getOperand();
2926        int expressionTypeId = getTypeId(operand);
2927
2928        String JavaDoc opToken = node.getOperator().toString();
2929        char char0 = opToken.charAt(0);
2930        
2931        if (expressionTypeId == Instruction.T_Object) {
2932
2933            int expressionUnBoxedTypeId= getUnBoxedTypeId(operand);
2934            
2935            AssignmentOperator assignmentInstruction= new AssignmentOperator(Instruction.T_Object, Instruction.T_Object, fCounter);
2936            push(assignmentInstruction);
2937            operand.accept(this);
2938            switch (char0) {
2939                case '+': // plus plus
2940
push(new PlusOperator(expressionUnBoxedTypeId, expressionUnBoxedTypeId, expressionUnBoxedTypeId, fCounter));
2941                    break;
2942                case '-': // minus minus
2943
push(new MinusOperator(expressionUnBoxedTypeId, expressionUnBoxedTypeId, expressionUnBoxedTypeId, fCounter));
2944                    break;
2945                default:
2946                    setHasError(true);
2947                    addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_postfix_operator____15 + opToken);
2948                    break;
2949            }
2950            push(new Value(fCounter));
2951            push(new Dup());
2952            storeInstruction(); // dup
2953
storeInstruction(); // value
2954
push(new DupX1());
2955            storeInstruction(); // dup_x1
2956
unBoxing(operand.resolveTypeBinding());
2957            storeInstruction(); // unboxing
2958
push(new PushInt(1));
2959            storeInstruction(); // push 1
2960
storeInstruction(); // operator
2961
boxing(operand.resolveTypeBinding(), null);
2962            storeInstruction(); // boxing
2963
storeInstruction(); // assigment
2964
push(new Pop(assignmentInstruction.getSize() + 1));
2965            
2966            
2967            return false;
2968        }
2969
2970        switch (char0) {
2971            case '+': // plus plus
2972
push(new PostfixPlusPlusOperator(expressionTypeId, fCounter));
2973                break;
2974            case '-': // minus minus
2975
push(new PostfixMinusMinusOperator(expressionTypeId, fCounter));
2976                break;
2977            default:
2978                setHasError(true);
2979                addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_postfix_operator____15 + opToken);
2980                break;
2981        }
2982
2983        return true;
2984    }
2985
2986    /**
2987     * @see ASTVisitor#visit(PrefixExpression)
2988     */

2989    public boolean visit(PrefixExpression node) {
2990        if (!isActive()) {
2991            return false;
2992        }
2993
2994        Expression operand= node.getOperand();
2995        int expressionTypeId = getTypeId(operand);
2996
2997        String JavaDoc opToken = node.getOperator().toString();
2998        int opTokenLength = opToken.length();
2999        char char0 = opToken.charAt(0);
3000        char char1 = '\0';
3001        if (opTokenLength > 1) {
3002            char1 = opToken.charAt(1);
3003        }
3004
3005        boolean unrecognized = false;
3006        
3007        if (expressionTypeId == Instruction.T_Object) {
3008            
3009            int expressionUnBoxedTypeId= getUnBoxedTypeId(operand);
3010            
3011            if (char1 == '\0') {
3012                switch (char0) {
3013                    case '+': // unary plus
3014
push(new UnaryPlusOperator(expressionUnBoxedTypeId, fCounter));
3015                        break;
3016                    case '-': // unary minus
3017
push(new UnaryMinusOperator(expressionUnBoxedTypeId, fCounter));
3018                        break;
3019                    case '~': // twiddle
3020
push(new TwiddleOperator(expressionUnBoxedTypeId, fCounter));
3021                        break;
3022                    case '!': // not
3023
push(new NotOperator(expressionUnBoxedTypeId, fCounter));
3024                        break;
3025                    default:
3026                        setHasError(true);
3027                        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16 + opToken);
3028                        break;
3029                }
3030    
3031                unBoxing(operand.resolveTypeBinding());
3032                operand.accept(this);
3033                storeInstruction(); // unboxing
3034

3035            } else {
3036                // plus plus and minus minus operators
3037

3038                push(new AssignmentOperator(Instruction.T_Object, Instruction.T_Object, fCounter));
3039                
3040                operand.accept(this);
3041                
3042                boxing(operand.resolveTypeBinding(), null);
3043                
3044                switch (char1) {
3045                    case '+':
3046                        push(new PlusOperator(expressionUnBoxedTypeId, expressionUnBoxedTypeId, expressionUnBoxedTypeId, fCounter));
3047                        break;
3048                    case '-':
3049                        push(new MinusOperator(expressionUnBoxedTypeId, expressionUnBoxedTypeId, expressionUnBoxedTypeId, fCounter));
3050                        break;
3051                    default:
3052                        setHasError(true);
3053                        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16 + opToken);
3054                        break;
3055                }
3056                
3057                unBoxing(operand.resolveTypeBinding());
3058                push(new Dup());
3059                storeInstruction(); // dup
3060
storeInstruction(); // unboxing
3061
push(new PushInt(1));
3062                storeInstruction(); // push 1
3063

3064                storeInstruction(); // operator
3065
storeInstruction(); // boxing
3066

3067            }
3068            
3069            return false;
3070        }
3071        
3072        switch (char0) {
3073            case '+': // plus plus or unary plus
3074
switch (char1) {
3075                    case '\0': // unary plus
3076
push(new UnaryPlusOperator(expressionTypeId, fCounter));
3077                        break;
3078                    case '+': // plus plus
3079
push(new PrefixPlusPlusOperator(expressionTypeId, fCounter));
3080                        break;
3081                    default:
3082                        unrecognized= true;
3083                        break;
3084                }
3085                break;
3086            case '-': // minus minus or unary minus
3087
switch (char1) {
3088                    case '\0': // unary minus
3089
push(new UnaryMinusOperator(expressionTypeId, fCounter));
3090                    break;
3091                    case '-': // minus minus
3092
push(new PrefixMinusMinusOperator(expressionTypeId, fCounter));
3093                    break;
3094                    default:
3095                        unrecognized= true;
3096                        break;
3097                }
3098                break;
3099            case '~': // twiddle
3100
push(new TwiddleOperator(expressionTypeId, fCounter));
3101                break;
3102            case '!': // not
3103
push(new NotOperator(expressionTypeId, fCounter));
3104                break;
3105            default:
3106                unrecognized= true;
3107                break;
3108        }
3109
3110
3111        if (unrecognized) {
3112            setHasError(true);
3113            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_unrecognized_prefix_operator____16 + opToken);
3114        }
3115
3116        return true;
3117    }
3118
3119    /**
3120     * @see ASTVisitor#visit(PrimitiveType)
3121     */

3122    public boolean visit(PrimitiveType node) {
3123        if (!isActive()) {
3124            return false;
3125        }
3126
3127        return true;
3128    }
3129
3130    /**
3131     * @see ASTVisitor#visit(QualifiedName)
3132     */

3133    public boolean visit(QualifiedName node) {
3134        if (!isActive()) {
3135            return false;
3136        }
3137
3138        if (hasErrors()) {
3139            return true;
3140        }
3141
3142        IBinding binding = node.resolveBinding();
3143        switch (binding.getKind()) {
3144            case IBinding.TYPE:
3145                node.getName().accept(this);
3146                break;
3147            case IBinding.VARIABLE:
3148                SimpleName fieldName= node.getName();
3149                IVariableBinding fieldBinding= (IVariableBinding) fieldName.resolveBinding();
3150                ITypeBinding declaringTypeBinding= fieldBinding.getDeclaringClass();
3151                String JavaDoc fieldId = fieldName.getIdentifier();
3152
3153                if (Modifier.isStatic(fieldBinding.getModifiers())) {
3154                    push(new PushStaticFieldVariable(fieldId, getTypeName(declaringTypeBinding), fCounter));
3155                } else {
3156                    if (declaringTypeBinding == null) {
3157                        push(new PushArrayLength(fCounter));
3158                    } else {
3159                        push(new PushFieldVariable(fieldId, getTypeSignature(declaringTypeBinding), fCounter));
3160                    }
3161                    node.getQualifier().accept(this);
3162                }
3163                storeInstruction();
3164                break;
3165        }
3166
3167        return false;
3168    }
3169
3170    /* (non-Javadoc)
3171     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.QualifiedType)
3172     */

3173    public boolean visit(QualifiedType node) {
3174        if (!isActive()) {
3175            return false;
3176        }
3177        ITypeBinding typeBinding = node.resolveBinding();
3178        push(new PushType(getTypeName(typeBinding)));
3179        return false;
3180    }
3181
3182    /**
3183     * @see ASTVisitor#visit(ReturnStatement)
3184     */

3185    public boolean visit(ReturnStatement node) {
3186        if (!isActive()) {
3187            return false;
3188        }
3189        push(new ReturnInstruction(fCounter));
3190        return true;
3191    }
3192
3193    /**
3194     * @see ASTVisitor#visit(SimpleName)
3195     */

3196    public boolean visit(SimpleName node) {
3197        if (!isActive()) {
3198            return false;
3199        }
3200
3201        if (hasErrors()) {
3202            return true;
3203        }
3204
3205        IBinding binding = node.resolveBinding();
3206
3207        String JavaDoc variableId = node.getIdentifier();
3208        if (binding == null) {
3209            setHasError(true);
3210            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_binding_null_for__17 + variableId);
3211            return true;
3212        }
3213
3214        switch (binding.getKind()) {
3215            case IBinding.TYPE:
3216                ITypeBinding typeBinding= (ITypeBinding) binding;
3217                push(new PushType(getTypeName(typeBinding)));
3218                break;
3219            case IBinding.VARIABLE:
3220                IVariableBinding variableBinding= (IVariableBinding) binding;
3221                ITypeBinding declaringTypeBinding= variableBinding.getDeclaringClass();
3222                if (variableBinding.isField()) {
3223                    if (Modifier.isStatic(variableBinding.getModifiers())) {
3224                        push(new PushStaticFieldVariable(variableId, getTypeName(declaringTypeBinding), fCounter));
3225                    } else {
3226                        if (isALocalType(declaringTypeBinding)) {
3227                            setHasError(true);
3228                            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_36);
3229                            return false;
3230                        }
3231                        push(new PushFieldVariable(variableId, getTypeSignature(declaringTypeBinding), fCounter));
3232                        push(new PushThis(getEnclosingLevel(node, declaringTypeBinding)));
3233                        storeInstruction();
3234                    }
3235                } else {
3236                    push(new PushLocalVariable(variableId));
3237                }
3238                break;
3239        }
3240        return true;
3241    }
3242
3243    /**
3244     * return false, don't visit child
3245     *
3246     * @see ASTVisitor#visit(SimpleType)
3247     */

3248    public boolean visit(SimpleType node) {
3249        if (!isActive()) {
3250            return false;
3251        }
3252
3253        ITypeBinding typeBinding = node.resolveBinding();
3254        push(new PushType(getTypeName(typeBinding)));
3255
3256        return false;
3257    }
3258
3259    /* (non-Javadoc)
3260     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.SingleMemberAnnotation)
3261     */

3262    public boolean visit(SingleMemberAnnotation node) {
3263        return false;
3264    }
3265    
3266    /**
3267     * @see ASTVisitor#visit(SingleVariableDeclaration)
3268     * return <code>false</code>, don't use the standart accept order.
3269     */

3270    public boolean visit(SingleVariableDeclaration node) {
3271        if (!isActive()) {
3272            return false;
3273        }
3274
3275        Expression initializer= node.getInitializer();
3276        boolean hasInitializer= initializer != null;
3277
3278        ITypeBinding typeBinding= node.getType().resolveBinding();
3279        int typeDimension= typeBinding.getDimensions();
3280        if (typeDimension != 0) {
3281            typeBinding= typeBinding.getElementType();
3282        }
3283
3284        push(new LocalVariableCreation(node.getName().getIdentifier(), getTypeSignature(typeBinding), typeDimension, typeBinding.isPrimitive(), hasInitializer, fCounter));
3285        if (hasInitializer) {
3286            initializer.accept(this);
3287        }
3288
3289        return false;
3290    }
3291
3292    /**
3293     * @see ASTVisitor#visit(StringLiteral)
3294     */

3295    public boolean visit(StringLiteral node) {
3296        if (!isActive()) {
3297            return false;
3298        }
3299
3300        push(new PushString(node.getLiteralValue()));
3301
3302        return true;
3303    }
3304
3305    /**
3306     * @see ASTVisitor#visit(SuperConstructorInvocation)
3307     */

3308    public boolean visit(SuperConstructorInvocation node) {
3309        if (!isActive()) {
3310            return false;
3311        }
3312        setHasError(true);
3313        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_super_constructor_invocation_cannot_be_used_in_an_evaluation_expression_19);
3314        return false;
3315    }
3316
3317    /**
3318     * @see ASTVisitor#visit(SuperFieldAccess)
3319     */

3320    public boolean visit(SuperFieldAccess node) {
3321        if (!isActive()) {
3322            return false;
3323        }
3324
3325        SimpleName fieldName= node.getName();
3326        IVariableBinding fieldBinding= (IVariableBinding) fieldName.resolveBinding();
3327        ITypeBinding declaringTypeBinding= fieldBinding.getDeclaringClass();
3328        String JavaDoc fieldId = fieldName.getIdentifier();
3329
3330        if (Modifier.isStatic(fieldBinding.getModifiers())) {
3331            push(new PushStaticFieldVariable(fieldId, getTypeName(declaringTypeBinding), fCounter));
3332        } else {
3333            Name qualifier = node.getQualifier();
3334            int superLevel= 1;
3335            int enclosingLevel= 0;
3336            if (qualifier != null) {
3337                superLevel= getSuperLevel(qualifier.resolveTypeBinding(), declaringTypeBinding);
3338                enclosingLevel= getEnclosingLevel(node, (ITypeBinding)qualifier.resolveBinding());
3339            }
3340            push(new PushFieldVariable(fieldId, superLevel, fCounter));
3341            push(new PushThis(enclosingLevel));
3342            storeInstruction();
3343        }
3344
3345        return false;
3346    }
3347
3348    /**
3349     * return false, don't visit name, visit arguments
3350     *
3351     * @see ASTVisitor#visit(SuperMethodInvocation)
3352     */

3353    public boolean visit(SuperMethodInvocation node) {
3354        if (!isActive()) {
3355            return false;
3356        }
3357
3358        IMethodBinding methodBinding = (IMethodBinding) node.getName().resolveBinding();
3359
3360        if (containsALocalType(methodBinding)) {
3361            setHasError(true);
3362            addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Method_which_contains_a_local_type_as_parameter_cannot_be_used_in_an_evaluation_expression_32);
3363        }
3364
3365        if (hasErrors()) {
3366            return true;
3367        }
3368
3369        ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
3370        int paramCount = parameterTypes.length;
3371        String JavaDoc selector = methodBinding.getName();
3372        String JavaDoc signature = getMethodSignature(methodBinding, null);
3373
3374        Name qualifier= node.getQualifier();
3375        if (Modifier.isStatic(methodBinding.getModifiers())) {
3376            push(new SendStaticMessage(getTypeName(methodBinding.getDeclaringClass()), selector, signature, paramCount, fCounter));
3377        } else {
3378            push(new SendMessage(selector, signature, paramCount, getTypeSignature(methodBinding.getDeclaringClass()), fCounter));
3379            int enclosingLevel= 0;
3380            if (qualifier != null) {
3381                enclosingLevel= getEnclosingLevel(node, (ITypeBinding)qualifier.resolveBinding());
3382            }
3383            push(new PushThis(enclosingLevel));
3384            storeInstruction();
3385        }
3386
3387        List JavaDoc arguments = node.arguments();
3388        int argCount = arguments.size();
3389        if (methodBinding.isVarargs() && !(paramCount == argCount && parameterTypes[paramCount - 1].getDimensions() == ((Expression)arguments.get(argCount - 1)).resolveTypeBinding().getDimensions())) {
3390            // if this method is a varargs, and if the method is invoked using the varargs syntax
3391
// (multiple arguments) and not an array
3392
Iterator JavaDoc iterator= arguments.iterator();
3393            // process the first arguments (no part of the var argument)
3394
for (int i= 0; i < paramCount - 1; i++) {
3395                Expression argument= (Expression) iterator.next();
3396                boolean storeRequired= checkAutoBoxing(argument.resolveTypeBinding(), parameterTypes[i]);
3397                argument.accept(this);
3398                if (storeRequired) {
3399                    storeInstruction();
3400                }
3401            }
3402            // create a array of the remainder arguments
3403
ITypeBinding varargsParameterType= parameterTypes[paramCount - 1];
3404            ITypeBinding varargsElementType= varargsParameterType.getElementType();
3405            push(new ArrayInitializerInstruction(getTypeSignature(varargsElementType), argCount - paramCount + 1, varargsParameterType.getDimensions(), fCounter));
3406            while (iterator.hasNext()) {
3407                Expression argument= (Expression) iterator.next();
3408                boolean storeRequired= checkAutoBoxing(argument.resolveTypeBinding(), varargsElementType);
3409                argument.accept(this);
3410                if (storeRequired) {
3411                    storeInstruction();
3412                }
3413            }
3414            storeInstruction();
3415        } else {
3416            Iterator JavaDoc iterator= arguments.iterator();
3417            int i= 0;
3418            while (iterator.hasNext()) {
3419                Expression argument= (Expression) iterator.next();
3420                boolean storeRequired= checkAutoBoxing(argument.resolveTypeBinding(), parameterTypes[i++]);
3421                argument.accept(this);
3422                if (storeRequired) {
3423                    storeInstruction();
3424                }
3425            }
3426        }
3427
3428        return false;
3429    }
3430
3431    /**
3432     * @see ASTVisitor#visit(SwitchCase)
3433     */

3434    public boolean visit(SwitchCase node) {
3435        // never called
3436
return false;
3437    }
3438
3439    /**
3440     * @see ASTVisitor#visit(SwitchStatement)
3441     */

3442    public boolean visit(SwitchStatement node) {
3443        if (!isActive()) {
3444            return false;
3445        }
3446        push(new NoOp(fCounter));
3447        int switchStart= fCounter;
3448        node.getExpression().accept(this);
3449        
3450        ArrayList JavaDoc statementsDefault= null;
3451        Jump jumpDefault= null;
3452        ArrayList JavaDoc jumpsStatements= new ArrayList JavaDoc();
3453        ArrayList JavaDoc[] currentJumpsStatements= new ArrayList JavaDoc[] {new ArrayList JavaDoc(), null};
3454        jumpsStatements.add(currentJumpsStatements);
3455        
3456        for (Iterator JavaDoc iter= node.statements().iterator(); iter.hasNext();) {
3457            Statement statement= (Statement) iter.next();
3458            if (statement instanceof SwitchCase) {
3459                SwitchCase switchCase= (SwitchCase) statement;
3460                if (switchCase.isDefault()) {
3461                    jumpDefault= new Jump();
3462                    push(jumpDefault);
3463                    storeInstruction(); // jump
3464
statementsDefault= new ArrayList JavaDoc();
3465                } else {
3466                    push(new EqualEqualOperator(Instruction.T_int, Instruction.T_int, true, fCounter));
3467                    push(new Dup());
3468                    storeInstruction(); // dup
3469
switchCase.getExpression().accept(this);
3470                    storeInstruction(); // equalequal
3471
ConditionalJump condJump= new ConditionalJump(true);
3472                    push(condJump);
3473                    storeInstruction(); // cond jump
3474
if (currentJumpsStatements[1] != null) {
3475                        currentJumpsStatements= new ArrayList JavaDoc[] {new ArrayList JavaDoc(), null};
3476                        jumpsStatements.add(currentJumpsStatements);
3477                    }
3478                    currentJumpsStatements[0].add(condJump);
3479                }
3480            } else {
3481                if (statementsDefault != null) {
3482                    statementsDefault.add(statement);
3483                } else {
3484                    if (currentJumpsStatements[1] == null) {
3485                        currentJumpsStatements[1]= new ArrayList JavaDoc();
3486                    }
3487                    currentJumpsStatements[1].add(statement);
3488                }
3489            }
3490        }
3491        
3492        Jump jumpEnd= null;
3493        if (jumpDefault == null) {
3494            push(new Pop(0));
3495            storeInstruction(); // pop
3496
jumpEnd= new Jump();
3497            push(jumpEnd);
3498            storeInstruction(); // jump
3499
}
3500        
3501        for (Iterator JavaDoc iter= jumpsStatements.iterator(); iter.hasNext();) {
3502            currentJumpsStatements= (ArrayList JavaDoc[]) iter.next();
3503            for (Iterator JavaDoc iterator= currentJumpsStatements[0].iterator(); iterator.hasNext();) {
3504                ConditionalJump condJump= (ConditionalJump) iterator.next();
3505                condJump.setOffset((fCounter - fInstructions.indexOf(condJump)) - 1);
3506            }
3507            if (currentJumpsStatements[1] != null) {
3508                push(new Pop(0));
3509                storeInstruction(); // pop
3510
for (Iterator JavaDoc iterator= currentJumpsStatements[1].iterator(); iterator.hasNext();) {
3511                    ((Statement) iterator.next()).accept(this);
3512                }
3513            }
3514        }
3515        
3516        // default case
3517
if (jumpDefault != null) {
3518            jumpDefault.setOffset((fCounter - fInstructions.indexOf(jumpDefault)) - 1);
3519            push(new Pop(0));
3520            storeInstruction(); // pop
3521
for (Iterator JavaDoc iterator= statementsDefault.iterator(); iterator.hasNext();) {
3522                ((Statement) iterator.next()).accept(this);
3523            }
3524        } else {
3525            jumpEnd.setOffset((fCounter - fInstructions.indexOf(jumpEnd)) - 1);
3526        }
3527        
3528        // for each pending break or continue instruction which are related to
3529
// this loop, set the offset of the corresponding jump.
3530
String JavaDoc label= getLabel(node);
3531        for (Iterator JavaDoc iter= fCompleteInstructions.iterator(); iter.hasNext();) {
3532            CompleteInstruction instruction= (CompleteInstruction) iter.next();
3533            Jump jumpInstruction= instruction.fInstruction;
3534            int instructionAddress= fInstructions.indexOf(jumpInstruction);
3535            if (instructionAddress > switchStart && (instruction.fLabel == null || instruction.fLabel.equals(label))) {
3536                iter.remove();
3537                if (instruction.fIsBreak) {
3538                    // jump to the instruction after the last instruction of the switch
3539
jumpInstruction.setOffset((fCounter - instructionAddress) - 1);
3540                }
3541            }
3542        }
3543
3544        return false;
3545    }
3546
3547    /**
3548     * @see ASTVisitor#visit(SynchronizedStatement)
3549     */

3550    public boolean visit(SynchronizedStatement node) {
3551        if (!isActive()) {
3552            return false;
3553        }
3554        return true;
3555    }
3556
3557    /* (non-Javadoc)
3558     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TagElement)
3559     */

3560    public boolean visit(TagElement node) {
3561        return false;
3562    }
3563
3564    /* (non-Javadoc)
3565     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TextElement)
3566     */

3567    public boolean visit(TextElement node) {
3568        return false;
3569    }
3570
3571    /**
3572     * @see ASTVisitor#visit(ThisExpression)
3573     */

3574    public boolean visit(ThisExpression node) {
3575        if (!isActive()) {
3576            return false;
3577        }
3578
3579        Name qualifier= node.getQualifier();
3580        int enclosingLevel= 0;
3581        if (qualifier != null) {
3582            enclosingLevel= getEnclosingLevel(node, (ITypeBinding)qualifier.resolveBinding());
3583        }
3584        push(new PushThis(enclosingLevel));
3585
3586        return false;
3587    }
3588
3589    /**
3590     * @see ASTVisitor#visit(ThrowStatement)
3591     */

3592    public boolean visit(ThrowStatement node) {
3593        if (!isActive()) {
3594            return false;
3595        }
3596        push(new ThrowInstruction(fCounter));
3597        return true;
3598    }
3599
3600    /**
3601     * @see ASTVisitor#visit(TryStatement)
3602     */

3603    public boolean visit(TryStatement node) {
3604        if (!isActive()) {
3605            return false;
3606        }
3607        setHasError(true);
3608        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Try_statement_cannot_be_used_in_an_evaluation_expression_23);
3609        return true;
3610    }
3611
3612    /**
3613     * @see ASTVisitor#visit(TypeDeclaration)
3614     */

3615    public boolean visit(TypeDeclaration node) {
3616        if (!isActive()) {
3617            return true;
3618        }
3619        setHasError(true);
3620        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Type_declaration_cannot_be_used_in_an_evaluation_expression_24);
3621        return false;
3622    }
3623
3624    /**
3625     * @see ASTVisitor#visit(TypeDeclarationStatement)
3626     */

3627    public boolean visit(TypeDeclarationStatement node) {
3628        if (!isActive()) {
3629            return true;
3630        }
3631        setHasError(true);
3632        addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Type_declaration_statement_cannot_be_used_in_an_evaluation_expression_25);
3633        return false;
3634    }
3635
3636    /* (non-Javadoc)
3637     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeParameter)
3638     */

3639    public boolean visit(TypeParameter node) {
3640        return false;
3641    }
3642
3643    /**
3644     * @see ASTVisitor#visit(TypeLiteral)
3645     */

3646    public boolean visit(TypeLiteral node) {
3647        if (!isActive()) {
3648            return false;
3649        }
3650
3651        push(new PushClassLiteralValue(fCounter));
3652
3653        return true;
3654    }
3655
3656    /**
3657     * @see ASTVisitor#visit(VariableDeclarationExpression)
3658     */

3659    public boolean visit(VariableDeclarationExpression node) {
3660        /* if it is in the code to execute, return <code>false</code>,
3661         * we don't use the standart accept order.
3662         * Otherwise, return true. We want to search the code to execute
3663         * in variable declarations (in case of inner classes).
3664         */

3665        if (!isActive()) {
3666            return true;
3667        }
3668        for (Iterator JavaDoc iter= node.fragments().iterator(); iter.hasNext();) {
3669            ((VariableDeclarationFragment) iter.next()).accept(this);
3670        }
3671        return false;
3672    }
3673
3674    /**
3675     * @see ASTVisitor#visit(VariableDeclarationFragment)
3676     */

3677    public boolean visit(VariableDeclarationFragment node) {
3678        /* if it is in the code to execute, return <code>false</code>,
3679         * we don't use the standart accept order.
3680         * Otherwise, return true. We want to search the code to execute
3681         * in variable declarations (in case of inner classes).
3682         */

3683        if (!isActive()) {
3684            return true;
3685        }
3686        // get the type of the variable
3687
ITypeBinding varTypeBinding;
3688        ASTNode parent= node.getParent();
3689        switch (parent.getNodeType()) {
3690            case ASTNode.VARIABLE_DECLARATION_EXPRESSION:
3691                varTypeBinding= ((VariableDeclarationExpression)parent).getType().resolveBinding();
3692                break;
3693            case ASTNode.VARIABLE_DECLARATION_STATEMENT:
3694                varTypeBinding= ((VariableDeclarationStatement)parent).getType().resolveBinding();
3695                break;
3696            default:
3697                setHasError(true);
3698                addErrorMessage(EvaluationEngineMessages.ASTInstructionCompiler_Error_in_type_declaration_statement);
3699                return false;
3700        }
3701        int typeDimension= varTypeBinding.getDimensions();
3702        ITypeBinding elementBinding = varTypeBinding;
3703        if (typeDimension != 0) {
3704            elementBinding= elementBinding.getElementType();
3705        }
3706
3707        Expression initializer= node.getInitializer();
3708        boolean hasInitializer= initializer != null;
3709
3710        push(new LocalVariableCreation(node.getName().getIdentifier(), getTypeSignature(elementBinding), typeDimension, elementBinding.isPrimitive(), hasInitializer, fCounter));
3711
3712        if (hasInitializer) {
3713            initializer.accept(this);
3714            ITypeBinding expBindnig = initializer.resolveTypeBinding();
3715            if (expBindnig != null) {
3716                if (checkAutoBoxing(expBindnig, varTypeBinding)) {
3717                    storeInstruction();
3718                }
3719            }
3720        }
3721
3722        return false;
3723    }
3724
3725    /**
3726     * @see ASTVisitor#visit(VariableDeclarationStatement)
3727     */

3728    public boolean visit(VariableDeclarationStatement node) {
3729        /* if it is in the code to execute, return <code>false</code>,
3730         * we don't use the standart accept order.
3731         * Otherwise, return true. We want to search the code to execute
3732         * in variable declarations (in case of inner classes).
3733         */

3734        if (!isActive()) {
3735            return true;
3736        }
3737        for (Iterator JavaDoc iter= node.fragments().iterator(); iter.hasNext();) {
3738            ((VariableDeclarationFragment) iter.next()).accept(this);
3739        }
3740        return false;
3741    }
3742
3743    /* (non-Javadoc)
3744     * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.WildcardType)
3745     */

3746    public boolean visit(WildcardType node) {
3747        // we shouldn't have to do anything
3748
return false;
3749    }
3750
3751    /**
3752     * @see ASTVisitor#visit(WhileStatement)
3753     */

3754    public boolean visit(WhileStatement node) {
3755        if (!isActive()) {
3756            return false;
3757        }
3758
3759        push(new NoOp(fCounter));
3760        return true;
3761    }
3762
3763    //--------------------------
3764

3765    private int getTypeId(Expression expression) {
3766        ITypeBinding typeBinding = expression.resolveTypeBinding();
3767        String JavaDoc typeName = typeBinding.getQualifiedName();
3768        if (typeBinding.isPrimitive()) {
3769            return getPrimitiveTypeId(typeName);
3770        } else if ("java.lang.String".equals(typeName)){ //$NON-NLS-1$
3771
return Instruction.T_String;
3772        } else {
3773            return Instruction.T_Object;
3774        }
3775    }
3776
3777    private int getUnBoxedTypeId(Expression expression) {
3778        ITypeBinding typeBinding = expression.resolveTypeBinding();
3779        String JavaDoc typeName = typeBinding.getQualifiedName();
3780        if (typeBinding.isPrimitive()) {
3781            return getPrimitiveTypeId(typeName);
3782        } else if ("java.lang.String".equals(typeName)){ //$NON-NLS-1$
3783
return Instruction.T_String;
3784        } else {
3785            // unboxing
3786
if ("java.lang.Integer".equals(typeName)) { //$NON-NLS-1$
3787
return Instruction.T_int;
3788            } else if ("java.lang.Character".equals(typeName)) { //$NON-NLS-1$
3789
return Instruction.T_char;
3790            } else if ("java.lang.Byte".equals(typeName)) { //$NON-NLS-1$
3791
return Instruction.T_byte;
3792            } else if ("java.lang.Short".equals(typeName)) { //$NON-NLS-1$
3793
return Instruction.T_short;
3794            } else if ("java.lang.Long".equals(typeName)) { //$NON-NLS-1$
3795
return Instruction.T_long;
3796            } else if ("java.lang.Float".equals(typeName)) { //$NON-NLS-1$
3797
return Instruction.T_float;
3798            } else if ("java.lang.Double".equals(typeName)) { //$NON-NLS-1$
3799
return Instruction.T_double;
3800            } else if ("java.lang.Boolean".equals(typeName)) { //$NON-NLS-1$
3801
return Instruction.T_boolean;
3802            }
3803            return Instruction.T_Object;
3804        }
3805    }
3806
3807    private int getTypeId(Type type) {
3808        if (type.isPrimitiveType()) {
3809            return getPrimitiveTypeId(((PrimitiveType)type).getPrimitiveTypeCode().toString());
3810        } else if (type.isSimpleType()) {
3811            SimpleType simpleType = (SimpleType) type;
3812            if ("java.lang.String".equals(simpleType.getName())){ //$NON-NLS-1$
3813
return Instruction.T_String;
3814            }
3815            return Instruction.T_Object;
3816        } else if (type.isArrayType()) {
3817            return Instruction.T_Object;
3818        } else {
3819            return Instruction.T_undefined;
3820        }
3821
3822    }
3823
3824    private String JavaDoc getMethodSignature(IMethodBinding methodBinding, String JavaDoc enclosingTypeSignature) {
3825        methodBinding= methodBinding.getMethodDeclaration();
3826        ITypeBinding[] parameterTypes = methodBinding.getParameterTypes();
3827        int i;
3828        int argCount;
3829        String JavaDoc[] parameterSignatures;
3830        if (enclosingTypeSignature == null) {
3831            i= 0;
3832            argCount= parameterTypes.length;
3833            parameterSignatures= new String JavaDoc[argCount];
3834        } else {
3835            i= 1;
3836            argCount= parameterTypes.length + 1;
3837            parameterSignatures= new String JavaDoc[argCount];
3838            parameterSignatures[0]= enclosingTypeSignature;
3839        }
3840        for (; i < argCount; i++) {
3841            parameterSignatures[i]= getTypeSignature(parameterTypes[i]);
3842        }
3843        String JavaDoc signature= Signature.createMethodSignature(parameterSignatures, getTypeSignature(methodBinding.getReturnType()));
3844        return signature;
3845    }
3846
3847    private int getPrimitiveTypeId(String JavaDoc typeName) {
3848        switch (typeName.charAt(0)) {
3849            case 'b': // byte or boolean
3850
switch (typeName.charAt(1)) {
3851                    case 'o': // boolean;
3852
return Instruction.T_boolean;
3853                    case 'y': // byte
3854
return Instruction.T_byte;
3855                }
3856                break;
3857            case 'c': // char
3858
return Instruction.T_char;
3859            case 'd': // double
3860
return Instruction.T_double;
3861            case 'f': // float
3862
return Instruction.T_float;
3863            case 'i': // int
3864
return Instruction.T_int;
3865            case 'l': // long
3866
return Instruction.T_long;
3867            case 'n':
3868                return Instruction.T_null;
3869            case 's': // short
3870
return Instruction.T_short;
3871            case 'v': // void
3872
return Instruction.T_void;
3873        }
3874        return Instruction.T_undefined;
3875    }
3876}
3877
Popular Tags