001    /* Copyright (c) 2014, Erik Hogeman <Erik.Hogemn@gmail.com>
002     * All rights reserved.
003     *
004     * Redistribution and use in source and binary forms, with or without
005     * modification, are permitted provided that the following conditions are met:
006     *
007     *     * Redistributions of source code must retain the above copyright notice,
008     *       this list of conditions and the following disclaimer.
009     *     * Redistributions in binary form must reproduce the above copyright
010     *       notice, this list of conditions and the following disclaimer in the
011     *       documentation and/or other materials provided with the distribution.
012     *     * Neither the name of the Lund University nor the names of its
013     *       contributors may be used to endorse or promote products derived from
014     *       this software without specific prior written permission.
015     *
016     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
017     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
018     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
019     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
020     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
021     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
022     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
023     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
024     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
025     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
026     * POSSIBILITY OF SUCH DAMAGE.
027     */
028    aspect Java8CreateBCode {
029      public void LambdaExpr.createBCode(CodeGeneration gen) {
030        toClass().createBCode(gen);
031      }
032    
033      public void ExprMethodReference.createBCode(CodeGeneration gen) {
034        toClass().createBCode(gen);
035      }
036    
037      public void TypeMethodReference.createBCode(CodeGeneration gen) {
038        toClass().createBCode(gen);
039      }
040    
041      public void ConstructorReference.createBCode(CodeGeneration gen) {
042        toClass().createBCode(gen);
043      }
044    
045      refine CreateBCode
046      public void SuperAccess.createBCode(CodeGeneration gen) {
047        if (decl().isInterfaceDecl()) {
048          emitThis(gen, hostType());
049        } else {
050          emitThis(gen, decl());
051        }
052      }
053    
054      // TEMPORARY REFINE TO PREVENT SUPERACCESSORS FROM BEING CREATED WHEN INTERFACE IS THE QUALIFIER
055      refine GenericsCodegen
056      public void MethodAccess.createBCode(CodeGeneration gen) {
057        MethodDecl decl = decl().erasedMethod();
058        createLoadQualifier(gen);
059    
060        if (program().options().hasOption("-debug")) {
061          if (decl.type().isUnknown()) {
062            System.err.println("Could not bind " + this);
063            for (int i = 0; i < getNumArg(); ++i) {
064              System.err.println("Argument " + getArg(i)
065                  + " is of type " + getArg(i).type().typeName());
066              if (getArg(i).varDecl() != null) {
067                System.err.println(getArg(i).varDecl() + " in "
068                    + getArg(i).varDecl().hostType().typeName());
069              }
070            }
071            if (isQualified()) {
072              System.err.println("Qualifier " + qualifier()
073                  + " is of type " + qualifier().type().typeName());
074            }
075            throw new Error("Could not bind " + this);
076          }
077          if (decl.getNumParameter() != getNumArg()) {
078            System.out.println(this
079                + " does not have the same number of arguments as " + decl);
080          }
081        }
082    
083        for (int i = 0; i < getNumArg(); ++i) {
084          getArg(i).createBCode(gen);
085          // the cast or boxing/unboxing operation must know the bound rather than the erased type
086          getArg(i).type().emitCastTo(gen, decl().getParameter(i).type()); // MethodInvocationConversion
087        }
088    
089        if (!decl.isStatic() && isQualified() && prevExpr().isSuperAccess()) {
090          if (!hostType().instanceOf(prevExpr().type()) && !prevExpr().type().isInterfaceDecl()) {
091            /* should this be decl instead? possible copy/paste error? */
092            decl().createSuperAccessor(superAccessorTarget()).emitInvokeMethod(gen, superAccessorTarget());
093          } else {
094            decl.emitInvokeSpecialMethod(gen, methodQualifierType());
095          }
096        } else {
097          decl.emitInvokeMethod(gen, methodQualifierType());
098        }
099    
100        if (decl.type() != decl().type()) {
101          gen.emitCheckCast(decl().type());
102        }
103      }
104    }