summaryrefslogtreecommitdiffstats
path: root/searchlib/src/main/java/com/yahoo/searchlib/rankingexpression/evaluation/Value.java
blob: 207603c5038d6d073992c59da9a2d4e34b7385c0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.searchlib.rankingexpression.evaluation;

import com.yahoo.javacc.UnicodeUtilities;
import com.yahoo.searchlib.rankingexpression.rule.Function;
import com.yahoo.searchlib.rankingexpression.rule.TruthOperator;
import com.yahoo.tensor.Tensor;
import com.yahoo.tensor.TensorAddress;
import com.yahoo.tensor.TensorType;

/**
 * The result of a ranking expression evaluation.
 * Concrete subclasses of this provides implementations of these methods or throws
 * UnsupportedOperationException if the operation is not supported.
 *
 * @author bratseth
 */
public abstract class Value {

    private boolean frozen = false;

    /** Returns the type of this value */
    public abstract TensorType type();

    /** Returns this value as a double, or throws UnsupportedOperationException if it cannot be represented as a double */
    public abstract double asDouble();

    /** Returns this value as a double value, or throws UnsupportedOperationException if it cannot be represented as a double */
    public DoubleValue asDoubleValue() {
        return new DoubleValue(asDouble());
    }

    /** Returns true if this has a double value which is NaN */
    public boolean isNaN() {
        return hasDouble() && Double.isNaN(asDouble());
    }

    /** Returns this as a tensor value */
    public abstract Tensor asTensor();

    /** A utility method for wrapping a double in a rank 0 tensor */
    protected Tensor doubleAsTensor(double value) {
        return Tensor.Builder.of(TensorType.empty).cell(TensorAddress.of(), value).build();
    }

    /** Returns true if this value can return itself as a double, i.e asDoubleValue will return a value and not throw */
    public abstract boolean hasDouble();

    /** Returns this value as a boolean. */
    public abstract boolean asBoolean();

    public abstract Value negate();

    public abstract Value add(Value value);

    public abstract Value subtract(Value value);

    public abstract Value multiply(Value value);

    public abstract Value divide(Value value);

    public abstract Value modulo(Value value);

    public abstract Value and(Value value);

    public abstract Value or(Value value);

    public abstract Value not();

    public abstract Value power(Value value);

    /** Perform the comparison specified by the operator between this value and the given value */
    public abstract Value compare(TruthOperator operator, Value value);

    /** Perform the given binary function on this value and the given value */
    public abstract Value function(Function function, Value value);

    /**
     * Irreversibly makes this immutable. Overriders must always call super.freeze() and return this
     *
     * @return this for convenience
     */
    public Value freeze() {
        frozen = true;
        return this;
    }

    /** Returns true if this is immutable, false otherwise */
    public final boolean isFrozen() { return frozen; }

    /** Returns this is mutable, or a mutable copy otherwise */
    public abstract Value asMutable();

    @Override
    public abstract String toString();

    @Override
    public abstract boolean equals(Object other);

    /** Returns a hash which only depends on the content of this value. */
    @Override
    public abstract int hashCode();

    /**
     * Parses the given string to a value and returns it.
     * Different subtypes of Value will be returned depending on the string.
     *
     * @return a mutable Value
     * @throws IllegalArgumentException if the given string is not parseable as a value
     */
    public static Value parse(String value) {
        if (value.equals("true"))
            return new BooleanValue(true);
        else if (value.equals("false"))
            return new BooleanValue(false);
        else if (value.startsWith("\"") || value.startsWith("'"))
            return new StringValue(value);
        else if (value.startsWith("{"))
            return new TensorValue(Tensor.from(value));
        else if ((value.indexOf('.') == -1) && (value.indexOf('e') == -1) && (value.indexOf('E') == -1))
            return new LongValue(Long.parseLong(value));
         else
             return new DoubleValue(Double.parseDouble(value));
    }

    public static Value of(Tensor tensor) {
        return new TensorValue(tensor);
    }

    public static Value of(double scalar) {
        return new DoubleValue(scalar);
    }

}