Skip to content

Commit

Permalink
Full add support
Browse files Browse the repository at this point in the history
  • Loading branch information
pontusmelke committed May 30, 2018
1 parent ceb802b commit b17880e
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,32 @@

import org.opencypher.v9_0.util.CypherTypeException;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

import org.neo4j.internal.kernel.api.CursorFactory;
import org.neo4j.internal.kernel.api.NodeCursor;
import org.neo4j.internal.kernel.api.PropertyCursor;
import org.neo4j.internal.kernel.api.Transaction;
import org.neo4j.kernel.impl.util.ValueUtils;
import org.neo4j.values.AnyValue;
import org.neo4j.values.storable.ArrayValue;
import org.neo4j.values.storable.DoubleValue;
import org.neo4j.values.storable.DurationValue;
import org.neo4j.values.storable.NumberValue;
import org.neo4j.values.storable.PointValue;
import org.neo4j.values.storable.StringValue;
import org.neo4j.values.storable.TemporalValue;
import org.neo4j.values.storable.TextValue;
import org.neo4j.values.storable.Value;
import org.neo4j.values.storable.Values;
import org.neo4j.values.virtual.ListValue;
import org.neo4j.values.virtual.VirtualValues;

import static org.neo4j.values.storable.Values.NO_VALUE;
import static org.neo4j.values.storable.Values.doubleValue;
import static org.neo4j.values.storable.Values.stringValue;

public final class AnyValueMath
{
Expand Down Expand Up @@ -74,17 +87,90 @@ public static DoubleValue rand()
return doubleValue( ThreadLocalRandom.current().nextDouble() );
}

//TODO this is horrible spaghetti code, we should push most of this down to AnyValue
public static AnyValue add( AnyValue lhs, AnyValue rhs )
{
if ( lhs == NO_VALUE || rhs == NO_VALUE )
{
return NO_VALUE;
}
if ( lhs instanceof NumberValue && rhs instanceof NumberValue )
{
return ((NumberValue) lhs).plus( (NumberValue) rhs );
}
else
//List addition
boolean lhsIsListValue = lhs instanceof ListValue;
if ( lhsIsListValue && rhs instanceof ListValue )
{
//todo
throw new CypherTypeException( "can only add numbers", null );
return VirtualValues.concat( (ListValue) lhs, (ListValue) rhs );
}
else if ( lhsIsListValue )
{
return VirtualValues.appendToList( (ListValue) lhs, rhs );
}
else if ( rhs instanceof ListValue )
{
return VirtualValues.prependToList( (ListValue) rhs, lhs );
}

// String addition
if ( lhs instanceof TextValue )
{
if ( rhs instanceof Value )
{
// Unfortunately string concatenation is not defined for temporal and spatial types, so we need to
// exclude them
if ( !(rhs instanceof TemporalValue || rhs instanceof DurationValue || rhs instanceof PointValue) )
{
return stringValue( ((TextValue) lhs).stringValue() + ((Value) rhs).prettyPrint());
}
else
{
//TODO this seems wrong but it is what we currently do in compiled runtime
return stringValue(((TextValue) lhs).stringValue() + String.valueOf( rhs ));
}
}
}
if ( rhs instanceof TextValue )
{
if ( lhs instanceof Value )
{
// Unfortunately string concatenation is not defined for temporal and spatial types, so we need to
// exclude them
if ( !(lhs instanceof TemporalValue || lhs instanceof DurationValue || lhs instanceof PointValue) )
{
return stringValue( ((Value) lhs).prettyPrint() + ((TextValue) rhs).stringValue());
}
else
{
//TODO this seems wrong but it is what we currently do in compiled runtime
return stringValue(String.valueOf( lhs ) + ((TextValue) rhs).stringValue() );
}
}
}

// Temporal values
if ( lhs instanceof TemporalValue )
{
if ( rhs instanceof DurationValue )
{
return ((TemporalValue) lhs).plus( (DurationValue) rhs );
}
}
if ( lhs instanceof DurationValue )
{
if ( rhs instanceof TemporalValue )
{
return ((TemporalValue) rhs).plus( (DurationValue) lhs );
}
if ( rhs instanceof DurationValue )
{
return ((DurationValue) lhs).add( (DurationValue) rhs );
}
}

throw new CypherTypeException(
String.format( "Don't know how to add `%s` and `%s`", lhs, rhs), null );
}

public static AnyValue subtract( AnyValue lhs, AnyValue rhs )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class CodeGenerationTest extends CypherFunSuite with AstConstructionTestSupport
value should (be > 0.0 and be <= 1.0)
}

test("add function") {
test("add numbers") {
// Given
val expression = add(literalInt(42), literalInt(10))

Expand All @@ -84,6 +84,18 @@ class CodeGenerationTest extends CypherFunSuite with AstConstructionTestSupport
compiled.compute(ctx, tx, EMPTY_MAP) should equal(longValue(52))
}

test("add with NO_VALUE") {
// Given
val expression = add(parameter("a"), parameter("b"))

// When
val compiled = compile(expression)

// Then
compiled.compute(ctx, tx, map(Array("a", "b"), Array(longValue(42), NO_VALUE))) should equal(NO_VALUE)
compiled.compute(ctx, tx, map(Array("a", "b"), Array(NO_VALUE, longValue(42)))) should equal(NO_VALUE)
}

test("subtract function") {
// Given
val expression = subtract(literalInt(42), literalInt(10))
Expand Down

0 comments on commit b17880e

Please sign in to comment.