/** * Copyright (c) 2012-2016 André Bargull * Alle Rechte vorbehalten / All Rights Reserved. Use is subject to license terms. * * <https://github.com/anba/es6draft> */ package com.github.anba.es6draft.compiler.assembler; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; /** * */ public final class Type { /** Internal type to represent the reserved slot of a two-byte slot type. */ static final Type RESERVED = new Type("reserved"); /** The {@code void} type. */ public static final Type VOID_TYPE = new Type("V", org.objectweb.asm.Type.VOID_TYPE); /** The {@code boolean} type. */ public static final Type BOOLEAN_TYPE = new Type("Z", org.objectweb.asm.Type.BOOLEAN_TYPE); /** The {@code char} type. */ public static final Type CHAR_TYPE = new Type("C", org.objectweb.asm.Type.CHAR_TYPE); /** The {@code byte} type. */ public static final Type BYTE_TYPE = new Type("B", org.objectweb.asm.Type.BYTE_TYPE); /** The {@code short} type. */ public static final Type SHORT_TYPE = new Type("S", org.objectweb.asm.Type.SHORT_TYPE); /** The {@code int} type. */ public static final Type INT_TYPE = new Type("I", org.objectweb.asm.Type.INT_TYPE); /** The {@code long} type. */ public static final Type LONG_TYPE = new Type("J", org.objectweb.asm.Type.LONG_TYPE); /** The {@code float} type. */ public static final Type FLOAT_TYPE = new Type("F", org.objectweb.asm.Type.FLOAT_TYPE); /** The {@code double} type. */ public static final Type DOUBLE_TYPE = new Type("D", org.objectweb.asm.Type.DOUBLE_TYPE); private final String descriptor; private transient org.objectweb.asm.Type type; private Type(String descriptor) { this.descriptor = descriptor; } private Type(String descriptor, org.objectweb.asm.Type type) { this.descriptor = descriptor; this.type = type; } @Override public String toString() { return descriptor; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null || obj.getClass() != Type.class) { return false; } return descriptor.equals(((Type) obj).descriptor); } @Override public int hashCode() { return descriptor.hashCode(); } /*package*/org.objectweb.asm.Type type() { if (type == null) { type = org.objectweb.asm.Type.getType(descriptor); } return type; } /** * Returns the type descriptor string. * * @return the type descriptor string */ /*package*/String descriptor() { return descriptor; } /** * Returns the internal name. * * @return the internal name */ /*package*/String internalName() { return type().getInternalName(); } /** * Returns the size of this type. * * @return the size */ public int getSize() { return type().getSize(); } public boolean isPrimitive() { return getSort() < Type.Sort.ARRAY; } /*package*/int getSort() { return type().getSort(); } /*package*/int getOpcode(int opcode) { return type().getOpcode(opcode); } /*package*/Type asArray() { return Type.of("[" + descriptor()); } /** * Returns the wrapper for the type, or {@code this} if it does not represent a primitive. * * @return the type's wrapper object */ /*package*/Type asWrapper() { switch (getSort()) { case Type.Sort.VOID: return Types.Void; case Type.Sort.BOOLEAN: return Types.Boolean; case Type.Sort.CHAR: return Types.Character; case Type.Sort.BYTE: return Types.Byte; case Type.Sort.SHORT: return Types.Short; case Type.Sort.INT: return Types.Integer; case Type.Sort.FLOAT: return Types.Float; case Type.Sort.LONG: return Types.Long; case Type.Sort.DOUBLE: return Types.Double; case Type.Sort.ARRAY: case Type.Sort.OBJECT: case Type.Sort.METHOD: default: return this; } } static final class Sort { private Sort() { } static final int VOID = org.objectweb.asm.Type.VOID; static final int BOOLEAN = org.objectweb.asm.Type.BOOLEAN; static final int CHAR = org.objectweb.asm.Type.CHAR; static final int BYTE = org.objectweb.asm.Type.BYTE; static final int SHORT = org.objectweb.asm.Type.SHORT; static final int INT = org.objectweb.asm.Type.INT; static final int FLOAT = org.objectweb.asm.Type.FLOAT; static final int LONG = org.objectweb.asm.Type.LONG; static final int DOUBLE = org.objectweb.asm.Type.DOUBLE; static final int ARRAY = org.objectweb.asm.Type.ARRAY; static final int OBJECT = org.objectweb.asm.Type.OBJECT; static final int METHOD = org.objectweb.asm.Type.METHOD; } /** * Create a type instance for a named object. * * @param internalName * the internal name of the object * @return the type object */ /*package*/static Type forName(String internalName) { return of(org.objectweb.asm.Type.getObjectType(internalName).getDescriptor()); } /** * Returns the binary name for an internal name. * * @param internalName * the internal name * @return the corresponding binary name */ public static String className(String internalName) { return internalName.replace('/', '.'); } /** * Create a type instance for the given type descriptor string. * * @param descriptor * the type descriptor string * @return the type object */ /*package*/static Type of(String descriptor) { return new Type(descriptor); } private static final Map<Class<?>, Type> typeCache = Collections.synchronizedMap(new WeakHashMap<>()); /** * Create a type instance for the given class. * * @param clazz * the class instance * @return the type object */ public static Type of(Class<?> clazz) { Type type = typeCache.get(clazz); if (type == null) { typeCache.put(clazz, type = new Type(org.objectweb.asm.Type.getDescriptor(clazz))); } return type; } /** * Create a type instance for the given sort kind. * * @param sort * the sort kind * @return the type object */ /*package*/static Type of(int sort) { switch (sort) { case Type.Sort.VOID: return Type.VOID_TYPE; case Type.Sort.BOOLEAN: return Type.BOOLEAN_TYPE; case Type.Sort.CHAR: return Type.CHAR_TYPE; case Type.Sort.BYTE: return Type.BYTE_TYPE; case Type.Sort.SHORT: return Type.SHORT_TYPE; case Type.Sort.INT: return Type.INT_TYPE; case Type.Sort.FLOAT: return Type.FLOAT_TYPE; case Type.Sort.LONG: return Type.LONG_TYPE; case Type.Sort.DOUBLE: return Type.DOUBLE_TYPE; case Type.Sort.ARRAY: return Types.Object_; case Type.Sort.OBJECT: return Types.Object; case Type.Sort.METHOD: default: return null; } } /** * Convenience method for {@link MethodTypeDescriptor#methodType(Type, Type...)}. * * @param returnType * the return type * @param parameters * the parameter types * @return the method type descriptor */ public static MethodTypeDescriptor methodType(Type returnType, Type... parameters) { return MethodTypeDescriptor.methodType(returnType, parameters); } }