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.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.ast.*;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/* Code generator accepting extended Java syntax for Javassist.
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class JvstCodeGen extends MemberCodeGen {
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String paramArrayName = null;
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String paramListName = null;
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    CtClass[] paramTypeList = null;
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int paramVarBase = 0;       // variable index for $0 or $1.
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private boolean useParam0 = false;  // true if $0 is used.
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private String param0Type = null;   // JVM name
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String sigName = "$sig";
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String dollarTypeName = "$type";
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String clazzName = "$class";
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private CtClass dollarType = null;
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    CtClass returnType = null;
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String returnCastName = null;
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private String returnVarName = null;        // null if $_ is not used.
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String wrapperCastName = "$w";
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    String proceedName = null;
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static final String cflowName = "$cflow";
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    ProceedHandler procHandler = null;  // null if not used.
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public JvstCodeGen(Bytecode b, CtClass cc, ClassPool cp) {
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(b, cc, cp);
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setTypeChecker(new JvstTypeChecker(cc, cp, this));
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* Index of $1.
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int indexOfParam1() {
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return paramVarBase + (useParam0 ? 1 : 0);
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* Records a ProceedHandler obejct.
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param name      the name of the special method call.
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  it is usually $proceed.
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setProceedHandler(ProceedHandler h, String name) {
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        proceedName = name;
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        procHandler = h;
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* If the type of the expression compiled last is void,
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * add ACONST_NULL and change exprType, arrayDim, className.
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void addNullIfVoid() {
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (exprType == VOID) {
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addOpcode(ACONST_NULL);
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = CLASS;
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = 0;
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = jvmJavaLangObject;
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* To support $args, $sig, and $type.
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * $args is an array of parameter list.
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void atMember(Member mem) throws CompileError {
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name = mem.get();
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (name.equals(paramArrayName)) {
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            compileParameterList(bytecode, paramTypeList, indexOfParam1());
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = CLASS;
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = 1;
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = jvmJavaLangObject;
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (name.equals(sigName)) {
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addLdc(Descriptor.ofMethod(returnType, paramTypeList));
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addInvokestatic("javassist/runtime/Desc", "getParams",
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                "(Ljava/lang/String;)[Ljava/lang/Class;");
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = CLASS;
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = 1;
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = "java/lang/Class";
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (name.equals(dollarTypeName)) {
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (dollarType == null)
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError(dollarTypeName + " is not available");
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addLdc(Descriptor.of(dollarType));
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            callGetType("getType");
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (name.equals(clazzName)) {
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (param0Type == null)
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError(clazzName + " is not available");
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addLdc(param0Type);
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            callGetType("getClazz");
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super.atMember(mem);
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void callGetType(String method) {
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bytecode.addInvokestatic("javassist/runtime/Desc", method,
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                "(Ljava/lang/String;)Ljava/lang/Class;");
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        exprType = CLASS;
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        arrayDim = 0;
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        className = "java/lang/Class";
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void atFieldAssign(Expr expr, int op, ASTree left,
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        ASTree right, boolean doDup) throws CompileError
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (left instanceof Member
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            && ((Member)left).get().equals(paramArrayName)) {
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (op != '=')
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError("bad operator for " + paramArrayName);
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            right.accept(this);
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (arrayDim != 1 || exprType != CLASS)
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError("invalid type for " + paramArrayName);
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            atAssignParamList(paramTypeList, bytecode);
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (!doDup)
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addOpcode(POP);
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super.atFieldAssign(expr, op, left, right, doDup);
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void atAssignParamList(CtClass[] params, Bytecode code)
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (params == null)
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int varNo = indexOfParam1();
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = params.length;
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addOpcode(DUP);
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addIconst(i);
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addOpcode(AALOAD);
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            compileUnwrapValue(params[i], code);
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addStore(varNo, params[i]);
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            varNo += is2word(exprType, arrayDim) ? 2 : 1;
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void atCastExpr(CastExpr expr) throws CompileError {
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ASTList classname = expr.getClassName();
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (classname != null && expr.getArrayDim() == 0) {
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ASTree p = classname.head();
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (p instanceof Symbol && classname.tail() == null) {
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                String typename = ((Symbol)p).get();
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (typename.equals(returnCastName)) {
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    atCastToRtype(expr);
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return;
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else if (typename.equals(wrapperCastName)) {
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    atCastToWrapper(expr);
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    return;
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super.atCastExpr(expr);
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Inserts a cast operator to the return type.
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the return type is void, this does nothing.
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void atCastToRtype(CastExpr expr) throws CompileError {
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        expr.getOprand().accept(this);
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (exprType == VOID || isRefType(exprType) || arrayDim > 0)
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            compileUnwrapValue(returnType, bytecode);
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (returnType instanceof CtPrimitiveType) {
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtPrimitiveType pt = (CtPrimitiveType)returnType;
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int destType = MemberResolver.descToType(pt.getDescriptor());
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            atNumCastExpr(exprType, destType);
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = destType;
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = 0;
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = null;
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError("invalid cast");
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void atCastToWrapper(CastExpr expr) throws CompileError {
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        expr.getOprand().accept(this);
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (isRefType(exprType) || arrayDim > 0)
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;     // Object type.  do nothing.
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass clazz = resolver.lookupClass(exprType, arrayDim, className);
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (clazz instanceof CtPrimitiveType) {
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtPrimitiveType pt = (CtPrimitiveType)clazz;
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String wrapper = pt.getWrapperName();
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addNew(wrapper);           // new <wrapper>
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addOpcode(DUP);            // dup
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (pt.getDataSize() > 1)
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addOpcode(DUP2_X2);    // dup2_x2
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addOpcode(DUP2_X1);    // dup2_x1
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addOpcode(POP2);           // pop2
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addInvokespecial(wrapper, "<init>",
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                      "(" + pt.getDescriptor() + ")V");
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                // invokespecial
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = CLASS;
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = 0;
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = jvmJavaLangObject;
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* Delegates to a ProcHandler object if the method call is
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * $proceed().  It may process $cflow().
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void atCallExpr(CallExpr expr) throws CompileError {
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ASTree method = expr.oprand1();
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (method instanceof Member) {
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String name = ((Member)method).get();
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (procHandler != null && name.equals(proceedName)) {
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                procHandler.doit(this, bytecode, (ASTList)expr.oprand2());
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (name.equals(cflowName)) {
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                atCflow((ASTList)expr.oprand2());
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super.atCallExpr(expr);
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* To support $cflow().
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void atCflow(ASTList cname) throws CompileError {
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        StringBuffer sbuf = new StringBuffer();
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (cname == null || cname.tail() != null)
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError("bad " + cflowName);
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        makeCflowName(sbuf, cname.head());
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String name = sbuf.toString();
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Object[] names = resolver.getClassPool().lookupCflow(name);
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (names == null)
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError("no such " + cflowName + ": " + name);
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bytecode.addGetstatic((String)names[0], (String)names[1],
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              "Ljavassist/runtime/Cflow;");
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bytecode.addInvokevirtual("javassist.runtime.Cflow",
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  "value", "()I");
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        exprType = INT;
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        arrayDim = 0;
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        className = null;
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* Syntax:
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <cflow> : $cflow '(' <cflow name> ')'
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <cflow name> : <identifier> ('.' <identifier>)*
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private static void makeCflowName(StringBuffer sbuf, ASTree name)
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (name instanceof Symbol) {
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            sbuf.append(((Symbol)name).get());
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (name instanceof Expr) {
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Expr expr = (Expr)name;
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (expr.getOperator() == '.') {
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                makeCflowName(sbuf, expr.oprand1());
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                sbuf.append('.');
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                makeCflowName(sbuf, expr.oprand2());
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                return;
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throw new CompileError("bad " + cflowName);
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* To support $$.  ($$) is equivalent to ($1, ..., $n).
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It can be used only as a parameter list of method call.
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isParamListName(ASTList args) {
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (paramTypeList != null
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            && args != null && args.tail() == null) {
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ASTree left = args.head();
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return (left instanceof Member
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    && ((Member)left).get().equals(paramListName));
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return false;
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /*
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getMethodArgsLength(ASTList args) {
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!isParamListName(args))
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return super.getMethodArgsLength(args);
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return paramTypeList.length;
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    */
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getMethodArgsLength(ASTList args) {
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String pname = paramListName;
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = 0;
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (args != null) {
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ASTree a = args.head();
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (a instanceof Member && ((Member)a).get().equals(pname)) {
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (paramTypeList != null)
32369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    n += paramTypeList.length;
32469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
32569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
32669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ++n;
32769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
32869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            args = args.tail();
32969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
33069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return n;
33269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
33369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
33469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void atMethodArgs(ASTList args, int[] types, int[] dims,
33569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                String[] cnames) throws CompileError {
33669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass[] params = paramTypeList;
33769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String pname = paramListName;
33869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int i = 0;
33969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while (args != null) {
34069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ASTree a = args.head();
34169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (a instanceof Member && ((Member)a).get().equals(pname)) {
34269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (params != null) {
34369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int n = params.length;
34469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int regno = indexOfParam1();
34569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    for (int k = 0; k < n; ++k) {
34669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        CtClass p = params[k];
34769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        regno += bytecode.addLoad(regno, p);
34869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        setType(p);
34969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        types[i] = exprType;
35069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        dims[i] = arrayDim;
35169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        cnames[i] = className;
35269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        ++i;
35369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    }
35469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
35569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
35669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
35769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                a.accept(this);
35869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                types[i] = exprType;
35969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                dims[i] = arrayDim;
36069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cnames[i] = className;
36169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ++i;
36269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
36369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            args = args.tail();
36569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
36669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
36769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
36869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /*
36969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void atMethodArgs(ASTList args, int[] types, int[] dims,
37069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                String[] cnames) throws CompileError {
37169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (!isParamListName(args)) {
37269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            super.atMethodArgs(args, types, dims, cnames);
37369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
37469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
37569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
37669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass[] params = paramTypeList;
37769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (params == null)
37869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
37969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
38069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int n = params.length;
38169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int regno = indexOfParam1();
38269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < n; ++i) {
38369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass p = params[i];
38469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            regno += bytecode.addLoad(regno, p);
38569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            setType(p);
38669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            types[i] = exprType;
38769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            dims[i] = arrayDim;
38869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            cnames[i] = className;
38969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
39069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
39169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    */
39269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
39369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* called by Javac#recordSpecialProceed().
39469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
39569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    void compileInvokeSpecial(ASTree target, String classname,
39669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              String methodname, String descriptor,
39769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              ASTList args)
39869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
39969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
40069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        target.accept(this);
40169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int nargs = getMethodArgsLength(args);
40269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        atMethodArgs(args, new int[nargs], new int[nargs],
40369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                     new String[nargs]);
40469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        bytecode.addInvokespecial(classname, methodname, descriptor);
40569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setReturnType(descriptor, false, false);
40669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        addNullIfVoid();
40769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
40869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
40969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /*
41069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes it valid to write "return <expr>;" for a void method.
41169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
41269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void atReturnStmnt(Stmnt st) throws CompileError {
41369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ASTree result = st.getLeft();
41469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (result != null && returnType == CtClass.voidType) {
41569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            compileExpr(result);
41669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (is2word(exprType, arrayDim))
41769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addOpcode(POP2);
41869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else if (exprType != VOID)
41969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addOpcode(POP);
42069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            result = null;
42269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
42369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        atReturnStmnt2(result);
42569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
42669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
42769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
42869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes a cast to the return type ($r) available.
42969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * It also enables $_.
43069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
43169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>If the return type is void, ($r) does nothing.
43269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The type of $_ is java.lang.Object.
43369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
43469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param resultName        null if $_ is not used.
43569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return          -1 or the variable index assigned to $_.
43669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
43769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordReturnType(CtClass type, String castName,
43869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                 String resultName, SymbolTable tbl) throws CompileError
43969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
44069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        returnType = type;
44169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        returnCastName = castName;
44269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        returnVarName = resultName;
44369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (resultName == null)
44469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return -1;
44569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
44669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int varNo = getMaxLocals();
44769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int locals = varNo + recordVar(type, resultName, varNo, tbl);
44869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            setMaxLocals(locals);
44969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return varNo;
45069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
45169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
45269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
45369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
45469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes $type available.
45569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
45669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void recordType(CtClass t) {
45769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        dollarType = t;
45869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
45969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
46069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
46169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes method parameters $0, $1, ..., $args, $$, and $class available.
46269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * $0 is equivalent to THIS if the method is not static.  Otherwise,
46369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * if the method is static, then $0 is not available.
46469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
46569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordParams(CtClass[] params, boolean isStatic,
46669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                             String prefix, String paramVarName,
46769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                             String paramsName, SymbolTable tbl)
46869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
46969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
47069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return recordParams(params, isStatic, prefix, paramVarName,
47169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            paramsName, !isStatic, 0, getThisName(), tbl);
47269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
47369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
47469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
47569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes method parameters $0, $1, ..., $args, $$, and $class available.
47669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * $0 is available only if use0 is true.  It might not be equivalent
47769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * to THIS.
47869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
47969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param params    the parameter types (the types of $1, $2, ..)
48069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param prefix    it must be "$" (the first letter of $0, $1, ...)
48169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param paramVarName      it must be "$args"
48269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param paramsName        it must be "$$"
48369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param use0      true if $0 is used.
48469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param paramBase the register number of $0 (use0 is true)
48569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                          or $1 (otherwise).
48669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param target    the class of $0.  If use0 is false, target
48769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  can be null.  The value of "target" is also used
48869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  as the name of the type represented by $class.
48969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param isStatic  true if the method in which the compiled bytecode
49069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  is embedded is static.
49169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
49269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordParams(CtClass[] params, boolean isStatic,
49369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            String prefix, String paramVarName,
49469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            String paramsName, boolean use0,
49569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            int paramBase, String target,
49669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            SymbolTable tbl)
49769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
49869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
49969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int varNo;
50069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        paramTypeList = params;
50269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        paramArrayName = paramVarName;
50369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        paramListName = paramsName;
50469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        paramVarBase = paramBase;
50569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        useParam0 = use0;
50669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
50769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (target != null)
50869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            param0Type = MemberResolver.jvmToJavaName(target);
50969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
51069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        inStaticMethod = isStatic;
51169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        varNo = paramBase;
51269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (use0) {
51369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String varName = prefix + "0";
51469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Declarator decl
51569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                = new Declarator(CLASS, MemberResolver.javaToJvmName(target),
51669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                 0, varNo++, new Symbol(varName));
51769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            tbl.append(varName, decl);
51869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
51969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        for (int i = 0; i < params.length; ++i)
52169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            varNo += recordVar(params[i], prefix + (i + 1), varNo, tbl);
52269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (getMaxLocals() < varNo)
52469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            setMaxLocals(varNo);
52569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return varNo;
52769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
52869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
52969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
53069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes the given variable name available.
53169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
53269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param type      variable type
53369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param varName   variable name
53469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
53569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int recordVariable(CtClass type, String varName, SymbolTable tbl)
53669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
53769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
53869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (varName == null)
53969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return -1;
54069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
54169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int varNo = getMaxLocals();
54269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int locals = varNo + recordVar(type, varName, varNo, tbl);
54369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            setMaxLocals(locals);
54469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return varNo;
54569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
54669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
54769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
54869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private int recordVar(CtClass cc, String varName, int varNo,
54969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                          SymbolTable tbl) throws CompileError
55069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
55169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (cc == CtClass.voidType) {
55269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = CLASS;
55369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = 0;
55469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = jvmJavaLangObject;
55569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
55669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else
55769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            setType(cc);
55869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
55969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Declarator decl
56069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = new Declarator(exprType, className, arrayDim,
56169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                             varNo, new Symbol(varName));
56269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        tbl.append(varName, decl);
56369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return is2word(exprType, arrayDim) ? 2 : 1;
56469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
56569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
56669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
56769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Makes the given variable name available.
56869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
56969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param typeDesc  the type descriptor of the variable
57069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param varName   variable name
57169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param varNo     an index into the local variable array
57269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
57369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void recordVariable(String typeDesc, String varName, int varNo,
57469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                               SymbolTable tbl) throws CompileError
57569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
57669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        char c;
57769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int dim = 0;
57869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        while ((c = typeDesc.charAt(dim)) == '[')
57969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            ++dim;
58069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
58169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int type = MemberResolver.descToType(c);
58269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        String cname = null;
58369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type == CLASS) {
58469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (dim == 0)
58569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cname = typeDesc.substring(1, typeDesc.length() - 1);
58669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
58769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                cname = typeDesc.substring(dim + 1, typeDesc.length() - 1);
58869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
58969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Declarator decl
59169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            = new Declarator(type, cname, dim, varNo, new Symbol(varName));
59269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        tbl.append(varName, decl);
59369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
59469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
59569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* compileParameterList() returns the stack size used
59669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * by the produced code.
59769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
59869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This method correctly computes the max_stack value.
59969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
60069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param regno     the index of the local variable in which
60169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  the first argument is received.
60269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *                  (0: static method, 1: regular method.)
60369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
60469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public static int compileParameterList(Bytecode code,
60569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                CtClass[] params, int regno) {
60669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (params == null) {
60769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addIconst(0);                          // iconst_0
60869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addAnewarray(javaLangObject);          // anewarray Object
60969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 1;
61069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
61169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
61269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass[] args = new CtClass[1];
61369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int n = params.length;
61469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addIconst(n);                          // iconst_<n>
61569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addAnewarray(javaLangObject);          // anewarray Object
61669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            for (int i = 0; i < n; ++i) {
61769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                code.addOpcode(Bytecode.DUP);           // dup
61869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                code.addIconst(i);                      // iconst_<i>
61969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (params[i].isPrimitive()) {
62069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    CtPrimitiveType pt = (CtPrimitiveType)params[i];
62169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    String wrapper = pt.getWrapperName();
62269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    code.addNew(wrapper);               // new <wrapper>
62369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    code.addOpcode(Bytecode.DUP);       // dup
62469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    int s = code.addLoad(regno, pt);    // ?load <regno>
62569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    regno += s;
62669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    args[0] = pt;
62769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    code.addInvokespecial(wrapper, "<init>",
62869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                Descriptor.ofMethod(CtClass.voidType, args));
62969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                        // invokespecial
63069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
63169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else {
63269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    code.addAload(regno);               // aload <regno>
63369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    ++regno;
63469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
63569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
63669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                code.addOpcode(Bytecode.AASTORE);       // aastore
63769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
63869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
63969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return 8;
64069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
64169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
64269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
64369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected void compileUnwrapValue(CtClass type, Bytecode code)
64469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        throws CompileError
64569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    {
64669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type == CtClass.voidType) {
64769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            addNullIfVoid();
64869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            return;
64969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
65069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
65169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (exprType == VOID)
65269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CompileError("invalid type for " + returnCastName);
65369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
65469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type instanceof CtPrimitiveType) {
65569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtPrimitiveType pt = (CtPrimitiveType)type;
65669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            // pt is not voidType.
65769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            String wrapper = pt.getWrapperName();
65869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addCheckcast(wrapper);
65969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addInvokevirtual(wrapper, pt.getGetMethodName(),
66069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                  pt.getGetMethodDescriptor());
66169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            setType(type);
66269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
66369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
66469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            code.addCheckcast(type);
66569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            setType(type);
66669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
66769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
66869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
66969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* Sets exprType, arrayDim, and className;
67069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If type is void, then this method does nothing.
67169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
67269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void setType(CtClass type) throws CompileError {
67369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        setType(type, 0);
67469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
67569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
67669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private void setType(CtClass type, int dim) throws CompileError {
67769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (type.isPrimitive()) {
67869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtPrimitiveType pt = (CtPrimitiveType)type;
67969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = MemberResolver.descToType(pt.getDescriptor());
68069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = dim;
68169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = null;
68269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
68369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else if (type.isArray())
68469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            try {
68569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                setType(type.getComponentType(), dim + 1);
68669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
68769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            catch (NotFoundException e) {
68869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError("undefined type: " + type.getName());
68969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
69069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        else {
69169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            exprType = CLASS;
69269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            arrayDim = dim;
69369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            className = MemberResolver.javaToJvmName(type.getName());
69469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
69569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
69669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
69769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* Performs implicit coercion from exprType to type.
69869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
69969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void doNumCast(CtClass type) throws CompileError {
70069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        if (arrayDim == 0 && !isRefType(exprType))
70169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (type instanceof CtPrimitiveType) {
70269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                CtPrimitiveType pt = (CtPrimitiveType)type;
70369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                atNumCastExpr(exprType,
70469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                              MemberResolver.descToType(pt.getDescriptor()));
70569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
70669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
70769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError("type mismatch");
70869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
70969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
710