From 09d78604ac4269e71609e5b39aa8cc7baf3b1b06 Mon Sep 17 00:00:00 2001 From: Pontus Melke Date: Mon, 18 Jan 2016 22:34:20 +0100 Subject: [PATCH] Support for ternary operator --- .../bytecode/ByteCodeExpressionVisitor.java | 10 ++- .../org/neo4j/codegen/CodeGenerationTest.java | 61 ++++++++++++++++++- 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/community/codegen/src/main/java/org/neo4j/codegen/bytecode/ByteCodeExpressionVisitor.java b/community/codegen/src/main/java/org/neo4j/codegen/bytecode/ByteCodeExpressionVisitor.java index e2897063e2d32..5adff1d94d955 100644 --- a/community/codegen/src/main/java/org/neo4j/codegen/bytecode/ByteCodeExpressionVisitor.java +++ b/community/codegen/src/main/java/org/neo4j/codegen/bytecode/ByteCodeExpressionVisitor.java @@ -162,7 +162,15 @@ public void not( Expression expression ) @Override public void ternary( Expression test, Expression onTrue, Expression onFalse ) { - + test.accept( this ); + Label l0 = new Label(); + methodVisitor.visitJumpInsn( IFEQ, l0 ); + onTrue.accept( this ); + Label l1 = new Label(); + methodVisitor.visitJumpInsn( GOTO, l1 ); + methodVisitor.visitLabel( l0 ); + onFalse.accept( this ); + methodVisitor.visitLabel( l1 ); } @Override diff --git a/community/codegen/src/test/java/org/neo4j/codegen/CodeGenerationTest.java b/community/codegen/src/test/java/org/neo4j/codegen/CodeGenerationTest.java index 613123941648b..fb8960619e605 100644 --- a/community/codegen/src/test/java/org/neo4j/codegen/CodeGenerationTest.java +++ b/community/codegen/src/test/java/org/neo4j/codegen/CodeGenerationTest.java @@ -60,6 +60,7 @@ import static org.neo4j.codegen.Expression.newInstance; import static org.neo4j.codegen.Expression.not; import static org.neo4j.codegen.Expression.or; +import static org.neo4j.codegen.Expression.ternary; import static org.neo4j.codegen.ExpressionTemplate.cast; import static org.neo4j.codegen.ExpressionTemplate.load; import static org.neo4j.codegen.ExpressionTemplate.self; @@ -644,7 +645,6 @@ public void shouldGenerateMethodUsingOr() throws Throwable handle = simple.handle(); } - // when MethodHandle conditional = instanceMethod( handle.newInstance(), "conditional", boolean.class, boolean.class); @@ -657,7 +657,7 @@ public void shouldGenerateMethodUsingOr() throws Throwable } @Test - public void shouldGenerateMethodUsingNot() throws Throwable + public void shouldHandleNot() throws Throwable { // given ClassHandle handle; @@ -672,7 +672,6 @@ public void shouldGenerateMethodUsingNot() throws Throwable handle = simple.handle(); } - // when MethodHandle conditional = instanceMethod( handle.newInstance(), "conditional", boolean.class); @@ -682,6 +681,62 @@ public void shouldGenerateMethodUsingNot() throws Throwable assertThat(conditional.invoke( false), equalTo(true)); } + @Test + public void shouldHandleTernaryOperator() throws Throwable + { + // given + ClassHandle handle; + try ( ClassGenerator simple = generateClass( "SimpleClass" ) ) + { + try ( CodeBlock conditional = simple.generateMethod( String.class, "ternary", + param( boolean.class, "test"), param( TernaryChecker.class, "check" )) ) + { + conditional.returns( + ternary( conditional.load( "test" ), + invoke( conditional.load("check"), methodReference( TernaryChecker.class, String.class, "onTrue" ) ), + invoke( conditional.load("check"), methodReference( TernaryChecker.class, String.class, "onFalse" ) ))); + } + + handle = simple.handle(); + } + + // when + MethodHandle ternary = + instanceMethod( handle.newInstance(), "ternary", boolean.class, TernaryChecker.class); + + // then + TernaryChecker checker1 = new TernaryChecker(); + assertThat(ternary.invoke( true, checker1), equalTo("on true")); + assertTrue(checker1.ranOnTrue); + assertFalse(checker1.ranOnFalse); + + + TernaryChecker checker2 = new TernaryChecker(); + assertThat(ternary.invoke( false, checker2), equalTo("on false")); + assertFalse(checker2.ranOnTrue); + assertTrue(checker2.ranOnFalse); + } + + public static class TernaryChecker + { + private boolean ranOnTrue = false; + private boolean ranOnFalse = false; + + public String onTrue() + { + ranOnTrue = true; + return "on true"; + } + + public String onFalse() + { + ranOnFalse = true; + return "on false"; + } + + + } + public static class ResourceFactory {