001    /*
002     * The JastAdd Extensible Java Compiler (http://jastadd.org) is covered
003     * by the modified BSD License. You should have received a copy of the
004     * modified BSD license with this compiler.
005     * 
006     * Copyright (c) 2005-2008, Torbjorn Ekman
007     * All rights reserved.
008     */
009    
010    import java.util.*;
011    import java.io.*;
012    aspect CreateBCode {
013      inh TypeDecl CatchClause.hostType();
014    
015      public abstract void CatchClause.exceptionTableEntries(CodeGeneration gen, TryStmt tryStmt);
016    
017      public void BasicCatch.exceptionTableEntries(CodeGeneration gen, TryStmt tryStmt) {
018        gen.addException(
019          gen.addressOf(tryStmt.label_begin()),
020          gen.addressOf(tryStmt.label_block_end()),
021          gen.addressOf(label()),
022          gen.constantPool().addClass(getParameter().type().constantPoolName())
023          );
024      }
025      
026      syn lazy boolean TypeDecl.hasClinit() {
027        for(int i = 0; i < getNumBodyDecl(); i++) {
028          BodyDecl b = getBodyDecl(i);
029          if(b instanceof FieldDeclaration) {
030            FieldDeclaration f = (FieldDeclaration)b;
031            if(f.isStatic() && f.hasInit()) {
032              return true;
033            }
034          }
035          else if(b instanceof StaticInitializer) {
036            return true;
037          }
038        }
039        return false;
040      }
041    
042      syn lazy CodeGeneration TypeDecl.bytecodes(ConstantPool constantPool) {
043        CodeGeneration gen = new CodeGeneration(constantPool);
044        generateBytecodes(gen);
045        if(!gen.numberFormatError())
046          return gen;
047        gen = new CodeGeneration(constantPool, true);
048        generateBytecodes(gen);
049        if(!gen.numberFormatError())
050          return gen;
051        throw new Error("Could not generate code for initializers in " + hostType().typeName());
052      }
053      private void TypeDecl.generateBytecodes(CodeGeneration gen) {
054        for(int i = 0; i < getNumBodyDecl(); i++) {
055          BodyDecl b = getBodyDecl(i);
056          if(b instanceof FieldDeclaration && b.isBytecodeField() && b.generate()) {
057            FieldDeclaration f = (FieldDeclaration)b;
058            if(f.isStatic() && f.hasInit()) {
059              f.getInit().createBCode(gen);
060              f.getInit().type().emitAssignConvTo(gen, f.type()); // AssignConversion
061              f.emitStoreField(gen, this);
062            }
063          }
064          else if(b instanceof StaticInitializer) {
065            b.createBCode(gen);
066          }
067        }
068        gen.emitReturn();
069      }
070    
071      syn lazy CodeGeneration MethodDecl.bytecodes(ConstantPool constantPool) {
072        //if(options().verbose())
073        //  System.out.println("Generating bytecodes for " + signature() + " in " + hostType().fullName());
074        CodeGeneration gen = new CodeGeneration(constantPool);
075        generateBytecodes(gen);
076        if(!gen.numberFormatError())
077          return gen;
078        gen = new CodeGeneration(constantPool, true);
079        generateBytecodes(gen);
080        if(!gen.numberFormatError())
081          return gen;
082        throw new Error("Could not generate code for " + signature() + " in " + hostType().typeName());
083      }
084      private void MethodDecl.generateBytecodes(CodeGeneration gen) {
085        int label = gen.variableScopeLabel();
086        if(!isStatic())
087          gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label);
088        for(int i = 0; i < getNumParameter(); i++) {
089          ParameterDeclaration p = (ParameterDeclaration)getParameter(i);
090          gen.addLocalVariableEntryAtCurrentPC(
091            p.name(), p.type().typeDescriptor(), p.localNum(), label
092          );
093        }
094        createBCode(gen);
095        if(type() instanceof VoidType) // TODO: canCompleteNormally check as well
096          gen.emitReturn();
097        gen.addVariableScopeLabel(label);
098      }
099      
100      syn lazy CodeGeneration ConstructorDecl.bytecodes(ConstantPool constantPool) {
101        CodeGeneration gen = new CodeGeneration(constantPool);
102        generateBytecodes(gen);
103        if(!gen.numberFormatError())
104          return gen;
105        gen = new CodeGeneration(constantPool, true);
106        generateBytecodes(gen);
107        if(!gen.numberFormatError())
108          return gen;
109        throw new Error("Could not generate code for " + signature() + " in " + hostType().typeName());
110      }
111      private void ConstructorDecl.generateBytecodes(CodeGeneration gen) {
112        int label = gen.variableScopeLabel();
113        gen.addLocalVariableEntryAtCurrentPC("this", hostType().typeDescriptor(), 0, label);
114        for(int i = 0; i < getNumParameter(); i++) {
115          ParameterDeclaration p = (ParameterDeclaration)getParameter(i);
116          gen.addLocalVariableEntryAtCurrentPC(
117            p.name(), p.type().typeDescriptor(), p.localNum(), label
118          );
119        }
120        createBCode(gen);
121        gen.emitReturn();
122        gen.addVariableScopeLabel(label);
123      }
124    
125      public void MethodDecl.createBCode(CodeGeneration gen) {
126        try {
127          if(hasBlock()) {
128            gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum());
129            getBlock().createBCode(gen);
130          }
131        } catch (Error e) {
132          System.err.println(hostType().typeName() + ": " + this);
133          throw e;
134        }
135      }
136    
137      public void ConstructorDecl.createBCode(CodeGeneration gen) {
138        try {
139        boolean needsInit = true;
140    
141        if(hasConstructorInvocation()) {
142          getConstructorInvocation().createBCode(gen);
143          Stmt stmt = getConstructorInvocation();
144          if(stmt instanceof ExprStmt) {
145            ExprStmt exprStmt = (ExprStmt)stmt;
146            Expr expr = exprStmt.getExpr();
147            if(!expr.isSuperConstructorAccess())
148              needsInit = false;
149    
150          }
151        }
152    
153        if(needsEnclosing()) {
154          gen.emitLoadReference(0);
155          gen.emitLoadReference(1);
156          String classname = hostType().constantPoolName();
157          String desc = enclosing().typeDescriptor();
158          String name = "this$0";
159          int index = gen.constantPool().addFieldref(classname, name, desc);
160          gen.emit(Bytecode.PUTFIELD, -2).add2(index);
161        }
162    
163        int localIndex = offsetFirstEnclosingVariable();
164        for(Iterator iter = hostType().enclosingVariables().iterator(); iter.hasNext(); ) {
165            Variable v = (Variable)iter.next();
166            gen.emitLoadReference(0);
167            v.type().emitLoadLocal(gen, localIndex);
168            String classname = hostType().constantPoolName();
169            String desc = v.type().typeDescriptor();
170            String name = "val$" + v.name();
171            int index = gen.constantPool().addFieldref(classname, name, desc);
172            gen.emit(Bytecode.PUTFIELD, -1 - v.type().variableSize()).add2(index);
173            localIndex += v.type().variableSize();
174        }
175    
176        if(needsInit) {
177          TypeDecl typeDecl = hostType();
178          for(int i = 0; i < typeDecl.getNumBodyDecl(); i++) {
179            BodyDecl b = typeDecl.getBodyDecl(i);
180            if(b instanceof FieldDeclaration && b.isBytecodeField() && b.generate()) {
181              FieldDeclaration f = (FieldDeclaration)b;
182              if(!f.isStatic() && f.hasInit()) {
183                gen.emit(Bytecode.ALOAD_0);
184                f.getInit().createBCode(gen);
185                f.getInit().type().emitAssignConvTo(gen, f.type()); // AssignConversion
186                f.emitStoreField(gen, hostType());
187              }
188            }
189            else if(b instanceof InstanceInitializer) {
190              b.createBCode(gen);
191            }
192          }
193        }
194        gen.maxLocals = Math.max(gen.maxLocals, getBlock().localNum());
195        getBlock().createBCode(gen);
196        } catch (Error e) {
197          System.err.println(hostType().typeName() + ": " + this);
198          throw e;
199        }
200      }
201    
202      public void ASTNode.createBCode(CodeGeneration gen) {
203        for (int i=0; i<getNumChild(); i++)
204          getChild(i).createBCode(gen);
205      }
206    
207      public void Literal.createBCode(CodeGeneration gen) {      
208        emitPushConstant(gen);
209      }
210    
211      protected boolean Expr.needsPush() {
212        ASTNode n = getParent();
213        while(n instanceof ParExpr)
214          n = n.getParent();
215        return !(n instanceof ExprStmt);
216      }
217    
218      syn boolean ExprStmt.needsPop() = getExpr().needsPop();
219      syn boolean Expr.needsPop() = true;
220      eq AbstractDot.needsPop() = lastAccess().needsPop();
221      eq ConstructorAccess.needsPop() = false;
222    
223      eq ParExpr.needsPop() = getExpr().needsPop();
224      //eq AssignExpr.needsPop() = false; // if dest is instance variable that needs accessor
225      eq AssignExpr.needsPop() = getDest().isVarAccessWithAccessor();
226      eq PreIncExpr.needsPop() = false;
227      eq PostIncExpr.needsPop() = getOperand().isVarAccessWithAccessor();
228      eq PreDecExpr.needsPop() = false;
229      eq PostDecExpr.needsPop() = getOperand().isVarAccessWithAccessor();
230    
231      syn boolean Expr.isVarAccessWithAccessor() = false;
232      eq ParExpr.isVarAccessWithAccessor() = getExpr().isVarAccessWithAccessor();
233      eq AbstractDot.isVarAccessWithAccessor() = lastAccess().isVarAccessWithAccessor();
234      eq VarAccess.isVarAccessWithAccessor() = decl() instanceof FieldDeclaration && 
235            decl().isInstanceVariable() && requiresAccessor();
236    
237      public void VariableDeclaration.createBCode(CodeGeneration gen) {
238        super.createBCode(gen);
239        if(hasInit()) {
240          gen.addLocalVariableEntryAtCurrentPC(name(), type().typeDescriptor(), localNum(), variableScopeEndLabel(gen));
241          getInit().createBCode(gen);
242          getInit().type().emitAssignConvTo(gen, type()); // AssignConversion
243          type().emitStoreLocal(gen, localNum());
244        }
245      }
246      
247      // simple assign expression
248      public void AssignSimpleExpr.createBCode(CodeGeneration gen) {
249        getDest().createAssignSimpleLoadDest(gen);
250        getSource().createBCode(gen);
251        getSource().type().emitAssignConvTo(gen, getDest().type()); // AssignConversion
252        if(needsPush()) {
253          getDest().createPushAssignmentResult(gen);
254        }
255        getDest().emitStore(gen);
256      }
257    
258      // compund assign expression
259      public void AssignExpr.createBCode(CodeGeneration gen) {
260        TypeDecl dest = getDest().type();
261        TypeDecl source = getSource().type();
262        TypeDecl type;
263        if(dest.isNumericType() && source.isNumericType())
264          type = dest.binaryNumericPromotion(source);
265        else 
266          type = dest;
267        getDest().createAssignLoadDest(gen);
268        dest.emitCastTo(gen, type);
269        getSource().createBCode(gen);
270        source.emitCastTo(gen, type);
271        createAssignOp(gen, type);
272        type.emitCastTo(gen, dest);
273        if(needsPush()) {
274          getDest().createPushAssignmentResult(gen);
275        }
276        getDest().emitStore(gen);
277      }
278    
279      // string addition assign expression
280      public void AssignPlusExpr.createBCode(CodeGeneration gen) {
281        TypeDecl dest = getDest().type();
282        TypeDecl source = getSource().type();
283        if(dest.isString()) {
284          getDest().createAssignLoadDest(gen);
285          
286          // new StringBuffer()
287          TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer");
288          String classname = stringBuffer.constantPoolName();
289          String desc;
290          int index;
291          TypeDecl argumentType;
292          stringBuffer.emitNew(gen); // new StringBuffer
293          gen.emitDup();             // dup
294          desc = "()V";
295          index = gen.constantPool().addMethodref(classname, "<init>", desc);
296          gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer()
297    
298          gen.emitSwap();
299    
300          // append
301          argumentType = dest.stringPromotion();
302          desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
303          index = gen.constantPool().addMethodref(classname, "append", desc);
304          gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
305          
306          getSource().createBCode(gen);
307    
308          // typed append
309          argumentType = source.stringPromotion();
310          desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
311          index = gen.constantPool().addMethodref(classname, "append", desc);
312          gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
313          
314          // toString
315          desc = "()" + type().typeDescriptor();
316          index = gen.constantPool().addMethodref(classname, "toString", desc);
317          gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString
318          
319          if(needsPush()) {
320            getDest().createPushAssignmentResult(gen);
321          }
322          getDest().emitStore(gen);
323        }
324        else {
325          super.createBCode(gen);
326        }
327      }
328    
329      // shift assign expression
330      public void AssignExpr.emitShiftExpr(CodeGeneration gen) {
331        TypeDecl dest = getDest().type();
332        TypeDecl source = getSource().type();
333        TypeDecl type = dest.unaryNumericPromotion();
334        getDest().createAssignLoadDest(gen);
335        dest.emitCastTo(gen, type);
336        getSource().createBCode(gen);
337        source.emitCastTo(gen, typeInt());
338        createAssignOp(gen, type);
339        type.emitCastTo(gen, dest);
340        if(needsPush()) {
341          getDest().createPushAssignmentResult(gen);
342        }
343        getDest().emitStore(gen);
344      }
345      public void AssignLShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); }
346      public void AssignRShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); }
347      public void AssignURShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); }
348    
349      // load left hand side of destination in a simple assign expression
350      public void Expr.createAssignSimpleLoadDest(CodeGeneration gen) {
351      }
352      public void AbstractDot.createAssignSimpleLoadDest(CodeGeneration gen) {
353        lastAccess().createAssignSimpleLoadDest(gen);
354      }
355      public void VarAccess.createAssignSimpleLoadDest(CodeGeneration gen) {
356        createLoadQualifier(gen);
357      }
358      public void ArrayAccess.createAssignSimpleLoadDest(CodeGeneration gen) {
359        prevExpr().createBCode(gen);
360        getExpr().createBCode(gen);
361      }
362      
363      /**
364       * duplicate top value on stack and store below destination element
365       */
366      public void Expr.createPushAssignmentResult(CodeGeneration gen) {
367      }
368      public void AbstractDot.createPushAssignmentResult(CodeGeneration gen) {
369        lastAccess().createPushAssignmentResult(gen);
370      }
371      public void VarAccess.createPushAssignmentResult(CodeGeneration gen) {
372        if(hostType().needsAccessorFor(decl()))
373          return;
374        if(decl().isInstanceVariable())
375          type().emitDup_x1(gen);
376        else
377          type().emitDup(gen);
378      }
379      public void ArrayAccess.createPushAssignmentResult(CodeGeneration gen) {
380        type().emitDup_x2(gen);
381      }
382      
383      // load left hand side of destination in a compound assign expression
384      public void Expr.createAssignLoadDest(CodeGeneration gen) {
385      }
386      public void AbstractDot.createAssignLoadDest(CodeGeneration gen) {
387        lastAccess().createAssignLoadDest(gen);
388      }
389      public void VarAccess.createAssignLoadDest(CodeGeneration gen) {
390        createLoadQualifier(gen);
391        Variable v = decl();
392        if(v.isInstanceVariable())
393          gen.emitDup();
394        if(v instanceof VariableDeclaration) {
395          VariableDeclaration decl = (VariableDeclaration)v;
396          decl.type().emitLoadLocal(gen, decl.localNum());
397        }
398        else if(v instanceof ParameterDeclaration) {
399          ParameterDeclaration decl = (ParameterDeclaration)v;
400          decl.type().emitLoadLocal(gen, decl.localNum());
401        }
402        else if(v instanceof FieldDeclaration) {
403          FieldDeclaration f = (FieldDeclaration)v;
404          if(requiresAccessor())
405            f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType());
406          else
407            f.emitLoadField(gen, fieldQualifierType());
408        }
409      }
410      public void ArrayAccess.createAssignLoadDest(CodeGeneration gen) {
411        prevExpr().createBCode(gen);
412        gen.emitDup();
413        getExpr().createBCode(gen);
414        typeInt().emitDup_x1(gen);
415        gen.emit(type().arrayLoad());
416      }
417      
418      // select the typed operation for a compound assign expression
419      public void AssignExpr.createAssignOp(CodeGeneration gen, TypeDecl type) {
420        throw new Error("Operation createAssignOp is not implemented for " + getClass().getName());
421      }
422      public void AssignMulExpr.createAssignOp(CodeGeneration gen, TypeDecl type)     { type.mul(gen); }
423      public void AssignDivExpr.createAssignOp(CodeGeneration gen, TypeDecl type)     { type.div(gen); }
424      public void AssignModExpr.createAssignOp(CodeGeneration gen, TypeDecl type)     { type.rem(gen); }
425      public void AssignPlusExpr.createAssignOp(CodeGeneration gen, TypeDecl type)    { type.add(gen); }
426      public void AssignMinusExpr.createAssignOp(CodeGeneration gen, TypeDecl type)   { type.sub(gen); }
427      public void AssignLShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type)  { type.shl(gen); }
428      public void AssignRShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type)  { type.shr(gen); }
429      public void AssignURShiftExpr.createAssignOp(CodeGeneration gen, TypeDecl type) { type.ushr(gen); }
430      public void AssignAndExpr.createAssignOp(CodeGeneration gen, TypeDecl type)     { type.bitand(gen); }
431      public void AssignXorExpr.createAssignOp(CodeGeneration gen, TypeDecl type)     { type.bitxor(gen); }
432      public void AssignOrExpr.createAssignOp(CodeGeneration gen, TypeDecl type)      { type.bitor(gen); }
433    
434      public void AbstractDot.createBCode(CodeGeneration gen) {
435        lastAccess().createBCode(gen);
436      }
437    
438      public void VarAccess.createBCode(CodeGeneration gen) {
439        Variable v = decl();
440        if(v instanceof VariableDeclaration) {
441          VariableDeclaration decl = (VariableDeclaration)v;
442          if(decl.hostType() == hostType())
443            decl.type().emitLoadLocal(gen, decl.localNum());
444          else
445            emitLoadLocalInNestedClass(gen, decl);
446        }
447        else if(v instanceof ParameterDeclaration) {
448          ParameterDeclaration decl = (ParameterDeclaration)v;
449          if(decl.hostType() == hostType())
450            decl.type().emitLoadLocal(gen, decl.localNum());
451          else
452            emitLoadLocalInNestedClass(gen, decl);
453        }
454        else if(v instanceof FieldDeclaration) {
455          FieldDeclaration f = (FieldDeclaration)v;
456          createLoadQualifier(gen);
457          if(f.isConstant() && (f.type().isPrimitive() || f.type().isString())) {
458            if(!f.isStatic())
459              fieldQualifierType().emitPop(gen);
460            f.constant().createBCode(gen);
461          }
462          else if(requiresAccessor())
463            f.createAccessor(fieldQualifierType()).emitInvokeMethod(gen, fieldQualifierType());
464          else
465            f.emitLoadField(gen, fieldQualifierType());
466        }
467      }
468    
469      syn boolean TypeDecl.needsAccessorFor(Variable v) {
470        if(!(v instanceof FieldDeclaration))
471          return false;
472        FieldDeclaration f = (FieldDeclaration)v;
473        if(f.isConstant() && (f.type().isPrimitive() || f.type().isString()))
474          return false;
475        return f.isPrivate() && !hasField(v.name());
476      }
477    
478      inh boolean Access.inExplicitConstructorInvocation();
479      public void Access.emitLoadLocalInNestedClass(CodeGeneration gen, Variable v) {
480        if(inExplicitConstructorInvocation() && enclosingBodyDecl() instanceof ConstructorDecl) {
481          ConstructorDecl c = (ConstructorDecl)enclosingBodyDecl();
482          v.type().emitLoadLocal(gen, c.localIndexOfEnclosingVariable(v));
483        }
484        else {
485          String classname = hostType().constantPoolName();
486          String      desc = v.type().typeDescriptor();
487          String      name = "val$" + v.name();
488          int index = gen.constantPool().addFieldref(classname, name, desc);
489          gen.emit(Bytecode.ALOAD_0);
490          gen.emit(Bytecode.GETFIELD, v.type().variableSize() - 1).add2(index);
491        }
492      }
493    
494      protected void VarAccess.createLoadQualifier(CodeGeneration gen) {
495        Variable v = decl();
496        if(v instanceof FieldDeclaration) {
497          FieldDeclaration f = (FieldDeclaration)v;
498          if(hasPrevExpr()) {
499            // load explicit qualifier
500            prevExpr().createBCode(gen);
501            // pop qualifier stack element for class variables
502            // this qualifier must be computed to ensure side effects
503            if(!prevExpr().isTypeAccess() && f.isClassVariable())
504              prevExpr().type().emitPop(gen);
505          }
506          else if(f.isInstanceVariable()) {
507            emitThis(gen, fieldQualifierType());
508          }
509        }
510      }
511    
512      public void MethodAccess.createBCode(CodeGeneration gen) {
513        createLoadQualifier(gen);
514        if(decl().type().isUnknown()) {
515          System.err.println("Could not bind " + this);
516          for (int i = 0; i < getNumArg(); ++i) {
517            System.err.println("Argument " + getArg(i) + " is of type " + getArg(i).type().typeName());
518            if(getArg(i).varDecl() != null) System.err.println(getArg(i).varDecl() + " in " + getArg(i).varDecl().hostType().typeName());
519          }
520          if(isQualified())
521            System.err.println("Qualifier " + qualifier() + " is of type " + qualifier().type().typeName());
522          throw new Error("Could not bind " + this);
523        }
524        if(decl().getNumParameter() != getNumArg()) {
525          System.out.println(this + " does not have the same number of arguments as " + decl());
526        }
527        for (int i = 0; i < getNumArg(); ++i) {
528          getArg(i).createBCode(gen);
529          getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion
530        }
531        /*
532        if(decl().isPrivate() && !hostType().hasMethod(name())) {
533          decl().emitInvokeMethodAccessor(gen, methodQualifierType());
534        }
535        
536        else*/ {
537          if(!decl().isStatic() && isQualified() && prevExpr().isSuperAccess()) {
538            if(!hostType().instanceOf(prevExpr().type()))
539              decl().createSuperAccessor(superAccessorTarget()).emitInvokeMethod(gen, superAccessorTarget());
540            else
541              decl().emitInvokeSpecialMethod(gen, methodQualifierType());
542          }
543          else
544            decl().emitInvokeMethod(gen, methodQualifierType());
545        }
546      }
547    
548      protected void MethodAccess.createLoadQualifier(CodeGeneration gen) {
549        MethodDecl m = decl();
550        if(hasPrevExpr()) {
551          // load explicit qualifier
552          prevExpr().createBCode(gen);
553          // pop qualifier stack element for class variables
554          // this qualifier must be computed to ensure side effects
555          if(m.isStatic() && !prevExpr().isTypeAccess())
556            prevExpr().type().emitPop(gen);
557        }
558        else if(!m.isStatic()) {
559          // load implicit this qualifier
560          emitThis(gen, methodQualifierType());
561        }
562      }
563    
564      public void ArrayAccess.createBCode(CodeGeneration gen) {
565        prevExpr().createBCode(gen);
566        getExpr().createBCode(gen);
567        gen.emit(type().arrayLoad());
568      }
569    
570      public void ThisAccess.createBCode(CodeGeneration gen) {
571        emitThis(gen, decl());
572      }
573      public void SuperAccess.createBCode(CodeGeneration gen) {
574        emitThis(gen, decl());
575      }
576    
577      // load this where hostType is the target this instance 
578      // supporting inner classes and in explicit contructor invocations
579      public void Access.emitThis(CodeGeneration gen, TypeDecl targetDecl) {
580        if(targetDecl == hostType())
581          gen.emit(Bytecode.ALOAD_0);
582        else {
583          TypeDecl enclosing = hostType();
584          if(inExplicitConstructorInvocation()) {
585            gen.emit(Bytecode.ALOAD_1);
586            enclosing = enclosing.enclosing();
587          }
588          else {
589            gen.emit(Bytecode.ALOAD_0);
590          }
591          while(enclosing != targetDecl) {
592            String classname = enclosing.constantPoolName();
593            enclosing = enclosing.enclosingType();
594            String desc = enclosing.typeDescriptor();
595            int index = gen.constantPool().addFieldref(classname, "this$0", desc);
596            gen.emit(Bytecode.GETFIELD, 0).add2(index);
597          }
598        }
599      }
600    
601    
602      public void ConstructorAccess.createBCode(CodeGeneration gen) {
603        ConstructorDecl c = decl();
604        int index = 0;
605        // this
606        gen.emitLoadReference(index++);
607        // this$0
608        if(c.needsEnclosing())
609          gen.emitLoadReference(index++);
610        if(c.needsSuperEnclosing())
611          gen.emitLoadReference(index++);
612    
613        // args
614        for (int i = 0; i < getNumArg(); ++i) {
615          getArg(i).createBCode(gen);
616          getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion
617        }
618        if(decl().isPrivate() && decl().hostType() != hostType()) {
619          gen.emit(Bytecode.ACONST_NULL);
620          decl().createAccessor().emitInvokeConstructor(gen);
621        }
622        else {
623          decl().emitInvokeConstructor(gen);
624        }
625      }
626      
627      public void SuperConstructorAccess.createBCode(CodeGeneration gen) {
628        ConstructorDecl c = decl();
629        
630        // this
631        gen.emit(Bytecode.ALOAD_0);
632        
633        if(c.needsEnclosing()) {
634          if(hasPrevExpr() && !prevExpr().isTypeAccess()) {
635            prevExpr().createBCode(gen);
636            gen.emitDup();
637            int index = gen.constantPool().addMethodref("java/lang/Object", "getClass", "()Ljava/lang/Class;");
638            gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index);
639            gen.emitPop();
640          }
641          else {
642            if(hostType().needsSuperEnclosing()) {
643              if(hostType().needsEnclosing())
644                gen.emit(Bytecode.ALOAD_2);
645              else
646                gen.emit(Bytecode.ALOAD_1);
647            }
648            else {
649              emitThis(gen, superConstructorQualifier(c.hostType().enclosingType()));
650            }
651          }
652        }
653    
654        // args
655        for (int i = 0; i < getNumArg(); ++i) {
656          getArg(i).createBCode(gen);
657          getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion
658        }
659        if(decl().isPrivate() && decl().hostType() != hostType()) {
660          gen.emit(Bytecode.ACONST_NULL);
661          decl().createAccessor().emitInvokeConstructor(gen);
662        }
663        else {
664          decl().emitInvokeConstructor(gen);
665        }
666      }
667    
668      // 15.9.2
669      private void ClassInstanceExpr.emitLocalEnclosing(CodeGeneration gen, TypeDecl localClass) {
670        if(!localClass.inStaticContext()) {
671          emitThis(gen, localClass.enclosingType());
672        }
673      }
674      private void ClassInstanceExpr.emitInnerMemberEnclosing(CodeGeneration gen, TypeDecl innerClass) {
675        if(hasPrevExpr()) {
676          prevExpr().createBCode(gen);
677          gen.emitDup();
678          int index = gen.constantPool().addMethodref("java/lang/Object", "getClass", "()Ljava/lang/Class;");
679          gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index);
680          gen.emitPop();
681        }
682        else {
683          TypeDecl enclosing = hostType();
684          while(enclosing != null && !enclosing.hasType(innerClass.name()))
685            enclosing = enclosing.enclosingType();
686          if(enclosing == null)
687            throw new Error(errorPrefix() + "Could not find enclosing for " + this);
688          else
689            emitThis(gen, enclosing);
690        }
691      }
692      public void ClassInstanceExpr.createBCode(CodeGeneration gen) {
693        type().emitNew(gen);
694        type().emitDup(gen);
695    
696        // 15.9.2 first part
697        if(type().isAnonymous()) {
698          if(type().isAnonymousInNonStaticContext()) {
699            if(type().inExplicitConstructorInvocation())
700              gen.emit(Bytecode.ALOAD_1);
701            else
702              gen.emit(Bytecode.ALOAD_0);
703          }
704          // 15.9.2 second part
705          ClassDecl C = (ClassDecl)type();
706          TypeDecl S = C.superclass();
707          if(S.isLocalClass()) {
708            if(!type().inStaticContext())
709              emitLocalEnclosing(gen, S);
710          }
711          else if(S.isInnerType()) {
712            emitInnerMemberEnclosing(gen, S);
713          }
714        }
715        else if(type().isLocalClass()) {
716          if(!type().inStaticContext())
717            emitLocalEnclosing(gen, type());
718        }
719        else if(type().isInnerType()) {
720          emitInnerMemberEnclosing(gen, type());
721        }
722        /*
723        // 15.9.2 first part
724        if(type().isAnonymous()) {
725          if(type().isAnonymousInNonStaticContext()) {
726            if(type().inExplicitConstructorInvocation())
727              gen.emit(Bytecode.ALOAD_1);
728            else
729              gen.emit(Bytecode.ALOAD_0);
730          }
731          if(type().needsSuperEnclosing()) {
732            // 15.9.2 second part
733            ClassDecl C = (ClassDecl)type();
734            TypeDecl S = C.superclass();
735            if(S.isLocalClass()) {
736              emitLocalEnclosing(gen, S);
737            }
738            else if(S.isInnerType()) {
739              emitInnerMemberEnclosing(gen, S);
740            }
741          }
742        }
743        else if(type().isLocalClass()) {
744          emitLocalEnclosing(gen, type());
745        }
746        else if(type().isInnerType()) {
747          emitInnerMemberEnclosing(gen, type());
748        }
749        */
750    
751        for (int i = 0; i < getNumArg(); ++i) {
752          getArg(i).createBCode(gen);
753          getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion
754        }
755        
756        if(decl().isPrivate() && type() != hostType()) {
757          gen.emit(Bytecode.ACONST_NULL);
758          decl().createAccessor().emitInvokeConstructor(gen);
759        }
760        else {
761          decl().emitInvokeConstructor(gen);
762        }
763      }
764    
765      public void ArrayCreationExpr.createBCode(CodeGeneration gen) {
766        if(hasArrayInit()){
767          getArrayInit().createBCode(gen);
768        }
769        else {
770          getTypeAccess().createBCode(gen); // push array sizes
771          if(type().componentType().isPrimitive()) {
772            gen.emit(Bytecode.NEWARRAY).add(type().componentType().arrayPrimitiveTypeDescriptor());
773          }
774          else {
775            if(numArrays() == 1) {
776              String n = type().componentType().arrayTypeDescriptor();
777              int index = gen.constantPool().addClass(n);
778              gen.emit(Bytecode.ANEWARRAY).add2(index);
779            }
780            else {
781              String n = type().arrayTypeDescriptor();
782              int index = gen.constantPool().addClass(n);
783              gen.emit(Bytecode.MULTIANEWARRAY, 1 - numArrays()).add2(index).add(numArrays());
784            }
785          }
786        }
787      }
788      
789      public void ArrayInit.createBCode(CodeGeneration gen) {
790        IntegerLiteral.push(gen, getNumInit());
791        if(type().componentType().isPrimitive()) {
792          gen.emit(Bytecode.NEWARRAY).add(type().componentType().arrayPrimitiveTypeDescriptor());
793        } 
794        else {
795          String n = type().componentType().arrayTypeDescriptor();
796          int index = gen.constantPool().addClass(n);
797          gen.emit(Bytecode.ANEWARRAY).add2(index);
798        }
799        for(int i = 0; i < getNumInit(); i++) {
800          gen.emitDup();
801          IntegerLiteral.push(gen, i);
802          getInit(i).createBCode(gen);
803          if(getInit(i) instanceof ArrayInit)
804            gen.emit(Bytecode.AASTORE);
805          else {
806            getInit(i).type().emitAssignConvTo(gen, expectedType()); // AssignConversion
807            gen.emit(expectedType().arrayStore());
808          }
809        }
810      }
811      
812      public void ArrayTypeAccess.createBCode(CodeGeneration gen) {
813        getAccess().createBCode(gen);
814      }
815      public void ArrayTypeWithSizeAccess.createBCode(CodeGeneration gen) {
816        getAccess().createBCode(gen);
817        getExpr().createBCode(gen);
818      }
819    
820      syn String TypeDecl.arrayTypeDescriptor() { throw new Error("Operation not supported"); }
821      eq ArrayDecl.arrayTypeDescriptor() = typeDescriptor();
822      eq ClassDecl.arrayTypeDescriptor() = constantPoolName();
823      eq InterfaceDecl.arrayTypeDescriptor() = constantPoolName();
824    
825      syn int TypeDecl.arrayPrimitiveTypeDescriptor() { error(); return -1; }
826      eq BooleanType.arrayPrimitiveTypeDescriptor() = 4; // T_BOOLEAN
827      eq CharType.arrayPrimitiveTypeDescriptor()    = 5; // T_CHAR
828      eq FloatType.arrayPrimitiveTypeDescriptor()   = 6; // T_FLOAT
829      eq DoubleType.arrayPrimitiveTypeDescriptor()  = 7; // T_DOUBLE
830      eq ByteType.arrayPrimitiveTypeDescriptor()    = 8; // T_BYTE
831      eq ShortType.arrayPrimitiveTypeDescriptor()   = 9; // T_SHORT
832      eq IntType.arrayPrimitiveTypeDescriptor()     = 10; // T_INT
833      eq LongType.arrayPrimitiveTypeDescriptor()    = 11; // T_LONG
834    
835      public void Unary.createBCode(CodeGeneration gen) {   
836        super.createBCode(gen);
837        emitOperation(gen);
838      } 
839    
840      public void CastExpr.createBCode(CodeGeneration gen) {
841        getExpr().createBCode(gen);
842        getExpr().type().emitCastTo(gen, type());
843      }
844    
845      // TODO: consider using IINC or WIDE,IINC
846    
847      public void Unary.emitPostfix(CodeGeneration gen, int constant) {
848        Expr operand = getOperand();
849        while(operand instanceof ParExpr)
850          operand = ((ParExpr)operand).getExpr();
851        Access access = ((Access)operand).lastAccess();
852        access.createAssignLoadDest(gen);
853        if(needsPush())
854          access.createPushAssignmentResult(gen);
855        TypeDecl type = access.type().binaryNumericPromotion(typeInt());
856        type.emitPushConstant(gen, constant);
857        type.add(gen);
858        type.emitCastTo(gen, access.type());
859        access.emitStore(gen);
860      }
861      public void PostIncExpr.createBCode(CodeGeneration gen) { emitPostfix(gen, 1); }
862      public void PostDecExpr.createBCode(CodeGeneration gen) { emitPostfix(gen, -1); }
863    
864      public void Unary.emitPrefix(CodeGeneration gen, int constant) {
865        Expr operand = getOperand();
866        while(operand instanceof ParExpr)
867          operand = ((ParExpr)operand).getExpr();
868        Access access = ((Access)operand).lastAccess();
869        access.createAssignLoadDest(gen);
870        TypeDecl type = access.type().binaryNumericPromotion(typeInt());
871        type.emitPushConstant(gen, constant);
872        type.add(gen);
873        type.emitCastTo(gen, access.type());
874        if(needsPush())
875          access.createPushAssignmentResult(gen);
876        access.emitStore(gen);
877      }
878      public void PreIncExpr.createBCode(CodeGeneration gen) { emitPrefix(gen, 1); }
879      public void PreDecExpr.createBCode(CodeGeneration gen) { emitPrefix(gen, -1); }
880    
881      public void Binary.createBCode(CodeGeneration gen) {   
882        getLeftOperand().createBCode(gen);
883        getLeftOperand().type().emitCastTo(gen, type()); // Binary numeric promotion
884        getRightOperand().createBCode(gen);
885        getRightOperand().type().emitCastTo(gen, type()); // Binary numeric promotion
886        emitOperation(gen);
887      }
888    
889      public void Binary.emitShiftExpr(CodeGeneration gen) {
890        getLeftOperand().createBCode(gen);
891        getLeftOperand().type().emitCastTo(gen, type()); // Binary numeric promotion
892        getRightOperand().createBCode(gen);
893        getRightOperand().type().emitCastTo(gen, typeInt());
894        emitOperation(gen);
895      }
896      public void LShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); }
897      public void RShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); }
898      public void URShiftExpr.createBCode(CodeGeneration gen) { emitShiftExpr(gen); }
899    
900      public void AddExpr.createBCode(CodeGeneration gen) {
901        if(!type().isString())
902          super.createBCode(gen);
903        else if(isConstant()) {
904          StringLiteral.push(gen, constant().stringValue());
905        }
906        else {
907          TypeDecl stringBuffer = lookupType("java.lang", "StringBuffer");
908          String classname = stringBuffer.constantPoolName();
909          String desc;
910          int index;
911          TypeDecl argumentType;
912          if(firstStringAddPart()) {
913            stringBuffer.emitNew(gen); // new StringBuffer
914            gen.emitDup();             // dup
915            desc = "()V";
916            index = gen.constantPool().addMethodref(classname, "<init>", desc);
917            gen.emit(Bytecode.INVOKESPECIAL, -1).add2(index); // invokespecial StringBuffer()
918            getLeftOperand().createBCode(gen); // left
919            argumentType = getLeftOperand().type().stringPromotion();
920            desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
921            index = gen.constantPool().addMethodref(classname, "append", desc);
922            gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
923          }
924          else {
925            getLeftOperand().createBCode(gen);
926          }
927          getRightOperand().createBCode(gen); // right
928          argumentType = getRightOperand().type().stringPromotion();
929          desc = "(" + argumentType.typeDescriptor() + ")" + stringBuffer.typeDescriptor();
930          index = gen.constantPool().addMethodref(classname, "append", desc);
931          gen.emit(Bytecode.INVOKEVIRTUAL, -argumentType.variableSize()).add2(index); // StringBuffer.append
932          if(lastStringAddPart()) {
933            desc = "()" + type().typeDescriptor();
934            index = gen.constantPool().addMethodref(classname, "toString", desc);
935            gen.emit(Bytecode.INVOKEVIRTUAL, 0).add2(index); // StringBuffer.toString
936          }
937        }
938      }
939    
940      // branch to this label if the expression is false
941      syn lazy int Expr.false_label() = getParent().definesLabel() ? condition_false_label() : hostType().constantPool().newLabel();
942      // branch to this label if the expression is true
943      syn lazy int Expr.true_label() = getParent().definesLabel() ? condition_true_label() : hostType().constantPool().newLabel();
944      
945      // these nodes defines labels for their children
946      syn boolean ASTNode.definesLabel() = false;
947      eq Opt.definesLabel() = getParent().definesLabel();
948      eq List.definesLabel() = getParent().definesLabel();
949      eq AbstractDot.definesLabel() = getParent().definesLabel();
950      eq ParExpr.definesLabel() = getParent().definesLabel();
951      
952      eq LogNotExpr.definesLabel() = true;
953      eq ConditionalExpr.definesLabel() = true;
954      eq RelationalExpr.definesLabel() = false;
955      
956      eq LogicalExpr.definesLabel() = true;
957      eq IfStmt.definesLabel() = true;
958      eq WhileStmt.definesLabel() = true;
959      eq DoStmt.definesLabel() = true;
960      eq ForStmt.definesLabel() = true;
961     
962      // provide labels for these control statement conditions
963      eq IfStmt.getCondition().condition_false_label() = else_branch_label();
964      eq IfStmt.getCondition().condition_true_label() = then_branch_label();
965      eq WhileStmt.getCondition().condition_false_label() = end_label();
966      eq WhileStmt.getCondition().condition_true_label() = stmt_label();
967      eq DoStmt.getCondition().condition_false_label() = end_label();
968      eq DoStmt.getCondition().condition_true_label() = begin_label();
969      eq ForStmt.getCondition().condition_false_label() = end_label();
970      eq ForStmt.getCondition().condition_true_label() = begin_label();
971      
972      // propagate labels downwards for complex boolean expressions
973      inh int Expr.condition_false_label();
974      eq Program.getChild(int i).condition_false_label() {
975        throw new Error("condition_false_label not implemented");
976      }
977      inh int Expr.condition_true_label();
978      eq Program.getChild(int i).condition_true_label() {
979        throw new Error("condition_true_label not implemented");
980      }
981      
982      eq LogNotExpr.getOperand().condition_false_label() = true_label();
983      eq LogNotExpr.getOperand().condition_true_label() = false_label();
984    
985      eq ConditionalExpr.getCondition().condition_false_label() = else_branch_label();
986      eq ConditionalExpr.getCondition().condition_true_label() = then_branch_label();
987      eq ConditionalExpr.getTrueExpr().condition_false_label() = false_label();
988      eq ConditionalExpr.getTrueExpr().condition_true_label() = true_label();
989      eq ConditionalExpr.getFalseExpr().condition_false_label() = false_label();
990      eq ConditionalExpr.getFalseExpr().condition_true_label() = true_label();
991      
992      eq RelationalExpr.getLeftOperand().condition_false_label() = false_label();
993      eq RelationalExpr.getLeftOperand().condition_true_label() = true_label();
994      eq RelationalExpr.getRightOperand().condition_false_label() = false_label();
995      eq RelationalExpr.getRightOperand().condition_true_label() = true_label();
996    
997      eq AndLogicalExpr.getLeftOperand().condition_false_label() = false_label();
998      eq AndLogicalExpr.getLeftOperand().condition_true_label() = next_test_label();
999      eq AndLogicalExpr.getRightOperand().condition_false_label() = false_label();
1000      eq AndLogicalExpr.getRightOperand().condition_true_label() = true_label();
1001      
1002      eq OrLogicalExpr.getLeftOperand().condition_false_label() = next_test_label();
1003      eq OrLogicalExpr.getLeftOperand().condition_true_label() = true_label();
1004      eq OrLogicalExpr.getRightOperand().condition_false_label() = false_label();
1005      eq OrLogicalExpr.getRightOperand().condition_true_label() = true_label();
1006    
1007      syn boolean Expr.canBeTrue() = !isFalse();
1008      eq ParExpr.canBeTrue() = getExpr().canBeTrue();
1009      eq AbstractDot.canBeTrue() = lastAccess().canBeTrue();
1010      eq OrLogicalExpr.canBeTrue() = getLeftOperand().canBeTrue() || getRightOperand().canBeTrue();
1011      eq AndLogicalExpr.canBeTrue() = getLeftOperand().canBeTrue() && getRightOperand().canBeTrue();
1012      eq ConditionalExpr.canBeTrue() = type().isBoolean() && (getTrueExpr().canBeTrue() && getFalseExpr().canBeTrue() 
1013        || getCondition().isTrue() && getTrueExpr().canBeTrue()
1014        || getCondition().isFalse() && getFalseExpr().canBeTrue());
1015      eq LogNotExpr.canBeTrue() = getOperand().canBeFalse();
1016      
1017      syn boolean Expr.canBeFalse() = !isTrue();
1018      eq ParExpr.canBeFalse() = getExpr().canBeFalse();
1019      eq AbstractDot.canBeFalse() = lastAccess().canBeFalse();
1020      eq OrLogicalExpr.canBeFalse() = getLeftOperand().canBeFalse() && getRightOperand().canBeFalse();
1021      eq AndLogicalExpr.canBeFalse() = getLeftOperand().canBeFalse() || getRightOperand().canBeFalse();
1022      eq ConditionalExpr.canBeFalse() = type().isBoolean() && (getTrueExpr().canBeFalse() && getFalseExpr().canBeFalse() 
1023        || getCondition().isTrue() && getTrueExpr().canBeFalse()
1024        || getCondition().isFalse() && getFalseExpr().canBeFalse());
1025      eq LogNotExpr.canBeFalse() = getOperand().canBeTrue();
1026      
1027      public void RelationalExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); }
1028      public void LogNotExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); }
1029      public void LogicalExpr.createBCode(CodeGeneration gen) { emitBooleanCondition(gen); }
1030      protected void Expr.emitBooleanCondition(CodeGeneration gen) {
1031        emitEvalBranch(gen);
1032        int end_label = hostType().constantPool().newLabel();
1033        gen.addLabel(false_label());
1034        BooleanLiteral.push(gen, false);
1035        gen.emitGoto(end_label);
1036        gen.changeStackDepth(-1); // discard false from stack depth computation
1037        gen.addLabel(true_label());
1038        BooleanLiteral.push(gen, true);
1039        gen.addLabel(end_label);
1040      }
1041    
1042      public void ConditionalExpr.createBCode(CodeGeneration gen) {
1043        if(type().isBoolean())
1044          emitBooleanCondition(gen);
1045        else {
1046          int endBranch = hostType().constantPool().newLabel();
1047          getCondition().emitEvalBranch(gen);
1048          if(getCondition().canBeTrue()) {
1049            gen.addLabel(then_branch_label());
1050            getTrueExpr().createBCode(gen);
1051            getTrueExpr().type().emitCastTo(gen, type());
1052            if(getCondition().canBeFalse()) {
1053              gen.changeStackDepth(-type().variableSize());
1054              gen.emitGoto(endBranch);
1055            }
1056          }
1057          if(getCondition().canBeFalse()) {
1058            gen.addLabel(else_branch_label());
1059            getFalseExpr().createBCode(gen);
1060            getFalseExpr().type().emitCastTo(gen, type());
1061          }
1062          gen.addLabel(endBranch);
1063        }
1064      }
1065      syn lazy int ConditionalExpr.else_branch_label() = hostType().constantPool().newLabel();
1066      syn lazy int ConditionalExpr.then_branch_label() = hostType().constantPool().newLabel();
1067      
1068      public void Expr.emitEvalBranch(CodeGeneration gen) {
1069        if(isTrue())
1070          gen.emitGoto(true_label());
1071        else if(isFalse())
1072          gen.emitGoto(false_label());
1073        else {
1074          createBCode(gen);
1075          gen.emitCompare(Bytecode.IFNE, true_label());
1076          gen.emitGoto(false_label());
1077          //gen.emitCompare(Bytecode.IFEQ, false_label());
1078          //gen.emitGoto(true_label());
1079        }
1080      }
1081      
1082      public void ParExpr.emitEvalBranch(CodeGeneration gen)     { getExpr().emitEvalBranch(gen); }
1083      public void AbstractDot.emitEvalBranch(CodeGeneration gen) { lastAccess().emitEvalBranch(gen); }
1084      public void LogNotExpr.emitEvalBranch(CodeGeneration gen)  { getOperand().emitEvalBranch(gen); }
1085      
1086      public void AndLogicalExpr.emitEvalBranch(CodeGeneration gen) {
1087        getLeftOperand().emitEvalBranch(gen);
1088        gen.addLabel(next_test_label());
1089        if(getLeftOperand().canBeTrue()) {
1090          getRightOperand().emitEvalBranch(gen);
1091          if(getRightOperand().canBeTrue())
1092            gen.emitGoto(true_label());
1093        }
1094      }
1095      syn lazy int AndLogicalExpr.next_test_label() = hostType().constantPool().newLabel();
1096      
1097      public void OrLogicalExpr.emitEvalBranch(CodeGeneration gen) {
1098        getLeftOperand().emitEvalBranch(gen);
1099        gen.addLabel(next_test_label());
1100        if(getLeftOperand().canBeFalse()) {
1101          getRightOperand().emitEvalBranch(gen);
1102          if(getRightOperand().canBeFalse())
1103            gen.emitGoto(false_label());
1104        }
1105      }
1106      syn lazy int OrLogicalExpr.next_test_label() = hostType().constantPool().newLabel();
1107      
1108      public void ConditionalExpr.emitEvalBranch(CodeGeneration gen) {
1109        int endBranch = hostType().constantPool().newLabel();
1110        getCondition().emitEvalBranch(gen);
1111        gen.addLabel(then_branch_label());
1112        if(getCondition().canBeTrue()) {
1113          getTrueExpr().emitEvalBranch(gen);
1114          gen.emitGoto(true_label());
1115        }  
1116        gen.addLabel(else_branch_label());
1117        if(getCondition().canBeFalse()) {
1118          getFalseExpr().emitEvalBranch(gen);
1119          gen.emitGoto(true_label());
1120        }
1121      }
1122      
1123      public void RelationalExpr.emitEvalBranch(CodeGeneration gen) {
1124        if(isTrue())
1125          gen.emitGoto(true_label());
1126        else if(isFalse())
1127          gen.emitGoto(false_label());
1128        else {
1129          TypeDecl type = getLeftOperand().type();
1130          if(type.isNumericType()) {
1131            type = binaryNumericPromotedType();
1132            getLeftOperand().createBCode(gen);
1133            getLeftOperand().type().emitCastTo(gen, type); // Binary numeric promotion
1134            getRightOperand().createBCode(gen);
1135            getRightOperand().type().emitCastTo(gen, type); // Binary numeric promotion
1136          }
1137          else {
1138            getLeftOperand().createBCode(gen);
1139            getRightOperand().createBCode(gen);
1140          }
1141          compareBranch(gen, true_label(), type);
1142          gen.emitGoto(false_label());
1143          // compareNotBranch does not work for float comparison with NaN
1144          //compareNotBranch(gen, false_label(), type);
1145          //gen.emitGoto(true_label());
1146        }
1147      }
1148    
1149      public void RelationalExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) {
1150        throw new Error("compareBranch not supported for " + getClass().getName());
1151      }
1152      public void LTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLT(gen, label); }
1153      public void LEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLE(gen, label); }
1154      public void GEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGE(gen, label); }
1155      public void GTExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGT(gen, label); }
1156      public void EQExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchEQ(gen, label); }
1157      public void NEExpr.compareBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchNE(gen, label); }
1158    
1159      public void RelationalExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) {
1160        throw new Error("compareBranch not supported for " + getClass().getName());
1161      }
1162      public void LTExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGE(gen, label); }
1163      public void LEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchGT(gen, label); }
1164      public void GEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLT(gen, label); }
1165      public void GTExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchLE(gen, label); }
1166      public void EQExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchNE(gen, label); }
1167      public void NEExpr.compareNotBranch(CodeGeneration gen, int label, TypeDecl typeDecl) { typeDecl.branchEQ(gen, label); }
1168    
1169      public void InstanceOfExpr.createBCode(CodeGeneration gen) {
1170        getExpr().createBCode(gen);
1171        gen.emitInstanceof(getTypeAccess().type());
1172      }
1173    
1174      public void Stmt.createBCode(CodeGeneration gen) {
1175        gen.addLineNumberEntryAtCurrentPC(this);
1176      }
1177      
1178      public void Block.createBCode(CodeGeneration gen) {
1179        //super.createBCode(gen);
1180        for(int i = 0; i < getNumStmt(); i++) {
1181          try {
1182            getStmt(i).createBCode(gen);
1183          } catch (Exception e) {
1184            e.printStackTrace();
1185            throw new Error("Error generating code for " + errorPrefix() + " " + getStmt(i));
1186          }
1187        }
1188        gen.addVariableScopeLabel(variableScopeEndLabel(gen));
1189      }
1190    
1191      public void EmptyStmt.createBCode(CodeGeneration gen) {
1192        super.createBCode(gen);
1193      }
1194    
1195      syn lazy int LabeledStmt.label() = hostType().constantPool().newLabel();
1196      syn lazy int LabeledStmt.end_label() = hostType().constantPool().newLabel();
1197      public void LabeledStmt.createBCode(CodeGeneration gen) {
1198        super.createBCode(gen);
1199        gen.addLabel(label());
1200        getStmt().createBCode(gen);
1201        gen.addLabel(end_label());
1202      }
1203    
1204      public void ExprStmt.createBCode(CodeGeneration gen) {
1205        super.createBCode(gen);
1206        getExpr().createBCode(gen);
1207        if(needsPop())
1208          getExpr().type().emitPop(gen);
1209      }
1210    
1211      syn lazy DefaultCase SwitchStmt.defaultCase() {
1212        for(int i= 0; i < getBlock().getNumStmt(); i++) {
1213          if(getBlock().getStmt(i) instanceof DefaultCase)
1214            return (DefaultCase)getBlock().getStmt(i);
1215        }
1216        return null;
1217      }
1218    
1219      syn lazy int SwitchStmt.end_label() = hostType().constantPool().newLabel();
1220    
1221      public void SwitchStmt.createBCode(CodeGeneration gen) {
1222        super.createBCode(gen);
1223        int cond_label = hostType().constantPool().newLabel();
1224        int switch_label = hostType().constantPool().newLabel();
1225    
1226        gen.emitGoto(cond_label);
1227        getBlock().createBCode(gen);
1228        if(canCompleteNormally())
1229          gen.emitGoto(end_label());
1230        gen.addLabel(cond_label);
1231        getExpr().createBCode(gen);
1232    
1233        TreeMap map = new TreeMap();
1234        for(int i = 0; i < getBlock().getNumStmt(); i++) {
1235          if(getBlock().getStmt(i) instanceof ConstCase) {
1236            ConstCase ca = (ConstCase)getBlock().getStmt(i);
1237            map.put(new Integer(ca.getValue().constant().intValue()), ca);
1238          }        
1239        }
1240    
1241        long low = map.isEmpty() ? 0 : ((Integer)map.firstKey()).intValue();
1242        long high = map.isEmpty() ? 0 : ((Integer)map.lastKey()).intValue();
1243    
1244        long tableSwitchSize = 8L + (high - low + 1L) * 4L;
1245        long lookupSwitchSize = 4L + map.size() * 8L;
1246    
1247        gen.addLabel(switch_label);
1248        if(tableSwitchSize < lookupSwitchSize) {
1249          gen.emit(Bytecode.TABLESWITCH);
1250          int pad = emitPad(gen);
1251          int defaultOffset = defaultOffset(gen, switch_label);
1252          if(defaultOffset == 0) {
1253            defaultOffset = 1 + pad + 4 + 4 + 4 + 4 * (int)(high - low + 1);
1254          }
1255          gen.add4(defaultOffset);
1256          gen.add4((int)low);
1257          gen.add4((int)high);
1258          for(long i = low; i <= high; i++) {
1259            ConstCase ca = (ConstCase)map.get(new Integer((int)i));
1260            if(ca != null) {
1261              int offset = gen.addressOf(ca.label(gen))
1262                - gen.addressOf(switch_label);
1263              gen.add4(offset);
1264            }
1265            else {
1266              gen.add4(defaultOffset);
1267            }
1268          }
1269        }
1270        else {
1271          gen.emit(Bytecode.LOOKUPSWITCH);
1272          int pad = emitPad(gen);
1273          int defaultOffset = defaultOffset(gen, switch_label);
1274          if(defaultOffset == 0) {
1275            defaultOffset = 1 + pad + 4 + 4 + 8 * numCase();
1276          }
1277          gen.add4(defaultOffset);
1278          gen.add4(map.size());
1279          for(Iterator iter = map.values().iterator(); iter.hasNext(); ) {
1280            ConstCase ca = (ConstCase)iter.next();
1281            gen.add4(ca.getValue().constant().intValue());
1282            int offset = gen.addressOf(ca.label(gen))
1283              - gen.addressOf(switch_label);
1284            gen.add4(offset);
1285          }
1286        }
1287        gen.addLabel(end_label());
1288      }
1289    
1290      syn int SwitchStmt.numCase() {
1291        int result = 0;
1292        for(int i = 0; i < getBlock().getNumStmt(); i++)
1293          if(getBlock().getStmt(i) instanceof Case)
1294            result++;
1295        return result;
1296      }
1297    
1298      private int SwitchStmt.emitPad(CodeGeneration gen) {
1299        int pad = (4 - (gen.pos() % 4)) % 4;
1300        for(int i = 0; i < pad; i++)
1301          gen.emit(Bytecode.NOP);
1302        if(gen.pos() % 4 != 0)
1303          throw new Error("Switch not at 4-byte boundary:" + gen.pos());
1304        return pad;
1305      }
1306      private int SwitchStmt.defaultOffset(CodeGeneration gen, int switch_label) {
1307        boolean hasDefault = defaultCase() != null;
1308        if(hasDefault) {
1309          int offset = gen.addressOf(defaultCase().label(gen))
1310            - gen.addressOf(switch_label);
1311          return offset;
1312        }
1313        return 0;
1314      }
1315    
1316      syn lazy int Case.label(CodeGeneration gen) = hostType().constantPool().newLabel();
1317    
1318      public void Case.createBCode(CodeGeneration gen) {
1319        gen.addLabel(label(gen));
1320      }
1321    
1322      syn lazy int IfStmt.else_branch_label() = hostType().constantPool().newLabel();
1323      syn lazy int IfStmt.then_branch_label() = hostType().constantPool().newLabel();
1324      public void IfStmt.createBCode(CodeGeneration gen) {
1325        super.createBCode(gen);
1326        int elseBranch = else_branch_label();
1327        int thenBranch = then_branch_label();
1328        int endBranch = hostType().constantPool().newLabel();
1329        getCondition().emitEvalBranch(gen);
1330        gen.addLabel(thenBranch);
1331        //if(getCondition().canBeTrue()) {
1332          getThen().createBCode(gen);
1333          if(getThen().canCompleteNormally() && hasElse() /*&& getCondition().canBeFalse()*/)
1334            gen.emitGoto(endBranch);
1335        //}
1336        gen.addLabel(elseBranch);
1337        if(hasElse() /*&& getCondition().canBeFalse()*/)
1338          getElse().createBCode(gen);
1339        gen.addLabel(endBranch);
1340      }
1341    
1342      syn lazy int WhileStmt.cond_label() = hostType().constantPool().newLabel();
1343      syn lazy int WhileStmt.end_label() = hostType().constantPool().newLabel();
1344      syn lazy int WhileStmt.stmt_label() = hostType().constantPool().newLabel();
1345    
1346      public void WhileStmt.createBCode(CodeGeneration gen) {
1347        super.createBCode(gen);
1348        gen.addLabel(cond_label());
1349        getCondition().emitEvalBranch(gen);
1350        gen.addLabel(stmt_label());
1351        if(getCondition().canBeTrue()) {
1352          getStmt().createBCode(gen);
1353          if(getStmt().canCompleteNormally())
1354            gen.emitGoto(cond_label());
1355        }
1356        gen.addLabel(end_label());
1357      }
1358    
1359      syn lazy int DoStmt.begin_label() = hostType().constantPool().newLabel();
1360      syn lazy int DoStmt.cond_label() = hostType().constantPool().newLabel();
1361      syn lazy int DoStmt.end_label() = hostType().constantPool().newLabel();
1362    
1363      public void DoStmt.createBCode(CodeGeneration gen) {
1364        super.createBCode(gen);
1365        gen.addLabel(begin_label());
1366        getStmt().createBCode(gen);
1367        gen.addLabel(cond_label());
1368        getCondition().emitEvalBranch(gen);
1369        gen.addLabel(end_label());
1370      }
1371    
1372      syn lazy int ForStmt.cond_label() = hostType().constantPool().newLabel();
1373      syn lazy int ForStmt.begin_label() = hostType().constantPool().newLabel();
1374      syn lazy int ForStmt.update_label() = hostType().constantPool().newLabel();
1375      syn lazy int ForStmt.end_label() = hostType().constantPool().newLabel();
1376    
1377      public void ForStmt.createBCode(CodeGeneration gen) {
1378        super.createBCode(gen);
1379        for (int i=0; i<getNumInitStmt(); i++) {
1380          getInitStmt(i).createBCode(gen);
1381        }
1382        gen.addLabel(cond_label());
1383        getCondition().emitEvalBranch(gen);
1384        if(getCondition().canBeTrue()) {
1385          gen.addLabel(begin_label());
1386          getStmt().createBCode(gen);
1387          gen.addLabel(update_label());      
1388          for (int i=0; i<getNumUpdateStmt(); i++)
1389            getUpdateStmt(i).createBCode(gen);
1390          gen.emitGoto(cond_label());
1391        }
1392        if(canCompleteNormally()) {
1393          gen.addLabel(end_label());
1394        }
1395        gen.addVariableScopeLabel(variableScopeEndLabel(gen));
1396      }
1397      
1398      syn int Stmt.break_label() {
1399        throw new UnsupportedOperationException("Can not break at this statement of type " + getClass().getName());
1400      }
1401      eq ForStmt.break_label() = end_label();
1402      eq WhileStmt.break_label() = end_label();
1403      eq DoStmt.break_label() = end_label();
1404      eq LabeledStmt.break_label() = end_label();
1405      eq SwitchStmt.break_label() = end_label();
1406      eq TryStmt.break_label() =  label_finally();
1407    
1408      public void BreakStmt.createBCode(CodeGeneration gen) {
1409        super.createBCode(gen);
1410        for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) {
1411          FinallyHost stmt = (FinallyHost)iter.next();
1412          gen.emitJsr(stmt.label_finally_block());
1413        }
1414        gen.emitGoto(targetStmt().break_label());
1415      }
1416    
1417      syn int Stmt.continue_label() {
1418        throw new UnsupportedOperationException("Can not continue at this statement");
1419      }
1420      eq ForStmt.continue_label() = update_label();
1421      eq WhileStmt.continue_label() = cond_label();
1422      eq DoStmt.continue_label() = cond_label();
1423      eq LabeledStmt.continue_label() = getStmt().continue_label();
1424      eq TryStmt.continue_label() = label_finally();
1425    
1426      public void ContinueStmt.createBCode(CodeGeneration gen) {
1427        super.createBCode(gen);
1428        for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) {
1429          FinallyHost stmt = (FinallyHost)iter.next();
1430          gen.emitJsr(stmt.label_finally_block());
1431        }
1432        gen.emitGoto(targetStmt().continue_label());
1433      }
1434    
1435      public void ReturnStmt.createBCode(CodeGeneration gen) {
1436        super.createBCode(gen);
1437        if(hasResult()) {
1438          TypeDecl type = null;
1439          BodyDecl b = enclosingBodyDecl();
1440          if(b instanceof MethodDecl) {
1441            type = ((MethodDecl)b).type();
1442          }
1443          else {
1444            throw new Error("Can not create code that returns value within non method");
1445          }
1446          getResult().createBCode(gen);
1447          getResult().type().emitCastTo(gen, type);
1448          if(!finallyList().isEmpty()) {
1449            type.emitStoreLocal(gen, resultSaveLocalNum());
1450          }
1451          for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) {
1452            FinallyHost stmt = (FinallyHost)iter.next();
1453            gen.emitJsr(stmt.label_finally_block());
1454          }
1455          if(!finallyList().isEmpty()) {
1456            type.emitLoadLocal(gen, resultSaveLocalNum());
1457          }
1458          type.emitReturn(gen);
1459        }
1460        else {
1461          for(Iterator iter = finallyList().iterator(); iter.hasNext(); ) {
1462            FinallyHost stmt = (FinallyHost)iter.next();
1463            gen.emitJsr(stmt.label_finally_block());
1464          }
1465          gen.emitReturn();
1466        }
1467      }
1468    
1469      public void ThrowStmt.createBCode(CodeGeneration gen) {
1470        super.createBCode(gen);
1471        getExpr().createBCode(gen);
1472        gen.emitThrow();
1473      }
1474      syn lazy int FinallyHost.label_finally_block();
1475    
1476      syn lazy int TryStmt.label_begin() = hostType().constantPool().newLabel();
1477      syn lazy int TryStmt.label_block_end() = hostType().constantPool().newLabel();
1478      syn lazy int TryStmt.label_end() = hostType().constantPool().newLabel();
1479      syn lazy int TryStmt.label_finally() = hostType().constantPool().newLabel();
1480      eq TryStmt.label_finally_block() = hostType().constantPool().newLabel();
1481      syn lazy int TryStmt.label_exception_handler() = hostType().constantPool().newLabel();
1482      syn lazy int TryStmt.label_catch_end() = hostType().constantPool().newLabel();
1483    
1484      public void TryStmt.createBCode(CodeGeneration gen) {
1485        super.createBCode(gen);
1486        gen.addLabel(label_begin());
1487        getBlock().createBCode(gen);
1488        if(getBlock().canCompleteNormally())
1489          gen.emitGoto(label_finally());
1490        gen.addLabel(label_block_end());
1491        for(int i = 0; i < getNumCatchClause(); i++) {
1492          getCatchClause(i).createBCode(gen);
1493          if(getCatchClause(i).getBlock().canCompleteNormally()) {
1494            if(!hasFinally())
1495              gen.emitGoto(label_finally());
1496            else
1497              gen.emitGoto(label_catch_end());
1498          }
1499        }
1500        
1501        gen.addLabel(label_catch_end());
1502        if(hasFinally() && getNumCatchClause() > 0) {
1503          gen.emitJsr(label_finally_block());
1504          if(canCompleteNormally())
1505            gen.emitGoto(label_end());
1506        }
1507        
1508        gen.addLabel(label_finally());
1509        if(hasFinally()) {
1510          if(getBlock().canCompleteNormally()) {
1511            gen.emitJsr(label_finally_block());
1512            if(canCompleteNormally())
1513              gen.emitGoto(label_end());
1514          }
1515          gen.addLabel(label_exception_handler());
1516          emitExceptionHandler(gen);
1517          gen.addLabel(label_finally_block());
1518          emitFinallyBlock(gen);
1519        }
1520        gen.addLabel(label_end());
1521        gen.createExceptionTable(this);
1522      }
1523    
1524      syn lazy int CatchClause.label() = hostType().constantPool().newLabel();
1525      public void BasicCatch.createBCode(CodeGeneration gen) {
1526        gen.addLabel(label());
1527        // add 1 to stack depth
1528        gen.changeStackDepth(1);
1529        getParameter().type().emitStoreLocal(gen, getParameter().localNum());
1530        getBlock().createBCode(gen);
1531      }
1532    
1533      syn lazy int SynchronizedStmt.label_begin() = hostType().constantPool().newLabel();
1534      syn lazy int SynchronizedStmt.label_end() = hostType().constantPool().newLabel();
1535      syn lazy int SynchronizedStmt.label_finally() = hostType().constantPool().newLabel();
1536      eq SynchronizedStmt.label_finally_block() = hostType().constantPool().newLabel();
1537      syn lazy int SynchronizedStmt.label_exception_handler() = hostType().constantPool().newLabel();
1538    
1539      public void SynchronizedStmt.createBCode(CodeGeneration gen) {
1540        super.createBCode(gen);
1541        getExpr().createBCode(gen);
1542        emitMonitorEnter(gen);
1543        gen.addLabel(label_begin());
1544        getBlock().createBCode(gen);
1545        gen.addLabel(label_finally());
1546        if(getBlock().canCompleteNormally()) {
1547          gen.emitJsr(label_finally_block());
1548          gen.emitGoto(label_end());
1549        }
1550        gen.addLabel(label_exception_handler());
1551        emitExceptionHandler(gen);
1552        gen.addLabel(label_finally_block());
1553        emitFinallyBlock(gen);
1554        gen.addLabel(label_end());
1555        gen.createExceptionTable(this);
1556      }
1557    
1558      /**
1559       * Assert statement bytecode is generated through the transformed
1560       * version of the assert statement!
1561       *
1562       * @see Java1.4Backend/Transformations.jrag
1563       */
1564      public void AssertStmt.createBCode(CodeGeneration gen) {
1565        throw new UnsupportedOperationException("Assert not implemented yet");
1566      }
1567    
1568      public void LocalClassDeclStmt.createBCode(CodeGeneration gen) {
1569      }
1570    
1571      public void ClassAccess.createBCode(CodeGeneration gen) {
1572        if(prevExpr().type().isPrimitiveType() || prevExpr().type().isVoid()) {
1573          TypeDecl typeDecl = lookupType("java.lang", prevExpr().type().primitiveClassName());
1574          SimpleSet c = typeDecl.memberFields("TYPE");
1575          FieldDeclaration f = (FieldDeclaration)c.iterator().next();
1576          f.emitLoadField(gen, typeDecl);
1577        }
1578        else {
1579          FieldDeclaration f = hostType().topLevelType().createStaticClassField(prevExpr().type().referenceClassFieldName());
1580          // add method to perform lookup as a side-effect
1581          MethodDecl m = hostType().topLevelType().createStaticClassMethod();
1582    
1583          int next_label = hostType().constantPool().newLabel();
1584          int end_label = hostType().constantPool().newLabel();
1585          f.emitLoadField(gen, hostType());
1586          gen.emitBranchNonNull(next_label);
1587          
1588          // emit string literal
1589          
1590          StringLiteral.push(gen, prevExpr().type().jvmName());
1591          m.emitInvokeMethod(gen, hostType());
1592          gen.emitDup();
1593          f.emitStoreField(gen, hostType());
1594          gen.emitGoto(end_label);
1595          gen.addLabel(next_label);
1596          gen.changeStackDepth(-1);
1597          f.emitLoadField(gen, hostType());
1598          gen.addLabel(end_label);
1599        }
1600      }
1601    }