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.expr;
1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.*;
1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.bytecode.*;
2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.*;
2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalimport javassist.compiler.ast.ASTList;
2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal/**
2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal * Expression for accessing a field.
2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal */
2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalpublic class FieldAccess extends Expr {
2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    int opcode;
2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    protected FieldAccess(int pos, CodeIterator i, CtClass declaring,
3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                          MethodInfo m, int op) {
3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        super(pos, i, declaring, m);
3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        opcode = op;
3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the method or constructor containing the field-access
3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * expression represented by this object.
3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtBehavior where() { return super.where(); }
4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the line number of the source line containing the
4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * field access.
4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return -1       if this information is not available.
4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public int getLineNumber() {
4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return super.getLineNumber();
4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the source file containing the field access.
5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @return null     if this information is not available.
5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getFileName() {
5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return super.getFileName();
5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if the field is static.
6269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isStatic() {
6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return isStatic(opcode);
6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static boolean isStatic(int c) {
6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return c == Opcode.GETSTATIC || c == Opcode.PUTSTATIC;
6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if the field is read.
7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isReader() {
7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return opcode == Opcode.GETFIELD || opcode ==  Opcode.GETSTATIC;
7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns true if the field is written in.
8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public boolean isWriter() {
8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return opcode == Opcode.PUTFIELD || opcode ==  Opcode.PUTSTATIC;
8369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the class in which the field is declared.
8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    private CtClass getCtClass() throws NotFoundException {
8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return thisClass.getClassPool().get(getClassName());
9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the name of the class in which the field is declared.
9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getClassName() {
9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = iterator.u16bitAt(currentPos + 1);
9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getConstPool().getFieldrefClassName(index);
9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the name of the field.
10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getFieldName() {
10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = iterator.u16bitAt(currentPos + 1);
10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getConstPool().getFieldrefName(index);
10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the field accessed by this expression.
11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtField getField() throws NotFoundException {
11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass cc = getCtClass();
11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return cc.getField(getFieldName());
11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the list of exceptions that the expression may throw.
11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * This list includes both the exceptions that the try-catch statements
11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * including the expression can catch and the exceptions that
12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the throws declaration allows the method to throw.
12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public CtClass[] mayThrow() {
12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return super.mayThrow();
12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Returns the signature of the field type.
12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * The signature is represented by a character string
12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * called field descriptor, which is defined in the JVM specification.
13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @see javassist.bytecode.Descriptor#toCtClass(String, ClassPool)
13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @since 3.1
13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public String getSignature() {
13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = iterator.u16bitAt(currentPos + 1);
13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        return getConstPool().getFieldrefType(index);
13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /**
14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * Replaces the method call with the bytecode derived from
14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * the given source text.
14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * <p>$0 is available even if the called method is static.
14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * If the field access is writing, $_ is available but the value
14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * of $_ is ignored.
14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *
14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     * @param statement         a Java statement except try-catch.
14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    public void replace(String statement) throws CannotCompileException {
15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        thisClass.getClassFile();   // to call checkModify().
15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ConstPool constPool = getConstPool();
15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int pos = currentPos;
15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int index = iterator.u16bitAt(pos + 1);
15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        Javac jc = new Javac(thisClass);
15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CodeAttribute ca = iterator.get();
15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        try {
15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass[] params;
15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass retType;
16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            CtClass fieldType
16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                = Descriptor.toCtClass(constPool.getFieldrefType(index),
16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                       thisClass.getClassPool());
16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean read = isReader();
16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (read) {
16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                params = new CtClass[0];
16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                retType = fieldType;
16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                params = new CtClass[1];
17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                params[0] = fieldType;
17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                retType = CtClass.voidType;
17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int paramVar = ca.getMaxLocals();
17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jc.recordParams(constPool.getFieldrefClassName(index), params,
17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                            true, paramVar, withinStatic());
17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            /* Is $_ included in the source code?
17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal             */
18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            boolean included = checkResultValue(retType, statement);
18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (read)
18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                included = true;
18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int retVar = jc.recordReturnType(retType, included);
18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (read)
18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                jc.recordProceed(new ProceedForRead(retType, opcode,
18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                    index, paramVar));
18869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
18969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                // because $type is not the return type...
19069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                jc.recordType(fieldType);
19169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                jc.recordProceed(new ProceedForWrite(params[0], opcode,
19269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                                                     index, paramVar));
19369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
19469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            Bytecode bytecode = jc.getBytecode();
19669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            storeStack(params, isStatic(), paramVar, bytecode);
19769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jc.recordLocalVariables(ca, pos);
19869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
19969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (included)
20069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                if (retType == CtClass.voidType) {
20169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    bytecode.addOpcode(ACONST_NULL);
20269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    bytecode.addAstore(retVar);
20369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
20469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                else {
20569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    bytecode.addConstZero(retType);
20669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                    bytecode.addStore(retVar, retType);     // initialize $_
20769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                }
20869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
20969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            jc.compileStmnt(statement);
21069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (read)
21169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addLoad(retVar, retType);
21269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
21369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            replace0(pos, bytecode, 3);
21469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
21569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (CompileError e) { throw new CannotCompileException(e); }
21669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (NotFoundException e) { throw new CannotCompileException(e); }
21769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        catch (BadBytecode e) {
21869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throw new CannotCompileException("broken method");
21969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
22069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
22169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* <field type> $proceed()
22369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
22469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class ProceedForRead implements ProceedHandler {
22569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass fieldType;
22669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int opcode;
22769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int targetVar, index;
22869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
22969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ProceedForRead(CtClass type, int op, int i, int var) {
23069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            fieldType = type;
23169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            targetVar = var;
23269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            opcode = op;
23369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            index = i;
23469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
23569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
23669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
23769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws CompileError
23869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
23969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (args != null && !gen.isParamListName(args))
24069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError(Javac.proceedName
24169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        + "() cannot take a parameter for field reading");
24269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
24369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int stack;
24469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (isStatic(opcode))
24569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stack = 0;
24669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
24769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stack = -1;
24869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addAload(targetVar);
24969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
25069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (fieldType instanceof CtPrimitiveType)
25269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stack += ((CtPrimitiveType)fieldType).getDataSize();
25369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
25469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                ++stack;
25569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
25669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.add(opcode);
25769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addIndex(index);
25869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.growStack(stack);
25969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            gen.setType(fieldType);
26069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
26169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void setReturnType(JvstTypeChecker c, ASTList args)
26369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws CompileError
26469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
26569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            c.setType(fieldType);
26669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
26769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
26869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
26969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    /* void $proceed(<field type>)
27069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     *          the return type is not the field type but void.
27169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal     */
27269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    static class ProceedForWrite implements ProceedHandler {
27369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        CtClass fieldType;
27469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int opcode;
27569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        int targetVar, index;
27669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
27769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        ProceedForWrite(CtClass type, int op, int i, int var) {
27869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            fieldType = type;
27969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            targetVar = var;
28069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            opcode = op;
28169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            index = i;
28269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
28369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
28469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void doit(JvstCodeGen gen, Bytecode bytecode, ASTList args)
28569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws CompileError
28669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
28769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (gen.getMethodArgsLength(args) != 1)
28869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                throw new CompileError(Javac.proceedName
28969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        + "() cannot take more than one parameter "
29069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                        + "for field writing");
29169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
29269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            int stack;
29369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (isStatic(opcode))
29469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stack = 0;
29569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else {
29669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stack = -1;
29769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                bytecode.addAload(targetVar);
29869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            }
29969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            gen.atMethodArgs(args, new int[1], new int[1], new String[1]);
30169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            gen.doNumCast(fieldType);
30269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            if (fieldType instanceof CtPrimitiveType)
30369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                stack -= ((CtPrimitiveType)fieldType).getDataSize();
30469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            else
30569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal                --stack;
30669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
30769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.add(opcode);
30869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.addIndex(index);
30969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            bytecode.growStack(stack);
31069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            gen.setType(CtClass.voidType);
31169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            gen.addNullIfVoid();
31269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
31369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal
31469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        public void setReturnType(JvstTypeChecker c, ASTList args)
31569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            throws CompileError
31669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        {
31769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            c.atMethodArgs(args, new int[1], new int[1], new String[1]);
31869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            c.setType(CtClass.voidType);
31969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal            c.addNullIfVoid();
32069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal        }
32169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal    }
32269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}
323