aboutsummaryrefslogtreecommitdiffstats
path: root/eval/src/vespa/eval/eval/value_type.h
blob: b35e23ee4e6e07971bfe8745d511855457dce367 (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
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#pragma once

#include "cell_type.h"
#include <vespa/vespalib/stllike/string.h>
#include <vector>

namespace vespalib::eval {

/**
 * The type of a Value. This is used for type-resolution during
 * compilation of interpreted functions using boxed polymorphic
 * values.
 **/
class ValueType
{
public:
    struct Dimension {
        using size_type = uint32_t;
        static constexpr size_type npos = -1;
        vespalib::string name;
        size_type size;
        Dimension(const vespalib::string &name_in) noexcept
            : name(name_in), size(npos) {}
        Dimension(const vespalib::string &name_in, size_type size_in) noexcept
            : name(name_in), size(size_in) {}
        bool operator==(const Dimension &rhs) const noexcept {
            return ((name == rhs.name) && (size == rhs.size));
        }
        bool operator!=(const Dimension &rhs) const noexcept { return !(*this == rhs); }
        bool is_mapped() const noexcept { return (size == npos); }
        bool is_indexed() const noexcept { return (size != npos); }
        bool is_trivial() const noexcept { return (size == 1); }
    };

private:
    bool                   _error;
    CellType               _cell_type;
    std::vector<Dimension> _dimensions;

    ValueType() noexcept
        : _error(true), _cell_type(CellType::DOUBLE), _dimensions() {}

    ValueType(CellType cell_type_in, std::vector<Dimension> &&dimensions_in) noexcept
        : _error(false), _cell_type(cell_type_in), _dimensions(std::move(dimensions_in)) {}

    static ValueType error_if(bool has_error, ValueType else_type);

public:
    ValueType(ValueType &&) noexcept = default;
    ValueType(const ValueType &);
    ValueType &operator=(ValueType &&) noexcept = default;
    ValueType &operator=(const ValueType &);
    ~ValueType();
    CellType cell_type() const { return _cell_type; }
    CellMeta cell_meta() const { return {_cell_type, is_double()}; }
    bool is_error() const { return _error; }
    bool is_double() const;
    bool has_dimensions() const noexcept { return !_dimensions.empty(); }
    bool is_sparse() const;
    bool is_dense() const;
    bool is_mixed() const;
    size_t count_indexed_dimensions() const;
    size_t count_mapped_dimensions() const;
    size_t dense_subspace_size() const;
    const std::vector<Dimension> &dimensions() const { return _dimensions; }
    std::vector<Dimension> nontrivial_indexed_dimensions() const;
    std::vector<Dimension> indexed_dimensions() const;
    std::vector<Dimension> mapped_dimensions() const;
    size_t dimension_index(const vespalib::string &name) const;
    size_t stride_of(const vespalib::string &name) const;
    bool has_dimension(const vespalib::string &name) const {
        return (dimension_index(name) != Dimension::npos);
    }
    std::vector<vespalib::string> dimension_names() const;
    bool operator==(const ValueType &rhs) const noexcept {
        return ((_error == rhs._error) &&
                (_cell_type == rhs._cell_type) &&
                (_dimensions == rhs._dimensions));
    }
    bool operator!=(const ValueType &rhs) const noexcept { return !(*this == rhs); }

    ValueType map() const;
    ValueType reduce(const std::vector<vespalib::string> &dimensions_in) const;
    ValueType peek(const std::vector<vespalib::string> &dimensions_in) const;
    ValueType rename(const std::vector<vespalib::string> &from,
                     const std::vector<vespalib::string> &to) const;
    ValueType cell_cast(CellType to_cell_type) const;

    static ValueType error_type() { return {}; }
    static ValueType make_type(CellType cell_type, std::vector<Dimension> dimensions_in);
    static ValueType double_type() { return make_type(CellType::DOUBLE, {}); }
    static ValueType from_spec(const vespalib::string &spec);
    static ValueType from_spec(const vespalib::string &spec, std::vector<ValueType::Dimension> &unsorted);
    vespalib::string to_spec() const;
    static ValueType join(const ValueType &lhs, const ValueType &rhs);
    static ValueType merge(const ValueType &lhs, const ValueType &rhs);
    static ValueType concat(const ValueType &lhs, const ValueType &rhs, const vespalib::string &dimension);
    static ValueType either(const ValueType &one, const ValueType &other);
};

std::ostream &operator<<(std::ostream &os, const ValueType &type);

} // namespace