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

net.sandius.rembulan.compiler.gen.asm.helpers.BoxedPrimitivesMethods Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016 Miroslav Janíček
 *
 * 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 net.sandius.rembulan.compiler.gen.asm.helpers;

import net.sandius.rembulan.util.Check;
import org.objectweb.asm.Type;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.LdcInsnNode;
import org.objectweb.asm.tree.MethodInsnNode;
import org.objectweb.asm.tree.TypeInsnNode;

import static org.objectweb.asm.Opcodes.ACONST_NULL;
import static org.objectweb.asm.Opcodes.CHECKCAST;
import static org.objectweb.asm.Opcodes.GETSTATIC;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;

public class BoxedPrimitivesMethods {

	private BoxedPrimitivesMethods() {
		// not to be instantiated
	}

	public static AbstractInsnNode loadNull() {
		return new InsnNode(ACONST_NULL);
	}

	public static AbstractInsnNode loadBoxedBoolean(boolean value) {
		return new FieldInsnNode(
				GETSTATIC,
				Type.getInternalName(Boolean.class),
				value ? "TRUE" : "FALSE",
				Type.getDescriptor(Boolean.class));
	}

	public static AbstractInsnNode booleanValue() {
		return new MethodInsnNode(
				INVOKEVIRTUAL,
				Type.getInternalName(Boolean.class),
				"booleanValue",
				Type.getMethodDescriptor(
						Type.BOOLEAN_TYPE),
				false);
	}

	public static AbstractInsnNode intValue(Class clazz) {
		return new MethodInsnNode(
				INVOKEVIRTUAL,
				Type.getInternalName(clazz),
				"intValue",
				Type.getMethodDescriptor(
						Type.INT_TYPE),
				false);
	}

	public static AbstractInsnNode longValue(Class clazz) {
		return new MethodInsnNode(
				INVOKEVIRTUAL,
				Type.getInternalName(clazz),
				"longValue",
				Type.getMethodDescriptor(
						Type.LONG_TYPE),
				false);
	}

	public static AbstractInsnNode doubleValue(Class clazz) {
		return new MethodInsnNode(
				INVOKEVIRTUAL,
				Type.getInternalName(clazz),
				"doubleValue",
				Type.getMethodDescriptor(
						Type.DOUBLE_TYPE),
				false);
	}

	public static MethodInsnNode box(Type from, Type to) {
		return new MethodInsnNode(
				INVOKESTATIC,
				to.getInternalName(),
				"valueOf",
				Type.getMethodDescriptor(
						to,
						from),
				false);
	}

	public static MethodInsnNode box(Type from, Class to) {
		return box(from, Type.getType(to));
	}

	public static AbstractInsnNode unbox(Class clazz, Type requiredType) {
		if (requiredType.equals(Type.LONG_TYPE)) {
			return BoxedPrimitivesMethods.longValue(clazz);
		}
		else if (requiredType.equals(Type.INT_TYPE)) {
			return BoxedPrimitivesMethods.intValue(clazz);
		}
		else if (requiredType.equals(Type.DOUBLE_TYPE)) {
			return BoxedPrimitivesMethods.doubleValue(clazz);
		}
		else {
			throw new UnsupportedOperationException("Unsupported primitive type: " + requiredType);
		}
	}

	public static InsnList loadBoxedConstant(Object k, Class castTo) {
		InsnList il = new InsnList();

		if (k == null) {
			il.add(loadNull());
		}
		else if (k instanceof Boolean) {
			il.add(BoxedPrimitivesMethods.loadBoxedBoolean((Boolean) k));
		}
		else if (k instanceof Double || k instanceof Float) {
			il.add(ASMUtils.loadDouble(((Number) k).doubleValue()));
			il.add(BoxedPrimitivesMethods.box(Type.DOUBLE_TYPE, Type.getType(Double.class)));
		}
		else if (k instanceof Number) {
			il.add(ASMUtils.loadLong(((Number) k).longValue()));
			il.add(BoxedPrimitivesMethods.box(Type.LONG_TYPE, Type.getType(Long.class)));
		}
		else if (k instanceof String) {
			il.add(new LdcInsnNode(k));
		}
		else {
			throw new UnsupportedOperationException("Illegal constant type: " + k.getClass());
		}

		if (castTo != null) {
			Check.notNull(k);
			if (!castTo.isAssignableFrom(k.getClass())) {
				il.add(new TypeInsnNode(CHECKCAST, Type.getInternalName(castTo)));
			}
		}

		return il;
	}

	public static InsnList loadBoxedConstant(Object k) {
		return loadBoxedConstant(k, null);
	}

	public static AbstractInsnNode loadNumericValue(Number n, Type requiredType) {
		if (n instanceof Double || n instanceof Float) {
			if (requiredType.equals(Type.LONG_TYPE)) return ASMUtils.loadLong(n.longValue());
			else if (requiredType.equals(Type.INT_TYPE)) return ASMUtils.loadInt(n.intValue());
			else if (requiredType.equals(Type.DOUBLE_TYPE)) return ASMUtils.loadDouble(n.doubleValue());
			else {
				throw new UnsupportedOperationException("Unsupported required type: " + requiredType);
			}
		}
		else {
			if (requiredType.equals(Type.LONG_TYPE)) return ASMUtils.loadLong(n.longValue());
			else if (requiredType.equals(Type.INT_TYPE)) return ASMUtils.loadInt(n.intValue());
			else if (requiredType.equals(Type.DOUBLE_TYPE)) return ASMUtils.loadDouble(n.doubleValue());
			else {
				throw new UnsupportedOperationException("Unsupported required type: " + requiredType);
			}
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy