Skip to content

Commit

Permalink
#246 Refactor Count/First/Last/FoldCat to OneToOneValueExpressions.
Browse files Browse the repository at this point in the history
  • Loading branch information
rdvdijk committed Aug 30, 2018
1 parent dede597 commit 67d1c77
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,11 @@

package io.parsingdata.metal.expression.value;

import static java.math.BigInteger.ZERO;

import static io.parsingdata.metal.data.Slice.createFromSource;
import static java.math.BigInteger.ZERO;

import java.util.Objects;
import java.util.Optional;

import io.parsingdata.metal.Util;
import io.parsingdata.metal.data.ConcatenatedValueSource;
import io.parsingdata.metal.data.ImmutableList;
import io.parsingdata.metal.data.ParseState;
Expand All @@ -36,36 +33,17 @@
* @see FoldLeft
* @see Cat
*/
public class FoldCat implements ValueExpression {

public final ValueExpression operand;
public class FoldCat extends OneToOneValueExpression {

public FoldCat(final ValueExpression operand) {
this.operand = operand;
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
return ConcatenatedValueSource.create(operand.eval(parseState, encoding))
.flatMap(source -> createFromSource(source, ZERO, source.length))
.map(slice -> new ImmutableList<Optional<Value>>().add(Optional.of(new Value(slice, encoding))))
.orElseGet(() -> ImmutableList.create(Optional.empty()));
}

@Override
public String toString() {
return getClass().getSimpleName() + "(" + operand + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(operand, ((FoldCat)obj).operand);
super(operand);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), operand);
public Optional<Value> eval(final ImmutableList<Optional<Value>> list, final ParseState parseState, final Encoding encoding) {
return ConcatenatedValueSource.create(list)
.flatMap(source -> createFromSource(source, ZERO, source.length))
.map(slice -> new Value(slice, encoding));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@
import io.parsingdata.metal.encoding.Encoding;

/**
* Base class for {@link ValueExpression}s with one operand.
* Base class for {@link ValueExpression}s with one operand that evaluates
* to multiple values.
* <p>
* A OneToManyValueExpression implements a ValueExpression that has one
* <code>operand</code> (a {@link ValueExpression}). The operand is first
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2013-2016 Netherlands Forensic Institute
*
* 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 io.parsingdata.metal.expression.value;

import static io.parsingdata.metal.Util.checkNotNull;

import java.util.Objects;
import java.util.Optional;

import io.parsingdata.metal.Util;
import io.parsingdata.metal.data.ImmutableList;
import io.parsingdata.metal.data.ParseState;
import io.parsingdata.metal.encoding.Encoding;

/**
* Base class for {@link ValueExpression}s with one operand that evaluates
* to a single value.
* <p>
* A OneToOneValueExpression implements a ValueExpression that has one
* <code>operand</code> (a {@link ValueExpression}). The operand is first
* evaluated. If it evaluates to {@link Optional#empty()}, the result of the
* ValueExpression itself will be that as well.
* <p>
* To implement a OneToOneValueExpression, only the
* {@link #eval(ImmutableList, ParseState, Encoding)} must
* be implemented, handling the case of evaluating a list of values. This
* base class takes care of evaluating the operand and handling list
* semantics.
*
* @see BinaryValueExpression
*/
public abstract class OneToOneValueExpression implements ValueExpression {

public final ValueExpression operand;

public OneToOneValueExpression(final ValueExpression operand) {
this.operand = checkNotNull(operand, "operand");
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
return ImmutableList.create(eval(operand.eval(parseState, encoding), parseState, encoding));
}

public abstract Optional<Value> eval(final ImmutableList<Optional<Value>> list, final ParseState parseState, final Encoding encoding);

@Override
public String toString() {
return getClass().getSimpleName() + "(" + operand + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(operand, ((OneToOneValueExpression)obj).operand);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), operand);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,56 +16,34 @@

package io.parsingdata.metal.expression.value.reference;

import static io.parsingdata.metal.Util.checkNotNull;

import java.util.Objects;
import java.util.Optional;

import io.parsingdata.metal.Util;
import io.parsingdata.metal.data.ImmutableList;
import io.parsingdata.metal.data.ParseState;
import io.parsingdata.metal.encoding.Encoding;
import io.parsingdata.metal.encoding.Sign;
import io.parsingdata.metal.expression.value.ConstantFactory;
import io.parsingdata.metal.expression.value.OneToOneValueExpression;
import io.parsingdata.metal.expression.value.Value;
import io.parsingdata.metal.expression.value.ValueExpression;

/**
* A {@link ValueExpression} that represents the amount of {@link Value}s
* returned by evaluating its <code>operand</code>.
*/
public class Count implements ValueExpression {

public final ValueExpression operand;
public class Count extends OneToOneValueExpression {

public Count(final ValueExpression operand) {
this.operand = checkNotNull(operand, "operand");
super(operand);
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
final ImmutableList<Optional<Value>> values = operand.eval(parseState, encoding);
return ImmutableList.create(Optional.of(fromNumeric(values.size)));
public Optional<Value> eval(final ImmutableList<Optional<Value>> list, final ParseState parseState, final Encoding encoding) {
return Optional.of(fromNumeric(list.size));
}

private static Value fromNumeric(final long length) {
return ConstantFactory.createFromNumeric(length, new Encoding(Sign.SIGNED));
}

@Override
public String toString() {
return getClass().getSimpleName() + "(" + operand + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(operand, ((Count)obj).operand);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), operand);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,55 +18,34 @@

import static io.parsingdata.metal.Trampoline.complete;
import static io.parsingdata.metal.Trampoline.intermediate;
import static io.parsingdata.metal.Util.checkNotNull;

import java.util.Objects;
import java.util.Optional;

import io.parsingdata.metal.Trampoline;
import io.parsingdata.metal.Util;
import io.parsingdata.metal.data.ImmutableList;
import io.parsingdata.metal.data.ParseState;
import io.parsingdata.metal.encoding.Encoding;
import io.parsingdata.metal.expression.value.OneToOneValueExpression;
import io.parsingdata.metal.expression.value.Value;
import io.parsingdata.metal.expression.value.ValueExpression;

/**
* A {@link ValueExpression} that represents the first {@link Value} returned
* by evaluating its <code>operand</code>.
*/
public class First implements ValueExpression {

public final ValueExpression operand;
public class First extends OneToOneValueExpression {

public First(final ValueExpression operand) {
this.operand = checkNotNull(operand, "operand");
super(operand);
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
final ImmutableList<Optional<Value>> list = operand.eval(parseState, encoding);
return list.isEmpty() ? list : ImmutableList.create(getFirst(list).computeResult());
public Optional<Value> eval(final ImmutableList<Optional<Value>> list, final ParseState parseState, final Encoding encoding) {
return list.isEmpty() ? Optional.empty() : getFirst(list).computeResult();
}

private Trampoline<Optional<Value>> getFirst(final ImmutableList<Optional<Value>> values) {
return values.tail.isEmpty() ? complete(() -> values.head) : intermediate(() -> getFirst(values.tail));
}

@Override
public String toString() {
return getClass().getSimpleName() + "(" + operand + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(operand, ((First)obj).operand);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), operand);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,50 +16,28 @@

package io.parsingdata.metal.expression.value.reference;

import static io.parsingdata.metal.Util.checkNotNull;

import java.util.Objects;
import java.util.Optional;

import io.parsingdata.metal.Util;
import io.parsingdata.metal.data.ImmutableList;
import io.parsingdata.metal.data.ParseState;
import io.parsingdata.metal.encoding.Encoding;
import io.parsingdata.metal.expression.value.OneToOneValueExpression;
import io.parsingdata.metal.expression.value.Value;
import io.parsingdata.metal.expression.value.ValueExpression;

/**
* A {@link ValueExpression} that represents the last {@link Value} returned
* by evaluating its <code>operand</code>.
*/
public class Last implements ValueExpression {

public final ValueExpression operand;
public class Last extends OneToOneValueExpression {

public Last(final ValueExpression operand) {
this.operand = checkNotNull(operand, "operand");
}

@Override
public ImmutableList<Optional<Value>> eval(final ParseState parseState, final Encoding encoding) {
final ImmutableList<Optional<Value>> list = operand.eval(parseState, encoding);
return list.isEmpty() ? list : ImmutableList.create(list.head);
}

@Override
public String toString() {
return getClass().getSimpleName() + "(" + operand + ")";
}

@Override
public boolean equals(final Object obj) {
return Util.notNullAndSameClass(this, obj)
&& Objects.equals(operand, ((Last)obj).operand);
super(operand);
}

@Override
public int hashCode() {
return Objects.hash(getClass(), operand);
public Optional<Value> eval(final ImmutableList<Optional<Value>> list, final ParseState parseState, final Encoding encoding) {
return list.isEmpty() ? Optional.empty() : list.head;
}

}

0 comments on commit 67d1c77

Please sign in to comment.