com.trigersoft.jaque.expression.ExpressionClassVisitor.java Source code

Java tutorial

Introduction

Here is the source code for com.trigersoft.jaque.expression.ExpressionClassVisitor.java

Source

/*
 * Copyright TrigerSoft <kostat@trigersoft.com> 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.trigersoft.jaque.expression;

import java.lang.reflect.Method;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;

/**
 * Represents a visitor or rewriter for expression trees.
 * 
 * @author <a href="mailto://kostat@trigersoft.com">Konstantin Triger</a>
 */

final class ExpressionClassVisitor extends ClassVisitor {

    private final ConstantExpression _me;
    private final String _method;
    private final String _methodDesc;
    private Expression _result;
    private Class<?> _type;
    private Class<?>[] _argTypes;

    Expression getResult() {
        return _result;
    }

    void setResult(Expression result) {
        _result = result;
    }

    Class<?> getType() {
        return _type;
    }

    ParameterExpression[] getParams() {
        ParameterExpression[] params = new ParameterExpression[_argTypes.length];
        for (int i = 0; i < params.length; i++)
            params[i] = Expression.parameter(_argTypes[i], i);
        return params;
    }

    public ExpressionClassVisitor(Object lambda, Method method) {
        super(Opcodes.ASM5);
        _me = Expression.constant(lambda, lambda.getClass());
        _method = method.getName();
        _methodDesc = Type.getMethodDescriptor(method);
    }

    Class<?> getClass(Type t) {
        try {
            switch (t.getSort()) {
            case Type.BOOLEAN:
                return Boolean.TYPE;
            case Type.CHAR:
                return Character.TYPE;
            case Type.BYTE:
                return Byte.TYPE;
            case Type.SHORT:
                return Short.TYPE;
            case Type.INT:
                return Integer.TYPE;
            case Type.FLOAT:
                return Float.TYPE;
            case Type.LONG:
                return Long.TYPE;
            case Type.DOUBLE:
                return Double.TYPE;
            case Type.VOID:
                return Void.TYPE;
            }
            String cn = t.getInternalName();
            cn = cn != null ? cn.replace('/', '.') : t.getClassName();

            return Class.forName(cn, false, _me.getResultType().getClassLoader());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {

        // if ((access & Opcodes.ACC_SYNTHETIC) != 0)
        // return null;

        if (!_method.equals(name) || !_methodDesc.equals(desc))
            return null;

        Type ret = Type.getReturnType(desc);
        if (ret.getSort() == Type.VOID)
            throw ExpressionMethodVisitor.notLambda(Opcodes.RETURN);

        _type = getClass(ret);

        Type[] args = Type.getArgumentTypes(desc);
        Class<?>[] argTypes = new Class<?>[args.length];

        for (int i = 0; i < args.length; i++)
            argTypes[i] = getClass(args[i]);

        _argTypes = argTypes;

        return new ExpressionMethodVisitor(this, (access & Opcodes.ACC_STATIC) == 0 ? _me : null, argTypes);
    }

}