169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/*
269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Javassist, a Java-bytecode translator toolkit.
369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Copyright (C) 1999-2007 Shigeru Chiba. All Rights Reserved.
469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * The contents of this file are subject to the Mozilla Public License Version
669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * 1.1 (the "License"); you may not use this file except in compliance with
769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the License.  Alternatively, the contents of this file may be used under
869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * the terms of the GNU Lesser General Public License Version 2.1 or later.
969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *
1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Software distributed under the License is distributed on an "AS IS" basis,
1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * for the specific language governing rights and limitations under the
1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * License.
1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpackage javassist.compiler;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtClass;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtPrimitiveType;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtMember;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtField;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtBehavior;
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtMethod;
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CtConstructor;
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.CannotCompileException;
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.Modifier;
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Bytecode;
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.CodeAttribute;
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.LocalVariableAttribute;
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.BadBytecode;
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.Opcode;
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.NotFoundException;
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.ast.*;
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class Javac {
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    JvstCodeGen gen;
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    SymbolTable stable;
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private Bytecode bytecode;
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String param0Name = "$0";
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String resultVarName = "$_";
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String proceedName = "$proceed";
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a compiler.
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param thisClass         the class that a compiled method/field
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          belongs to.
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Javac(CtClass thisClass) {
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        this(new Bytecode(thisClass.getClassFile2().getConstPool(), 0, 0),
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal             thisClass);
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Constructs a compiler.
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The produced bytecode is stored in the <code>Bytecode</code> object
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * specified by <code>b</code>.
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param thisClass         the class that a compiled method/field
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          belongs to.
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Javac(Bytecode b, CtClass thisClass) {
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen = new JvstCodeGen(b, thisClass, thisClass.getClassPool());
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        stable = new SymbolTable();
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bytecode = b;
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the produced bytecode.
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Bytecode getBytecode() { return bytecode; }
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Compiles a method, constructor, or field declaration
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * to a class.
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * A field declaration can declare only one field.
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>In a method or constructor body, $0, $1, ... and $_
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * are not available.
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return          a <code>CtMethod</code>, <code>CtConstructor</code>,
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  or <code>CtField</code> object.
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #recordProceed(String,String)
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtMember compile(String src) throws CompileError {
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Parser p = new Parser(new Lex(src));
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ASTList mem = p.parseMember1(stable);
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (mem instanceof FieldDecl)
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return compileField((FieldDecl)mem);
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CtBehavior cb = compileMethod(p, (MethodDecl)mem);
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CtClass decl = cb.getDeclaringClass();
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cb.getMethodInfo2()
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                  .rebuildStackMapIf6(decl.getClassPool(),
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                      decl.getClassFile2());
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return cb;
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode bb) {
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError(bb.getMessage());
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CannotCompileException e) {
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError(e.getMessage());
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static class CtFieldWithInit extends CtField {
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        private ASTree init;
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtFieldWithInit(CtClass type, String name, CtClass declaring)
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws CannotCompileException
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super(type, name, declaring);
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            init = null;
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected void setInit(ASTree i) { init = i; }
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        protected ASTree getInitAST() {
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return init;
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private CtField compileField(FieldDecl fd)
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError, CannotCompileException
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtFieldWithInit f;
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Declarator d = fd.getDeclarator();
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        f = new CtFieldWithInit(gen.resolver.lookupClass(d),
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                d.getVariable().get(), gen.getThisClass());
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        f.setModifiers(MemberResolver.getModifiers(fd.getModifiers()));
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (fd.getInit() != null)
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            f.setInit(fd.getInit());
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return f;
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private CtBehavior compileMethod(Parser p, MethodDecl md)
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int mod = MemberResolver.getModifiers(md.getModifiers());
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass[] plist = gen.makeParamList(md);
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass[] tlist = gen.makeThrowsList(md);
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        recordParams(plist, Modifier.isStatic(mod));
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        md = p.parseMethod2(stable, md);
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (md.isConstructor()) {
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CtConstructor cons = new CtConstructor(plist,
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                   gen.getThisClass());
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cons.setModifiers(mod);
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                md.accept(gen);
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cons.getMethodInfo().setCodeAttribute(
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        bytecode.toCodeAttribute());
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cons.setExceptionTypes(tlist);
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return cons;
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                Declarator r = md.getReturn();
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CtClass rtype = gen.resolver.lookupClass(r);
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                recordReturnType(rtype, false);
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CtMethod method = new CtMethod(rtype, r.getVariable().get(),
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                           plist, gen.getThisClass());
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                method.setModifiers(mod);
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                gen.setThisMethod(method);
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                md.accept(gen);
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (md.getBody() != null)
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    method.getMethodInfo().setCodeAttribute(
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                        bytecode.toCodeAttribute());
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    method.setModifiers(mod | Modifier.ABSTRACT);
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                method.setExceptionTypes(tlist);
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return method;
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError(e.toString());
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Compiles a method (or constructor) body.
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @src	a single statement or a block.
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *          If null, this method produces a body returning zero or null.
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public Bytecode compileBody(CtBehavior method, String src)
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int mod = method.getModifiers();
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            recordParams(method.getParameterTypes(), Modifier.isStatic(mod));
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass rtype;
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (method instanceof CtMethod) {
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                gen.setThisMethod((CtMethod)method);
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                rtype = ((CtMethod)method).getReturnType();
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                rtype = CtClass.voidType;
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            recordReturnType(rtype, false);
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean isVoid = rtype == CtClass.voidType;
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (src == null)
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                makeDefaultBody(bytecode, rtype);
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                Parser p = new Parser(new Lex(src));
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                SymbolTable stb = new SymbolTable(stable);
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                Stmnt s = p.parseStatement(stb);
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (p.hasMore())
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throw new CompileError(
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        "the method/constructor body must be surrounded by {}");
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                boolean callSuper = false;
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (method instanceof CtConstructor)
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    callSuper = !((CtConstructor)method).isClassInitializer();
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                gen.atMethodBody(s, callSuper, isVoid);
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return bytecode;
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) {
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError(e.toString());
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void makeDefaultBody(Bytecode b, CtClass type) {
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int op;
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int value;
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type instanceof CtPrimitiveType) {
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtPrimitiveType pt = (CtPrimitiveType)type;
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            op = pt.getReturnOp();
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (op == Opcode.DRETURN)
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                value = Opcode.DCONST_0;
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (op == Opcode.FRETURN)
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                value = Opcode.FCONST_0;
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (op == Opcode.LRETURN)
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                value = Opcode.LCONST_0;
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (op == Opcode.RETURN)
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                value = Opcode.NOP;
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                value = Opcode.ICONST_0;
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            op = Opcode.ARETURN;
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            value = Opcode.ACONST_NULL;
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (value != Opcode.NOP)
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            b.addOpcode(value);
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        b.addOpcode(op);
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Records local variables available at the specified program counter.
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the LocalVariableAttribute is not available, this method does not
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * record any local variable.  It only returns false.
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param pc    program counter (&gt;= 0)
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return false if the CodeAttribute does not include a
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *              LocalVariableAttribute.
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean recordLocalVariables(CodeAttribute ca, int pc)
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LocalVariableAttribute va
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = (LocalVariableAttribute)
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal              ca.getAttribute(LocalVariableAttribute.tag);
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (va == null)
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = va.tableLength();
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int start = va.startPc(i);
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int len = va.codeLength(i);
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (start <= pc && pc < start + len)
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                gen.recordVariable(va.descriptor(i), va.variableName(i),
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                   va.index(i), stable);
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return true;
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Records parameter names if the LocalVariableAttribute is available.
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It returns false unless the LocalVariableAttribute is available.
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param numOfLocalVars    the number of local variables used
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          for storing the parameters.
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return false if the CodeAttribute does not include a
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *              LocalVariableAttribute.
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean recordParamNames(CodeAttribute ca, int numOfLocalVars)
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        LocalVariableAttribute va
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = (LocalVariableAttribute)
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal              ca.getAttribute(LocalVariableAttribute.tag);
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (va == null)
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = va.tableLength();
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int index = va.index(i);
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (index < numOfLocalVars)
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                gen.recordVariable(va.descriptor(i), va.variableName(i),
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                   index, stable);
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return true;
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes variables $0 (this), $1, $2, ..., and $args represent method
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * parameters.  $args represents an array of all the parameters.
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It also makes $$ available as a parameter list of method call.
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This must be called before calling <code>compileStmnt()</code> and
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>compileExpr()</code>.  The correct value of
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>isStatic</code> must be recorded before compilation.
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>maxLocals</code> is updated to include $0,...
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordParams(CtClass[] params, boolean isStatic)
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return gen.recordParams(params, isStatic, "$", "$args", "$$", stable);
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes variables $0, $1, $2, ..., and $args represent method
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * parameters.  $args represents an array of all the parameters.
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It also makes $$ available as a parameter list of method call.
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * $0 can represent a local variable other than THIS (variable 0).
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * $class is also made available.
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This must be called before calling <code>compileStmnt()</code> and
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>compileExpr()</code>.  The correct value of
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>isStatic</code> must be recorded before compilation.
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>maxLocals</code> is updated to include $0,...
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @paaram use0     true if $0 is used.
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param varNo     the register number of $0 (use0 is true)
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          or $1 (otherwise).
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param target    the type of $0 (it can be null if use0 is false).
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  It is used as the name of the type represented
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  by $class.
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param isStatic  true if the method in which the compiled bytecode
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  is embedded is static.
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordParams(String target, CtClass[] params,
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                             boolean use0, int varNo, boolean isStatic)
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return gen.recordParams(params, isStatic, "$", "$args", "$$",
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                use0, varNo, target, stable);
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Sets <code>maxLocals</code> to <code>max</code>.
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method tells the compiler the local variables that have been
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * allocated for the rest of the code.  When the compiler needs
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * new local variables, the local variables at the index <code>max</code>,
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>max + 1</code>, ... are assigned.
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>This method is indirectly called by <code>recordParams</code>.
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setMaxLocals(int max) {
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen.setMaxLocals(max);
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prepares to use cast $r, $w, $_, and $type.
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * $type is made to represent the specified return type.
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It also enables to write a return statement with a return value
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * for void method.
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>If the return type is void, ($r) does nothing.
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The type of $_ is java.lang.Object.
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type              the return type.
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param useResultVar      true if $_ is used.
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return          -1 or the variable index assigned to $_.
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see #recordType(CtClass)
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordReturnType(CtClass type, boolean useResultVar)
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen.recordType(type);
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return gen.recordReturnType(type, "$r",
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        (useResultVar ? resultVarName : null), stable);
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prepares to use $type.  Note that recordReturnType() overwrites
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the value of $type.
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param t     the type represented by $type.
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void recordType(CtClass t) {
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen.recordType(t);
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes the given variable available.
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type      variable type
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      variable name
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordVariable(CtClass type, String name)
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return gen.recordVariable(type, name, stable);
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prepares to use $proceed().
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the return type of $proceed() is void, null is pushed on the
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * stack.
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param target    an expression specifying the target object.
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          if null, "this" is the target.
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param method    the method name.
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void recordProceed(String target, String method)
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Parser p = new Parser(new Lex(target));
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final ASTree texpr = p.parseExpression(stable);
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final String m = method;
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ProceedHandler h = new ProceedHandler() {
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throws CompileError
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                {
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ASTree expr = new Member(m);
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (texpr != null)
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        expr = Expr.make('.', texpr, expr);
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    expr = CallExpr.makeCall(expr, args);
44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    gen.compileExpr(expr);
44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    gen.addNullIfVoid();
44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                public void setReturnType(JvstTypeChecker check, ASTList args)
45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throws CompileError
45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                {
45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ASTree expr = new Member(m);
45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    if (texpr != null)
45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        expr = Expr.make('.', texpr, expr);
45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    expr = CallExpr.makeCall(expr, args);
45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    expr.accept(check);
46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    check.addNullIfVoid();
46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            };
46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen.setProceedHandler(h, proceedName);
46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prepares to use $proceed() representing a static method.
46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the return type of $proceed() is void, null is pushed on the
47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * stack.
47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param targetClass    the fully-qualified dot-separated name
47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *				of the class declaring the method.
47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param method         the method name.
47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void recordStaticProceed(String targetClass, String method)
47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final String c = targetClass;
48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final String m = method;
48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ProceedHandler h = new ProceedHandler() {
48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throws CompileError
48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                {
48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    Expr expr = Expr.make(TokenId.MEMBER,
48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                          new Symbol(c), new Member(m));
48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    expr = CallExpr.makeCall(expr, args);
48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    gen.compileExpr(expr);
49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    gen.addNullIfVoid();
49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                public void setReturnType(JvstTypeChecker check, ASTList args)
49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throws CompileError
49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                {
49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    Expr expr = Expr.make(TokenId.MEMBER,
49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                          new Symbol(c), new Member(m));
49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    expr = CallExpr.makeCall(expr, args);
49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    expr.accept(check);
50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    check.addNullIfVoid();
50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            };
50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen.setProceedHandler(h, proceedName);
50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prepares to use $proceed() representing a private/super's method.
50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the return type of $proceed() is void, null is pushed on the
51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * stack.  This method is for methods invoked by INVOKESPECIAL.
51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param target    an expression specifying the target object.
51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          if null, "this" is the target.
51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param classname	    the class name declaring the method.
51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param methodname    the method name.
51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param descriptor    the method descriptor.
51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void recordSpecialProceed(String target, String classname,
51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                     String methodname, String descriptor)
52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Parser p = new Parser(new Lex(target));
52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final ASTree texpr = p.parseExpression(stable);
52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final String cname = classname;
52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final String method = methodname;
52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        final String desc = descriptor;
52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ProceedHandler h = new ProceedHandler() {
52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                public void doit(JvstCodeGen gen, Bytecode b, ASTList args)
53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throws CompileError
53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                {
53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    gen.compileInvokeSpecial(texpr, cname, method, desc, args);
53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                public void setReturnType(JvstTypeChecker c, ASTList args)
53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    throws CompileError
53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                {
53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    c.compileInvokeSpecial(texpr, cname, method, desc, args);
53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            };
54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen.setProceedHandler(h, proceedName);
54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Prepares to use $proceed().
54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void recordProceed(ProceedHandler h) {
55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        gen.setProceedHandler(h, proceedName);
55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Compiles a statement (or a block).
55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <code>recordParams()</code> must be called before invoking
55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * this method.
55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Local variables that are not declared
55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * in the compiled source text might not be accessible within that
56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * source text.  Fields and method parameters ($0, $1, ..) are available.
56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void compileStmnt(String src) throws CompileError {
56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Parser p = new Parser(new Lex(src));
56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        SymbolTable stb = new SymbolTable(stable);
56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (p.hasMore()) {
56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Stmnt s = p.parseStatement(stb);
56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (s != null)
56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                s.accept(gen);
56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Compiles an exression.  <code>recordParams()</code> must be
57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * called before invoking this method.
57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Local variables are not accessible
57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * within the compiled source text.  Fields and method parameters
57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * ($0, $1, ..) are available if <code>recordParams()</code>
57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * have been invoked.
58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void compileExpr(String src) throws CompileError {
58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ASTree e = parseExpr(src, stable);
58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        compileExpr(e);
58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Parsers an expression.
58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static ASTree parseExpr(String src, SymbolTable st)
59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Parser p = new Parser(new Lex(src));
59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return p.parseExpression(st);
59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Compiles an exression.  <code>recordParams()</code> must be
59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * called before invoking this method.
59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>Local variables are not accessible
60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * within the compiled source text.  Fields and method parameters
60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * ($0, $1, ..) are available if <code>recordParams()</code>
60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * have been invoked.
60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void compileExpr(ASTree e) throws CompileError {
60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (e != null)
60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            gen.compileExpr(e);
60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
610