Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.facebook.presto.bytecode.expression.ComparisonBytecodeExpression Maven / Gradle / Ivy
/*
* 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.facebook.presto.bytecode.expression;
import com.facebook.presto.bytecode.BytecodeBlock;
import com.facebook.presto.bytecode.BytecodeNode;
import com.facebook.presto.bytecode.MethodGenerationContext;
import com.facebook.presto.bytecode.OpCode;
import com.facebook.presto.bytecode.instruction.JumpInstruction;
import com.facebook.presto.bytecode.instruction.LabelNode;
import com.google.common.collect.ImmutableList;
import java.util.List;
import static com.facebook.presto.bytecode.OpCode.DCMPG;
import static com.facebook.presto.bytecode.OpCode.DCMPL;
import static com.facebook.presto.bytecode.OpCode.FCMPG;
import static com.facebook.presto.bytecode.OpCode.FCMPL;
import static com.facebook.presto.bytecode.OpCode.IFEQ;
import static com.facebook.presto.bytecode.OpCode.IFGE;
import static com.facebook.presto.bytecode.OpCode.IFGT;
import static com.facebook.presto.bytecode.OpCode.IFLE;
import static com.facebook.presto.bytecode.OpCode.IFLT;
import static com.facebook.presto.bytecode.OpCode.IFNE;
import static com.facebook.presto.bytecode.OpCode.IF_ACMPEQ;
import static com.facebook.presto.bytecode.OpCode.IF_ACMPNE;
import static com.facebook.presto.bytecode.OpCode.IF_ICMPEQ;
import static com.facebook.presto.bytecode.OpCode.IF_ICMPGE;
import static com.facebook.presto.bytecode.OpCode.IF_ICMPGT;
import static com.facebook.presto.bytecode.OpCode.IF_ICMPLE;
import static com.facebook.presto.bytecode.OpCode.IF_ICMPLT;
import static com.facebook.presto.bytecode.OpCode.IF_ICMPNE;
import static com.facebook.presto.bytecode.OpCode.LCMP;
import static com.facebook.presto.bytecode.ParameterizedType.type;
import static com.google.common.base.Preconditions.checkArgument;
import static java.util.Objects.requireNonNull;
class ComparisonBytecodeExpression
extends BytecodeExpression
{
static BytecodeExpression lessThan(BytecodeExpression left, BytecodeExpression right)
{
checkArgumentTypes(left, right);
OpCode comparisonInstruction;
OpCode noMatchJumpInstruction;
Class> type = left.getType().getPrimitiveType();
if (type == int.class) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ICMPGE;
}
else if (type == long.class) {
comparisonInstruction = LCMP;
noMatchJumpInstruction = IFGE;
}
else if (type == float.class) {
comparisonInstruction = FCMPG;
noMatchJumpInstruction = IFGE;
}
else if (type == double.class) {
comparisonInstruction = DCMPG;
noMatchJumpInstruction = IFGE;
}
else {
throw new IllegalArgumentException("Less than does not support " + type);
}
return new ComparisonBytecodeExpression("<", comparisonInstruction, noMatchJumpInstruction, left, right);
}
static BytecodeExpression greaterThan(BytecodeExpression left, BytecodeExpression right)
{
checkArgumentTypes(left, right);
OpCode comparisonInstruction;
OpCode noMatchJumpInstruction;
Class> type = left.getType().getPrimitiveType();
if (type == int.class) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ICMPLE;
}
else if (type == long.class) {
comparisonInstruction = LCMP;
noMatchJumpInstruction = IFLE;
}
else if (type == float.class) {
comparisonInstruction = FCMPL;
noMatchJumpInstruction = IFLE;
}
else if (type == double.class) {
comparisonInstruction = DCMPL;
noMatchJumpInstruction = IFLE;
}
else {
throw new IllegalArgumentException("Greater than does not support " + type);
}
return new ComparisonBytecodeExpression(">", comparisonInstruction, noMatchJumpInstruction, left, right);
}
static BytecodeExpression lessThanOrEqual(BytecodeExpression left, BytecodeExpression right)
{
checkArgumentTypes(left, right);
OpCode comparisonInstruction;
OpCode noMatchJumpInstruction;
Class> type = left.getType().getPrimitiveType();
if (type == int.class) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ICMPGT;
}
else if (type == long.class) {
comparisonInstruction = LCMP;
noMatchJumpInstruction = IFGT;
}
else if (type == float.class) {
comparisonInstruction = FCMPG;
noMatchJumpInstruction = IFGT;
}
else if (type == double.class) {
comparisonInstruction = DCMPG;
noMatchJumpInstruction = IFGT;
}
else {
throw new IllegalArgumentException("Less than or equal does not support " + type);
}
return new ComparisonBytecodeExpression("<=", comparisonInstruction, noMatchJumpInstruction, left, right);
}
static BytecodeExpression greaterThanOrEqual(BytecodeExpression left, BytecodeExpression right)
{
checkArgumentTypes(left, right);
OpCode comparisonInstruction;
OpCode noMatchJumpInstruction;
Class> type = left.getType().getPrimitiveType();
if (type == int.class) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ICMPLT;
}
else if (type == long.class) {
comparisonInstruction = LCMP;
noMatchJumpInstruction = IFLT;
}
else if (type == float.class) {
comparisonInstruction = FCMPL;
noMatchJumpInstruction = IFLT;
}
else if (type == double.class) {
comparisonInstruction = DCMPL;
noMatchJumpInstruction = IFLT;
}
else {
throw new IllegalArgumentException("Greater than or equal does not support " + type);
}
return new ComparisonBytecodeExpression(">=", comparisonInstruction, noMatchJumpInstruction, left, right);
}
static BytecodeExpression equal(BytecodeExpression left, BytecodeExpression right)
{
requireNonNull(left, "left is null");
requireNonNull(right, "right is null");
checkArgument(left.getType().equals(right.getType()), "left and right must be the same type");
OpCode comparisonInstruction;
OpCode noMatchJumpInstruction;
Class> type = left.getType().getPrimitiveType();
if (type == int.class) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ICMPNE;
}
else if (type == long.class) {
comparisonInstruction = LCMP;
noMatchJumpInstruction = IFNE;
}
else if (type == float.class) {
comparisonInstruction = FCMPL;
noMatchJumpInstruction = IFNE;
}
else if (type == double.class) {
comparisonInstruction = DCMPL;
noMatchJumpInstruction = IFNE;
}
else if (type == null) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ACMPNE;
}
else {
throw new IllegalArgumentException("Equal does not support " + type);
}
return new ComparisonBytecodeExpression("==", comparisonInstruction, noMatchJumpInstruction, left, right);
}
static BytecodeExpression notEqual(BytecodeExpression left, BytecodeExpression right)
{
requireNonNull(left, "left is null");
requireNonNull(right, "right is null");
checkArgument(left.getType().equals(right.getType()), "left and right must be the same type");
OpCode comparisonInstruction;
OpCode noMatchJumpInstruction;
Class> type = left.getType().getPrimitiveType();
if (type == int.class) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ICMPEQ;
}
else if (type == long.class) {
comparisonInstruction = LCMP;
noMatchJumpInstruction = IFEQ;
}
else if (type == float.class) {
comparisonInstruction = FCMPL;
noMatchJumpInstruction = IFEQ;
}
else if (type == double.class) {
comparisonInstruction = DCMPL;
noMatchJumpInstruction = IFEQ;
}
else if (type == null) {
comparisonInstruction = null;
noMatchJumpInstruction = IF_ACMPEQ;
}
else {
throw new IllegalArgumentException("Not equal than does not support " + type);
}
return new ComparisonBytecodeExpression("!=", comparisonInstruction, noMatchJumpInstruction, left, right);
}
private static void checkArgumentTypes(BytecodeExpression left, BytecodeExpression right)
{
Class> leftType = getPrimitiveType(left, "left");
Class> rightType = getPrimitiveType(right, "right");
checkArgument(leftType == rightType, "left and right must be the same type");
}
private static Class> getPrimitiveType(BytecodeExpression expression, String name)
{
requireNonNull(expression, name + " is null");
Class> leftType = expression.getType().getPrimitiveType();
checkArgument(leftType != null, name + " is not a primitive");
checkArgument(leftType != void.class, name + " is void");
return leftType;
}
private final String infixSymbol;
private final OpCode comparisonInstruction;
private final OpCode noMatchJumpInstruction;
private final BytecodeExpression left;
private final BytecodeExpression right;
private ComparisonBytecodeExpression(
String infixSymbol,
OpCode comparisonInstruction,
OpCode noMatchJumpInstruction,
BytecodeExpression left,
BytecodeExpression right)
{
super(type(boolean.class));
this.infixSymbol = infixSymbol;
this.comparisonInstruction = comparisonInstruction;
this.noMatchJumpInstruction = noMatchJumpInstruction;
this.left = left;
this.right = right;
}
@Override
public BytecodeNode getBytecode(MethodGenerationContext generationContext)
{
BytecodeBlock block = new BytecodeBlock()
.append(left)
.append(right);
if (comparisonInstruction != null) {
block.append(comparisonInstruction);
}
LabelNode noMatch = new LabelNode("no_match");
LabelNode end = new LabelNode("end");
return block
.append(new JumpInstruction(noMatchJumpInstruction, noMatch))
.push(true)
.gotoLabel(end)
.append(noMatch)
.push(false)
.append(end);
}
@Override
public List getChildNodes()
{
return ImmutableList.of(left, right);
}
@Override
protected String formatOneLine()
{
return "(" + left + " " + infixSymbol + " " + right + ")";
}
}