code-template needs new context type
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / internal / compiler / ast / SynchronizedStatement.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpeclipse.internal.compiler.ast;
12
13 import net.sourceforge.phpdt.internal.compiler.IAbstractSyntaxTreeVisitor;
14 import net.sourceforge.phpdt.internal.compiler.codegen.Label;
15 import net.sourceforge.phpdt.internal.compiler.flow.FlowContext;
16 import net.sourceforge.phpdt.internal.compiler.flow.FlowInfo;
17 import net.sourceforge.phpdt.internal.compiler.flow.InsideSubRoutineFlowContext;
18 import net.sourceforge.phpdt.internal.compiler.lookup.BlockScope;
19 import net.sourceforge.phpdt.internal.compiler.lookup.LocalVariableBinding;
20 import net.sourceforge.phpdt.internal.compiler.lookup.TypeBinding;
21
22 public class SynchronizedStatement extends Statement {
23
24         public Expression expression;
25         public Block block;
26         public BlockScope scope;
27
28         boolean blockExit;
29         public LocalVariableBinding synchroVariable;
30         static final char[] SecretLocalDeclarationName = " syncValue".toCharArray(); //$NON-NLS-1$
31
32         public SynchronizedStatement(
33                 Expression expression,
34                 Block statement,
35                 int s,
36                 int e) {
37
38                 this.expression = expression;
39                 this.block = statement;
40                 sourceEnd = e;
41                 sourceStart = s;
42         }
43
44         public FlowInfo analyseCode(
45                 BlockScope currentScope,
46                 FlowContext flowContext,
47                 FlowInfo flowInfo) {
48
49                 // mark the synthetic variable as being used
50                 synchroVariable.useFlag = LocalVariableBinding.USED;
51
52                 // simple propagation to subnodes
53                 flowInfo =
54                         block.analyseCode(
55                                 scope,
56                                 new InsideSubRoutineFlowContext(flowContext, this),
57                                 expression.analyseCode(scope, flowContext, flowInfo));
58
59                 // optimizing code gen
60                 this.blockExit = !flowInfo.isReachable();
61
62                 return flowInfo;
63         }
64
65         /**
66          * Synchronized statement code generation
67          *
68          * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
69          * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
70          */
71 //      public void generateCode(BlockScope currentScope, CodeStream codeStream) {
72 //
73 //              if ((bits & IsReachableMASK) == 0) {
74 //                      return;
75 //              }
76 //              int pc = codeStream.position;
77 //
78 //              // generate the synchronization expression
79 //              expression.generateCode(scope, codeStream, true);
80 //              if (block.isEmptyBlock()) {
81 //                      if ((synchroVariable.type == LongBinding)
82 //                              || (synchroVariable.type == DoubleBinding)) {
83 //                              codeStream.dup2();
84 //                      } else {
85 //                              codeStream.dup();
86 //                      }
87 //                      // only take the lock
88 //                      codeStream.monitorenter();
89 //                      codeStream.monitorexit();
90 //              } else {
91 //                      // enter the monitor
92 //                      codeStream.store(synchroVariable, true);
93 //                      codeStream.monitorenter();
94 //
95 //                      // generate  the body of the synchronized block
96 //                      ExceptionLabel anyExceptionHandler = new ExceptionLabel(codeStream, null);
97 //                      //'null' denotes any kind of exception
98 //                      block.generateCode(scope, codeStream);
99 //                      Label endLabel = new Label(codeStream);
100 //                      if (!blockExit) {
101 //                              codeStream.load(synchroVariable);
102 //                              codeStream.monitorexit();
103 //                              codeStream.goto_(endLabel);
104 //                      }
105 //                      // generate the body of the exception handler
106 //                      anyExceptionHandler.placeEnd();
107 //                      anyExceptionHandler.place();
108 //                      codeStream.incrStackSize(1);
109 //                      codeStream.load(synchroVariable);
110 //                      codeStream.monitorexit();
111 //                      codeStream.athrow();
112 //                      if (!blockExit) {
113 //                              endLabel.place();
114 //                      }
115 //              }
116 //              if (scope != currentScope) {
117 //                      codeStream.exitUserScope(scope);
118 //              }
119 //              codeStream.recordPositionsFrom(pc, this.sourceStart);
120 //      }
121
122         public void resolve(BlockScope upperScope) {
123
124                 // special scope for secret locals optimization.
125                 scope = new BlockScope(upperScope);
126                 TypeBinding type = expression.resolveType(scope);
127                 if (type == null)
128                         return;
129                 switch (type.id) {
130                         case (T_boolean) :
131                         case (T_char) :
132                         case (T_float) :
133                         case (T_double) :
134                         case (T_byte) :
135                         case (T_short) :
136                         case (T_int) :
137                         case (T_long) :
138                                 scope.problemReporter().invalidTypeToSynchronize(expression, type);
139                                 break;
140                         case (T_void) :
141                                 scope.problemReporter().illegalVoidExpression(expression);
142                                 break;
143                         case (T_null) :
144                                 scope.problemReporter().invalidNullToSynchronize(expression);
145                                 break; 
146                 }
147                 //continue even on errors in order to have the TC done into the statements
148                 synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, AccDefault, false);
149                 scope.addLocalVariable(synchroVariable);
150                 synchroVariable.constant = NotAConstant; // not inlinable
151                 expression.implicitWidening(type, type);
152                 block.resolveUsing(scope);
153         }
154
155         public String toString(int tab) {
156
157                 String s = tabString(tab);
158                 s = s + "synchronized (" + expression.toStringExpression() + ")";  //$NON-NLS-1$ //$NON-NLS-2$
159                 s = s + "\n" + block.toString(tab + 1); //$NON-NLS-1$
160                 return s;
161         }
162
163         public void traverse(
164                 IAbstractSyntaxTreeVisitor visitor,
165                 BlockScope blockScope) {
166
167                 if (visitor.visit(this, blockScope)) {
168                         expression.traverse(visitor, scope);
169                         block.traverse(visitor, scope);
170                 }
171                 visitor.endVisit(this, blockScope);
172         }
173 }