lucee.transformer.bytecode.BytecodeFactory.java Source code

Java tutorial

Introduction

Here is the source code for lucee.transformer.bytecode.BytecodeFactory.java

Source

/**
 * Copyright (c) 2015, Lucee Assosication Switzerland. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either 
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public 
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package lucee.transformer.bytecode;

import lucee.runtime.config.Config;
import lucee.runtime.engine.ThreadLocalPageContext;
import lucee.runtime.op.Caster;
import lucee.runtime.type.util.KeyConstants;
import lucee.transformer.Context;
import lucee.transformer.Factory;
import lucee.transformer.Position;
import lucee.transformer.TransformerException;
import lucee.transformer.bytecode.cast.CastBoolean;
import lucee.transformer.bytecode.cast.CastDouble;
import lucee.transformer.bytecode.cast.CastInt;
import lucee.transformer.bytecode.cast.CastString;
import lucee.transformer.bytecode.expression.var.DataMemberImpl;
import lucee.transformer.bytecode.expression.var.EmptyArray;
import lucee.transformer.bytecode.expression.var.EmptyStruct;
import lucee.transformer.bytecode.expression.var.VariableImpl;
import lucee.transformer.bytecode.literal.LitBooleanImpl;
import lucee.transformer.bytecode.literal.LitDoubleImpl;
import lucee.transformer.bytecode.literal.LitFloatImpl;
import lucee.transformer.bytecode.literal.LitIntegerImpl;
import lucee.transformer.bytecode.literal.LitLongImpl;
import lucee.transformer.bytecode.literal.LitStringImpl;
import lucee.transformer.bytecode.literal.Null;
import lucee.transformer.bytecode.op.OpBool;
import lucee.transformer.bytecode.op.OpString;
import lucee.transformer.bytecode.util.Types;
import lucee.transformer.expression.ExprBoolean;
import lucee.transformer.expression.ExprDouble;
import lucee.transformer.expression.ExprInt;
import lucee.transformer.expression.ExprString;
import lucee.transformer.expression.Expression;
import lucee.transformer.expression.literal.LitBoolean;
import lucee.transformer.expression.literal.LitDouble;
import lucee.transformer.expression.literal.LitFloat;
import lucee.transformer.expression.literal.LitInteger;
import lucee.transformer.expression.literal.LitLong;
import lucee.transformer.expression.literal.LitString;
import lucee.transformer.expression.literal.Literal;
import lucee.transformer.expression.var.DataMember;
import lucee.transformer.expression.var.Variable;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;

public class BytecodeFactory extends Factory {
    private final static Method INIT = new Method("init", Types.COLLECTION_KEY, new Type[] { Types.STRING });

    private static final Type KEY_CONSTANTS = Type.getType(KeyConstants.class);

    private static BytecodeFactory instance;

    public static Factory getInstance(Config config) {
        if (instance == null)
            instance = new BytecodeFactory(config == null ? ThreadLocalPageContext.getConfig() : config);
        return instance;
    }

    private final LitBoolean TRUE;
    private final LitBoolean FALSE;
    private final LitString EMPTY;
    private final LitString NULL;
    private final LitDouble DOUBLE_ZERO;
    private final LitDouble DOUBLE_ONE;

    private final Config config;

    public BytecodeFactory(Config config) {
        TRUE = createLitBoolean(true);
        FALSE = createLitBoolean(false);
        EMPTY = createLitString("");
        NULL = createLitString("NULL");
        DOUBLE_ZERO = createLitDouble(0);
        DOUBLE_ONE = createLitDouble(1);
        this.config = config;
    }

    @Override
    public LitString createLitString(String str) {
        return new LitStringImpl(this, str, null, null);
    }

    @Override
    public LitString createLitString(String str, Position start, Position end) {
        return new LitStringImpl(this, str, start, end);
    }

    @Override
    public LitBoolean createLitBoolean(boolean b) {
        return new LitBooleanImpl(this, b, null, null);
    }

    @Override
    public LitBoolean createLitBoolean(boolean b, Position start, Position end) {
        return new LitBooleanImpl(this, b, start, end);
    }

    @Override
    public LitDouble createLitDouble(double d) {
        return new LitDoubleImpl(this, d, null, null);
    }

    @Override
    public LitDouble createLitDouble(double d, Position start, Position end) {
        return new LitDoubleImpl(this, d, start, end);
    }

    @Override
    public LitFloat createLitFloat(float f) {
        return new LitFloatImpl(this, f, null, null);
    }

    @Override
    public LitFloat createLitFloat(float f, Position start, Position end) {
        return new LitFloatImpl(this, f, start, end);
    }

    @Override
    public LitLong createLitLong(long l) {
        return new LitLongImpl(this, l, null, null);
    }

    @Override
    public LitLong createLitLong(long l, Position start, Position end) {
        return new LitLongImpl(this, l, start, end);
    }

    @Override
    public LitInteger createLitInteger(int i) {
        return new LitIntegerImpl(this, i, null, null);
    }

    @Override
    public LitInteger createLitInteger(int i, Position start, Position end) {
        return new LitIntegerImpl(this, i, start, end);
    }

    @Override
    public boolean isNull(Expression e) {
        return e instanceof Null;
    }

    @Override
    public Expression createNull() {
        return new Null(this, null, null);
    }

    @Override
    public Expression createNull(Position start, Position end) {
        return new Null(this, start, end);
    }

    @Override
    public DataMember createDataMember(ExprString name) {
        return new DataMemberImpl(name);
    }

    @Override
    public Literal createLiteral(Object obj, Literal defaultValue) {
        if (obj instanceof Boolean)
            return createLitBoolean(((Boolean) obj).booleanValue());
        if (obj instanceof Number) {
            if (obj instanceof Float)
                return createLitFloat(((Float) obj).floatValue());
            else if (obj instanceof Integer)
                return createLitInteger(((Integer) obj).intValue());
            else if (obj instanceof Long)
                return createLitLong(((Long) obj).longValue());
            else
                return createLitDouble(((Number) obj).doubleValue());
        }
        String str = Caster.toString(obj, null);
        if (str != null)
            return createLitString(str);
        return defaultValue;
    }

    @Override
    public LitBoolean TRUE() {
        return TRUE;
    }

    @Override
    public LitBoolean FALSE() {
        return FALSE;
    }

    @Override
    public LitString EMPTY() {
        return EMPTY;
    }

    @Override
    public LitDouble DOUBLE_ZERO() {
        return DOUBLE_ZERO;
    }

    @Override
    public LitDouble DOUBLE_ONE() {
        return DOUBLE_ONE;
    }

    @Override
    public LitString NULL() {
        return NULL;
    }

    @Override
    public ExprDouble toExprDouble(Expression expr) {
        return CastDouble.toExprDouble(expr);
    }

    @Override
    public ExprString toExprString(Expression expr) {
        return CastString.toExprString(expr);
    }

    @Override
    public ExprBoolean toExprBoolean(Expression expr) {
        return CastBoolean.toExprBoolean(expr);
    }

    @Override
    public ExprInt toExprInt(Expression expr) {
        return CastInt.toExprInt(expr);
    }

    @Override
    public Variable createVariable(Position start, Position end) {
        return new VariableImpl(this, start, end);
    }

    @Override
    public Variable createVariable(int scope, Position start, Position end) {
        return new VariableImpl(this, scope, start, end);
    }

    @Override
    public ExprString opString(Expression left, Expression right) {
        return OpString.toExprString(left, right, true);
    }

    @Override
    public ExprString opString(Expression left, Expression right, boolean concatStatic) {
        return OpString.toExprString(left, right, concatStatic);
    }

    @Override
    public ExprBoolean opBool(Expression left, Expression right, int operation) {
        return OpBool.toExprBoolean(left, right, operation);
    }

    @Override
    public void registerKey(Context c, Expression name, boolean doUpperCase) throws TransformerException {
        BytecodeContext bc = (BytecodeContext) c;
        if (name instanceof Literal) {
            Literal l = (Literal) name;

            LitString ls = name instanceof LitString ? (LitString) l
                    : c.getFactory().createLitString(l.getString());
            if (doUpperCase) {
                ls = ls.duplicate();
                ls.upperCase();
            }
            String key = KeyConstants.getFieldName(ls.getString());
            if (key != null) {
                bc.getAdapter().getStatic(KEY_CONSTANTS, key, Types.COLLECTION_KEY);
                return;
            }
            int index = bc.registerKey(ls);
            bc.getAdapter().visitVarInsn(Opcodes.ALOAD, 0);
            bc.getAdapter().visitFieldInsn(Opcodes.GETFIELD, bc.getClassName(), "keys",
                    Types.COLLECTION_KEY_ARRAY.toString());
            bc.getAdapter().push(index);
            bc.getAdapter().visitInsn(Opcodes.AALOAD);

            //ExpressionUtil.writeOutSilent(lit,bc, Expression.MODE_REF);
            //bc.getAdapter().invokeStatic(Page.KEY_IMPL, Page.KEY_INTERN);

            return;
        }
        name.writeOut(bc, Expression.MODE_REF);
        bc.getAdapter().invokeStatic(Page.KEY_IMPL, INIT);
        //bc.getAdapter().invokeStatic(Types.CASTER, TO_KEY);
        return;
    }

    @Override
    public Config getConfig() {
        return config;
    }

    @Override
    public Expression createStruct() {
        return new EmptyStruct(this);
    }

    @Override
    public Expression createArray() {
        return new EmptyArray(this);
    }
}