simple way to generate short-circuit boolean && and ||
This commit is contained in:
@@ -497,42 +497,74 @@ public class ExpressionCodegen extends JetVisitor {
|
|||||||
final IElementType opToken = expression.getOperationReference().getReferencedNameElementType();
|
final IElementType opToken = expression.getOperationReference().getReferencedNameElementType();
|
||||||
if (opToken == JetTokens.EQ) {
|
if (opToken == JetTokens.EQ) {
|
||||||
generateAssignmentExpression(expression);
|
generateAssignmentExpression(expression);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) {
|
else if (JetTokens.AUGMENTED_ASSIGNMENTS.contains(opToken)) {
|
||||||
generateAugmentedAssignment(expression);
|
generateAugmentedAssignment(expression);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
else if (opToken == JetTokens.ANDAND) {
|
||||||
if (op instanceof FunctionDescriptor) {
|
generateBooleanAnd(expression);
|
||||||
JetType returnType = bindingContext.getExpressionType(expression);
|
}
|
||||||
final Type asmType = typeMapper.mapType(returnType);
|
else if (opToken == JetTokens.OROR) {
|
||||||
DeclarationDescriptor cls = op.getContainingDeclaration();
|
generateBooleanOr(expression);
|
||||||
if (isNumberPrimitive(cls)) {
|
}
|
||||||
if (op.getName().equals("compareTo")) {
|
else {
|
||||||
generateCompareOp(expression, opToken, asmType);
|
DeclarationDescriptor op = bindingContext.resolveReferenceExpression(expression.getOperationReference());
|
||||||
}
|
if (op instanceof FunctionDescriptor) {
|
||||||
else {
|
JetType returnType = bindingContext.getExpressionType(expression);
|
||||||
int opcode = opcodeForMethod(op.getName());
|
final Type asmType = typeMapper.mapType(returnType);
|
||||||
generateBinaryOp(expression, (FunctionDescriptor) op, opcode);
|
DeclarationDescriptor cls = op.getContainingDeclaration();
|
||||||
}
|
if (isNumberPrimitive(cls)) {
|
||||||
return;
|
if (op.getName().equals("compareTo")) {
|
||||||
}
|
generateCompareOp(expression, opToken, asmType);
|
||||||
else if (isClass(cls, "Hashable")) {
|
|
||||||
if (op.getName().equals("equals")) {
|
|
||||||
final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft()));
|
|
||||||
final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight()));
|
|
||||||
if (isNumberPrimitive(leftType) && leftType == rightType) {
|
|
||||||
generateCompareOp(expression, opToken, leftType);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException("Don't know how to generate equality for these types");
|
int opcode = opcodeForMethod(op.getName());
|
||||||
|
generateBinaryOp(expression, (FunctionDescriptor) op, opcode);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (isClass(cls, "Hashable")) {
|
||||||
|
if (op.getName().equals("equals")) {
|
||||||
|
final Type leftType = typeMapper.mapType(bindingContext.getExpressionType(expression.getLeft()));
|
||||||
|
final Type rightType = typeMapper.mapType(bindingContext.getExpressionType(expression.getRight()));
|
||||||
|
if (isNumberPrimitive(leftType) && leftType == rightType) {
|
||||||
|
generateCompareOp(expression, opToken, leftType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new UnsupportedOperationException("Don't know how to generate equality for these types");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression);
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException("Don't know how to generate binary op " + expression);
|
}
|
||||||
|
|
||||||
|
private void generateBooleanAnd(JetBinaryExpression expression) {
|
||||||
|
gen(expression.getLeft(), Type.BOOLEAN_TYPE);
|
||||||
|
Label ifFalse = new Label();
|
||||||
|
v.ifeq(ifFalse);
|
||||||
|
gen(expression.getRight(), Type.BOOLEAN_TYPE);
|
||||||
|
Label end = new Label();
|
||||||
|
v.goTo(end);
|
||||||
|
v.mark(ifFalse);
|
||||||
|
v.aconst(false);
|
||||||
|
v.mark(end);
|
||||||
|
myStack.push(StackValue.onStack(Type.BOOLEAN_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateBooleanOr(JetBinaryExpression expression) {
|
||||||
|
gen(expression.getLeft(), Type.BOOLEAN_TYPE);
|
||||||
|
Label ifTrue = new Label();
|
||||||
|
v.ifne(ifTrue);
|
||||||
|
gen(expression.getRight(), Type.BOOLEAN_TYPE);
|
||||||
|
Label end = new Label();
|
||||||
|
v.goTo(end);
|
||||||
|
v.mark(ifTrue);
|
||||||
|
v.aconst(true);
|
||||||
|
v.mark(end);
|
||||||
|
myStack.push(StackValue.onStack(Type.BOOLEAN_TYPE));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) {
|
private static boolean isNumberPrimitive(DeclarationDescriptor descriptor) {
|
||||||
|
|||||||
@@ -451,6 +451,36 @@ public class NamespaceGenTest extends LightCodeInsightFixtureTestCase {
|
|||||||
assertEquals(0, main.invoke(null, 4));
|
assertEquals(0, main.invoke(null, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAnd() throws Exception {
|
||||||
|
loadText("fun foo(a : Int): Boolean = a > 0 && a/0 > 0");
|
||||||
|
final Method main = generateFunction();
|
||||||
|
assertEquals(false, main.invoke(null, 0));
|
||||||
|
boolean hadException = false;
|
||||||
|
try {
|
||||||
|
main.invoke(null, 5);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
if (e.getTargetException() instanceof ArithmeticException) {
|
||||||
|
hadException = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(hadException);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testOr() throws Exception {
|
||||||
|
loadText("fun foo(a : Int): Boolean = a > 0 || a/0 > 0");
|
||||||
|
final Method main = generateFunction();
|
||||||
|
assertEquals(true, main.invoke(null, 5));
|
||||||
|
boolean hadException = false;
|
||||||
|
try {
|
||||||
|
main.invoke(null, 0);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
if (e.getTargetException() instanceof ArithmeticException) {
|
||||||
|
hadException = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assertTrue(hadException);
|
||||||
|
}
|
||||||
|
|
||||||
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
|
private void binOpTest(final String text, final Object arg1, final Object arg2, final Object expected) throws Exception {
|
||||||
loadText(text);
|
loadText(text);
|
||||||
System.out.println(generateToText());
|
System.out.println(generateToText());
|
||||||
|
|||||||
Reference in New Issue
Block a user