com.feilong.lib.javassist.CtClass

Here are the examples of the java api com.feilong.lib.javassist.CtClass taken from open source projects. By voting up you can indicate which examples are most useful and appropriate.

167 Examples 7

19 Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong

/**
 * Convert a javreplacedist clreplaced to a java clreplaced
 *
 * @param ct
 *            the javreplacedist clreplaced
 * @param loader
 *            the loader
 * @throws CannotCompileException
 *             for any error
 */
@Override
public Clreplaced<?> toClreplaced(CtClreplaced ct, ClreplacedLoader loader, ProtectionDomain domain) throws CannotCompileException {
    // We need to preplaced up the clreplacedloader stored in this pool, as the
    // default implementation uses the Thread context cl.
    // In the case of JSP's in Tomcat,
    // org.apache.jasper.servlet.JasperLoader will be stored here, while
    // it's parent
    // org.jboss.web.tomcat.tc5.WebCtxLoader$ENCLoader is used as the Thread
    // context cl. The invocation clreplaced needs to
    // be generated in the JasperLoader clreplacedloader since in the case of
    // method invocations, the package name will be
    // the same as for the clreplaced generated from the jsp, i.e.
    // org.apache.jsp. For clreplacedes belonging to org.apache.jsp,
    // JasperLoader does NOT delegate to its parent if it cannot find them.
    lockInCache(ct);
    return super.toClreplaced(ct, getClreplacedLoader0(), domain);
}

19 Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong

/**
 * Whether the clreplaced is cached in this pooled
 *
 * @param clreplacedname
 *            the clreplaced name
 * @return the cached clreplaced
 */
protected CtClreplaced getCachedLocally(String clreplacedname) {
    CtClreplaced cached = (CtClreplaced) clreplacedes.get(clreplacedname);
    if (cached != null) {
        return cached;
    }
    synchronized (softcache) {
        return softcache.get(clreplacedname);
    }
}

19 Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong

/**
 * Lock a clreplaced into the cache
 *
 * @param c
 *            the clreplaced
 */
public void lockInCache(CtClreplaced c) {
    super.cacheCtClreplaced(c.getName(), c, false);
}

19 Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong

/**
 * Get the cached clreplaced
 *
 * @param clreplacedname
 *            the clreplaced name
 * @return the clreplaced
 */
@Override
protected CtClreplaced getCached(String clreplacedname) {
    CtClreplaced clazz = getCachedLocally(clreplacedname);
    if (clazz == null) {
        boolean isLocal = false;
        ClreplacedLoader dcl = getClreplacedLoader0();
        if (dcl != null) {
            final int lastIndex = clreplacedname.lastIndexOf('$');
            String clreplacedResourceName = null;
            if (lastIndex < 0) {
                clreplacedResourceName = clreplacedname.replaceAll("[\\.]", "/") + ".clreplaced";
            } else {
                clreplacedResourceName = clreplacedname.substring(0, lastIndex).replaceAll("[\\.]", "/") + clreplacedname.substring(lastIndex) + ".clreplaced";
            }
            isLocal = dcl.getResource(clreplacedResourceName) != null;
        }
        if (!isLocal) {
            Map<ClreplacedLoader, ScopedClreplacedPool> registeredCLs = repository.getRegisteredCLs();
            synchronized (registeredCLs) {
                for (ScopedClreplacedPool pool : registeredCLs.values()) {
                    if (pool.isUnloadedClreplacedLoader()) {
                        repository.unregisterClreplacedLoader(pool.getClreplacedLoader());
                        continue;
                    }
                    clazz = pool.getCachedLocally(clreplacedname);
                    if (clazz != null) {
                        return clazz;
                    }
                }
            }
        }
    }
    // *NOTE* NEED TO TEST WHEN SUPERCLreplaced IS IN ANOTHER UCL!!!!!!
    return clazz;
}

19 Source : ScopedClassPool.java
with Apache License 2.0
from ifeilong

/**
 * Get any local copy of the clreplaced
 *
 * @param clreplacedname
 *            the clreplaced name
 * @return the clreplaced
 * @throws NotFoundException
 *             when the clreplaced is not found
 */
public synchronized CtClreplaced getLocally(String clreplacedname) throws NotFoundException {
    softcache.remove(clreplacedname);
    CtClreplaced clazz = (CtClreplaced) clreplacedes.get(clreplacedname);
    if (clazz == null) {
        clazz = createCtClreplaced(clreplacedname, true);
        if (clazz == null) {
            throw new NotFoundException(clreplacedname);
        }
        super.cacheCtClreplaced(clreplacedname, clazz, false);
    }
    return clazz;
}

19 Source : ExprEditor.java
with Apache License 2.0
from ifeilong

/**
 * Visits each bytecode in the given range.
 */
boolean doit(CtClreplaced clazz, MethodInfo minfo, LoopContext context, CodeIterator iterator, int endPos) throws CannotCompileException {
    boolean edited = false;
    while (iterator.hasNext() && iterator.lookAhead() < endPos) {
        int size = iterator.getCodeLength();
        if (loopBody(iterator, clazz, minfo, context)) {
            edited = true;
            int size2 = iterator.getCodeLength();
            if (size != size2) {
                endPos += size2 - size;
            }
        }
    }
    return edited;
}

19 Source : Expr.java
with Apache License 2.0
from ifeilong

/**
 * Expression.
 */
public abstract clreplaced Expr implements Opcode {

    int currentPos;

    CodeIterator iterator;

    CtClreplaced thisClreplaced;

    MethodInfo thisMethod;

    boolean edited;

    int maxLocals, maxStack;

    static final String javaLangObject = "java.lang.Object";

    /**
     * Undoreplacedented constructor. Do not use; internal-use only.
     */
    protected Expr(int pos, CodeIterator i, CtClreplaced declaring, MethodInfo m) {
        currentPos = pos;
        iterator = i;
        thisClreplaced = declaring;
        thisMethod = m;
    }

    /**
     * Returns the clreplaced that declares the method enclosing
     * this expression.
     *
     * @since 3.7
     */
    public CtClreplaced getEnclosingClreplaced() {
        return thisClreplaced;
    }

    protected final ConstPool getConstPool() {
        return thisMethod.getConstPool();
    }

    protected final boolean edited() {
        return edited;
    }

    protected final int locals() {
        return maxLocals;
    }

    protected final int stack() {
        return maxStack;
    }

    /**
     * Returns true if this method is static.
     */
    protected final boolean withinStatic() {
        return (thisMethod.getAccessFlags() & AccessFlag.STATIC) != 0;
    }

    /**
     * Returns the constructor or method containing the expression.
     */
    public CtBehavior where() {
        MethodInfo mi = thisMethod;
        CtBehavior[] cb = thisClreplaced.getDeclaredBehaviors();
        for (int i = cb.length - 1; i >= 0; --i) {
            if (cb[i].getMethodInfo2() == mi) {
                return cb[i];
            }
        }
        CtConstructor init = thisClreplaced.getClreplacedInitializer();
        if (init != null && init.getMethodInfo2() == mi) {
            return init;
        }
        /*
         * getDeclaredBehaviors() returns a list of methods/constructors.
         * Although the list is cached in a CtClreplaced object, it might be
         * recreated for some reason. Thus, the member name and the signature
         * must be also checked.
         */
        for (int i = cb.length - 1; i >= 0; --i) {
            if (thisMethod.getName().equals(cb[i].getMethodInfo2().getName()) && thisMethod.getDescriptor().equals(cb[i].getMethodInfo2().getDescriptor())) {
                return cb[i];
            }
        }
        throw new RuntimeException("fatal: not found");
    }

    /**
     * Returns the list of exceptions that the expression may throw. This list
     * includes both the exceptions that the try-catch statements including the
     * expression can catch and the exceptions that the throws declaration
     * allows the method to throw.
     */
    public CtClreplaced[] mayThrow() {
        ClreplacedPool pool = thisClreplaced.getClreplacedPool();
        ConstPool cp = thisMethod.getConstPool();
        List<CtClreplaced> list = new LinkedList<>();
        try {
            CodeAttribute ca = thisMethod.getCodeAttribute();
            ExceptionTable et = ca.getExceptionTable();
            int pos = currentPos;
            int n = et.size();
            for (int i = 0; i < n; ++i) {
                if (et.startPc(i) <= pos && pos < et.endPc(i)) {
                    int t = et.catchType(i);
                    if (t > 0) {
                        try {
                            addClreplaced(list, pool.get(cp.getClreplacedInfo(t)));
                        } catch (NotFoundException e) {
                        }
                    }
                }
            }
        } catch (NullPointerException e) {
        }
        ExceptionsAttribute ea = thisMethod.getExceptionsAttribute();
        if (ea != null) {
            String[] exceptions = ea.getExceptions();
            if (exceptions != null) {
                int n = exceptions.length;
                for (int i = 0; i < n; ++i) {
                    try {
                        addClreplaced(list, pool.get(exceptions[i]));
                    } catch (NotFoundException e) {
                    }
                }
            }
        }
        return list.toArray(new CtClreplaced[list.size()]);
    }

    private static void addClreplaced(List<CtClreplaced> list, CtClreplaced c) {
        if (list.contains(c)) {
            return;
        }
        list.add(c);
    }

    /**
     * Returns the index of the bytecode corresponding to the expression. It is
     * the index into the byte array containing the Java bytecode that
     * implements the method.
     */
    public int indexOfBytecode() {
        return currentPos;
    }

    /**
     * Returns the line number of the source line containing the expression.
     *
     * @return -1 if this information is not available.
     */
    public int getLineNumber() {
        return thisMethod.getLineNumber(currentPos);
    }

    /**
     * Returns the source file containing the expression.
     *
     * @return null if this information is not available.
     */
    public String getFileName() {
        ClreplacedFile cf = thisClreplaced.getClreplacedFile2();
        if (cf == null) {
            return null;
        }
        return cf.getSourceFile();
    }

    static final boolean checkResultValue(CtClreplaced retType, String prog) throws CannotCompileException {
        /*
         * Is $_ included in the source code?
         */
        boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
        if (!hasIt && retType != CtClreplaced.voidType) {
            throw new CannotCompileException("the resulting value is not stored in " + Javac.resultVarName);
        }
        return hasIt;
    }

    /*
     * If isStaticCall is true, null is replacedigned to $0. So $0 must be declared
     * by calling Javac.recordParams().
     * 
     * After executing this method, the current stack depth might be less than
     * 0.
     */
    static final void storeStack(CtClreplaced[] params, boolean isStaticCall, int regno, Bytecode bytecode) {
        storeStack0(0, params.length, params, regno + 1, bytecode);
        if (isStaticCall) {
            bytecode.addOpcode(ACONST_NULL);
        }
        bytecode.addAstore(regno);
    }

    private static void storeStack0(int i, int n, CtClreplaced[] params, int regno, Bytecode bytecode) {
        if (i >= n) {
            return;
        }
        CtClreplaced c = params[i];
        int size;
        if (c instanceof CtPrimitiveType) {
            size = ((CtPrimitiveType) c).getDataSize();
        } else {
            size = 1;
        }
        storeStack0(i + 1, n, params, regno + size, bytecode);
        bytecode.addStore(regno, c);
    }

    // The implementation of replace() should call thisClreplaced.checkModify()
    // so that isModify() will return true.  Otherwise, thisClreplaced.clreplacedfile
    // might be released during compilation and the compiler might generate
    // bytecode with a wrong copy of ConstPool.
    /**
     * Replaces this expression with the bytecode derived from
     * the given source text.
     *
     * @param statement
     *            a Java statement except try-catch.
     */
    public abstract void replace(String statement) throws CannotCompileException;

    /**
     * Replaces this expression with the bytecode derived from
     * the given source text and <code>ExprEditor</code>.
     *
     * @param statement
     *            a Java statement except try-catch.
     * @param recursive
     *            if not null, the subsreplaceduted bytecode
     *            is recursively processed by the given
     *            <code>ExprEditor</code>.
     * @since 3.1
     */
    public void replace(String statement, ExprEditor recursive) throws CannotCompileException {
        replace(statement);
        if (recursive != null) {
            runEditor(recursive, iterator);
        }
    }

    protected void replace0(int pos, Bytecode bytecode, int size) throws BadBytecode {
        byte[] code = bytecode.get();
        edited = true;
        int gap = code.length - size;
        for (int i = 0; i < size; ++i) {
            iterator.writeByte(NOP, pos + i);
        }
        if (gap > 0) {
            pos = iterator.insertGapAt(pos, gap, false).position;
        }
        iterator.write(code, pos);
        iterator.insert(bytecode.getExceptionTable(), pos);
        maxLocals = bytecode.getMaxLocals();
        maxStack = bytecode.getMaxStack();
    }

    protected void runEditor(ExprEditor ed, CodeIterator oldIterator) throws CannotCompileException {
        CodeAttribute codeAttr = oldIterator.get();
        int orgLocals = codeAttr.getMaxLocals();
        int orgStack = codeAttr.getMaxStack();
        int newLocals = locals();
        codeAttr.setMaxStack(stack());
        codeAttr.setMaxLocals(newLocals);
        ExprEditor.LoopContext context = new ExprEditor.LoopContext(newLocals);
        int size = oldIterator.getCodeLength();
        int endPos = oldIterator.lookAhead();
        oldIterator.move(currentPos);
        if (ed.doit(thisClreplaced, thisMethod, context, oldIterator, endPos)) {
            edited = true;
        }
        oldIterator.move(endPos + oldIterator.getCodeLength() - size);
        codeAttr.setMaxLocals(orgLocals);
        codeAttr.setMaxStack(orgStack);
        maxLocals = context.maxLocals;
        maxStack += context.maxStack;
    }
}

19 Source : Expr.java
with Apache License 2.0
from ifeilong

private static void addClreplaced(List<CtClreplaced> list, CtClreplaced c) {
    if (list.contains(c)) {
        return;
    }
    list.add(c);
}

19 Source : Expr.java
with Apache License 2.0
from ifeilong

static final boolean checkResultValue(CtClreplaced retType, String prog) throws CannotCompileException {
    /*
         * Is $_ included in the source code?
         */
    boolean hasIt = (prog.indexOf(Javac.resultVarName) >= 0);
    if (!hasIt && retType != CtClreplaced.voidType) {
        throw new CannotCompileException("the resulting value is not stored in " + Javac.resultVarName);
    }
    return hasIt;
}

19 Source : TransformReadField.java
with Apache License 2.0
from ifeilong

public clreplaced TransformReadField extends Transformer {

    protected String fieldname;

    protected CtClreplaced fieldClreplaced;

    protected boolean isPrivate;

    protected String methodClreplacedname, methodName;

    public TransformReadField(Transformer next, CtField field, String methodClreplacedname, String methodName) {
        super(next);
        this.fieldClreplaced = field.getDeclaringClreplaced();
        this.fieldname = field.getName();
        this.methodClreplacedname = methodClreplacedname;
        this.methodName = methodName;
        this.isPrivate = Modifier.isPrivate(field.getModifiers());
    }

    static String isField(ClreplacedPool pool, ConstPool cp, CtClreplaced fclreplaced, String fname, boolean is_private, int index) {
        if (!cp.getFieldrefName(index).equals(fname)) {
            return null;
        }
        try {
            CtClreplaced c = pool.get(cp.getFieldrefClreplacedName(index));
            if (c == fclreplaced || (!is_private && isFieldInSuper(c, fclreplaced, fname))) {
                return cp.getFieldrefType(index);
            }
        } catch (NotFoundException e) {
        }
        return null;
    }

    static boolean isFieldInSuper(CtClreplaced clazz, CtClreplaced fclreplaced, String fname) {
        if (!clazz.subclreplacedOf(fclreplaced)) {
            return false;
        }
        try {
            CtField f = clazz.getField(fname);
            return f.getDeclaringClreplaced() == fclreplaced;
        } catch (NotFoundException e) {
        }
        return false;
    }

    @Override
    public int transform(CtClreplaced tclazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode {
        int c = iterator.byteAt(pos);
        if (c == GETFIELD || c == GETSTATIC) {
            int index = iterator.u16bitAt(pos + 1);
            String typedesc = isField(tclazz.getClreplacedPool(), cp, fieldClreplaced, fieldname, isPrivate, index);
            if (typedesc != null) {
                if (c == GETSTATIC) {
                    iterator.move(pos);
                    // insertGap() may insert 4 bytes.
                    pos = iterator.insertGap(1);
                    iterator.writeByte(ACONST_NULL, pos);
                    pos = iterator.next();
                }
                String type = "(Ljava/lang/Object;)" + typedesc;
                int mi = cp.addClreplacedInfo(methodClreplacedname);
                int methodref = cp.addMethodrefInfo(mi, methodName, type);
                iterator.writeByte(INVOKESTATIC, pos);
                iterator.write16bit(methodref, pos + 1);
                return pos;
            }
        }
        return pos;
    }
}

19 Source : TransformReadField.java
with Apache License 2.0
from ifeilong

static boolean isFieldInSuper(CtClreplaced clazz, CtClreplaced fclreplaced, String fname) {
    if (!clazz.subclreplacedOf(fclreplaced)) {
        return false;
    }
    try {
        CtField f = clazz.getField(fname);
        return f.getDeclaringClreplaced() == fclreplaced;
    } catch (NotFoundException e) {
    }
    return false;
}

19 Source : TypeChecker.java
with Apache License 2.0
from ifeilong

public clreplaced TypeChecker extends Visitor implements Opcode, TokenId {

    static final String javaLangObject = "java.lang.Object";

    static final String jvmJavaLangObject = "java/lang/Object";

    static final String jvmJavaLangString = "java/lang/String";

    static final String jvmJavaLangClreplaced = "java/lang/Clreplaced";

    /*
     * The following fields are used by atXXX() methods
     * for returning the type of the compiled expression.
     */
    // VOID, NULL, CLreplaced, BOOLEAN, INT, ...
    protected int exprType;

    protected int arrayDim;

    // JVM-internal representation
    protected String clreplacedName;

    protected MemberResolver resolver;

    protected CtClreplaced thisClreplaced;

    protected MethodInfo thisMethod;

    public TypeChecker(CtClreplaced cc, ClreplacedPool cp) {
        resolver = new MemberResolver(cp);
        thisClreplaced = cc;
        thisMethod = null;
    }

    /*
     * Converts an array of tuples of exprType, arrayDim, and clreplacedName
     * into a String object.
     */
    protected static String argTypesToString(int[] types, int[] dims, String[] cnames) {
        StringBuffer sbuf = new StringBuffer();
        sbuf.append('(');
        int n = types.length;
        if (n > 0) {
            int i = 0;
            while (true) {
                typeToString(sbuf, types[i], dims[i], cnames[i]);
                if (++i < n) {
                    sbuf.append(',');
                } else {
                    break;
                }
            }
        }
        sbuf.append(')');
        return sbuf.toString();
    }

    /*
     * Converts a tuple of exprType, arrayDim, and clreplacedName
     * into a String object.
     */
    protected static StringBuffer typeToString(StringBuffer sbuf, int type, int dim, String cname) {
        String s;
        if (type == CLreplaced) {
            s = MemberResolver.jvmToJavaName(cname);
        } else if (type == NULL) {
            s = "Object";
        } else {
            try {
                s = MemberResolver.getTypeName(type);
            } catch (CompileError e) {
                s = "?";
            }
        }
        sbuf.append(s);
        while (dim-- > 0) {
            sbuf.append("[]");
        }
        return sbuf;
    }

    /**
     * Records the currently compiled method.
     */
    public void setThisMethod(MethodInfo m) {
        thisMethod = m;
    }

    protected static void fatal() throws CompileError {
        throw new CompileError("fatal");
    }

    /**
     * Returns the JVM-internal representation of this clreplaced name.
     */
    protected String getThisName() {
        return MemberResolver.javaToJvmName(thisClreplaced.getName());
    }

    /**
     * Returns the JVM-internal representation of this super clreplaced name.
     */
    protected String getSuperName() throws CompileError {
        return MemberResolver.javaToJvmName(MemberResolver.getSuperclreplaced(thisClreplaced).getName());
    }

    /*
     * Converts a clreplaced name into a JVM-internal representation.
     *
     * It may also expand a simple clreplaced name to java.lang.*.
     * For example, this converts Object into java/lang/Object.
     */
    protected String resolveClreplacedName(ASTList name) throws CompileError {
        return resolver.resolveClreplacedName(name);
    }

    /*
     * Expands a simple clreplaced name to java.lang.*.
     * For example, this converts Object into java/lang/Object.
     */
    protected String resolveClreplacedName(String jvmName) throws CompileError {
        return resolver.resolveJvmClreplacedName(jvmName);
    }

    @Override
    public void atNewExpr(NewExpr expr) throws CompileError {
        if (expr.isArray()) {
            atNewArrayExpr(expr);
        } else {
            CtClreplaced clazz = resolver.lookupClreplacedByName(expr.getClreplacedName());
            String cname = clazz.getName();
            ASTList args = expr.getArguments();
            atMethodCallCore(clazz, MethodInfo.nameInit, args);
            exprType = CLreplaced;
            arrayDim = 0;
            clreplacedName = MemberResolver.javaToJvmName(cname);
        }
    }

    public void atNewArrayExpr(NewExpr expr) throws CompileError {
        int type = expr.getArrayType();
        ASTList size = expr.getArraySize();
        ASTList clreplacedname = expr.getClreplacedName();
        ASTree init = expr.getInitializer();
        if (init != null) {
            init.accept(this);
        }
        if (size.length() > 1) {
            atMultiNewArray(type, clreplacedname, size);
        } else {
            ASTree sizeExpr = size.head();
            if (sizeExpr != null) {
                sizeExpr.accept(this);
            }
            exprType = type;
            arrayDim = 1;
            if (type == CLreplaced) {
                clreplacedName = resolveClreplacedName(clreplacedname);
            } else {
                clreplacedName = null;
            }
        }
    }

    @Override
    public void atArrayInit(ArrayInit init) throws CompileError {
        ASTList list = init;
        while (list != null) {
            ASTree h = list.head();
            list = list.tail();
            if (h != null) {
                h.accept(this);
            }
        }
    }

    protected void atMultiNewArray(int type, ASTList clreplacedname, ASTList size) throws CompileError {
        @SuppressWarnings("unused")
        int count, dim;
        dim = size.length();
        for (count = 0; size != null; size = size.tail()) {
            ASTree s = size.head();
            if (s == null) {
                // int[][][] a = new int[3][4][];
                break;
            }
            ++count;
            s.accept(this);
        }
        exprType = type;
        arrayDim = dim;
        if (type == CLreplaced) {
            clreplacedName = resolveClreplacedName(clreplacedname);
        } else {
            clreplacedName = null;
        }
    }

    @Override
    public void atreplacedignExpr(replacedignExpr expr) throws CompileError {
        // =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, >>>=
        int op = expr.getOperator();
        ASTree left = expr.oprand1();
        ASTree right = expr.oprand2();
        if (left instanceof Variable) {
            atVariablereplacedign(expr, op, (Variable) left, ((Variable) left).getDeclarator(), right);
        } else {
            if (left instanceof Expr) {
                Expr e = (Expr) left;
                if (e.getOperator() == ARRAY) {
                    atArrayreplacedign(expr, op, (Expr) left, right);
                    return;
                }
            }
            atFieldreplacedign(expr, op, left, right);
        }
    }

    /*
     * op is either =, %=, &=, *=, /=, +=, -=, ^=, |=, <<=, >>=, or >>>=.
     *
     * expr and var can be null.
     */
    private void atVariablereplacedign(Expr expr, int op, Variable var, Declarator d, ASTree right) throws CompileError {
        int varType = d.getType();
        int varArray = d.getArrayDim();
        String varClreplaced = d.getClreplacedName();
        if (op != '=') {
            atVariable(var);
        }
        right.accept(this);
        exprType = varType;
        arrayDim = varArray;
        clreplacedName = varClreplaced;
    }

    private void atArrayreplacedign(Expr expr, int op, Expr array, ASTree right) throws CompileError {
        atArrayRead(array.oprand1(), array.oprand2());
        int aType = exprType;
        int aDim = arrayDim;
        String cname = clreplacedName;
        right.accept(this);
        exprType = aType;
        arrayDim = aDim;
        clreplacedName = cname;
    }

    protected void atFieldreplacedign(Expr expr, int op, ASTree left, ASTree right) throws CompileError {
        CtField f = fieldAccess(left);
        atFieldRead(f);
        int fType = exprType;
        int fDim = arrayDim;
        String cname = clreplacedName;
        right.accept(this);
        exprType = fType;
        arrayDim = fDim;
        clreplacedName = cname;
    }

    @Override
    public void atCondExpr(CondExpr expr) throws CompileError {
        booleanExpr(expr.condExpr());
        expr.thenExpr().accept(this);
        int type1 = exprType;
        int dim1 = arrayDim;
        @SuppressWarnings("unused")
        String cname1 = clreplacedName;
        expr.elseExpr().accept(this);
        if (dim1 == 0 && dim1 == arrayDim) {
            if (CodeGen.rightIsStrong(type1, exprType)) {
                expr.setThen(new CastExpr(exprType, 0, expr.thenExpr()));
            } else if (CodeGen.rightIsStrong(exprType, type1)) {
                expr.setElse(new CastExpr(type1, 0, expr.elseExpr()));
                exprType = type1;
            }
        }
    }

    /*
     * If atBinExpr() subsreplacedutes a new expression for the original
     * binary-operator expression, it changes the operator name to '+'
     * (if the original is not '+') and sets the new expression to the
     * left-hand-side expression and null to the right-hand-side expression.
     */
    @Override
    public void atBinExpr(BinExpr expr) throws CompileError {
        int token = expr.getOperator();
        int k = CodeGen.lookupBinOp(token);
        if (k >= 0) {
            /*
             * arithmetic operators: +, -, *, /, %, |, ^, &, <<, >>, >>>
             */
            if (token == '+') {
                Expr e = atPlusExpr(expr);
                if (e != null) {
                    /*
                     * String concatenation has been translated into
                     * an expression using StringBuffer.
                     */
                    e = CallExpr.makeCall(Expr.make('.', e, new Member("toString")), null);
                    expr.setOprand1(e);
                    // <---- look at this!
                    expr.setOprand2(null);
                    clreplacedName = jvmJavaLangString;
                }
            } else {
                ASTree left = expr.oprand1();
                ASTree right = expr.oprand2();
                left.accept(this);
                int type1 = exprType;
                right.accept(this);
                if (!isConstant(expr, token, left, right)) {
                    computeBinExprType(expr, token, type1);
                }
            }
        } else {
            /*
             * equation: &&, ||, ==, !=, <=, >=, <, >
             */
            booleanExpr(expr);
        }
    }

    /*
     * EXPR must be a + expression.
     * atPlusExpr() returns non-null if the given expression is string
     * concatenation. The returned value is "new StringBuffer().append..".
     */
    private Expr atPlusExpr(BinExpr expr) throws CompileError {
        ASTree left = expr.oprand1();
        ASTree right = expr.oprand2();
        if (right == null) {
            // this expression has been already type-checked.
            // see atBinExpr() above.
            left.accept(this);
            return null;
        }
        if (isPlusExpr(left)) {
            Expr newExpr = atPlusExpr((BinExpr) left);
            if (newExpr != null) {
                right.accept(this);
                exprType = CLreplaced;
                arrayDim = 0;
                clreplacedName = "java/lang/StringBuffer";
                return makeAppendCall(newExpr, right);
            }
        } else {
            left.accept(this);
        }
        int type1 = exprType;
        int dim1 = arrayDim;
        String cname = clreplacedName;
        right.accept(this);
        if (isConstant(expr, '+', left, right)) {
            return null;
        }
        if ((type1 == CLreplaced && dim1 == 0 && jvmJavaLangString.equals(cname)) || (exprType == CLreplaced && arrayDim == 0 && jvmJavaLangString.equals(clreplacedName))) {
            ASTList sbufClreplaced = ASTList.make(new Symbol("java"), new Symbol("lang"), new Symbol("StringBuffer"));
            ASTree e = new NewExpr(sbufClreplaced, null);
            exprType = CLreplaced;
            arrayDim = 0;
            clreplacedName = "java/lang/StringBuffer";
            return makeAppendCall(makeAppendCall(e, left), right);
        }
        computeBinExprType(expr, '+', type1);
        return null;
    }

    private boolean isConstant(BinExpr expr, int op, ASTree left, ASTree right) throws CompileError {
        left = stripPlusExpr(left);
        right = stripPlusExpr(right);
        ASTree newExpr = null;
        if (left instanceof StringL && right instanceof StringL && op == '+') {
            newExpr = new StringL(((StringL) left).get() + ((StringL) right).get());
        } else if (left instanceof IntConst) {
            newExpr = ((IntConst) left).compute(op, right);
        } else if (left instanceof DoubleConst) {
            newExpr = ((DoubleConst) left).compute(op, right);
        }
        if (newExpr == null) {
            // not a constant expression
            return false;
        }
        expr.setOperator('+');
        expr.setOprand1(newExpr);
        expr.setOprand2(null);
        // for setting exprType, arrayDim, ...
        newExpr.accept(this);
        return true;
    }

    /*
     * CodeGen.atSwitchStmnt() also calls stripPlusExpr().
     */
    static ASTree stripPlusExpr(ASTree expr) {
        if (expr instanceof BinExpr) {
            BinExpr e = (BinExpr) expr;
            if (e.getOperator() == '+' && e.oprand2() == null) {
                return e.getLeft();
            }
        } else if (expr instanceof Expr) {
            // note: BinExpr extends Expr.
            Expr e = (Expr) expr;
            int op = e.getOperator();
            if (op == MEMBER) {
                ASTree cexpr = getConstantFieldValue((Member) e.oprand2());
                if (cexpr != null) {
                    return cexpr;
                }
            } else if (op == '+' && e.getRight() == null) {
                return e.getLeft();
            }
        } else if (expr instanceof Member) {
            ASTree cexpr = getConstantFieldValue((Member) expr);
            if (cexpr != null) {
                return cexpr;
            }
        }
        return expr;
    }

    /**
     * If MEM is a static final field, this method returns a constant
     * expression representing the value of that field.
     */
    private static ASTree getConstantFieldValue(Member mem) {
        return getConstantFieldValue(mem.getField());
    }

    public static ASTree getConstantFieldValue(CtField f) {
        if (f == null) {
            return null;
        }
        Object value = f.getConstantValue();
        if (value == null) {
            return null;
        }
        if (value instanceof String) {
            return new StringL((String) value);
        } else if (value instanceof Double || value instanceof Float) {
            int token = (value instanceof Double) ? DoubleConstant : FloatConstant;
            return new DoubleConst(((Number) value).doubleValue(), token);
        } else if (value instanceof Number) {
            int token = (value instanceof Long) ? LongConstant : IntConstant;
            return new IntConst(((Number) value).longValue(), token);
        } else if (value instanceof Boolean) {
            return new Keyword(((Boolean) value).booleanValue() ? TokenId.TRUE : TokenId.FALSE);
        } else {
            return null;
        }
    }

    private static boolean isPlusExpr(ASTree expr) {
        if (expr instanceof BinExpr) {
            BinExpr bexpr = (BinExpr) expr;
            int token = bexpr.getOperator();
            return token == '+';
        }
        return false;
    }

    private static Expr makeAppendCall(ASTree target, ASTree arg) {
        return CallExpr.makeCall(Expr.make('.', target, new Member("append")), new ASTList(arg));
    }

    private void computeBinExprType(BinExpr expr, int token, int type1) throws CompileError {
        // arrayDim should be 0.
        int type2 = exprType;
        if (token == LSHIFT || token == RSHIFT || token == ARSHIFT) {
            exprType = type1;
        } else {
            insertCast(expr, type1, type2);
        }
        if (CodeGen.isP_INT(exprType) && exprType != BOOLEAN) {
            // type1 may be BYTE, ...
            exprType = INT;
        }
    }

    private void booleanExpr(ASTree expr) throws CompileError {
        int op = CodeGen.getCompOperator(expr);
        if (op == EQ) {
            // ==, !=, ...
            BinExpr bexpr = (BinExpr) expr;
            bexpr.oprand1().accept(this);
            int type1 = exprType;
            int dim1 = arrayDim;
            bexpr.oprand2().accept(this);
            if (dim1 == 0 && arrayDim == 0) {
                insertCast(bexpr, type1, exprType);
            }
        } else if (op == '!') {
            ((Expr) expr).oprand1().accept(this);
        } else if (op == ANDAND || op == OROR) {
            BinExpr bexpr = (BinExpr) expr;
            bexpr.oprand1().accept(this);
            bexpr.oprand2().accept(this);
        } else {
            expr.accept(this);
        }
        exprType = BOOLEAN;
        arrayDim = 0;
    }

    private void insertCast(BinExpr expr, int type1, int type2) throws CompileError {
        if (CodeGen.rightIsStrong(type1, type2)) {
            expr.setLeft(new CastExpr(type2, 0, expr.oprand1()));
        } else {
            exprType = type1;
        }
    }

    @Override
    public void atCastExpr(CastExpr expr) throws CompileError {
        String cname = resolveClreplacedName(expr.getClreplacedName());
        expr.getOprand().accept(this);
        exprType = expr.getType();
        arrayDim = expr.getArrayDim();
        clreplacedName = cname;
    }

    @Override
    public void atInstanceOfExpr(InstanceOfExpr expr) throws CompileError {
        expr.getOprand().accept(this);
        exprType = BOOLEAN;
        arrayDim = 0;
    }

    @Override
    public void atExpr(Expr expr) throws CompileError {
        // array access, member access,
        // (unary) +, (unary) -, ++, --, !, ~
        int token = expr.getOperator();
        ASTree oprand = expr.oprand1();
        if (token == '.') {
            String member = ((Symbol) expr.oprand2()).get();
            if (member.equals("length")) {
                try {
                    atArrayLength(expr);
                } catch (NoFieldException nfe) {
                    // length might be a clreplaced or package name.
                    atFieldRead(expr);
                }
            } else if (member.equals("clreplaced")) {
                // .clreplaced
                atClreplacedObject(expr);
            } else {
                atFieldRead(expr);
            }
        } else if (token == MEMBER) {
            // field read
            String member = ((Symbol) expr.oprand2()).get();
            if (member.equals("clreplaced")) {
                // .clreplaced
                atClreplacedObject(expr);
            } else {
                atFieldRead(expr);
            }
        } else if (token == ARRAY) {
            atArrayRead(oprand, expr.oprand2());
        } else if (token == PLUSPLUS || token == MINUSMINUS) {
            atPlusPlus(token, oprand, expr);
        } else if (token == '!') {
            booleanExpr(expr);
        } else if (token == CALL) {
            fatal();
        } else {
            oprand.accept(this);
            if (!isConstant(expr, token, oprand)) {
                if (token == '-' || token == '~') {
                    if (CodeGen.isP_INT(exprType)) {
                        // type may be BYTE, ...
                        exprType = INT;
                    }
                }
            }
        }
    }

    private boolean isConstant(Expr expr, int op, ASTree oprand) {
        oprand = stripPlusExpr(oprand);
        if (oprand instanceof IntConst) {
            IntConst c = (IntConst) oprand;
            long v = c.get();
            if (op == '-') {
                v = -v;
            } else if (op == '~') {
                v = ~v;
            } else {
                return false;
            }
            c.set(v);
        } else if (oprand instanceof DoubleConst) {
            DoubleConst c = (DoubleConst) oprand;
            if (op == '-') {
                c.set(-c.get());
            } else {
                return false;
            }
        } else {
            return false;
        }
        expr.setOperator('+');
        return true;
    }

    @Override
    public void atCallExpr(CallExpr expr) throws CompileError {
        String mname = null;
        CtClreplaced targetClreplaced = null;
        ASTree method = expr.oprand1();
        ASTList args = (ASTList) expr.oprand2();
        if (method instanceof Member) {
            mname = ((Member) method).get();
            targetClreplaced = thisClreplaced;
        } else if (method instanceof Keyword) {
            // constructor
            // <init>
            mname = MethodInfo.nameInit;
            if (((Keyword) method).get() == SUPER) {
                targetClreplaced = MemberResolver.getSuperclreplaced(thisClreplaced);
            } else {
                targetClreplaced = thisClreplaced;
            }
        } else if (method instanceof Expr) {
            Expr e = (Expr) method;
            mname = ((Symbol) e.oprand2()).get();
            int op = e.getOperator();
            if (op == MEMBER) {
                targetClreplaced = resolver.lookupClreplaced(((Symbol) e.oprand1()).get(), false);
            } else if (op == '.') {
                ASTree target = e.oprand1();
                String clreplacedFollowedByDotSuper = isDotSuper(target);
                if (clreplacedFollowedByDotSuper != null) {
                    targetClreplaced = MemberResolver.getSuperInterface(thisClreplaced, clreplacedFollowedByDotSuper);
                } else {
                    try {
                        target.accept(this);
                    } catch (NoFieldException nfe) {
                        if (nfe.getExpr() != target) {
                            throw nfe;
                        }
                        // it should be a static method.
                        exprType = CLreplaced;
                        arrayDim = 0;
                        // JVM-internal
                        clreplacedName = nfe.getField();
                        e.setOperator(MEMBER);
                        e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(clreplacedName)));
                    }
                    if (arrayDim > 0) {
                        targetClreplaced = resolver.lookupClreplaced(javaLangObject, true);
                    } else if (exprType == CLreplaced) /* && arrayDim == 0 */
                    {
                        targetClreplaced = resolver.lookupClreplacedByJvmName(clreplacedName);
                    } else {
                        badMethod();
                    }
                }
            } else {
                badMethod();
            }
        } else {
            fatal();
        }
        MemberResolver.Method minfo = atMethodCallCore(targetClreplaced, mname, args);
        expr.setMethod(minfo);
    }

    private static void badMethod() throws CompileError {
        throw new CompileError("bad method");
    }

    /**
     * Returns non-null if target is something like Foo.super
     * for accessing the default method in an interface.
     * Otherwise, null.
     *
     * @return the clreplaced name followed by {@code .super} or null.
     */
    static String isDotSuper(ASTree target) {
        if (target instanceof Expr) {
            Expr e = (Expr) target;
            if (e.getOperator() == '.') {
                ASTree right = e.oprand2();
                if (right instanceof Keyword && ((Keyword) right).get() == SUPER) {
                    return ((Symbol) e.oprand1()).get();
                }
            }
        }
        return null;
    }

    /**
     * @return a pair of the clreplaced declaring the invoked method
     *         and the MethodInfo of that method. Never null.
     */
    public MemberResolver.Method atMethodCallCore(CtClreplaced targetClreplaced, String mname, ASTList args) throws CompileError {
        int nargs = getMethodArgsLength(args);
        int[] types = new int[nargs];
        int[] dims = new int[nargs];
        String[] cnames = new String[nargs];
        atMethodArgs(args, types, dims, cnames);
        MemberResolver.Method found = resolver.lookupMethod(targetClreplaced, thisClreplaced, thisMethod, mname, types, dims, cnames);
        if (found == null) {
            String clazz = targetClreplaced.getName();
            String signature = argTypesToString(types, dims, cnames);
            String msg;
            if (mname.equals(MethodInfo.nameInit)) {
                msg = "cannot find constructor " + clazz + signature;
            } else {
                msg = mname + signature + " not found in " + clazz;
            }
            throw new CompileError(msg);
        }
        String desc = found.info.getDescriptor();
        setReturnType(desc);
        return found;
    }

    public int getMethodArgsLength(ASTList args) {
        return ASTList.length(args);
    }

    public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError {
        int i = 0;
        while (args != null) {
            ASTree a = args.head();
            a.accept(this);
            types[i] = exprType;
            dims[i] = arrayDim;
            cnames[i] = clreplacedName;
            ++i;
            args = args.tail();
        }
    }

    void setReturnType(String desc) throws CompileError {
        int i = desc.indexOf(')');
        if (i < 0) {
            badMethod();
        }
        char c = desc.charAt(++i);
        int dim = 0;
        while (c == '[') {
            ++dim;
            c = desc.charAt(++i);
        }
        arrayDim = dim;
        if (c == 'L') {
            int j = desc.indexOf(';', i + 1);
            if (j < 0) {
                badMethod();
            }
            exprType = CLreplaced;
            clreplacedName = desc.substring(i + 1, j);
        } else {
            exprType = MemberResolver.descToType(c);
            clreplacedName = null;
        }
    }

    private void atFieldRead(ASTree expr) throws CompileError {
        atFieldRead(fieldAccess(expr));
    }

    private void atFieldRead(CtField f) throws CompileError {
        FieldInfo finfo = f.getFieldInfo2();
        String type = finfo.getDescriptor();
        int i = 0;
        int dim = 0;
        char c = type.charAt(i);
        while (c == '[') {
            ++dim;
            c = type.charAt(++i);
        }
        arrayDim = dim;
        exprType = MemberResolver.descToType(c);
        if (c == 'L') {
            clreplacedName = type.substring(i + 1, type.indexOf(';', i + 1));
        } else {
            clreplacedName = null;
        }
    }

    /*
     * if EXPR is to access a static field, fieldAccess() translates EXPR
     * into an expression using '#' (MEMBER). For example, it translates
     * java.lang.Integer.TYPE into java.lang.Integer#TYPE. This translation
     * speeds up type resolution by MemberCodeGen.
     */
    protected CtField fieldAccess(ASTree expr) throws CompileError {
        if (expr instanceof Member) {
            Member mem = (Member) expr;
            String name = mem.get();
            try {
                CtField f = thisClreplaced.getField(name);
                if (Modifier.isStatic(f.getModifiers())) {
                    mem.setField(f);
                }
                return f;
            } catch (NotFoundException e) {
                // EXPR might be part of a static member access?
                throw new NoFieldException(name, expr);
            }
        } else if (expr instanceof Expr) {
            Expr e = (Expr) expr;
            int op = e.getOperator();
            if (op == MEMBER) {
                Member mem = (Member) e.oprand2();
                CtField f = resolver.lookupField(((Symbol) e.oprand1()).get(), mem);
                mem.setField(f);
                return f;
            } else if (op == '.') {
                try {
                    e.oprand1().accept(this);
                } catch (NoFieldException nfe) {
                    if (nfe.getExpr() != e.oprand1()) {
                        throw nfe;
                    }
                    /*
                     * EXPR should be a static field.
                     * If EXPR might be part of a qualified clreplaced name,
                     * lookupFieldByJvmName2() throws NoFieldException.
                     */
                    return fieldAccess2(e, nfe.getField());
                }
                CompileError err = null;
                try {
                    if (exprType == CLreplaced && arrayDim == 0) {
                        return resolver.lookupFieldByJvmName(clreplacedName, (Symbol) e.oprand2());
                    }
                } catch (CompileError ce) {
                    err = ce;
                }
                /*
                 * If a filed name is the same name as a package's,
                 * a static member of a clreplaced in that package is not
                 * visible. For example,
                 *
                 * clreplaced Foo {
                 * int javreplacedist;
                 * }
                 *
                 * It is impossible to add the following method:
                 *
                 * String m() { return javreplacedist.CtClreplaced.intType.toString(); }
                 *
                 * because javreplacedist is a field name. However, this is
                 * often inconvenient, this compiler allows it. The following
                 * code is for that.
                 */
                ASTree oprnd1 = e.oprand1();
                if (oprnd1 instanceof Symbol) {
                    return fieldAccess2(e, ((Symbol) oprnd1).get());
                }
                if (err != null) {
                    throw err;
                }
            }
        }
        throw new CompileError("bad filed access");
    }

    private CtField fieldAccess2(Expr e, String jvmClreplacedName) throws CompileError {
        Member fname = (Member) e.oprand2();
        CtField f = resolver.lookupFieldByJvmName2(jvmClreplacedName, fname, e);
        e.setOperator(MEMBER);
        e.setOprand1(new Symbol(MemberResolver.jvmToJavaName(jvmClreplacedName)));
        fname.setField(f);
        return f;
    }

    public void atClreplacedObject(Expr expr) throws CompileError {
        exprType = CLreplaced;
        arrayDim = 0;
        clreplacedName = jvmJavaLangClreplaced;
    }

    public void atArrayLength(Expr expr) throws CompileError {
        expr.oprand1().accept(this);
        if (arrayDim == 0) {
            throw new NoFieldException("length", expr);
        }
        exprType = INT;
        arrayDim = 0;
    }

    public void atArrayRead(ASTree array, ASTree index) throws CompileError {
        array.accept(this);
        int type = exprType;
        int dim = arrayDim;
        String cname = clreplacedName;
        index.accept(this);
        exprType = type;
        arrayDim = dim - 1;
        clreplacedName = cname;
    }

    private void atPlusPlus(int token, ASTree oprand, Expr expr) throws CompileError {
        // ++i or i++?
        boolean isPost = oprand == null;
        if (isPost) {
            oprand = expr.oprand2();
        }
        if (oprand instanceof Variable) {
            Declarator d = ((Variable) oprand).getDeclarator();
            exprType = d.getType();
            arrayDim = d.getArrayDim();
        } else {
            if (oprand instanceof Expr) {
                Expr e = (Expr) oprand;
                if (e.getOperator() == ARRAY) {
                    atArrayRead(e.oprand1(), e.oprand2());
                    // arrayDim should be 0.
                    int t = exprType;
                    if (t == INT || t == BYTE || t == CHAR || t == SHORT) {
                        exprType = INT;
                    }
                    return;
                }
            }
            atFieldPlusPlus(oprand);
        }
    }

    protected void atFieldPlusPlus(ASTree oprand) throws CompileError {
        CtField f = fieldAccess(oprand);
        atFieldRead(f);
        int t = exprType;
        if (t == INT || t == BYTE || t == CHAR || t == SHORT) {
            exprType = INT;
        }
    }

    @Override
    public void atMember(Member mem) throws CompileError {
        atFieldRead(mem);
    }

    @Override
    public void atVariable(Variable v) throws CompileError {
        Declarator d = v.getDeclarator();
        exprType = d.getType();
        arrayDim = d.getArrayDim();
        clreplacedName = d.getClreplacedName();
    }

    @Override
    public void atKeyword(Keyword k) throws CompileError {
        arrayDim = 0;
        int token = k.get();
        switch(token) {
            case TRUE:
            case FALSE:
                exprType = BOOLEAN;
                break;
            case NULL:
                exprType = NULL;
                break;
            case THIS:
            case SUPER:
                exprType = CLreplaced;
                if (token == THIS) {
                    clreplacedName = getThisName();
                } else {
                    clreplacedName = getSuperName();
                }
                break;
            default:
                fatal();
        }
    }

    @Override
    public void atStringL(StringL s) throws CompileError {
        exprType = CLreplaced;
        arrayDim = 0;
        clreplacedName = jvmJavaLangString;
    }

    @Override
    public void atIntConst(IntConst i) throws CompileError {
        arrayDim = 0;
        int type = i.getType();
        if (type == IntConstant || type == CharConstant) {
            exprType = (type == IntConstant ? INT : CHAR);
        } else {
            exprType = LONG;
        }
    }

    @Override
    public void atDoubleConst(DoubleConst d) throws CompileError {
        arrayDim = 0;
        if (d.getType() == DoubleConstant) {
            exprType = DOUBLE;
        } else {
            exprType = FLOAT;
        }
    }
}

19 Source : MemberResolver.java
with Apache License 2.0
from ifeilong

/**
 * @param clreplacedname
 *            jvm clreplaced name.
 */
public CtClreplaced lookupClreplaced(int type, int dim, String clreplacedname) throws CompileError {
    String cname = "";
    CtClreplaced clazz;
    if (type == CLreplaced) {
        clazz = lookupClreplacedByJvmName(clreplacedname);
        if (dim > 0) {
            cname = clazz.getName();
        } else {
            return clazz;
        }
    } else {
        cname = getTypeName(type);
    }
    while (dim-- > 0) {
        cname += "[]";
    }
    return lookupClreplaced(cname, false);
}

19 Source : MemberResolver.java
with Apache License 2.0
from ifeilong

private CtClreplaced lookupClreplaced0(String clreplacedname, boolean notCheckInner) throws NotFoundException {
    CtClreplaced cc = null;
    do {
        try {
            cc = clreplacedPool.get(clreplacedname);
        } catch (NotFoundException e) {
            int i = clreplacedname.lastIndexOf('.');
            if (notCheckInner || i < 0) {
                throw e;
            }
            StringBuffer sbuf = new StringBuffer(clreplacedname);
            sbuf.setCharAt(i, '$');
            clreplacedname = sbuf.toString();
        }
    } while (cc == null);
    return cc;
}

19 Source : MemberCodeGen.java
with Apache License 2.0
from ifeilong

/* Code generator methods depending on javreplacedist.* clreplacedes.
 */
public clreplaced MemberCodeGen extends CodeGen {

    protected MemberResolver resolver;

    protected CtClreplaced thisClreplaced;

    protected MethodInfo thisMethod;

    protected boolean resultStatic;

    public MemberCodeGen(Bytecode b, CtClreplaced cc, ClreplacedPool cp) {
        super(b);
        resolver = new MemberResolver(cp);
        thisClreplaced = cc;
        thisMethod = null;
    }

    /**
     * Returns the major version of the clreplaced file
     * targeted by this compilation.
     */
    public int getMajorVersion() {
        ClreplacedFile cf = thisClreplaced.getClreplacedFile2();
        if (cf == null) {
            // JDK 1.3
            return ClreplacedFile.MAJOR_VERSION;
        }
        return cf.getMajorVersion();
    }

    /**
     * Records the currently compiled method.
     */
    public void setThisMethod(CtMethod m) {
        thisMethod = m.getMethodInfo2();
        if (typeChecker != null) {
            typeChecker.setThisMethod(thisMethod);
        }
    }

    public CtClreplaced getThisClreplaced() {
        return thisClreplaced;
    }

    /**
     * Returns the JVM-internal representation of this clreplaced name.
     */
    @Override
    protected String getThisName() {
        return MemberResolver.javaToJvmName(thisClreplaced.getName());
    }

    /**
     * Returns the JVM-internal representation of this super clreplaced name.
     */
    @Override
    protected String getSuperName() throws CompileError {
        return MemberResolver.javaToJvmName(MemberResolver.getSuperclreplaced(thisClreplaced).getName());
    }

    @Override
    protected void insertDefaultSuperCall() throws CompileError {
        bytecode.addAload(0);
        bytecode.addInvokespecial(MemberResolver.getSuperclreplaced(thisClreplaced), "<init>", "()V");
    }

    static clreplaced JsrHook extends ReturnHook {

        List<int[]> jsrList;

        CodeGen cgen;

        int var;

        JsrHook(CodeGen gen) {
            super(gen);
            jsrList = new ArrayList<>();
            cgen = gen;
            var = -1;
        }

        private int getVar(int size) {
            if (var < 0) {
                var = cgen.getMaxLocals();
                cgen.incMaxLocals(size);
            }
            return var;
        }

        private void jsrJmp(Bytecode b) {
            b.addOpcode(Opcode.GOTO);
            jsrList.add(new int[] { b.currentPc(), var });
            b.addIndex(0);
        }

        @Override
        protected boolean doit(Bytecode b, int opcode) {
            switch(opcode) {
                case Opcode.RETURN:
                    jsrJmp(b);
                    break;
                case ARETURN:
                    b.addAstore(getVar(1));
                    jsrJmp(b);
                    b.addAload(var);
                    break;
                case IRETURN:
                    b.addIstore(getVar(1));
                    jsrJmp(b);
                    b.addIload(var);
                    break;
                case LRETURN:
                    b.addLstore(getVar(2));
                    jsrJmp(b);
                    b.addLload(var);
                    break;
                case DRETURN:
                    b.addDstore(getVar(2));
                    jsrJmp(b);
                    b.addDload(var);
                    break;
                case FRETURN:
                    b.addFstore(getVar(1));
                    jsrJmp(b);
                    b.addFload(var);
                    break;
                default:
                    throw new RuntimeException("fatal");
            }
            return false;
        }
    }

    static clreplaced JsrHook2 extends ReturnHook {

        int var;

        int target;

        JsrHook2(CodeGen gen, int[] retTarget) {
            super(gen);
            target = retTarget[0];
            var = retTarget[1];
        }

        @Override
        protected boolean doit(Bytecode b, int opcode) {
            switch(opcode) {
                case Opcode.RETURN:
                    break;
                case ARETURN:
                    b.addAstore(var);
                    break;
                case IRETURN:
                    b.addIstore(var);
                    break;
                case LRETURN:
                    b.addLstore(var);
                    break;
                case DRETURN:
                    b.addDstore(var);
                    break;
                case FRETURN:
                    b.addFstore(var);
                    break;
                default:
                    throw new RuntimeException("fatal");
            }
            b.addOpcode(Opcode.GOTO);
            b.addIndex(target - b.currentPc() + 3);
            return true;
        }
    }

    @Override
    protected void atTryStmnt(Stmnt st) throws CompileError {
        Bytecode bc = bytecode;
        Stmnt body = (Stmnt) st.getLeft();
        if (body == null) {
            return;
        }
        ASTList catchList = (ASTList) st.getRight().getLeft();
        Stmnt finallyBlock = (Stmnt) st.getRight().getRight().getLeft();
        List<Integer> gotoList = new ArrayList<>();
        JsrHook jsrHook = null;
        if (finallyBlock != null) {
            jsrHook = new JsrHook(this);
        }
        int start = bc.currentPc();
        body.accept(this);
        int end = bc.currentPc();
        if (start == end) {
            throw new CompileError("empty try block");
        }
        boolean tryNotReturn = !hasReturned;
        if (tryNotReturn) {
            bc.addOpcode(Opcode.GOTO);
            gotoList.add(bc.currentPc());
            // correct later
            bc.addIndex(0);
        }
        int var = getMaxLocals();
        incMaxLocals(1);
        while (catchList != null) {
            // catch clause
            Pair p = (Pair) catchList.head();
            catchList = catchList.tail();
            Declarator decl = (Declarator) p.getLeft();
            Stmnt block = (Stmnt) p.getRight();
            decl.setLocalVar(var);
            CtClreplaced type = resolver.lookupClreplacedByJvmName(decl.getClreplacedName());
            decl.setClreplacedName(MemberResolver.javaToJvmName(type.getName()));
            bc.addExceptionHandler(start, end, bc.currentPc(), type);
            bc.growStack(1);
            bc.addAstore(var);
            hasReturned = false;
            if (block != null) {
                block.accept(this);
            }
            if (!hasReturned) {
                bc.addOpcode(Opcode.GOTO);
                gotoList.add(bc.currentPc());
                // correct later
                bc.addIndex(0);
                tryNotReturn = true;
            }
        }
        if (finallyBlock != null) {
            jsrHook.remove(this);
            // catch (any) clause
            int pcAnyCatch = bc.currentPc();
            bc.addExceptionHandler(start, pcAnyCatch, pcAnyCatch, 0);
            bc.growStack(1);
            bc.addAstore(var);
            hasReturned = false;
            finallyBlock.accept(this);
            if (!hasReturned) {
                bc.addAload(var);
                bc.addOpcode(ATHROW);
            }
            addFinally(jsrHook.jsrList, finallyBlock);
        }
        int pcEnd = bc.currentPc();
        patchGoto(gotoList, pcEnd);
        hasReturned = !tryNotReturn;
        if (finallyBlock != null) {
            if (tryNotReturn) {
                finallyBlock.accept(this);
            }
        }
    }

    /**
     * Adds a finally clause for earch return statement.
     */
    private void addFinally(List<int[]> returnList, Stmnt finallyBlock) throws CompileError {
        Bytecode bc = bytecode;
        for (final int[] ret : returnList) {
            int pc = ret[0];
            bc.write16bit(pc, bc.currentPc() - pc + 1);
            ReturnHook hook = new JsrHook2(this, ret);
            finallyBlock.accept(this);
            hook.remove(this);
            if (!hasReturned) {
                bc.addOpcode(Opcode.GOTO);
                bc.addIndex(pc + 3 - bc.currentPc());
            }
        }
    }

    @Override
    public void atNewExpr(NewExpr expr) throws CompileError {
        if (expr.isArray()) {
            atNewArrayExpr(expr);
        } else {
            CtClreplaced clazz = resolver.lookupClreplacedByName(expr.getClreplacedName());
            String cname = clazz.getName();
            ASTList args = expr.getArguments();
            bytecode.addNew(cname);
            bytecode.addOpcode(DUP);
            atMethodCallCore(clazz, MethodInfo.nameInit, args, false, true, -1, null);
            exprType = CLreplaced;
            arrayDim = 0;
            clreplacedName = MemberResolver.javaToJvmName(cname);
        }
    }

    public void atNewArrayExpr(NewExpr expr) throws CompileError {
        int type = expr.getArrayType();
        ASTList size = expr.getArraySize();
        ASTList clreplacedname = expr.getClreplacedName();
        ArrayInit init = expr.getInitializer();
        if (size.length() > 1) {
            if (init != null) {
                throw new CompileError("sorry, multi-dimensional array initializer " + "for new is not supported");
            }
            atMultiNewArray(type, clreplacedname, size);
            return;
        }
        ASTree sizeExpr = size.head();
        atNewArrayExpr2(type, sizeExpr, Declarator.astToClreplacedName(clreplacedname, '/'), init);
    }

    private void atNewArrayExpr2(int type, ASTree sizeExpr, String jvmClreplacedname, ArrayInit init) throws CompileError {
        if (init == null) {
            if (sizeExpr == null) {
                throw new CompileError("no array size");
            } else {
                sizeExpr.accept(this);
            }
        } else if (sizeExpr == null) {
            int s = init.length();
            bytecode.addIconst(s);
        } else {
            throw new CompileError("unnecessary array size specified for new");
        }
        String elementClreplaced;
        if (type == CLreplaced) {
            elementClreplaced = resolveClreplacedName(jvmClreplacedname);
            bytecode.addAnewarray(MemberResolver.jvmToJavaName(elementClreplaced));
        } else {
            elementClreplaced = null;
            int atype = 0;
            switch(type) {
                case BOOLEAN:
                    atype = T_BOOLEAN;
                    break;
                case CHAR:
                    atype = T_CHAR;
                    break;
                case FLOAT:
                    atype = T_FLOAT;
                    break;
                case DOUBLE:
                    atype = T_DOUBLE;
                    break;
                case BYTE:
                    atype = T_BYTE;
                    break;
                case SHORT:
                    atype = T_SHORT;
                    break;
                case INT:
                    atype = T_INT;
                    break;
                case LONG:
                    atype = T_LONG;
                    break;
                default:
                    badNewExpr();
                    break;
            }
            bytecode.addOpcode(NEWARRAY);
            bytecode.add(atype);
        }
        if (init != null) {
            int s = init.length();
            ASTList list = init;
            for (int i = 0; i < s; i++) {
                bytecode.addOpcode(DUP);
                bytecode.addIconst(i);
                list.head().accept(this);
                if (!isRefType(type)) {
                    atNumCastExpr(exprType, type);
                }
                bytecode.addOpcode(getArrayWriteOp(type, 0));
                list = list.tail();
            }
        }
        exprType = type;
        arrayDim = 1;
        clreplacedName = elementClreplaced;
    }

    private static void badNewExpr() throws CompileError {
        throw new CompileError("bad new expression");
    }

    @Override
    protected void atArrayVariablereplacedign(ArrayInit init, int varType, int varArray, String varClreplaced) throws CompileError {
        atNewArrayExpr2(varType, null, varClreplaced, init);
    }

    @Override
    public void atArrayInit(ArrayInit init) throws CompileError {
        throw new CompileError("array initializer is not supported");
    }

    protected void atMultiNewArray(int type, ASTList clreplacedname, ASTList size) throws CompileError {
        int count, dim;
        dim = size.length();
        for (count = 0; size != null; size = size.tail()) {
            ASTree s = size.head();
            if (s == null) {
                // int[][][] a = new int[3][4][];
                break;
            }
            ++count;
            s.accept(this);
            if (exprType != INT) {
                throw new CompileError("bad type for array size");
            }
        }
        String desc;
        exprType = type;
        arrayDim = dim;
        if (type == CLreplaced) {
            clreplacedName = resolveClreplacedName(clreplacedname);
            desc = toJvmArrayName(clreplacedName, dim);
        } else {
            desc = toJvmTypeName(type, dim);
        }
        bytecode.addMultiNewarray(desc, count);
    }

    @Override
    public void atCallExpr(CallExpr expr) throws CompileError {
        String mname = null;
        CtClreplaced targetClreplaced = null;
        ASTree method = expr.oprand1();
        ASTList args = (ASTList) expr.oprand2();
        boolean isStatic = false;
        boolean isSpecial = false;
        int aload0pos = -1;
        MemberResolver.Method cached = expr.getMethod();
        if (method instanceof Member) {
            mname = ((Member) method).get();
            targetClreplaced = thisClreplaced;
            if (inStaticMethod || (cached != null && cached.isStatic())) {
                // should be static
                isStatic = true;
            } else {
                aload0pos = bytecode.currentPc();
                // this
                bytecode.addAload(0);
            }
        } else if (method instanceof Keyword) {
            // constructor
            isSpecial = true;
            // <init>
            mname = MethodInfo.nameInit;
            targetClreplaced = thisClreplaced;
            if (inStaticMethod) {
                throw new CompileError("a constructor cannot be static");
            }
            // this
            bytecode.addAload(0);
            if (((Keyword) method).get() == SUPER) {
                targetClreplaced = MemberResolver.getSuperclreplaced(targetClreplaced);
            }
        } else if (method instanceof Expr) {
            Expr e = (Expr) method;
            mname = ((Symbol) e.oprand2()).get();
            int op = e.getOperator();
            if (op == MEMBER) {
                // static method
                targetClreplaced = resolver.lookupClreplaced(((Symbol) e.oprand1()).get(), false);
                isStatic = true;
            } else if (op == '.') {
                ASTree target = e.oprand1();
                String clreplacedFollowedByDotSuper = TypeChecker.isDotSuper(target);
                if (clreplacedFollowedByDotSuper != null) {
                    isSpecial = true;
                    targetClreplaced = MemberResolver.getSuperInterface(thisClreplaced, clreplacedFollowedByDotSuper);
                    if (inStaticMethod || (cached != null && cached.isStatic())) {
                        // should be static
                        isStatic = true;
                    } else {
                        aload0pos = bytecode.currentPc();
                        // this
                        bytecode.addAload(0);
                    }
                } else {
                    if (target instanceof Keyword) {
                        if (((Keyword) target).get() == SUPER) {
                            isSpecial = true;
                        }
                    }
                    try {
                        target.accept(this);
                    } catch (NoFieldException nfe) {
                        if (nfe.getExpr() != target) {
                            throw nfe;
                        }
                        // it should be a static method.
                        exprType = CLreplaced;
                        arrayDim = 0;
                        // JVM-internal
                        clreplacedName = nfe.getField();
                        isStatic = true;
                    }
                    if (arrayDim > 0) {
                        targetClreplaced = resolver.lookupClreplaced(javaLangObject, true);
                    } else if (exprType == CLreplaced) /* && arrayDim == 0 */
                    {
                        targetClreplaced = resolver.lookupClreplacedByJvmName(clreplacedName);
                    } else {
                        badMethod();
                    }
                }
            } else {
                badMethod();
            }
        } else {
            fatal();
        }
        atMethodCallCore(targetClreplaced, mname, args, isStatic, isSpecial, aload0pos, cached);
    }

    private static void badMethod() throws CompileError {
        throw new CompileError("bad method");
    }

    /*
     * atMethodCallCore() is also called by doit() in NewExpr.ProceedForNew
     *
     * @param targetClreplaced the clreplaced at which method lookup starts.
     * 
     * @param found not null if the method look has been already done.
     */
    public void atMethodCallCore(CtClreplaced targetClreplaced, String mname, ASTList args, boolean isStatic, boolean isSpecial, int aload0pos, MemberResolver.Method found) throws CompileError {
        int nargs = getMethodArgsLength(args);
        int[] types = new int[nargs];
        int[] dims = new int[nargs];
        String[] cnames = new String[nargs];
        if (!isStatic && found != null && found.isStatic()) {
            bytecode.addOpcode(POP);
            isStatic = true;
        }
        @SuppressWarnings("unused")
        int stack = bytecode.getStackDepth();
        // generate code for evaluating arguments.
        atMethodArgs(args, types, dims, cnames);
        if (found == null) {
            found = resolver.lookupMethod(targetClreplaced, thisClreplaced, thisMethod, mname, types, dims, cnames);
        }
        if (found == null) {
            String msg;
            if (mname.equals(MethodInfo.nameInit)) {
                msg = "constructor not found";
            } else {
                msg = "Method " + mname + " not found in " + targetClreplaced.getName();
            }
            throw new CompileError(msg);
        }
        atMethodCallCore2(targetClreplaced, mname, isStatic, isSpecial, aload0pos, found);
    }

    private void atMethodCallCore2(CtClreplaced targetClreplaced, String mname, boolean isStatic, boolean isSpecial, int aload0pos, MemberResolver.Method found) throws CompileError {
        CtClreplaced declClreplaced = found.declaring;
        MethodInfo minfo = found.info;
        String desc = minfo.getDescriptor();
        int acc = minfo.getAccessFlags();
        if (mname.equals(MethodInfo.nameInit)) {
            isSpecial = true;
            if (declClreplaced != targetClreplaced) {
                throw new CompileError("no such constructor: " + targetClreplaced.getName());
            }
            if (declClreplaced != thisClreplaced && AccessFlag.isPrivate(acc)) {
                desc = getAccessibleConstructor(desc, declClreplaced, minfo);
                // the last parameter
                bytecode.addOpcode(Opcode.ACONST_NULL);
            }
        } else if (AccessFlag.isPrivate(acc)) {
            if (declClreplaced == thisClreplaced) {
                isSpecial = true;
            } else {
                isSpecial = false;
                isStatic = true;
                String origDesc = desc;
                if ((acc & AccessFlag.STATIC) == 0) {
                    desc = Descriptor.insertParameter(declClreplaced.getName(), origDesc);
                }
                acc = AccessFlag.setPackage(acc) | AccessFlag.STATIC;
                mname = getAccessiblePrivate(mname, origDesc, desc, minfo, declClreplaced);
            }
        }
        boolean popTarget = false;
        if ((acc & AccessFlag.STATIC) != 0) {
            if (!isStatic) {
                /*
                 * this method is static but the target object is
                 * on stack. It must be popped out. If aload0pos >= 0,
                 * then the target object was pushed by aload_0. It is
                 * overwritten by NOP.
                 */
                isStatic = true;
                if (aload0pos >= 0) {
                    bytecode.write(aload0pos, NOP);
                } else {
                    popTarget = true;
                }
            }
            bytecode.addInvokestatic(declClreplaced, mname, desc);
        } else if (isSpecial) {
            bytecode.addInvokespecial(targetClreplaced, mname, desc);
        } else {
            if (!Modifier.isPublic(declClreplaced.getModifiers()) || declClreplaced.isInterface() != targetClreplaced.isInterface()) {
                declClreplaced = targetClreplaced;
            }
            if (declClreplaced.isInterface()) {
                int nargs = Descriptor.paramSize(desc) + 1;
                bytecode.addInvokeinterface(declClreplaced, mname, desc, nargs);
            } else if (isStatic) {
                throw new CompileError(mname + " is not static");
            } else {
                bytecode.addInvokevirtual(declClreplaced, mname, desc);
            }
        }
        setReturnType(desc, isStatic, popTarget);
    }

    /*
     * Finds (or adds if necessary) a hidden accessor if the method
     * is in an enclosing clreplaced.
     *
     * @param desc the descriptor of the method.
     * 
     * @param declClreplaced the clreplaced declaring the method.
     */
    protected String getAccessiblePrivate(String methodName, String desc, String newDesc, MethodInfo minfo, CtClreplaced declClreplaced) throws CompileError {
        if (isEnclosing(declClreplaced, thisClreplaced)) {
            AccessorMaker maker = declClreplaced.getAccessorMaker();
            if (maker != null) {
                return maker.getMethodAccessor(methodName, desc, newDesc, minfo);
            }
        }
        throw new CompileError("Method " + methodName + " is private");
    }

    /*
     * Finds (or adds if necessary) a hidden constructor if the given
     * constructor is in an enclosing clreplaced.
     *
     * @param desc the descriptor of the constructor.
     * 
     * @param declClreplaced the clreplaced declaring the constructor.
     * 
     * @param minfo the method info of the constructor.
     * 
     * @return the descriptor of the hidden constructor.
     */
    protected String getAccessibleConstructor(String desc, CtClreplaced declClreplaced, MethodInfo minfo) throws CompileError {
        if (isEnclosing(declClreplaced, thisClreplaced)) {
            AccessorMaker maker = declClreplaced.getAccessorMaker();
            if (maker != null) {
                return maker.getConstructor(declClreplaced, desc, minfo);
            }
        }
        throw new CompileError("the called constructor is private in " + declClreplaced.getName());
    }

    private boolean isEnclosing(CtClreplaced outer, CtClreplaced inner) {
        try {
            while (inner != null) {
                inner = inner.getDeclaringClreplaced();
                if (inner == outer) {
                    return true;
                }
            }
        } catch (NotFoundException e) {
        }
        return false;
    }

    public int getMethodArgsLength(ASTList args) {
        return ASTList.length(args);
    }

    public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError {
        int i = 0;
        while (args != null) {
            ASTree a = args.head();
            a.accept(this);
            types[i] = exprType;
            dims[i] = arrayDim;
            cnames[i] = clreplacedName;
            ++i;
            args = args.tail();
        }
    }

    void setReturnType(String desc, boolean isStatic, boolean popTarget) throws CompileError {
        int i = desc.indexOf(')');
        if (i < 0) {
            badMethod();
        }
        char c = desc.charAt(++i);
        int dim = 0;
        while (c == '[') {
            ++dim;
            c = desc.charAt(++i);
        }
        arrayDim = dim;
        if (c == 'L') {
            int j = desc.indexOf(';', i + 1);
            if (j < 0) {
                badMethod();
            }
            exprType = CLreplaced;
            clreplacedName = desc.substring(i + 1, j);
        } else {
            exprType = MemberResolver.descToType(c);
            clreplacedName = null;
        }
        int etype = exprType;
        if (isStatic) {
            if (popTarget) {
                if (is2word(etype, dim)) {
                    bytecode.addOpcode(DUP2_X1);
                    bytecode.addOpcode(POP2);
                    bytecode.addOpcode(POP);
                } else if (etype == VOID) {
                    bytecode.addOpcode(POP);
                } else {
                    bytecode.addOpcode(SWAP);
                    bytecode.addOpcode(POP);
                }
            }
        }
    }

    @Override
    protected void atFieldreplacedign(Expr expr, int op, ASTree left, ASTree right, boolean doDup) throws CompileError {
        CtField f = fieldAccess(left, false);
        boolean is_static = resultStatic;
        if (op != '=' && !is_static) {
            bytecode.addOpcode(DUP);
        }
        int fi;
        if (op == '=') {
            FieldInfo finfo = f.getFieldInfo2();
            setFieldType(finfo);
            AccessorMaker maker = isAccessibleField(f, finfo);
            if (maker == null) {
                fi = addFieldrefInfo(f, finfo);
            } else {
                fi = 0;
            }
        } else {
            fi = atFieldRead(f, is_static);
        }
        int fType = exprType;
        int fDim = arrayDim;
        String cname = clreplacedName;
        atreplacedignCore(expr, op, right, fType, fDim, cname);
        boolean is2w = is2word(fType, fDim);
        if (doDup) {
            int dup_code;
            if (is_static) {
                dup_code = (is2w ? DUP2 : DUP);
            } else {
                dup_code = (is2w ? DUP2_X1 : DUP_X1);
            }
            bytecode.addOpcode(dup_code);
        }
        atFieldreplacedignCore(f, is_static, fi, is2w);
        exprType = fType;
        arrayDim = fDim;
        clreplacedName = cname;
    }

    /*
     * If fi == 0, the field must be a private field in an enclosing clreplaced.
     */
    private void atFieldreplacedignCore(CtField f, boolean is_static, int fi, boolean is2byte) throws CompileError {
        if (fi != 0) {
            if (is_static) {
                bytecode.add(PUTSTATIC);
                bytecode.growStack(is2byte ? -2 : -1);
            } else {
                bytecode.add(PUTFIELD);
                bytecode.growStack(is2byte ? -3 : -2);
            }
            bytecode.addIndex(fi);
        } else {
            CtClreplaced declClreplaced = f.getDeclaringClreplaced();
            AccessorMaker maker = declClreplaced.getAccessorMaker();
            // make should be non null.
            FieldInfo finfo = f.getFieldInfo2();
            MethodInfo minfo = maker.getFieldSetter(finfo, is_static);
            bytecode.addInvokestatic(declClreplaced, minfo.getName(), minfo.getDescriptor());
        }
    }

    /*
     * overwritten in JvstCodeGen.
     */
    @Override
    public void atMember(Member mem) throws CompileError {
        atFieldRead(mem);
    }

    @Override
    protected void atFieldRead(ASTree expr) throws CompileError {
        CtField f = fieldAccess(expr, true);
        if (f == null) {
            atArrayLength(expr);
            return;
        }
        boolean is_static = resultStatic;
        ASTree cexpr = TypeChecker.getConstantFieldValue(f);
        if (cexpr == null) {
            atFieldRead(f, is_static);
        } else {
            cexpr.accept(this);
            setFieldType(f.getFieldInfo2());
        }
    }

    private void atArrayLength(ASTree expr) throws CompileError {
        if (arrayDim == 0) {
            throw new CompileError(".length applied to a non array");
        }
        bytecode.addOpcode(ARRAYLENGTH);
        exprType = INT;
        arrayDim = 0;
    }

    /**
     * Generates bytecode for reading a field value.
     * It returns a fieldref_info index or zero if the field is a private
     * one declared in an enclosing clreplaced.
     */
    private int atFieldRead(CtField f, boolean isStatic) throws CompileError {
        FieldInfo finfo = f.getFieldInfo2();
        boolean is2byte = setFieldType(finfo);
        AccessorMaker maker = isAccessibleField(f, finfo);
        if (maker != null) {
            MethodInfo minfo = maker.getFieldGetter(finfo, isStatic);
            bytecode.addInvokestatic(f.getDeclaringClreplaced(), minfo.getName(), minfo.getDescriptor());
            return 0;
        }
        int fi = addFieldrefInfo(f, finfo);
        if (isStatic) {
            bytecode.add(GETSTATIC);
            bytecode.growStack(is2byte ? 2 : 1);
        } else {
            bytecode.add(GETFIELD);
            bytecode.growStack(is2byte ? 1 : 0);
        }
        bytecode.addIndex(fi);
        return fi;
    }

    /**
     * Returns null if the field is accessible. Otherwise, it throws
     * an exception or it returns AccessorMaker if the field is a private
     * one declared in an enclosing clreplaced.
     */
    private AccessorMaker isAccessibleField(CtField f, FieldInfo finfo) throws CompileError {
        if (AccessFlag.isPrivate(finfo.getAccessFlags()) && f.getDeclaringClreplaced() != thisClreplaced) {
            CtClreplaced declClreplaced = f.getDeclaringClreplaced();
            if (isEnclosing(declClreplaced, thisClreplaced)) {
                AccessorMaker maker = declClreplaced.getAccessorMaker();
                if (maker != null) {
                    return maker;
                }
            }
            throw new CompileError("Field " + f.getName() + " in " + declClreplaced.getName() + " is private.");
        }
        // accessible field
        return null;
    }

    /**
     * Sets exprType, arrayDim, and clreplacedName.
     *
     * @return true if the field type is long or double.
     */
    private boolean setFieldType(FieldInfo finfo) throws CompileError {
        String type = finfo.getDescriptor();
        int i = 0;
        int dim = 0;
        char c = type.charAt(i);
        while (c == '[') {
            ++dim;
            c = type.charAt(++i);
        }
        arrayDim = dim;
        exprType = MemberResolver.descToType(c);
        if (c == 'L') {
            clreplacedName = type.substring(i + 1, type.indexOf(';', i + 1));
        } else {
            clreplacedName = null;
        }
        boolean is2byte = dim == 0 && (c == 'J' || c == 'D');
        return is2byte;
    }

    private int addFieldrefInfo(CtField f, FieldInfo finfo) {
        ConstPool cp = bytecode.getConstPool();
        String cname = f.getDeclaringClreplaced().getName();
        int ci = cp.addClreplacedInfo(cname);
        String name = finfo.getName();
        String type = finfo.getDescriptor();
        return cp.addFieldrefInfo(ci, name, type);
    }

    @Override
    protected void atClreplacedObject2(String cname) throws CompileError {
        if (getMajorVersion() < ClreplacedFile.JAVA_5) {
            super.atClreplacedObject2(cname);
        } else {
            bytecode.addLdc(bytecode.getConstPool().addClreplacedInfo(cname));
        }
    }

    @Override
    protected void atFieldPlusPlus(int token, boolean isPost, ASTree oprand, Expr expr, boolean doDup) throws CompileError {
        CtField f = fieldAccess(oprand, false);
        boolean is_static = resultStatic;
        if (!is_static) {
            bytecode.addOpcode(DUP);
        }
        int fi = atFieldRead(f, is_static);
        int t = exprType;
        boolean is2w = is2word(t, arrayDim);
        int dup_code;
        if (is_static) {
            dup_code = (is2w ? DUP2 : DUP);
        } else {
            dup_code = (is2w ? DUP2_X1 : DUP_X1);
        }
        atPlusPlusCore(dup_code, doDup, token, isPost, expr);
        atFieldreplacedignCore(f, is_static, fi, is2w);
    }

    /*
     * This method also returns a value in resultStatic.
     *
     * @param acceptLength true if array length is acceptable
     */
    protected CtField fieldAccess(ASTree expr, boolean acceptLength) throws CompileError {
        if (expr instanceof Member) {
            String name = ((Member) expr).get();
            CtField f = null;
            try {
                f = thisClreplaced.getField(name);
            } catch (NotFoundException e) {
                // EXPR might be part of a static member access?
                throw new NoFieldException(name, expr);
            }
            boolean is_static = Modifier.isStatic(f.getModifiers());
            if (!is_static) {
                if (inStaticMethod) {
                    throw new CompileError("not available in a static method: " + name);
                } else {
                    // this
                    bytecode.addAload(0);
                }
            }
            resultStatic = is_static;
            return f;
        } else if (expr instanceof Expr) {
            Expr e = (Expr) expr;
            int op = e.getOperator();
            if (op == MEMBER) {
                /*
                 * static member by # (extension by Javreplacedist)
                 * For example, if int.clreplaced is parsed, the resulting tree
                 * is (# "java.lang.Integer" "TYPE").
                 */
                CtField f = resolver.lookupField(((Symbol) e.oprand1()).get(), (Symbol) e.oprand2());
                resultStatic = true;
                return f;
            } else if (op == '.') {
                CtField f = null;
                try {
                    e.oprand1().accept(this);
                    /*
                     * Don't call lookupFieldByJvmName2().
                     * The left operand of . is not a clreplaced name but
                     * a normal expression.
                     */
                    if (exprType == CLreplaced && arrayDim == 0) {
                        f = resolver.lookupFieldByJvmName(clreplacedName, (Symbol) e.oprand2());
                    } else if (acceptLength && arrayDim > 0 && ((Symbol) e.oprand2()).get().equals("length")) {
                        // expr is an array length.
                        return null;
                    } else {
                        badLvalue();
                    }
                    boolean is_static = Modifier.isStatic(f.getModifiers());
                    if (is_static) {
                        bytecode.addOpcode(POP);
                    }
                    resultStatic = is_static;
                    return f;
                } catch (NoFieldException nfe) {
                    if (nfe.getExpr() != e.oprand1()) {
                        throw nfe;
                    }
                    /*
                     * EXPR should be a static field.
                     * If EXPR might be part of a qualified clreplaced name,
                     * lookupFieldByJvmName2() throws NoFieldException.
                     */
                    Symbol fname = (Symbol) e.oprand2();
                    String cname = nfe.getField();
                    f = resolver.lookupFieldByJvmName2(cname, fname, expr);
                    resultStatic = true;
                    return f;
                }
            } else {
                badLvalue();
            }
        } else {
            badLvalue();
        }
        resultStatic = false;
        // never reach
        return null;
    }

    private static void badLvalue() throws CompileError {
        throw new CompileError("bad l-value");
    }

    public CtClreplaced[] makeParamList(MethodDecl md) throws CompileError {
        CtClreplaced[] params;
        ASTList plist = md.getParams();
        if (plist == null) {
            params = new CtClreplaced[0];
        } else {
            int i = 0;
            params = new CtClreplaced[plist.length()];
            while (plist != null) {
                params[i++] = resolver.lookupClreplaced((Declarator) plist.head());
                plist = plist.tail();
            }
        }
        return params;
    }

    public CtClreplaced[] makeThrowsList(MethodDecl md) throws CompileError {
        CtClreplaced[] clist;
        ASTList list = md.getThrows();
        if (list == null) {
            return null;
        }
        int i = 0;
        clist = new CtClreplaced[list.length()];
        while (list != null) {
            clist[i++] = resolver.lookupClreplacedByName((ASTList) list.head());
            list = list.tail();
        }
        return clist;
    }

    /*
     * Converts a clreplaced name into a JVM-internal representation.
     *
     * It may also expand a simple clreplaced name to java.lang.*.
     * For example, this converts Object into java/lang/Object.
     */
    @Override
    protected String resolveClreplacedName(ASTList name) throws CompileError {
        return resolver.resolveClreplacedName(name);
    }

    /*
     * Expands a simple clreplaced name to java.lang.*.
     * For example, this converts Object into java/lang/Object.
     */
    @Override
    protected String resolveClreplacedName(String jvmName) throws CompileError {
        return resolver.resolveJvmClreplacedName(jvmName);
    }
}

19 Source : MemberCodeGen.java
with Apache License 2.0
from ifeilong

private boolean isEnclosing(CtClreplaced outer, CtClreplaced inner) {
    try {
        while (inner != null) {
            inner = inner.getDeclaringClreplaced();
            if (inner == outer) {
                return true;
            }
        }
    } catch (NotFoundException e) {
    }
    return false;
}

19 Source : JvstTypeChecker.java
with Apache License 2.0
from ifeilong

protected void compileUnwrapValue(CtClreplaced type) throws CompileError {
    if (type == CtClreplaced.voidType) {
        addNullIfVoid();
    } else {
        setType(type);
    }
}

19 Source : JvstTypeChecker.java
with Apache License 2.0
from ifeilong

/*
     * Sets exprType, arrayDim, and clreplacedName;
     * If type is void, then this method does nothing.
     */
public void setType(CtClreplaced type) throws CompileError {
    setType(type, 0);
}

19 Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong

/* Code generator accepting extended Java syntax for Javreplacedist.
 */
public clreplaced JvstCodeGen extends MemberCodeGen {

    String paramArrayName = null;

    String paramListName = null;

    CtClreplaced[] paramTypeList = null;

    // variable index for $0 or $1.
    private int paramVarBase = 0;

    // true if $0 is used.
    private boolean useParam0 = false;

    // JVM name
    private String param0Type = null;

    public static final String sigName = "$sig";

    public static final String dollarTypeName = "$type";

    public static final String clazzName = "$clreplaced";

    private CtClreplaced dollarType = null;

    CtClreplaced returnType = null;

    String returnCastName = null;

    @SuppressWarnings("unused")
    private String // null if $_ is not used.
    returnVarName = null;

    public static final String wrapperCastName = "$w";

    String proceedName = null;

    public static final String cflowName = "$cflow";

    // null if not used.
    ProceedHandler procHandler = null;

    public JvstCodeGen(Bytecode b, CtClreplaced cc, ClreplacedPool cp) {
        super(b, cc, cp);
        setTypeChecker(new JvstTypeChecker(cc, cp, this));
    }

    /*
     * Index of $1.
     */
    private int indexOfParam1() {
        return paramVarBase + (useParam0 ? 1 : 0);
    }

    /*
     * Records a ProceedHandler obejct.
     *
     * @param name the name of the special method call.
     * it is usually $proceed.
     */
    public void setProceedHandler(ProceedHandler h, String name) {
        proceedName = name;
        procHandler = h;
    }

    /*
     * If the type of the expression compiled last is void,
     * add ACONST_NULL and change exprType, arrayDim, clreplacedName.
     */
    public void addNullIfVoid() {
        if (exprType == VOID) {
            bytecode.addOpcode(ACONST_NULL);
            exprType = CLreplaced;
            arrayDim = 0;
            clreplacedName = jvmJavaLangObject;
        }
    }

    /*
     * To support $args, $sig, and $type.
     * $args is an array of parameter list.
     */
    @Override
    public void atMember(Member mem) throws CompileError {
        String name = mem.get();
        if (name.equals(paramArrayName)) {
            compileParameterList(bytecode, paramTypeList, indexOfParam1());
            exprType = CLreplaced;
            arrayDim = 1;
            clreplacedName = jvmJavaLangObject;
        } else if (name.equals(sigName)) {
            bytecode.addLdc(Descriptor.ofMethod(returnType, paramTypeList));
            bytecode.addInvokestatic("javreplacedist/runtime/Desc", "getParams", "(Ljava/lang/String;)[Ljava/lang/Clreplaced;");
            exprType = CLreplaced;
            arrayDim = 1;
            clreplacedName = "java/lang/Clreplaced";
        } else if (name.equals(dollarTypeName)) {
            if (dollarType == null) {
                throw new CompileError(dollarTypeName + " is not available");
            }
            bytecode.addLdc(Descriptor.of(dollarType));
            callGetType("getType");
        } else if (name.equals(clazzName)) {
            if (param0Type == null) {
                throw new CompileError(clazzName + " is not available");
            }
            bytecode.addLdc(param0Type);
            callGetType("getClazz");
        } else {
            super.atMember(mem);
        }
    }

    private void callGetType(String method) {
        bytecode.addInvokestatic("javreplacedist/runtime/Desc", method, "(Ljava/lang/String;)Ljava/lang/Clreplaced;");
        exprType = CLreplaced;
        arrayDim = 0;
        clreplacedName = "java/lang/Clreplaced";
    }

    @Override
    protected void atFieldreplacedign(Expr expr, int op, ASTree left, ASTree right, boolean doDup) throws CompileError {
        if (left instanceof Member && ((Member) left).get().equals(paramArrayName)) {
            if (op != '=') {
                throw new CompileError("bad operator for " + paramArrayName);
            }
            right.accept(this);
            if (arrayDim != 1 || exprType != CLreplaced) {
                throw new CompileError("invalid type for " + paramArrayName);
            }
            atreplacedignParamList(paramTypeList, bytecode);
            if (!doDup) {
                bytecode.addOpcode(POP);
            }
        } else {
            super.atFieldreplacedign(expr, op, left, right, doDup);
        }
    }

    protected void atreplacedignParamList(CtClreplaced[] params, Bytecode code) throws CompileError {
        if (params == null) {
            return;
        }
        int varNo = indexOfParam1();
        int n = params.length;
        for (int i = 0; i < n; ++i) {
            code.addOpcode(DUP);
            code.addIconst(i);
            code.addOpcode(AALOAD);
            compileUnwrapValue(params[i], code);
            code.addStore(varNo, params[i]);
            varNo += is2word(exprType, arrayDim) ? 2 : 1;
        }
    }

    @Override
    public void atCastExpr(CastExpr expr) throws CompileError {
        ASTList clreplacedname = expr.getClreplacedName();
        if (clreplacedname != null && expr.getArrayDim() == 0) {
            ASTree p = clreplacedname.head();
            if (p instanceof Symbol && clreplacedname.tail() == null) {
                String typename = ((Symbol) p).get();
                if (typename.equals(returnCastName)) {
                    atCastToRtype(expr);
                    return;
                } else if (typename.equals(wrapperCastName)) {
                    atCastToWrapper(expr);
                    return;
                }
            }
        }
        super.atCastExpr(expr);
    }

    /**
     * Inserts a cast operator to the return type.
     * If the return type is void, this does nothing.
     */
    protected void atCastToRtype(CastExpr expr) throws CompileError {
        expr.getOprand().accept(this);
        if (exprType == VOID || isRefType(exprType) || arrayDim > 0) {
            compileUnwrapValue(returnType, bytecode);
        } else if (returnType instanceof CtPrimitiveType) {
            CtPrimitiveType pt = (CtPrimitiveType) returnType;
            int destType = MemberResolver.descToType(pt.getDescriptor());
            atNumCastExpr(exprType, destType);
            exprType = destType;
            arrayDim = 0;
            clreplacedName = null;
        } else {
            throw new CompileError("invalid cast");
        }
    }

    protected void atCastToWrapper(CastExpr expr) throws CompileError {
        expr.getOprand().accept(this);
        if (isRefType(exprType) || arrayDim > 0) {
            // Object type.  do nothing.
            return;
        }
        CtClreplaced clazz = resolver.lookupClreplaced(exprType, arrayDim, clreplacedName);
        if (clazz instanceof CtPrimitiveType) {
            CtPrimitiveType pt = (CtPrimitiveType) clazz;
            String wrapper = pt.getWrapperName();
            // new <wrapper>
            bytecode.addNew(wrapper);
            // dup
            bytecode.addOpcode(DUP);
            if (pt.getDataSize() > 1) {
                // dup2_x2
                bytecode.addOpcode(DUP2_X2);
            } else {
                // dup2_x1
                bytecode.addOpcode(DUP2_X1);
            }
            // pop2
            bytecode.addOpcode(POP2);
            bytecode.addInvokespecial(wrapper, "<init>", "(" + pt.getDescriptor() + ")V");
            // invokespecial
            exprType = CLreplaced;
            arrayDim = 0;
            clreplacedName = jvmJavaLangObject;
        }
    }

    /*
     * Delegates to a ProcHandler object if the method call is
     * $proceed(). It may process $cflow().
     */
    @Override
    public void atCallExpr(CallExpr expr) throws CompileError {
        ASTree method = expr.oprand1();
        if (method instanceof Member) {
            String name = ((Member) method).get();
            if (procHandler != null && name.equals(proceedName)) {
                procHandler.doit(this, bytecode, (ASTList) expr.oprand2());
                return;
            } else if (name.equals(cflowName)) {
                atCflow((ASTList) expr.oprand2());
                return;
            }
        }
        super.atCallExpr(expr);
    }

    /*
     * To support $cflow().
     */
    protected void atCflow(ASTList cname) throws CompileError {
        StringBuffer sbuf = new StringBuffer();
        if (cname == null || cname.tail() != null) {
            throw new CompileError("bad " + cflowName);
        }
        makeCflowName(sbuf, cname.head());
        String name = sbuf.toString();
        Object[] names = resolver.getClreplacedPool().lookupCflow(name);
        if (names == null) {
            throw new CompileError("no such " + cflowName + ": " + name);
        }
        bytecode.addGetstatic((String) names[0], (String) names[1], "Ljavreplacedist/runtime/Cflow;");
        bytecode.addInvokevirtual(com.feilong.lib.javreplacedist.runtime.Cflow.clreplaced.getName(), "value", "()I");
        exprType = INT;
        arrayDim = 0;
        clreplacedName = null;
    }

    /*
     * Syntax:
     *
     * <cflow> : $cflow '(' <cflow name> ')'
     * <cflow name> : <identifier> ('.' <identifier>)*
     */
    private static void makeCflowName(StringBuffer sbuf, ASTree name) throws CompileError {
        if (name instanceof Symbol) {
            sbuf.append(((Symbol) name).get());
            return;
        } else if (name instanceof Expr) {
            Expr expr = (Expr) name;
            if (expr.getOperator() == '.') {
                makeCflowName(sbuf, expr.oprand1());
                sbuf.append('.');
                makeCflowName(sbuf, expr.oprand2());
                return;
            }
        }
        throw new CompileError("bad " + cflowName);
    }

    /*
     * To support $$. ($$) is equivalent to ($1, ..., $n).
     * It can be used only as a parameter list of method call.
     */
    public boolean isParamListName(ASTList args) {
        if (paramTypeList != null && args != null && args.tail() == null) {
            ASTree left = args.head();
            return (left instanceof Member && ((Member) left).get().equals(paramListName));
        }
        return false;
    }

    /*
     * public int getMethodArgsLength(ASTList args) {
     * if (!isParamListName(args))
     * return super.getMethodArgsLength(args);
     * 
     * return paramTypeList.length;
     * }
     */
    @Override
    public int getMethodArgsLength(ASTList args) {
        String pname = paramListName;
        int n = 0;
        while (args != null) {
            ASTree a = args.head();
            if (a instanceof Member && ((Member) a).get().equals(pname)) {
                if (paramTypeList != null) {
                    n += paramTypeList.length;
                }
            } else {
                ++n;
            }
            args = args.tail();
        }
        return n;
    }

    @Override
    public void atMethodArgs(ASTList args, int[] types, int[] dims, String[] cnames) throws CompileError {
        CtClreplaced[] params = paramTypeList;
        String pname = paramListName;
        int i = 0;
        while (args != null) {
            ASTree a = args.head();
            if (a instanceof Member && ((Member) a).get().equals(pname)) {
                if (params != null) {
                    int n = params.length;
                    int regno = indexOfParam1();
                    for (int k = 0; k < n; ++k) {
                        CtClreplaced p = params[k];
                        regno += bytecode.addLoad(regno, p);
                        setType(p);
                        types[i] = exprType;
                        dims[i] = arrayDim;
                        cnames[i] = clreplacedName;
                        ++i;
                    }
                }
            } else {
                a.accept(this);
                types[i] = exprType;
                dims[i] = arrayDim;
                cnames[i] = clreplacedName;
                ++i;
            }
            args = args.tail();
        }
    }

    /*
     * public void atMethodArgs(ASTList args, int[] types, int[] dims,
     * String[] cnames) throws CompileError {
     * if (!isParamListName(args)) {
     * super.atMethodArgs(args, types, dims, cnames);
     * return;
     * }
     * 
     * CtClreplaced[] params = paramTypeList;
     * if (params == null)
     * return;
     * 
     * int n = params.length;
     * int regno = indexOfParam1();
     * for (int i = 0; i < n; ++i) {
     * CtClreplaced p = params[i];
     * regno += bytecode.addLoad(regno, p);
     * setType(p);
     * types[i] = exprType;
     * dims[i] = arrayDim;
     * cnames[i] = clreplacedName;
     * }
     * }
     */
    /*
     * called by Javac#recordSpecialProceed().
     */
    void compileInvokeSpecial(ASTree target, int methodIndex, String descriptor, ASTList args) throws CompileError {
        target.accept(this);
        int nargs = getMethodArgsLength(args);
        atMethodArgs(args, new int[nargs], new int[nargs], new String[nargs]);
        bytecode.addInvokespecial(methodIndex, descriptor);
        setReturnType(descriptor, false, false);
        addNullIfVoid();
    }

    /*
     * Makes it valid to write "return <expr>;" for a void method.
     */
    @Override
    protected void atReturnStmnt(Stmnt st) throws CompileError {
        ASTree result = st.getLeft();
        if (result != null && returnType == CtClreplaced.voidType) {
            compileExpr(result);
            if (is2word(exprType, arrayDim)) {
                bytecode.addOpcode(POP2);
            } else if (exprType != VOID) {
                bytecode.addOpcode(POP);
            }
            result = null;
        }
        atReturnStmnt2(result);
    }

    /**
     * Makes a cast to the return type ($r) available.
     * It also enables $_.
     *
     * <p>
     * If the return type is void, ($r) does nothing.
     * The type of $_ is java.lang.Object.
     *
     * @param resultName
     *            null if $_ is not used.
     * @return -1 or the variable index replacedigned to $_.
     */
    public int recordReturnType(CtClreplaced type, String castName, String resultName, SymbolTable tbl) throws CompileError {
        returnType = type;
        returnCastName = castName;
        returnVarName = resultName;
        if (resultName == null) {
            return -1;
        }
        int varNo = getMaxLocals();
        int locals = varNo + recordVar(type, resultName, varNo, tbl);
        setMaxLocals(locals);
        return varNo;
    }

    /**
     * Makes $type available.
     */
    public void recordType(CtClreplaced t) {
        dollarType = t;
    }

    /**
     * Makes method parameters $0, $1, ..., $args, $$, and $clreplaced available.
     * $0 is equivalent to THIS if the method is not static. Otherwise,
     * if the method is static, then $0 is not available.
     */
    public int recordParams(CtClreplaced[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, SymbolTable tbl) throws CompileError {
        return recordParams(params, isStatic, prefix, paramVarName, paramsName, !isStatic, 0, getThisName(), tbl);
    }

    /**
     * Makes method parameters $0, $1, ..., $args, $$, and $clreplaced available.
     * $0 is available only if use0 is true. It might not be equivalent
     * to THIS.
     *
     * @param params
     *            the parameter types (the types of $1, $2, ..)
     * @param prefix
     *            it must be "$" (the first letter of $0, $1, ...)
     * @param paramVarName
     *            it must be "$args"
     * @param paramsName
     *            it must be "$$"
     * @param use0
     *            true if $0 is used.
     * @param paramBase
     *            the register number of $0 (use0 is true)
     *            or $1 (otherwise).
     * @param target
     *            the clreplaced of $0. If use0 is false, target
     *            can be null. The value of "target" is also used
     *            as the name of the type represented by $clreplaced.
     * @param isStatic
     *            true if the method in which the compiled bytecode
     *            is embedded is static.
     */
    public int recordParams(CtClreplaced[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, boolean use0, int paramBase, String target, SymbolTable tbl) throws CompileError {
        int varNo;
        paramTypeList = params;
        paramArrayName = paramVarName;
        paramListName = paramsName;
        paramVarBase = paramBase;
        useParam0 = use0;
        if (target != null) {
            param0Type = MemberResolver.jvmToJavaName(target);
        }
        inStaticMethod = isStatic;
        varNo = paramBase;
        if (use0) {
            String varName = prefix + "0";
            Declarator decl = new Declarator(CLreplaced, MemberResolver.javaToJvmName(target), 0, varNo++, new Symbol(varName));
            tbl.append(varName, decl);
        }
        for (int i = 0; i < params.length; ++i) {
            varNo += recordVar(params[i], prefix + (i + 1), varNo, tbl);
        }
        if (getMaxLocals() < varNo) {
            setMaxLocals(varNo);
        }
        return varNo;
    }

    /**
     * Makes the given variable name available.
     *
     * @param type
     *            variable type
     * @param varName
     *            variable name
     */
    public int recordVariable(CtClreplaced type, String varName, SymbolTable tbl) throws CompileError {
        if (varName == null) {
            return -1;
        }
        int varNo = getMaxLocals();
        int locals = varNo + recordVar(type, varName, varNo, tbl);
        setMaxLocals(locals);
        return varNo;
    }

    private int recordVar(CtClreplaced cc, String varName, int varNo, SymbolTable tbl) throws CompileError {
        if (cc == CtClreplaced.voidType) {
            exprType = CLreplaced;
            arrayDim = 0;
            clreplacedName = jvmJavaLangObject;
        } else {
            setType(cc);
        }
        Declarator decl = new Declarator(exprType, clreplacedName, arrayDim, varNo, new Symbol(varName));
        tbl.append(varName, decl);
        return is2word(exprType, arrayDim) ? 2 : 1;
    }

    /**
     * Makes the given variable name available.
     *
     * @param typeDesc
     *            the type descriptor of the variable
     * @param varName
     *            variable name
     * @param varNo
     *            an index into the local variable array
     */
    public void recordVariable(String typeDesc, String varName, int varNo, SymbolTable tbl) throws CompileError {
        char c;
        int dim = 0;
        while ((c = typeDesc.charAt(dim)) == '[') {
            ++dim;
        }
        int type = MemberResolver.descToType(c);
        String cname = null;
        if (type == CLreplaced) {
            if (dim == 0) {
                cname = typeDesc.substring(1, typeDesc.length() - 1);
            } else {
                cname = typeDesc.substring(dim + 1, typeDesc.length() - 1);
            }
        }
        Declarator decl = new Declarator(type, cname, dim, varNo, new Symbol(varName));
        tbl.append(varName, decl);
    }

    /*
     * compileParameterList() returns the stack size used
     * by the produced code.
     *
     * This method correctly computes the max_stack value.
     *
     * @param regno the index of the local variable in which
     * the first argument is received.
     * (0: static method, 1: regular method.)
     */
    public static int compileParameterList(Bytecode code, CtClreplaced[] params, int regno) {
        if (params == null) {
            // iconst_0
            code.addIconst(0);
            // anewarray Object
            code.addAnewarray(javaLangObject);
            return 1;
        }
        CtClreplaced[] args = new CtClreplaced[1];
        int n = params.length;
        // iconst_<n>
        code.addIconst(n);
        // anewarray Object
        code.addAnewarray(javaLangObject);
        for (int i = 0; i < n; ++i) {
            // dup
            code.addOpcode(Opcode.DUP);
            // iconst_<i>
            code.addIconst(i);
            if (params[i].isPrimitive()) {
                CtPrimitiveType pt = (CtPrimitiveType) params[i];
                String wrapper = pt.getWrapperName();
                // new <wrapper>
                code.addNew(wrapper);
                // dup
                code.addOpcode(Opcode.DUP);
                // ?load <regno>
                int s = code.addLoad(regno, pt);
                regno += s;
                args[0] = pt;
                code.addInvokespecial(wrapper, "<init>", Descriptor.ofMethod(CtClreplaced.voidType, args));
            // invokespecial
            } else {
                // aload <regno>
                code.addAload(regno);
                ++regno;
            }
            // aastore
            code.addOpcode(Opcode.AASTORE);
        }
        return 8;
    }

    protected void compileUnwrapValue(CtClreplaced type, Bytecode code) throws CompileError {
        if (type == CtClreplaced.voidType) {
            addNullIfVoid();
            return;
        }
        if (exprType == VOID) {
            throw new CompileError("invalid type for " + returnCastName);
        }
        if (type instanceof CtPrimitiveType) {
            CtPrimitiveType pt = (CtPrimitiveType) type;
            // pt is not voidType.
            String wrapper = pt.getWrapperName();
            code.addCheckcast(wrapper);
            code.addInvokevirtual(wrapper, pt.getGetMethodName(), pt.getGetMethodDescriptor());
            setType(type);
        } else {
            code.addCheckcast(type);
            setType(type);
        }
    }

    /*
     * Sets exprType, arrayDim, and clreplacedName;
     * If type is void, then this method does nothing.
     */
    public void setType(CtClreplaced type) throws CompileError {
        setType(type, 0);
    }

    private void setType(CtClreplaced type, int dim) throws CompileError {
        if (type.isPrimitive()) {
            CtPrimitiveType pt = (CtPrimitiveType) type;
            exprType = MemberResolver.descToType(pt.getDescriptor());
            arrayDim = dim;
            clreplacedName = null;
        } else if (type.isArray()) {
            try {
                setType(type.getComponentType(), dim + 1);
            } catch (NotFoundException e) {
                throw new CompileError("undefined type: " + type.getName());
            }
        } else {
            exprType = CLreplaced;
            arrayDim = dim;
            clreplacedName = MemberResolver.javaToJvmName(type.getName());
        }
    }

    /*
     * Performs implicit coercion from exprType to type.
     */
    public void doNumCast(CtClreplaced type) throws CompileError {
        if (arrayDim == 0 && !isRefType(exprType)) {
            if (type instanceof CtPrimitiveType) {
                CtPrimitiveType pt = (CtPrimitiveType) type;
                atNumCastExpr(exprType, MemberResolver.descToType(pt.getDescriptor()));
            } else {
                throw new CompileError("type mismatch");
            }
        }
    }
}

19 Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong

/**
 * Makes a cast to the return type ($r) available.
 * It also enables $_.
 *
 * <p>
 * If the return type is void, ($r) does nothing.
 * The type of $_ is java.lang.Object.
 *
 * @param resultName
 *            null if $_ is not used.
 * @return -1 or the variable index replacedigned to $_.
 */
public int recordReturnType(CtClreplaced type, String castName, String resultName, SymbolTable tbl) throws CompileError {
    returnType = type;
    returnCastName = castName;
    returnVarName = resultName;
    if (resultName == null) {
        return -1;
    }
    int varNo = getMaxLocals();
    int locals = varNo + recordVar(type, resultName, varNo, tbl);
    setMaxLocals(locals);
    return varNo;
}

19 Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong

/**
 * Makes $type available.
 */
public void recordType(CtClreplaced t) {
    dollarType = t;
}

19 Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong

/**
 * Makes method parameters $0, $1, ..., $args, $$, and $clreplaced available.
 * $0 is equivalent to THIS if the method is not static. Otherwise,
 * if the method is static, then $0 is not available.
 */
public int recordParams(CtClreplaced[] params, boolean isStatic, String prefix, String paramVarName, String paramsName, SymbolTable tbl) throws CompileError {
    return recordParams(params, isStatic, prefix, paramVarName, paramsName, !isStatic, 0, getThisName(), tbl);
}

19 Source : JvstCodeGen.java
with Apache License 2.0
from ifeilong

/**
 * Makes the given variable name available.
 *
 * @param type
 *            variable type
 * @param varName
 *            variable name
 */
public int recordVariable(CtClreplaced type, String varName, SymbolTable tbl) throws CompileError {
    if (varName == null) {
        return -1;
    }
    int varNo = getMaxLocals();
    int locals = varNo + recordVar(type, varName, varNo, tbl);
    setMaxLocals(locals);
    return varNo;
}

19 Source : Javac.java
with Apache License 2.0
from ifeilong

/**
 * Prepares to use cast $r, $w, $_, and $type.
 * $type is made to represent the specified return type.
 * It also enables to write a return statement with a return value
 * for void method.
 *
 * <p>
 * If the return type is void, ($r) does nothing.
 * The type of $_ is java.lang.Object.
 *
 * @param type
 *            the return type.
 * @param useResultVar
 *            true if $_ is used.
 * @return -1 or the variable index replacedigned to $_.
 * @see #recordType(CtClreplaced)
 */
public int recordReturnType(CtClreplaced type, boolean useResultVar) throws CompileError {
    gen.recordType(type);
    return gen.recordReturnType(type, "$r", (useResultVar ? resultVarName : null), stable);
}

19 Source : Javac.java
with Apache License 2.0
from ifeilong

/**
 * Makes variables $0, $1, $2, ..., and $args represent method
 * parameters. $args represents an array of all the parameters.
 * It also makes $$ available as a parameter list of method call.
 * $0 can represent a local variable other than THIS (variable 0).
 * $clreplaced is also made available.
 *
 * <p>
 * This must be called before calling <code>compileStmnt()</code> and
 * <code>compileExpr()</code>. The correct value of
 * <code>isStatic</code> must be recorded before compilation.
 * <code>maxLocals</code> is updated to include $0,...
 *
 * @param use0
 *            true if $0 is used.
 * @param varNo
 *            the register number of $0 (use0 is true)
 *            or $1 (otherwise).
 * @param target
 *            the type of $0 (it can be null if use0 is false).
 *            It is used as the name of the type represented
 *            by $clreplaced.
 * @param isStatic
 *            true if the method in which the compiled bytecode
 *            is embedded is static.
 */
public int recordParams(String target, CtClreplaced[] params, boolean use0, int varNo, boolean isStatic) throws CompileError {
    return gen.recordParams(params, isStatic, "$", "$args", "$$", use0, varNo, target, stable);
}

19 Source : Javac.java
with Apache License 2.0
from ifeilong

/**
 * Makes the given variable available.
 *
 * @param type
 *            variable type
 * @param name
 *            variable name
 */
public int recordVariable(CtClreplaced type, String name) throws CompileError {
    return gen.recordVariable(type, name, stable);
}

19 Source : Javac.java
with Apache License 2.0
from ifeilong

/**
 * Prepares to use $type. Note that recordReturnType() overwrites
 * the value of $type.
 *
 * @param t
 *            the type represented by $type.
 */
public void recordType(CtClreplaced t) {
    gen.recordType(t);
}

19 Source : Javac.java
with Apache License 2.0
from ifeilong

/**
 * Makes variables $0 (this), $1, $2, ..., and $args represent method
 * parameters. $args represents an array of all the parameters.
 * It also makes $$ available as a parameter list of method call.
 *
 * <p>
 * This must be called before calling <code>compileStmnt()</code> and
 * <code>compileExpr()</code>. The correct value of
 * <code>isStatic</code> must be recorded before compilation.
 * <code>maxLocals</code> is updated to include $0,...
 */
public int recordParams(CtClreplaced[] params, boolean isStatic) throws CompileError {
    return gen.recordParams(params, isStatic, "$", "$args", "$$", stable);
}

19 Source : AccessorMaker.java
with Apache License 2.0
from ifeilong

/**
 * AccessorMaker maintains accessors to private members of an enclosing
 * clreplaced. It is necessary for compiling a method in an inner clreplaced.
 */
public clreplaced AccessorMaker {

    private final CtClreplaced clazz;

    private int uniqueNumber;

    private final Map<String, Object> accessors;

    static final String lastParamType = com.feilong.lib.javreplacedist.runtime.Inner.clreplaced.getName();

    public AccessorMaker(CtClreplaced c) {
        clazz = c;
        uniqueNumber = 1;
        accessors = new HashMap<>();
    }

    public String getConstructor(CtClreplaced c, String desc, MethodInfo orig) throws CompileError {
        String key = "<init>:" + desc;
        String consDesc = (String) accessors.get(key);
        if (consDesc != null) {
            // already exists.
            return consDesc;
        }
        consDesc = Descriptor.appendParameter(lastParamType, desc);
        // turn on the modified flag.
        ClreplacedFile cf = clazz.getClreplacedFile();
        try {
            ConstPool cp = cf.getConstPool();
            ClreplacedPool pool = clazz.getClreplacedPool();
            MethodInfo minfo = new MethodInfo(cp, MethodInfo.nameInit, consDesc);
            minfo.setAccessFlags(0);
            minfo.addAttribute(new SyntheticAttribute(cp));
            ExceptionsAttribute ea = orig.getExceptionsAttribute();
            if (ea != null) {
                minfo.addAttribute(ea.copy(cp, null));
            }
            CtClreplaced[] params = Descriptor.getParameterTypes(desc, pool);
            Bytecode code = new Bytecode(cp);
            code.addAload(0);
            int regno = 1;
            for (CtClreplaced param : params) {
                regno += code.addLoad(regno, param);
            }
            // the last parameter is added.
            code.setMaxLocals(regno + 1);
            code.addInvokespecial(clazz, MethodInfo.nameInit, desc);
            code.addReturn(null);
            minfo.setCodeAttribute(code.toCodeAttribute());
            cf.addMethod(minfo);
        } catch (CannotCompileException e) {
            throw new CompileError(e);
        } catch (NotFoundException e) {
            throw new CompileError(e);
        }
        accessors.put(key, consDesc);
        return consDesc;
    }

    /**
     * Returns the name of the method for accessing a private method.
     *
     * @param name
     *            the name of the private method.
     * @param desc
     *            the descriptor of the private method.
     * @param accDesc
     *            the descriptor of the accessor method. The first
     *            parameter type is <code>clazz</code>.
     *            If the private method is static,
     *            <code>accDesc</code> must be identical to <code>desc</code>.
     *
     * @param orig
     *            the method info of the private method.
     * @return
     */
    public String getMethodAccessor(String name, String desc, String accDesc, MethodInfo orig) throws CompileError {
        String key = name + ":" + desc;
        String accName = (String) accessors.get(key);
        if (accName != null) {
            // already exists.
            return accName;
        }
        // turn on the modified flag.
        ClreplacedFile cf = clazz.getClreplacedFile();
        accName = findAccessorName(cf);
        try {
            ConstPool cp = cf.getConstPool();
            ClreplacedPool pool = clazz.getClreplacedPool();
            MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
            minfo.setAccessFlags(AccessFlag.STATIC);
            minfo.addAttribute(new SyntheticAttribute(cp));
            ExceptionsAttribute ea = orig.getExceptionsAttribute();
            if (ea != null) {
                minfo.addAttribute(ea.copy(cp, null));
            }
            CtClreplaced[] params = Descriptor.getParameterTypes(accDesc, pool);
            int regno = 0;
            Bytecode code = new Bytecode(cp);
            for (CtClreplaced param : params) {
                regno += code.addLoad(regno, param);
            }
            code.setMaxLocals(regno);
            if (desc == accDesc) {
                code.addInvokestatic(clazz, name, desc);
            } else {
                code.addInvokevirtual(clazz, name, desc);
            }
            code.addReturn(Descriptor.getReturnType(desc, pool));
            minfo.setCodeAttribute(code.toCodeAttribute());
            cf.addMethod(minfo);
        } catch (CannotCompileException e) {
            throw new CompileError(e);
        } catch (NotFoundException e) {
            throw new CompileError(e);
        }
        accessors.put(key, accName);
        return accName;
    }

    /**
     * Returns the method_info representing the added getter.
     */
    public MethodInfo getFieldGetter(FieldInfo finfo, boolean is_static) throws CompileError {
        String fieldName = finfo.getName();
        String key = fieldName + ":getter";
        Object res = accessors.get(key);
        if (res != null) {
            // already exists.
            return (MethodInfo) res;
        }
        // turn on the modified flag.
        ClreplacedFile cf = clazz.getClreplacedFile();
        String accName = findAccessorName(cf);
        try {
            ConstPool cp = cf.getConstPool();
            ClreplacedPool pool = clazz.getClreplacedPool();
            String fieldType = finfo.getDescriptor();
            String accDesc;
            if (is_static) {
                accDesc = "()" + fieldType;
            } else {
                accDesc = "(" + Descriptor.of(clazz) + ")" + fieldType;
            }
            MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
            minfo.setAccessFlags(AccessFlag.STATIC);
            minfo.addAttribute(new SyntheticAttribute(cp));
            Bytecode code = new Bytecode(cp);
            if (is_static) {
                code.addGetstatic(Bytecode.THIS, fieldName, fieldType);
            } else {
                code.addAload(0);
                code.addGetfield(Bytecode.THIS, fieldName, fieldType);
                code.setMaxLocals(1);
            }
            code.addReturn(Descriptor.toCtClreplaced(fieldType, pool));
            minfo.setCodeAttribute(code.toCodeAttribute());
            cf.addMethod(minfo);
            accessors.put(key, minfo);
            return minfo;
        } catch (CannotCompileException e) {
            throw new CompileError(e);
        } catch (NotFoundException e) {
            throw new CompileError(e);
        }
    }

    /**
     * Returns the method_info representing the added setter.
     */
    public MethodInfo getFieldSetter(FieldInfo finfo, boolean is_static) throws CompileError {
        String fieldName = finfo.getName();
        String key = fieldName + ":setter";
        Object res = accessors.get(key);
        if (res != null) {
            // already exists.
            return (MethodInfo) res;
        }
        // turn on the modified flag.
        ClreplacedFile cf = clazz.getClreplacedFile();
        String accName = findAccessorName(cf);
        try {
            ConstPool cp = cf.getConstPool();
            ClreplacedPool pool = clazz.getClreplacedPool();
            String fieldType = finfo.getDescriptor();
            String accDesc;
            if (is_static) {
                accDesc = "(" + fieldType + ")V";
            } else {
                accDesc = "(" + Descriptor.of(clazz) + fieldType + ")V";
            }
            MethodInfo minfo = new MethodInfo(cp, accName, accDesc);
            minfo.setAccessFlags(AccessFlag.STATIC);
            minfo.addAttribute(new SyntheticAttribute(cp));
            Bytecode code = new Bytecode(cp);
            int reg;
            if (is_static) {
                reg = code.addLoad(0, Descriptor.toCtClreplaced(fieldType, pool));
                code.addPutstatic(Bytecode.THIS, fieldName, fieldType);
            } else {
                code.addAload(0);
                reg = code.addLoad(1, Descriptor.toCtClreplaced(fieldType, pool)) + 1;
                code.addPutfield(Bytecode.THIS, fieldName, fieldType);
            }
            code.addReturn(null);
            code.setMaxLocals(reg);
            minfo.setCodeAttribute(code.toCodeAttribute());
            cf.addMethod(minfo);
            accessors.put(key, minfo);
            return minfo;
        } catch (CannotCompileException e) {
            throw new CompileError(e);
        } catch (NotFoundException e) {
            throw new CompileError(e);
        }
    }

    private String findAccessorName(ClreplacedFile cf) {
        String accName;
        do {
            accName = "access$" + uniqueNumber++;
        } while (cf.getMethod(accName) != null);
        return accName;
    }
}

19 Source : TypeData.java
with Apache License 2.0
from ifeilong

static boolean eq(CtClreplaced one, CtClreplaced two) {
    return one == two || (one != null && two != null && one.getName().equals(two.getName()));
}

19 Source : TypeData.java
with Apache License 2.0
from ifeilong

/**
 * Finds the most specific common super clreplaced of the given clreplacedes
 * by considering array types.
 */
public static CtClreplaced commonSuperClreplacedEx(CtClreplaced one, CtClreplaced two) throws NotFoundException {
    if (one == two) {
        return one;
    } else if (one.isArray() && two.isArray()) {
        CtClreplaced ele1 = one.getComponentType();
        CtClreplaced ele2 = two.getComponentType();
        CtClreplaced element = commonSuperClreplacedEx(ele1, ele2);
        if (element == ele1) {
            return one;
        } else if (element == ele2) {
            return two;
        } else {
            return one.getClreplacedPool().get(element == null ? "java.lang.Object" : element.getName() + "[]");
        }
    } else if (one.isPrimitive() || two.isPrimitive()) {
        // TOP
        return null;
    } else if (one.isArray() || two.isArray()) {
        return one.getClreplacedPool().get("java.lang.Object");
    } else {
        return commonSuperClreplaced(one, two);
    }
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Returns a <code>CtClreplaced</code> object representing the type
 * specified by the given descriptor.
 *
 * <p>
 * This method works even if the package-clreplaced separator is
 * not <code>/</code> but <code>.</code> (period). For example,
 * it accepts <code>Ljava.lang.Object;</code>
 * as well as <code>Ljava/lang/Object;</code>.
 *
 * @param desc
 *            descriptor.
 * @param cp
 *            the clreplaced pool used for obtaining
 *            a <code>CtClreplaced</code> object.
 */
public static CtClreplaced toCtClreplaced(String desc, ClreplacedPool cp) throws NotFoundException {
    CtClreplaced[] clazz = new CtClreplaced[1];
    int res = toCtClreplaced(cp, desc, 0, clazz, 0);
    if (res >= 0) {
        return clazz[0];
    }
    // maybe, you forgot to surround the clreplaced name with
    // L and ;.  It violates the protocol, but I'm tolerant...
    return cp.get(desc.replace('/', '.'));
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

static CtClreplaced toPrimitiveClreplaced(char c) {
    CtClreplaced type = null;
    switch(c) {
        case 'Z':
            type = CtClreplaced.booleanType;
            break;
        case 'C':
            type = CtClreplaced.charType;
            break;
        case 'B':
            type = CtClreplaced.byteType;
            break;
        case 'S':
            type = CtClreplaced.shortType;
            break;
        case 'I':
            type = CtClreplaced.intType;
            break;
        case 'J':
            type = CtClreplaced.longType;
            break;
        case 'F':
            type = CtClreplaced.floatType;
            break;
        case 'D':
            type = CtClreplaced.doubleType;
            break;
        case 'V':
            type = CtClreplaced.voidType;
            break;
    }
    return type;
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Inserts a parameter type at the beginning of the parameter
 * list represented
 * by the given descriptor.
 *
 * @param type
 *            the type of the inserted parameter.
 * @param descriptor
 *            the descriptor of the method.
 */
public static String insertParameter(CtClreplaced type, String descriptor) {
    if (descriptor.charAt(0) != '(') {
        return descriptor;
    }
    return "(" + of(type) + descriptor.substring(1);
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Returns the <code>CtClreplaced</code> objects representing the parameter
 * types specified by the given descriptor.
 *
 * @param desc
 *            descriptor
 * @param cp
 *            the clreplaced pool used for obtaining
 *            a <code>CtClreplaced</code> object.
 */
public static CtClreplaced[] getParameterTypes(String desc, ClreplacedPool cp) throws NotFoundException {
    if (desc.charAt(0) != '(') {
        return null;
    }
    int num = numOfParameters(desc);
    CtClreplaced[] args = new CtClreplaced[num];
    int n = 0;
    int i = 1;
    do {
        i = toCtClreplaced(cp, desc, i, args, n++);
    } while (i > 0);
    return args;
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Returns the descriptor representing a list of parameter types.
 * For example, if the given parameter types are two <code>int</code>,
 * then this method returns <code>"(II)"</code>.
 *
 * @param paramTypes
 *            parameter types
 */
public static String ofParameters(CtClreplaced[] paramTypes) {
    return ofMethod(null, paramTypes);
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Returns the descriptor representing a method that receives
 * the given parameter types and returns the given type.
 *
 * @param returnType
 *            return type
 * @param paramTypes
 *            parameter types
 */
public static String ofMethod(CtClreplaced returnType, CtClreplaced[] paramTypes) {
    StringBuffer desc = new StringBuffer();
    desc.append('(');
    if (paramTypes != null) {
        int n = paramTypes.length;
        for (int i = 0; i < n; ++i) {
            toDescriptor(desc, paramTypes[i]);
        }
    }
    desc.append(')');
    if (returnType != null) {
        toDescriptor(desc, returnType);
    }
    return desc.toString();
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Returns the descriptor representing a constructor receiving
 * the given parameter types.
 *
 * @param paramTypes
 *            parameter types
 */
public static String ofConstructor(CtClreplaced[] paramTypes) {
    return ofMethod(CtClreplaced.voidType, paramTypes);
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Returns the <code>CtClreplaced</code> object representing the return
 * type specified by the given descriptor.
 *
 * @param desc
 *            descriptor
 * @param cp
 *            the clreplaced pool used for obtaining
 *            a <code>CtClreplaced</code> object.
 */
public static CtClreplaced getReturnType(String desc, ClreplacedPool cp) throws NotFoundException {
    int i = desc.indexOf(')');
    if (i < 0) {
        return null;
    }
    CtClreplaced[] type = new CtClreplaced[1];
    toCtClreplaced(cp, desc, i + 1, type, 0);
    return type[0];
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

private static int toCtClreplaced(ClreplacedPool cp, String desc, int i, CtClreplaced[] args, int n) throws NotFoundException {
    int i2;
    String name;
    int arrayDim = 0;
    char c = desc.charAt(i);
    while (c == '[') {
        ++arrayDim;
        c = desc.charAt(++i);
    }
    if (c == 'L') {
        i2 = desc.indexOf(';', ++i);
        name = desc.substring(i, i2++).replace('/', '.');
    } else {
        CtClreplaced type = toPrimitiveClreplaced(c);
        if (type == null) {
            // error
            return -1;
        }
        i2 = i + 1;
        if (arrayDim == 0) {
            args[n] = type;
            // neither an array type or a clreplaced type
            return i2;
        }
        name = type.getName();
    }
    if (arrayDim > 0) {
        StringBuffer sbuf = new StringBuffer(name);
        while (arrayDim-- > 0) {
            sbuf.append("[]");
        }
        name = sbuf.toString();
    }
    args[n] = cp.get(name);
    return i2;
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Appends a parameter type to the parameter list represented
 * by the given descriptor. The appended parameter becomes
 * the last parameter.
 *
 * @param type
 *            the type of the appended parameter.
 * @param descriptor
 *            the original descriptor.
 */
public static String appendParameter(CtClreplaced type, String descriptor) {
    int i = descriptor.indexOf(')');
    if (i < 0) {
        return descriptor;
    }
    StringBuffer newdesc = new StringBuffer();
    newdesc.append(descriptor.substring(0, i));
    toDescriptor(newdesc, type);
    newdesc.append(descriptor.substring(i));
    return newdesc.toString();
}

19 Source : Descriptor.java
with Apache License 2.0
from ifeilong

/**
 * Returns the descriptor representing the given type.
 */
public static String of(CtClreplaced type) {
    StringBuffer sbuf = new StringBuffer();
    toDescriptor(sbuf, type);
    return sbuf.toString();
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

/**
 * A utility clreplaced for producing a bytecode sequence.
 *
 * <p>
 * A <code>Bytecode</code> object is an unbounded array
 * containing bytecode. For example,
 *
 * <pre>
 * ConstPool cp = ...;    // constant pool table
 * Bytecode b = new Bytecode(cp, 1, 0);
 * b.addIconst(3);
 * b.addReturn(CtClreplaced.intType);
 * CodeAttribute ca = b.toCodeAttribute();
 * </pre>
 *
 * <p>
 * This program produces a Code attribute including a bytecode
 * sequence:
 *
 * <pre>
 * iconst_3
 * ireturn
 * </pre>
 *
 * @see ConstPool
 * @see CodeAttribute
 */
public clreplaced Bytecode extends ByteVector implements Cloneable, Opcode {

    /**
     * Represents the <code>CtClreplaced</code> file using the
     * constant pool table given to this <code>Bytecode</code> object.
     */
    public static final CtClreplaced THIS = ConstPool.THIS;

    ConstPool constPool;

    int maxStack, maxLocals;

    ExceptionTable tryblocks;

    private int stackDepth;

    /**
     * Constructs a <code>Bytecode</code> object with an empty bytecode
     * sequence.
     *
     * <p>
     * The parameters <code>stacksize</code> and <code>localvars</code>
     * specify initial values
     * of <code>max_stack</code> and <code>max_locals</code>.
     * They can be changed later.
     *
     * @param cp
     *            constant pool table.
     * @param stacksize
     *            <code>max_stack</code>.
     * @param localvars
     *            <code>max_locals</code>.
     */
    public Bytecode(ConstPool cp, int stacksize, int localvars) {
        constPool = cp;
        maxStack = stacksize;
        maxLocals = localvars;
        tryblocks = new ExceptionTable(cp);
        stackDepth = 0;
    }

    /**
     * Constructs a <code>Bytecode</code> object with an empty bytecode
     * sequence. The initial values of <code>max_stack</code> and
     * <code>max_locals</code> are zero.
     *
     * @param cp
     *            constant pool table.
     * @see Bytecode#setMaxStack(int)
     * @see Bytecode#setMaxLocals(int)
     */
    public Bytecode(ConstPool cp) {
        this(cp, 0, 0);
    }

    /**
     * Creates and returns a copy of this object.
     * The constant pool object is shared between this object
     * and the cloned object.
     */
    @Override
    public Object clone() {
        try {
            Bytecode bc = (Bytecode) super.clone();
            bc.tryblocks = (ExceptionTable) tryblocks.clone();
            return bc;
        } catch (CloneNotSupportedException cnse) {
            throw new RuntimeException(cnse);
        }
    }

    /**
     * Gets a constant pool table.
     */
    public ConstPool getConstPool() {
        return constPool;
    }

    /**
     * Returns <code>exception_table</code>.
     */
    public ExceptionTable getExceptionTable() {
        return tryblocks;
    }

    /**
     * Converts to a <code>CodeAttribute</code>.
     */
    public CodeAttribute toCodeAttribute() {
        return new CodeAttribute(constPool, maxStack, maxLocals, get(), tryblocks);
    }

    /**
     * Returns the length of the bytecode sequence.
     */
    public int length() {
        return getSize();
    }

    /**
     * Returns the produced bytecode sequence.
     */
    public byte[] get() {
        return copy();
    }

    /**
     * Gets <code>max_stack</code>.
     */
    public int getMaxStack() {
        return maxStack;
    }

    /**
     * Sets <code>max_stack</code>.
     *
     * <p>
     * This value may be automatically updated when an instruction
     * is appended. A <code>Bytecode</code> object maintains the current
     * stack depth whenever an instruction is added
     * by <code>addOpcode()</code>. For example, if DUP is appended,
     * the current stack depth is increased by one. If the new stack
     * depth is more than <code>max_stack</code>, then it is replacedigned
     * to <code>max_stack</code>. However, if branch instructions are
     * appended, the current stack depth may not be correctly maintained.
     *
     * @see #addOpcode(int)
     */
    public void setMaxStack(int size) {
        maxStack = size;
    }

    /**
     * Gets <code>max_locals</code>.
     */
    public int getMaxLocals() {
        return maxLocals;
    }

    /**
     * Sets <code>max_locals</code>.
     */
    public void setMaxLocals(int size) {
        maxLocals = size;
    }

    /**
     * Sets <code>max_locals</code>.
     *
     * <p>
     * This computes the number of local variables
     * used to preplaced method parameters and sets <code>max_locals</code>
     * to that number plus <code>locals</code>.
     *
     * @param isStatic
     *            true if <code>params</code> must be
     *            interpreted as parameters to a static method.
     * @param params
     *            parameter types.
     * @param locals
     *            the number of local variables excluding
     *            ones used to preplaced parameters.
     */
    public void setMaxLocals(boolean isStatic, CtClreplaced[] params, int locals) {
        if (!isStatic) {
            ++locals;
        }
        if (params != null) {
            CtClreplaced doubleType = CtClreplaced.doubleType;
            CtClreplaced longType = CtClreplaced.longType;
            int n = params.length;
            for (int i = 0; i < n; ++i) {
                CtClreplaced type = params[i];
                if (type == doubleType || type == longType) {
                    locals += 2;
                } else {
                    ++locals;
                }
            }
        }
        maxLocals = locals;
    }

    /**
     * Increments <code>max_locals</code>.
     */
    public void incMaxLocals(int diff) {
        maxLocals += diff;
    }

    /**
     * Adds a new entry of <code>exception_table</code>.
     */
    public void addExceptionHandler(int start, int end, int handler, CtClreplaced type) {
        addExceptionHandler(start, end, handler, constPool.addClreplacedInfo(type));
    }

    /**
     * Adds a new entry of <code>exception_table</code>.
     *
     * @param type
     *            the fully-qualified name of a throwable clreplaced.
     */
    public void addExceptionHandler(int start, int end, int handler, String type) {
        addExceptionHandler(start, end, handler, constPool.addClreplacedInfo(type));
    }

    /**
     * Adds a new entry of <code>exception_table</code>.
     */
    public void addExceptionHandler(int start, int end, int handler, int type) {
        tryblocks.add(start, end, handler, type);
    }

    /**
     * Returns the length of bytecode sequence
     * that have been added so far.
     */
    public int currentPc() {
        return getSize();
    }

    /**
     * Reads a signed 8bit value at the offset from the beginning of the
     * bytecode sequence.
     *
     * @throws ArrayIndexOutOfBoundsException
     *             if offset is invalid.
     */
    @Override
    public int read(int offset) {
        return super.read(offset);
    }

    /**
     * Reads a signed 16bit value at the offset from the beginning of the
     * bytecode sequence.
     */
    public int read16bit(int offset) {
        int v1 = read(offset);
        int v2 = read(offset + 1);
        return (v1 << 8) + (v2 & 0xff);
    }

    /**
     * Reads a signed 32bit value at the offset from the beginning of the
     * bytecode sequence.
     */
    public int read32bit(int offset) {
        int v1 = read16bit(offset);
        int v2 = read16bit(offset + 2);
        return (v1 << 16) + (v2 & 0xffff);
    }

    /**
     * Writes an 8bit value at the offset from the beginning of the
     * bytecode sequence.
     *
     * @throws ArrayIndexOutOfBoundsException
     *             if offset is invalid.
     */
    @Override
    public void write(int offset, int value) {
        super.write(offset, value);
    }

    /**
     * Writes an 16bit value at the offset from the beginning of the
     * bytecode sequence.
     */
    public void write16bit(int offset, int value) {
        write(offset, value >> 8);
        write(offset + 1, value);
    }

    /**
     * Writes an 32bit value at the offset from the beginning of the
     * bytecode sequence.
     */
    public void write32bit(int offset, int value) {
        write16bit(offset, value >> 16);
        write16bit(offset + 2, value);
    }

    /**
     * Appends an 8bit value to the end of the bytecode sequence.
     */
    @Override
    public void add(int code) {
        super.add(code);
    }

    /**
     * Appends a 32bit value to the end of the bytecode sequence.
     */
    public void add32bit(int value) {
        add(value >> 24, value >> 16, value >> 8, value);
    }

    /**
     * Appends the length-byte gap to the end of the bytecode sequence.
     *
     * @param length
     *            the gap length in byte.
     */
    @Override
    public void addGap(int length) {
        super.addGap(length);
    }

    /**
     * Appends an 8bit opcode to the end of the bytecode sequence.
     * The current stack depth is updated.
     * <code>max_stack</code> is updated if the current stack depth
     * is the deepest so far.
     *
     * <p>
     * Note: some instructions such as INVOKEVIRTUAL does not
     * update the current stack depth since the increment depends
     * on the method signature.
     * <code>growStack()</code> must be explicitly called.
     */
    public void addOpcode(int code) {
        add(code);
        growStack(STACK_GROW[code]);
    }

    /**
     * Increases the current stack depth.
     * It also updates <code>max_stack</code> if the current stack depth
     * is the deepest so far.
     *
     * @param diff
     *            the number added to the current stack depth.
     */
    public void growStack(int diff) {
        setStackDepth(stackDepth + diff);
    }

    /**
     * Returns the current stack depth.
     */
    public int getStackDepth() {
        return stackDepth;
    }

    /**
     * Sets the current stack depth.
     * It also updates <code>max_stack</code> if the current stack depth
     * is the deepest so far.
     *
     * @param depth
     *            new value.
     */
    public void setStackDepth(int depth) {
        stackDepth = depth;
        if (stackDepth > maxStack) {
            maxStack = stackDepth;
        }
    }

    /**
     * Appends a 16bit value to the end of the bytecode sequence.
     * It never changes the current stack depth.
     */
    public void addIndex(int index) {
        add(index >> 8, index);
    }

    /**
     * Appends ALOAD or (WIDE) ALOAD_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addAload(int n) {
        if (n < 4) {
            // aload_<n>
            addOpcode(42 + n);
        } else if (n < 0x100) {
            // aload
            addOpcode(ALOAD);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(ALOAD);
            addIndex(n);
        }
    }

    /**
     * Appends ASTORE or (WIDE) ASTORE_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addAstore(int n) {
        if (n < 4) {
            // astore_<n>
            addOpcode(75 + n);
        } else if (n < 0x100) {
            // astore
            addOpcode(ASTORE);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(ASTORE);
            addIndex(n);
        }
    }

    /**
     * Appends ICONST or ICONST_<n>
     *
     * @param n
     *            the pushed integer constant.
     */
    public void addIconst(int n) {
        if (n < 6 && -2 < n) {
            // iconst_<i>   -1..5
            addOpcode(3 + n);
        } else if (n <= 127 && -128 <= n) {
            // bipush
            addOpcode(16);
            add(n);
        } else if (n <= 32767 && -32768 <= n) {
            // sipush
            addOpcode(17);
            add(n >> 8);
            add(n);
        } else {
            addLdc(constPool.addIntegerInfo(n));
        }
    }

    /**
     * Appends an instruction for pushing zero or null on the stack.
     * If the type is void, this method does not append any instruction.
     *
     * @param type
     *            the type of the zero value (or null).
     */
    public void addConstZero(CtClreplaced type) {
        if (type.isPrimitive()) {
            if (type == CtClreplaced.longType) {
                addOpcode(LCONST_0);
            } else if (type == CtClreplaced.floatType) {
                addOpcode(FCONST_0);
            } else if (type == CtClreplaced.doubleType) {
                addOpcode(DCONST_0);
            } else if (type == CtClreplaced.voidType) {
                throw new RuntimeException("void type?");
            } else {
                addOpcode(ICONST_0);
            }
        } else {
            addOpcode(ACONST_NULL);
        }
    }

    /**
     * Appends ILOAD or (WIDE) ILOAD_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addIload(int n) {
        if (n < 4) {
            // iload_<n>
            addOpcode(26 + n);
        } else if (n < 0x100) {
            // iload
            addOpcode(ILOAD);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(ILOAD);
            addIndex(n);
        }
    }

    /**
     * Appends ISTORE or (WIDE) ISTORE_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addIstore(int n) {
        if (n < 4) {
            // istore_<n>
            addOpcode(59 + n);
        } else if (n < 0x100) {
            // istore
            addOpcode(ISTORE);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(ISTORE);
            addIndex(n);
        }
    }

    /**
     * Appends LCONST or LCONST_<n>
     *
     * @param n
     *            the pushed long integer constant.
     */
    public void addLconst(long n) {
        if (n == 0 || n == 1) {
            // lconst_<n>
            addOpcode(9 + (int) n);
        } else {
            addLdc2w(n);
        }
    }

    /**
     * Appends LLOAD or (WIDE) LLOAD_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addLload(int n) {
        if (n < 4) {
            // lload_<n>
            addOpcode(30 + n);
        } else if (n < 0x100) {
            // lload
            addOpcode(LLOAD);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(LLOAD);
            addIndex(n);
        }
    }

    /**
     * Appends LSTORE or LSTORE_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addLstore(int n) {
        if (n < 4) {
            // lstore_<n>
            addOpcode(63 + n);
        } else if (n < 0x100) {
            // lstore
            addOpcode(LSTORE);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(LSTORE);
            addIndex(n);
        }
    }

    /**
     * Appends DCONST or DCONST_<n>
     *
     * @param d
     *            the pushed double constant.
     */
    public void addDconst(double d) {
        if (d == 0.0 || d == 1.0) {
            // dconst_<n>
            addOpcode(14 + (int) d);
        } else {
            addLdc2w(d);
        }
    }

    /**
     * Appends DLOAD or (WIDE) DLOAD_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addDload(int n) {
        if (n < 4) {
            // dload_<n>
            addOpcode(38 + n);
        } else if (n < 0x100) {
            // dload
            addOpcode(DLOAD);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(DLOAD);
            addIndex(n);
        }
    }

    /**
     * Appends DSTORE or (WIDE) DSTORE_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addDstore(int n) {
        if (n < 4) {
            // dstore_<n>
            addOpcode(71 + n);
        } else if (n < 0x100) {
            // dstore
            addOpcode(DSTORE);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(DSTORE);
            addIndex(n);
        }
    }

    /**
     * Appends FCONST or FCONST_<n>
     *
     * @param f
     *            the pushed float constant.
     */
    public void addFconst(float f) {
        if (f == 0.0f || f == 1.0f || f == 2.0f) {
            // fconst_<n>
            addOpcode(11 + (int) f);
        } else {
            addLdc(constPool.addFloatInfo(f));
        }
    }

    /**
     * Appends FLOAD or (WIDE) FLOAD_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addFload(int n) {
        if (n < 4) {
            // fload_<n>
            addOpcode(34 + n);
        } else if (n < 0x100) {
            // fload
            addOpcode(FLOAD);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(FLOAD);
            addIndex(n);
        }
    }

    /**
     * Appends FSTORE or FSTORE_<n>
     *
     * @param n
     *            an index into the local variable array.
     */
    public void addFstore(int n) {
        if (n < 4) {
            // fstore_<n>
            addOpcode(67 + n);
        } else if (n < 0x100) {
            // fstore
            addOpcode(FSTORE);
            add(n);
        } else {
            addOpcode(WIDE);
            addOpcode(FSTORE);
            addIndex(n);
        }
    }

    /**
     * Appends an instruction for loading a value from the
     * local variable at the index <code>n</code>.
     *
     * @param n
     *            the index.
     * @param type
     *            the type of the loaded value.
     * @return the size of the value (1 or 2 word).
     */
    public int addLoad(int n, CtClreplaced type) {
        if (type.isPrimitive()) {
            if (type == CtClreplaced.booleanType || type == CtClreplaced.charType || type == CtClreplaced.byteType || type == CtClreplaced.shortType || type == CtClreplaced.intType) {
                addIload(n);
            } else if (type == CtClreplaced.longType) {
                addLload(n);
                return 2;
            } else if (type == CtClreplaced.floatType) {
                addFload(n);
            } else if (type == CtClreplaced.doubleType) {
                addDload(n);
                return 2;
            } else {
                throw new RuntimeException("void type?");
            }
        } else {
            addAload(n);
        }
        return 1;
    }

    /**
     * Appends an instruction for storing a value into the
     * local variable at the index <code>n</code>.
     *
     * @param n
     *            the index.
     * @param type
     *            the type of the stored value.
     * @return 2 if the type is long or double. Otherwise 1.
     */
    public int addStore(int n, CtClreplaced type) {
        if (type.isPrimitive()) {
            if (type == CtClreplaced.booleanType || type == CtClreplaced.charType || type == CtClreplaced.byteType || type == CtClreplaced.shortType || type == CtClreplaced.intType) {
                addIstore(n);
            } else if (type == CtClreplaced.longType) {
                addLstore(n);
                return 2;
            } else if (type == CtClreplaced.floatType) {
                addFstore(n);
            } else if (type == CtClreplaced.doubleType) {
                addDstore(n);
                return 2;
            } else {
                throw new RuntimeException("void type?");
            }
        } else {
            addAstore(n);
        }
        return 1;
    }

    /**
     * Appends instructions for loading all the parameters onto the
     * operand stack.
     *
     * @param offset
     *            the index of the first parameter. It is 0
     *            if the method is static. Otherwise, it is 1.
     */
    public int addLoadParameters(CtClreplaced[] params, int offset) {
        int stacksize = 0;
        if (params != null) {
            int n = params.length;
            for (int i = 0; i < n; ++i) {
                stacksize += addLoad(stacksize + offset, params[i]);
            }
        }
        return stacksize;
    }

    /**
     * Appends CHECKCAST.
     *
     * @param c
     *            the type.
     */
    public void addCheckcast(CtClreplaced c) {
        addOpcode(CHECKCAST);
        addIndex(constPool.addClreplacedInfo(c));
    }

    /**
     * Appends CHECKCAST.
     *
     * @param clreplacedname
     *            a fully-qualified clreplaced name.
     */
    public void addCheckcast(String clreplacedname) {
        addOpcode(CHECKCAST);
        addIndex(constPool.addClreplacedInfo(clreplacedname));
    }

    /**
     * Appends INSTANCEOF.
     *
     * @param clreplacedname
     *            the clreplaced name.
     */
    public void addInstanceof(String clreplacedname) {
        addOpcode(INSTANCEOF);
        addIndex(constPool.addClreplacedInfo(clreplacedname));
    }

    /**
     * Appends GETFIELD.
     *
     * @param c
     *            the clreplaced.
     * @param name
     *            the field name.
     * @param type
     *            the descriptor of the field type.
     *
     * @see Descriptor#of(CtClreplaced)
     */
    public void addGetfield(CtClreplaced c, String name, String type) {
        add(GETFIELD);
        int ci = constPool.addClreplacedInfo(c);
        addIndex(constPool.addFieldrefInfo(ci, name, type));
        growStack(Descriptor.dataSize(type) - 1);
    }

    /**
     * Appends GETFIELD.
     *
     * @param c
     *            the fully-qualified clreplaced name.
     * @param name
     *            the field name.
     * @param type
     *            the descriptor of the field type.
     *
     * @see Descriptor#of(CtClreplaced)
     */
    public void addGetfield(String c, String name, String type) {
        add(GETFIELD);
        int ci = constPool.addClreplacedInfo(c);
        addIndex(constPool.addFieldrefInfo(ci, name, type));
        growStack(Descriptor.dataSize(type) - 1);
    }

    /**
     * Appends GETSTATIC.
     *
     * @param c
     *            the clreplaced
     * @param name
     *            the field name
     * @param type
     *            the descriptor of the field type.
     *
     * @see Descriptor#of(CtClreplaced)
     */
    public void addGetstatic(CtClreplaced c, String name, String type) {
        add(GETSTATIC);
        int ci = constPool.addClreplacedInfo(c);
        addIndex(constPool.addFieldrefInfo(ci, name, type));
        growStack(Descriptor.dataSize(type));
    }

    /**
     * Appends GETSTATIC.
     *
     * @param c
     *            the fully-qualified clreplaced name
     * @param name
     *            the field name
     * @param type
     *            the descriptor of the field type.
     *
     * @see Descriptor#of(CtClreplaced)
     */
    public void addGetstatic(String c, String name, String type) {
        add(GETSTATIC);
        int ci = constPool.addClreplacedInfo(c);
        addIndex(constPool.addFieldrefInfo(ci, name, type));
        growStack(Descriptor.dataSize(type));
    }

    /**
     * Appends INVOKESPECIAL.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name.
     * @param returnType
     *            the return type.
     * @param paramTypes
     *            the parameter types.
     */
    public void addInvokespecial(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
        String desc = Descriptor.ofMethod(returnType, paramTypes);
        addInvokespecial(clazz, name, desc);
    }

    /**
     * Appends INVOKESPECIAL.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     * @see Descriptor#ofConstructor(CtClreplaced[])
     */
    public void addInvokespecial(CtClreplaced clazz, String name, String desc) {
        boolean isInterface = clazz == null ? false : clazz.isInterface();
        addInvokespecial(isInterface, constPool.addClreplacedInfo(clazz), name, desc);
    }

    /**
     * Appends INVOKESPECIAL. The invoked method must not be a default
     * method declared in an interface.
     *
     * @param clazz
     *            the fully-qualified clreplaced name.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     * @see Descriptor#ofConstructor(CtClreplaced[])
     */
    public void addInvokespecial(String clazz, String name, String desc) {
        addInvokespecial(false, constPool.addClreplacedInfo(clazz), name, desc);
    }

    /**
     * Appends INVOKESPECIAL. The invoked method must not be a default
     * method declared in an interface.
     *
     * @param clazz
     *            the index of <code>CONSTANT_Clreplaced_info</code>
     *            structure.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     * @see Descriptor#ofConstructor(CtClreplaced[])
     */
    public void addInvokespecial(int clazz, String name, String desc) {
        addInvokespecial(false, clazz, name, desc);
    }

    /**
     * Appends INVOKESPECIAL.
     *
     * @param isInterface
     *            true if the invoked method is a default method
     *            declared in an interface.
     * @param clazz
     *            the index of <code>CONSTANT_Clreplaced_info</code>
     *            structure.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     * @see Descriptor#ofConstructor(CtClreplaced[])
     */
    public void addInvokespecial(boolean isInterface, int clazz, String name, String desc) {
        int index;
        if (isInterface) {
            index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
        } else {
            index = constPool.addMethodrefInfo(clazz, name, desc);
        }
        addInvokespecial(index, desc);
    }

    /**
     * Appends INVOKESPECIAL.
     *
     * @param index
     *            the index of <code>CONSTANT_Methodref_info</code>
     *            or <code>CONSTANT_InterfaceMethodref_info</code>
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     * @see Descriptor#ofConstructor(CtClreplaced[])
     */
    public void addInvokespecial(int index, String desc) {
        add(INVOKESPECIAL);
        addIndex(index);
        growStack(Descriptor.dataSize(desc) - 1);
    }

    /**
     * Appends INVOKESTATIC.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name
     * @param returnType
     *            the return type.
     * @param paramTypes
     *            the parameter types.
     */
    public void addInvokestatic(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
        String desc = Descriptor.ofMethod(returnType, paramTypes);
        addInvokestatic(clazz, name, desc);
    }

    /**
     * Appends INVOKESTATIC.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokestatic(CtClreplaced clazz, String name, String desc) {
        boolean isInterface;
        if (clazz == THIS) {
            isInterface = false;
        } else {
            isInterface = clazz.isInterface();
        }
        addInvokestatic(constPool.addClreplacedInfo(clazz), name, desc, isInterface);
    }

    /**
     * Appends INVOKESTATIC.
     *
     * @param clreplacedname
     *            the fully-qualified clreplaced name.
     *            It must not be an interface-type name.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokestatic(String clreplacedname, String name, String desc) {
        addInvokestatic(constPool.addClreplacedInfo(clreplacedname), name, desc);
    }

    /**
     * Appends INVOKESTATIC.
     *
     * @param clazz
     *            the index of <code>CONSTANT_Clreplaced_info</code>
     *            structure. It must not be an interface type.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokestatic(int clazz, String name, String desc) {
        addInvokestatic(clazz, name, desc, false);
    }

    private void addInvokestatic(int clazz, String name, String desc, boolean isInterface) {
        add(INVOKESTATIC);
        int index;
        if (isInterface) {
            index = constPool.addInterfaceMethodrefInfo(clazz, name, desc);
        } else {
            index = constPool.addMethodrefInfo(clazz, name, desc);
        }
        addIndex(index);
        growStack(Descriptor.dataSize(desc));
    }

    /**
     * Appends INVOKEVIRTUAL.
     *
     * <p>
     * The specified method must not be an inherited method.
     * It must be directly declared in the clreplaced specified
     * in <code>clazz</code>.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name
     * @param returnType
     *            the return type.
     * @param paramTypes
     *            the parameter types.
     */
    public void addInvokevirtual(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
        String desc = Descriptor.ofMethod(returnType, paramTypes);
        addInvokevirtual(clazz, name, desc);
    }

    /**
     * Appends INVOKEVIRTUAL.
     *
     * <p>
     * The specified method must not be an inherited method.
     * It must be directly declared in the clreplaced specified
     * in <code>clazz</code>.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokevirtual(CtClreplaced clazz, String name, String desc) {
        addInvokevirtual(constPool.addClreplacedInfo(clazz), name, desc);
    }

    /**
     * Appends INVOKEVIRTUAL.
     *
     * <p>
     * The specified method must not be an inherited method.
     * It must be directly declared in the clreplaced specified
     * in <code>clreplacedname</code>.
     *
     * @param clreplacedname
     *            the fully-qualified clreplaced name.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokevirtual(String clreplacedname, String name, String desc) {
        addInvokevirtual(constPool.addClreplacedInfo(clreplacedname), name, desc);
    }

    /**
     * Appends INVOKEVIRTUAL.
     *
     * <p>
     * The specified method must not be an inherited method.
     * It must be directly declared in the clreplaced specified
     * by <code>clazz</code>.
     *
     * @param clazz
     *            the index of <code>CONSTANT_Clreplaced_info</code>
     *            structure.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokevirtual(int clazz, String name, String desc) {
        add(INVOKEVIRTUAL);
        addIndex(constPool.addMethodrefInfo(clazz, name, desc));
        growStack(Descriptor.dataSize(desc) - 1);
    }

    /**
     * Appends INVOKEINTERFACE.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name
     * @param returnType
     *            the return type.
     * @param paramTypes
     *            the parameter types.
     * @param count
     *            the count operand of the instruction.
     */
    public void addInvokeinterface(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes, int count) {
        String desc = Descriptor.ofMethod(returnType, paramTypes);
        addInvokeinterface(clazz, name, desc, count);
    }

    /**
     * Appends INVOKEINTERFACE.
     *
     * @param clazz
     *            the target clreplaced.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     * @param count
     *            the count operand of the instruction.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokeinterface(CtClreplaced clazz, String name, String desc, int count) {
        addInvokeinterface(constPool.addClreplacedInfo(clazz), name, desc, count);
    }

    /**
     * Appends INVOKEINTERFACE.
     *
     * @param clreplacedname
     *            the fully-qualified clreplaced name.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     * @param count
     *            the count operand of the instruction.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokeinterface(String clreplacedname, String name, String desc, int count) {
        addInvokeinterface(constPool.addClreplacedInfo(clreplacedname), name, desc, count);
    }

    /**
     * Appends INVOKEINTERFACE.
     *
     * @param clazz
     *            the index of <code>CONSTANT_Clreplaced_info</code>
     *            structure.
     * @param name
     *            the method name
     * @param desc
     *            the descriptor of the method signature.
     * @param count
     *            the count operand of the instruction.
     *
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     */
    public void addInvokeinterface(int clazz, String name, String desc, int count) {
        add(INVOKEINTERFACE);
        addIndex(constPool.addInterfaceMethodrefInfo(clazz, name, desc));
        add(count);
        add(0);
        growStack(Descriptor.dataSize(desc) - 1);
    }

    /**
     * Appends INVOKEDYNAMIC.
     *
     * @param bootstrap
     *            an index into the <code>bootstrap_methods</code> array
     *            of the bootstrap method table.
     * @param name
     *            the method name.
     * @param desc
     *            the method descriptor.
     * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
     * @since 3.17
     */
    public void addInvokedynamic(int bootstrap, String name, String desc) {
        int nt = constPool.addNameAndTypeInfo(name, desc);
        int dyn = constPool.addInvokeDynamicInfo(bootstrap, nt);
        add(INVOKEDYNAMIC);
        addIndex(dyn);
        add(0, 0);
        // replacedume ConstPool#REF_invokeStatic
        growStack(Descriptor.dataSize(desc));
    }

    /**
     * Appends LDC or LDC_W. The pushed item is a <code>String</code>
     * object.
     *
     * @param s
     *            the character string pushed by LDC or LDC_W.
     */
    public void addLdc(String s) {
        addLdc(constPool.addStringInfo(s));
    }

    /**
     * Appends LDC or LDC_W.
     *
     * @param i
     *            index into the constant pool.
     */
    public void addLdc(int i) {
        if (i > 0xFF) {
            addOpcode(LDC_W);
            addIndex(i);
        } else {
            addOpcode(LDC);
            add(i);
        }
    }

    /**
     * Appends LDC2_W. The pushed item is a long value.
     */
    public void addLdc2w(long l) {
        addOpcode(LDC2_W);
        addIndex(constPool.addLongInfo(l));
    }

    /**
     * Appends LDC2_W. The pushed item is a double value.
     */
    public void addLdc2w(double d) {
        addOpcode(LDC2_W);
        addIndex(constPool.addDoubleInfo(d));
    }

    /**
     * Appends NEW.
     *
     * @param clazz
     *            the clreplaced of the created instance.
     */
    public void addNew(CtClreplaced clazz) {
        addOpcode(NEW);
        addIndex(constPool.addClreplacedInfo(clazz));
    }

    /**
     * Appends NEW.
     *
     * @param clreplacedname
     *            the fully-qualified clreplaced name.
     */
    public void addNew(String clreplacedname) {
        addOpcode(NEW);
        addIndex(constPool.addClreplacedInfo(clreplacedname));
    }

    /**
     * Appends ANEWARRAY.
     *
     * @param clreplacedname
     *            the qualified clreplaced name of the element type.
     */
    public void addAnewarray(String clreplacedname) {
        addOpcode(ANEWARRAY);
        addIndex(constPool.addClreplacedInfo(clreplacedname));
    }

    /**
     * Appends ICONST and ANEWARRAY.
     *
     * @param clazz
     *            the elememnt type.
     * @param length
     *            the array length.
     */
    public void addAnewarray(CtClreplaced clazz, int length) {
        addIconst(length);
        addOpcode(ANEWARRAY);
        addIndex(constPool.addClreplacedInfo(clazz));
    }

    /**
     * Appends NEWARRAY for primitive types.
     *
     * @param atype
     *            <code>T_BOOLEAN</code>, <code>T_CHAR</code>, ...
     * @see Opcode
     */
    public void addNewarray(int atype, int length) {
        addIconst(length);
        addOpcode(NEWARRAY);
        add(atype);
    }

    /**
     * Appends MULTINEWARRAY.
     *
     * @param clazz
     *            the array type.
     * @param dimensions
     *            the sizes of all dimensions.
     * @return the length of <code>dimensions</code>.
     */
    public int addMultiNewarray(CtClreplaced clazz, int[] dimensions) {
        int len = dimensions.length;
        for (int i = 0; i < len; ++i) {
            addIconst(dimensions[i]);
        }
        growStack(len);
        return addMultiNewarray(clazz, len);
    }

    /**
     * Appends MULTINEWARRAY. The size of every dimension must have been
     * already pushed on the stack.
     *
     * @param clazz
     *            the array type.
     * @param dim
     *            the number of the dimensions.
     * @return the value of <code>dim</code>.
     */
    public int addMultiNewarray(CtClreplaced clazz, int dim) {
        add(MULTIANEWARRAY);
        addIndex(constPool.addClreplacedInfo(clazz));
        add(dim);
        growStack(1 - dim);
        return dim;
    }

    /**
     * Appends MULTINEWARRAY.
     *
     * @param desc
     *            the type descriptor of the created array.
     * @param dim
     *            dimensions.
     * @return the value of <code>dim</code>.
     */
    public int addMultiNewarray(String desc, int dim) {
        add(MULTIANEWARRAY);
        addIndex(constPool.addClreplacedInfo(desc));
        add(dim);
        growStack(1 - dim);
        return dim;
    }

    /**
     * Appends PUTFIELD.
     *
     * @param c
     *            the target clreplaced.
     * @param name
     *            the field name.
     * @param desc
     *            the descriptor of the field type.
     */
    public void addPutfield(CtClreplaced c, String name, String desc) {
        addPutfield0(c, null, name, desc);
    }

    /**
     * Appends PUTFIELD.
     *
     * @param clreplacedname
     *            the fully-qualified name of the target clreplaced.
     * @param name
     *            the field name.
     * @param desc
     *            the descriptor of the field type.
     */
    public void addPutfield(String clreplacedname, String name, String desc) {
        // if clreplacednaem is null, the target clreplaced is THIS.
        addPutfield0(null, clreplacedname, name, desc);
    }

    private void addPutfield0(CtClreplaced target, String clreplacedname, String name, String desc) {
        add(PUTFIELD);
        // target is null if it represents THIS.
        int ci = clreplacedname == null ? constPool.addClreplacedInfo(target) : constPool.addClreplacedInfo(clreplacedname);
        addIndex(constPool.addFieldrefInfo(ci, name, desc));
        growStack(-1 - Descriptor.dataSize(desc));
    }

    /**
     * Appends PUTSTATIC.
     *
     * @param c
     *            the target clreplaced.
     * @param name
     *            the field name.
     * @param desc
     *            the descriptor of the field type.
     */
    public void addPutstatic(CtClreplaced c, String name, String desc) {
        addPutstatic0(c, null, name, desc);
    }

    /**
     * Appends PUTSTATIC.
     *
     * @param clreplacedname
     *            the fully-qualified name of the target clreplaced.
     * @param fieldName
     *            the field name.
     * @param desc
     *            the descriptor of the field type.
     */
    public void addPutstatic(String clreplacedname, String fieldName, String desc) {
        // if clreplacedname is null, the target clreplaced is THIS.
        addPutstatic0(null, clreplacedname, fieldName, desc);
    }

    private void addPutstatic0(CtClreplaced target, String clreplacedname, String fieldName, String desc) {
        add(PUTSTATIC);
        // target is null if it represents THIS.
        int ci = clreplacedname == null ? constPool.addClreplacedInfo(target) : constPool.addClreplacedInfo(clreplacedname);
        addIndex(constPool.addFieldrefInfo(ci, fieldName, desc));
        growStack(-Descriptor.dataSize(desc));
    }

    /**
     * Appends ARETURN, IRETURN, .., or RETURN.
     *
     * @param type
     *            the return type.
     */
    public void addReturn(CtClreplaced type) {
        if (type == null) {
            addOpcode(RETURN);
        } else if (type.isPrimitive()) {
            CtPrimitiveType ptype = (CtPrimitiveType) type;
            addOpcode(ptype.getReturnOp());
        } else {
            addOpcode(ARETURN);
        }
    }

    /**
     * Appends RET.
     *
     * @param var
     *            local variable
     */
    public void addRet(int var) {
        if (var < 0x100) {
            addOpcode(RET);
            add(var);
        } else {
            addOpcode(WIDE);
            addOpcode(RET);
            addIndex(var);
        }
    }

    /**
     * Appends instructions for executing
     * <code>java.lang.System.println(<i>message</i>)</code>.
     *
     * @param message
     *            printed message.
     */
    public void addPrintln(String message) {
        addGetstatic("java.lang.System", "err", "Ljava/io/PrintStream;");
        addLdc(message);
        addInvokevirtual("java.io.PrintStream", "println", "(Ljava/lang/String;)V");
    }
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

private void addPutfield0(CtClreplaced target, String clreplacedname, String name, String desc) {
    add(PUTFIELD);
    // target is null if it represents THIS.
    int ci = clreplacedname == null ? constPool.addClreplacedInfo(target) : constPool.addClreplacedInfo(clreplacedname);
    addIndex(constPool.addFieldrefInfo(ci, name, desc));
    growStack(-1 - Descriptor.dataSize(desc));
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

/**
 * Appends CHECKCAST.
 *
 * @param c
 *            the type.
 */
public void addCheckcast(CtClreplaced c) {
    addOpcode(CHECKCAST);
    addIndex(constPool.addClreplacedInfo(c));
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

/**
 * Appends INVOKEINTERFACE.
 *
 * @param clazz
 *            the target clreplaced.
 * @param name
 *            the method name
 * @param desc
 *            the descriptor of the method signature.
 * @param count
 *            the count operand of the instruction.
 *
 * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
 */
public void addInvokeinterface(CtClreplaced clazz, String name, String desc, int count) {
    addInvokeinterface(constPool.addClreplacedInfo(clazz), name, desc, count);
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

/**
 * Appends INVOKEVIRTUAL.
 *
 * <p>
 * The specified method must not be an inherited method.
 * It must be directly declared in the clreplaced specified
 * in <code>clazz</code>.
 *
 * @param clazz
 *            the target clreplaced.
 * @param name
 *            the method name
 * @param desc
 *            the descriptor of the method signature.
 *
 * @see Descriptor#ofMethod(CtClreplaced,CtClreplaced[])
 */
public void addInvokevirtual(CtClreplaced clazz, String name, String desc) {
    addInvokevirtual(constPool.addClreplacedInfo(clazz), name, desc);
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

/**
 * Appends instructions for loading all the parameters onto the
 * operand stack.
 *
 * @param offset
 *            the index of the first parameter. It is 0
 *            if the method is static. Otherwise, it is 1.
 */
public int addLoadParameters(CtClreplaced[] params, int offset) {
    int stacksize = 0;
    if (params != null) {
        int n = params.length;
        for (int i = 0; i < n; ++i) {
            stacksize += addLoad(stacksize + offset, params[i]);
        }
    }
    return stacksize;
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

/**
 * Appends PUTSTATIC.
 *
 * @param c
 *            the target clreplaced.
 * @param name
 *            the field name.
 * @param desc
 *            the descriptor of the field type.
 */
public void addPutstatic(CtClreplaced c, String name, String desc) {
    addPutstatic0(c, null, name, desc);
}

19 Source : Bytecode.java
with Apache License 2.0
from ifeilong

/**
 * Appends INVOKESTATIC.
 *
 * @param clazz
 *            the target clreplaced.
 * @param name
 *            the method name
 * @param returnType
 *            the return type.
 * @param paramTypes
 *            the parameter types.
 */
public void addInvokestatic(CtClreplaced clazz, String name, CtClreplaced returnType, CtClreplaced[] paramTypes) {
    String desc = Descriptor.ofMethod(returnType, paramTypes);
    addInvokestatic(clazz, name, desc);
}

See More Examples