All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.fastjson2.internal.codegen.Opcodes Maven / Gradle / Ivy

package com.alibaba.fastjson2.internal.codegen;

import com.alibaba.fastjson2.JSONException;

import static com.alibaba.fastjson2.internal.codegen.ClassWriter.getTypeName;

public class Opcodes {
    public static OpName THIS = var("this");
    public static OpName SUPER = var("super");

    public static Op arrayGet(Op owner, Op index) {
        return new ArrayGet(owner, index);
    }

    public static Op ldc(Object value) {
        return new OpConstant(value);
    }

    public static OpName var(String name) {
        return new OpName(name);
    }

    public static Op invoke(Op owner, String method, Op... args) {
        return new OpInvoke(owner, method, args);
    }

    public static Op invoke(String method, Op... args) {
        return new OpInvoke(THIS, method, args);
    }

    public static Op invokeStatic(Class type, String method, Op... args) {
        return new OpInvoke(var(getTypeName(type)), method, args);
    }

    public static MethodRef methodRef(String type, String method) {
        return new MethodRef(type, method);
    }

    public static Lambda lambda(String type, String name, Op op) {
        return new Lambda(new String[]{type}, new String[]{name}, op);
    }

    public static Lambda lambda(String type0, String name0, String type1, String name1, Op op) {
        return new Lambda(new String[]{type0, type1}, new String[]{name0, name1}, op);
    }

    public static Op allocate(Class type, Op... args) {
        return new OpAllocate(getTypeName(type), args);
    }

    public static Op allocate(String type, Op... args) {
        return new OpAllocate(type, args);
    }

    public static Op allocateArray(Class type, Op size, Op... values) {
        return new OpAllocateArray(getTypeName(type), size, values);
    }

    public static Op allocateArray(String type, Op size, Op... values) {
        return new OpAllocateArray(type, size, values);
    }

    public static Op putField(Op owner, String fieldName, Op value) {
        return new PutField(owner, fieldName, value);
    }

    public static Op getStatic(Class type, String field) {
        return new GetStatic(getTypeName(type), field);
    }

    public static Op getStatic(String type, String field) {
        return new GetStatic(type, field);
    }

    public static Op getField(String field) {
        return new GetField(THIS, field);
    }

    public static Op getField(Op owner, String field) {
        return new GetField(owner, field);
    }

    public static Op getField(String owner, String field) {
        return new GetField(var(owner), field);
    }

    public static Op eqNull(Op value) {
        return new OpBinary(value, "==", ldc(null));
    }

    public static Op notNull(Op value) {
        return new OpBinary(value, "!=", ldc(null));
    }

    public static Op cast(Op value, Class type) {
        return new Cast(getTypeName(type), value);
    }

    public static Op cast(Op value, String type) {
        return new Cast(type, value);
    }

    public static Op bitOr(Op a, Op b) {
        return new OpBinary(a, "|", b);
    }

    public static Op and(Op a, Op b) {
        return new OpBinary(a, "&&", b);
    }

    public static Op and(Op a, Op b, Op c) {
        return new OpBinary(new OpBinary(a, "&&", b), "&&", c);
    }

    public static Op assign(Op a, Op b) {
        return new OpBinary(a, "=", b);
    }

    public static Op assign(String name, Op b) {
        return new OpBinary(var(name), "=", b);
    }

    public static Op ne(Op a, Op b) {
        return new OpBinary(a, "!=", b);
    }

    public static Op eq(Op a, Op b) {
        return new OpBinary(a, "==", b);
    }

    public static Op urs(Op a, Op b) {
        return new OpBinary(a, ">>>", b);
    }

    public static Op eor(Op a, Op b) {
        return new OpBinary(a, "^", b);
    }

    public static Op lt(Op a, Op b) {
        return new OpBinary(a, "<", b);
    }

    public static Op increment(Op value) {
        return new OpUnary(value, "++");
    }

    public static Op not(Op value) {
        return new OpUnary(value, "!");
    }

    static class ArrayGet
            implements Op {
        final Op array;
        final Op index;

        public ArrayGet(Op array, Op index) {
            this.array = array;
            this.index = index;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            array.toString(mw, buf, indent);
            buf.append('[');
            index.toString(mw, buf, indent);
            buf.append(']');
        }
    }

    static class PutField
            implements Op {
        public final Op owner;
        public final String fieldName;
        public final Op value;

        public PutField(Op owner, String fieldName, Op value) {
            this.owner = owner;
            this.fieldName = fieldName;
            this.value = value;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            owner.toString(mw, buf, indent);
            buf.append('.');
            buf.append(fieldName).append(" = ");
            value.toString(mw, buf, indent);
        }
    }

    static class GetStatic
            implements Op {
        public final String type;
        public final String fieldName;

        public GetStatic(String type, String fieldName) {
            this.type = type;
            this.fieldName = fieldName;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            buf.append(type).append('.').append(fieldName);
        }
    }

    static class GetField
            implements Op {
        public final Op owner;
        public final String fieldName;

        public GetField(Op owner, String fieldName) {
            this.owner = owner;
            this.fieldName = fieldName;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            owner.toString(mw, buf, indent);
            buf.append('.').append(fieldName);
        }
    }

    static class Cast
            implements Op {
        public final String type;
        public final Op value;

        public Cast(String type, Op value) {
            this.type = type;
            this.value = value;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            buf.append('(').append(type).append(") ");
            boolean quote = value instanceof OpBinary;
            if (quote) {
                buf.append('(');
            }
            value.toString(mw, buf, indent);
            if (quote) {
                buf.append(')');
            }
        }
    }

    public interface Op {
        default void toString(MethodWriter mw, StringBuilder buf, int indent) {
            throw new JSONException("TODO " + this.getClass().getName());
        }
    }

    public static class OpInvoke
            implements Op {
        public final Op owner;
        public final String method;
        public final Op[] args;

        public OpInvoke(Op owner, String method, Op[] args) {
            this.owner = owner;
            this.method = method;
            this.args = args;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            if ("".equals(method)) {
                owner.toString(mw, buf, indent);
            } else {
                if (owner != null) {
                    owner.toString(mw, buf, indent);
                    buf.append('.');
                }
                buf.append(method);
            }

            buf.append('(');
            int start = buf.length();
            boolean newLine = args.length > 3;
            for (Op arg : args) {
                if (arg instanceof OpInvoke) {
                    newLine = true;
                }
            }

            if (newLine) {
                buf.append('\n');
                mw.ident(buf, indent + 2);
            }

            for (int i = 0; i < args.length; i++) {
                if (i != 0) {
                    if (newLine) {
                        buf.append(",\n");
                        mw.ident(buf, indent + 2);
                    } else {
                        buf.append(", ");
                    }
                }
                args[i].toString(mw, buf, indent + 2);
            }

            boolean hasNewLine = buf.toString().indexOf('\n', start) != -1;
            if (newLine) {
                buf.append('\n');
                mw.ident(buf, indent);
            } else if (hasNewLine) {
                for (int i = 0; i < indent + 2; i++) {
                    buf.insert(start, '\t');
                }
                buf.insert(start, '\n');

                buf.append('\n');
                mw.ident(buf, indent);
            }
            buf.append(')');
        }
    }

    public static class MethodRef
            implements Op {
        public final String type;
        public final String method;

        public MethodRef(String type, String method) {
            this.type = type;
            this.method = method;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            buf.append(type);
            buf.append("::");
            buf.append(method);
        }
    }

    public static class Lambda
            implements Op {
        public final String[] paramTypes;
        public final String[] paramNames;
        public final Op op;

        public Lambda(String[] paramTypes, String[] paramNames, Op op) {
            this.paramTypes = paramTypes;
            this.paramNames = paramNames;
            this.op = op;
        }

        @Override
        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            buf.append('(');
            for (int i = 0; i < paramNames.length; i++) {
                if (i != 0) {
                    buf.append(", ");
                }
                String paramName = paramNames[i];
                String type = paramTypes[i];
                if (type != null) {
                    buf.append(type);
                    buf.append(' ');
                }
                buf.append(paramName);
            }
            buf.append(") -> ");
            op.toString(mw, buf, indent);
        }
    }

    public static class OpAllocate
            implements Op {
        public final String type;
        public final Op[] args;

        public OpAllocate(String type, Op[] args) {
            this.type = type;
            this.args = args;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            buf.append("new ").append(type).append('(');
            for (int i = 0; i < args.length; i++) {
                if (i != 0) {
                    buf.append(", ");
                }
                args[i].toString(mw, buf, indent);
            }
            buf.append(')');
        }
    }

    public static class OpAllocateArray
            implements Op {
        public final String type;
        public final Op size;
        public final Op[] values;

        public OpAllocateArray(String type, Op size, Op[] values) {
            this.type = type;
            this.size = size;
            this.values = values;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            buf.append("new ").append(type).append('[');

            if (size != null) {
                size.toString(mw, buf, indent);
            }
            buf.append(']');
            if (values != null) {
                int length = values.length;
                if (length > 0) {
                    buf.append('{');

                    buf.append('\n');
                    mw.ident(buf, indent + 2);

                    for (int i = 0; i < length; i++) {
                        if (i != 0) {
                            buf.append(",\n");
                            mw.ident(buf, indent + 2);
                        }
                        values[i].toString(mw, buf, indent + 2);
                    }

                    buf.append('\n');
                    mw.ident(buf, indent);
                    buf.append('}');
                } else if (length == 0) {
                    buf.append("{}");
                }
            }
        }
    }

    static class OpConstant
            implements Op {
        public final Object value;

        public OpConstant(Object value) {
            this.value = value;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            if (value == null) {
                buf.append("null");
                return;
            }

            if (value instanceof String) {
                buf.append('"');
                buf.append(((String) value).replace("\"", "\\\""));
                buf.append('"');
                return;
            }

            if (value instanceof Byte) {
                buf.append("(byte) ").append(((Byte) value).intValue());
                return;
            }

            if (value instanceof Integer) {
                buf.append(((Integer) value).intValue());
                return;
            }

            if (value instanceof Long) {
                buf.append(((Long) value).longValue());
                buf.append('L');
                return;
            }

            if (value instanceof Character) {
                buf.append('\'')
                        .append(((Character) value).charValue())
                        .append('\'');
                return;
            }

            if (value instanceof Class) {
                buf.append(getTypeName((Class) value)).append(".class");
                return;
            }

            if (value instanceof Op) {
                ((Op) value).toString(mw, buf, indent);
                return;
            }

            throw new JSONException("TODO : " + value.getClass().getName());
        }
    }

    public static class OpName
            implements Op {
        public final String name;

        public OpName(String name) {
            this.name = name;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            buf.append(name);
        }
    }

    static class OpBinary
            implements Op {
        public final Op left;
        public final String op;
        public final Op right;

        public OpBinary(Op left, String op, Op right) {
            this.left = left;
            this.op = op;
            this.right = right;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            boolean lq = left instanceof OpBinary;
            if (lq) {
                buf.append('(');
            }
            left.toString(mw, buf, indent);
            if (lq) {
                buf.append(')');
            }

            buf.append(' ').append(op).append(' ');

            boolean rq = right instanceof OpBinary;
            if (rq) {
                buf.append('(');
            }
            right.toString(mw, buf, indent);
            if (rq) {
                buf.append(')');
            }
        }
    }

    static class OpUnary
            implements Op {
        public final Op left;
        public final String op;

        public OpUnary(Op left, String op) {
            this.left = left;
            this.op = op;
        }

        public void toString(MethodWriter mw, StringBuilder buf, int indent) {
            boolean prefix = "!".equals(op);
            if (prefix) {
                buf.append(op);
                left.toString(mw, buf, indent);
            } else {
                left.toString(mw, buf, indent);
                buf.append(op);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy