diff options
author | Håvard Pettersen <havardpe@oath.com> | 2019-04-10 09:50:06 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2019-04-25 12:24:03 +0000 |
commit | 974a0f2d3c588e35165177ac556e08cfdcc0e26f (patch) | |
tree | 46551c364a6cd1ee3cf88292f30537870f2956b4 /searchlib | |
parent | b186ca34ab5df612a463334772788752e1deec3c (diff) |
avoid abstract value types
remove basic value type ANY
remove concept of tensors with unknown dimensions
disallow value types with unbound indexed dimensions
remove predicates talking about abstract types
type of unknown values are now ERROR (was ANY)
require that overlapping indexed dimensions are of equal size
type unification now requires types to be equal ('if' expressions)
creating a tensor type without dimensions now gives a double type
make rank feature setup fail on invalid types (query/attribute)
Diffstat (limited to 'searchlib')
7 files changed, 20 insertions, 106 deletions
diff --git a/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp b/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp index bd814b0ad32..cbbaa518b16 100644 --- a/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp +++ b/searchlib/src/tests/attribute/tensorattribute/tensorattribute_test.cpp @@ -40,9 +40,6 @@ static bool operator==(const Tensor &lhs, const Tensor &rhs) vespalib::string sparseSpec("tensor(x{},y{})"); vespalib::string denseSpec("tensor(x[2],y[3])"); -vespalib::string denseAbstractSpec_xy("tensor(x[],y[])"); -vespalib::string denseAbstractSpec_x("tensor(x[2],y[])"); -vespalib::string denseAbstractSpec_y("tensor(x[],y[3])"); struct Fixture { @@ -307,7 +304,7 @@ Fixture::testSaveLoad() void Fixture::testCompaction() { - if (_useDenseTensorAttribute && _denseTensors && !_cfg.tensorType().is_abstract()) { + if (_useDenseTensorAttribute && _denseTensors) { LOG(info, "Skipping compaction test for tensor '%s' which is using free-lists", _cfg.tensorType().to_spec().c_str()); return; } @@ -411,34 +408,4 @@ TEST("Test dense tensors with dense tensor attribute") testAll([]() { return std::make_shared<Fixture>(denseSpec, true); }); } -TEST("Test dense tensors with generic tensor attribute with unbound x and y dims") -{ - testAll([]() { return std::make_shared<Fixture>(denseAbstractSpec_xy); }); -} - -TEST("Test dense tensors with dense tensor attribute with unbound x and y dims") -{ - testAll([]() { return std::make_shared<Fixture>(denseAbstractSpec_xy, true); }); -} - -TEST("Test dense tensors with generic tensor attribute with unbound x dim") -{ - testAll([]() { return std::make_shared<Fixture>(denseAbstractSpec_x); }); -} - -TEST("Test dense tensors with dense tensor attribute with unbound x dim") -{ - testAll([]() { return std::make_shared<Fixture>(denseAbstractSpec_x, true); }); -} - -TEST("Test dense tensors with generic tensor attribute with unbound y dim") -{ - testAll([]() { return std::make_shared<Fixture>(denseAbstractSpec_y); }); -} - -TEST("Test dense tensors with dense tensor attribute with unbound y dim") -{ - testAll([]() { return std::make_shared<Fixture>(denseAbstractSpec_y, true); }); -} - TEST_MAIN() { TEST_RUN_ALL(); vespalib::unlink("test.dat"); } diff --git a/searchlib/src/tests/features/ranking_expression/ranking_expression_test.cpp b/searchlib/src/tests/features/ranking_expression/ranking_expression_test.cpp index 2419f450950..c7c3447a4cc 100644 --- a/searchlib/src/tests/features/ranking_expression/ranking_expression_test.cpp +++ b/searchlib/src/tests/features/ranking_expression/ranking_expression_test.cpp @@ -54,7 +54,7 @@ ExpressionReplacer::SP make_replacer() { auto replacer = std::make_shared<ListExpressionReplacer>(); replacer->add(std::make_unique<NullExpressionReplacer>()); replacer->add(std::make_unique<DummyReplacer>("foo", FeatureType::number())); - replacer->add(std::make_unique<DummyReplacer>("bar", FeatureType::object(ValueType::from_spec("tensor(x[])")))); + replacer->add(std::make_unique<DummyReplacer>("bar", FeatureType::object(ValueType::from_spec("tensor(x[5])")))); return replacer; } @@ -124,15 +124,6 @@ TEST("require that ranking expression can resolve to concrete complex type") { FeatureType::object(ValueType::from_spec("tensor(x{},y{},z{})")))); } -TEST("require that ranking expression can resolve to abstract complex type") { - TEST_DO(verify_output_type({{"a", "tensor"}}, "a*b", FeatureType::object(ValueType::from_spec("tensor")))); -} - -TEST("require that ranking expression can resolve to 'any' type") { - TEST_DO(verify_output_type({{"a", "tensor(x{},y{})"}, {"b", "tensor"}}, "a*b", - FeatureType::object(ValueType::from_spec("any")))); -} - TEST("require that setup fails for incompatible types") { TEST_DO(verify_setup_fail({{"a", "tensor(x{},y{})"}, {"b", "tensor(y[10],z{})"}}, "a*b")); } @@ -150,7 +141,7 @@ TEST("require that replaced expressions override result type") { TEST_DO(verify_output_type({{"b", "tensor(z{})"}}, "foo*b*c", FeatureType::number())); TEST_DO(verify_output_type({{"b", "tensor(z{})"}}, "a*b*bar", - FeatureType::object(ValueType::from_spec("tensor(x[])")))); + FeatureType::object(ValueType::from_spec("tensor(x[5])")))); TEST_DO(verify_output_type({{"b", "tensor(z{})"}}, "foo*b*bar", FeatureType::number())); } diff --git a/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp b/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp index 9f47dede46a..1d80fec720a 100644 --- a/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp +++ b/searchlib/src/tests/tensor/dense_tensor_store/dense_tensor_store_test.cpp @@ -60,34 +60,6 @@ TEST_F("require that we can store 1d bound tensor", Fixture("tensor(x[3])")) add({{"x", 2}}, 5)); } -TEST_F("require that we can store 1d un-bound tensor", Fixture("tensor(x[])")) -{ - f.assertSetAndGetTensor(TensorSpec("tensor(x[3])"). - add({{"x", 0}}, 2). - add({{"x", 1}}, 3). - add({{"x", 2}}, 5)); -} - -TEST_F("require that un-bound dimension is concrete in returned 2d tensor", Fixture("tensor(x[3],y[])")) -{ - f.assertSetAndGetTensor(TensorSpec("tensor(x[3],y[2])"). - add({{"x", 0}, {"y", 0}}, 2). - add({{"x", 0}, {"y", 1}}, 3). - add({{"x", 1}, {"y", 0}}, 5). - add({{"x", 1}, {"y", 1}}, 7). - add({{"x", 2}, {"y", 0}}, 11). - add({{"x", 2}, {"y", 1}}, 13)); -} - -TEST_F("require that un-bound dimensions are concrete in returned 3d tensor", Fixture("tensor(x[],y[2],z[])")) -{ - f.assertSetAndGetTensor(TensorSpec("tensor(x[1],y[2],z[2])"). - add({{"x", 0}, {"y", 0}, {"z", 0}}, 2). - add({{"x", 0}, {"y", 0}, {"z", 1}}, 3). - add({{"x", 0}, {"y", 1}, {"z", 0}}, 5). - add({{"x", 0}, {"y", 1}, {"z", 1}}, 7)); -} - TEST_F("require that correct empty tensor is returned for 1d bound tensor", Fixture("tensor(x[3])")) { f.assertEmptyTensor(TensorSpec("tensor(x[3])"). @@ -96,21 +68,6 @@ TEST_F("require that correct empty tensor is returned for 1d bound tensor", Fixt add({{"x", 2}}, 0)); } -TEST_F("require that empty 2d tensor has size 1 in un-bound dimension", Fixture("tensor(x[3],y[])")) -{ - f.assertEmptyTensor(TensorSpec("tensor(x[3],y[1])"). - add({{"x", 0}, {"y", 0}}, 0). - add({{"x", 1}, {"y", 0}}, 0). - add({{"x", 2}, {"y", 0}}, 0)); -} - -TEST_F("require that empty 3d tensor has size 1 in un-bound dimensions", Fixture("tensor(x[],y[2],z[])")) -{ - f.assertEmptyTensor(TensorSpec("tensor(x[1],y[2],z[1])"). - add({{"x", 0}, {"y", 0}, {"z", 0}}, 0). - add({{"x", 0}, {"y", 1}, {"z", 0}}, 0)); -} - void assertArraySize(const vespalib::string &tensorType, uint32_t expArraySize) { Fixture f(tensorType); @@ -122,13 +79,7 @@ TEST("require that array size is calculated correctly") TEST_DO(assertArraySize("tensor(x[1])", 32)); TEST_DO(assertArraySize("tensor(x[10])", 96)); TEST_DO(assertArraySize("tensor(x[3])", 32)); - TEST_DO(assertArraySize("tensor(x[3],y[])", 32)); - TEST_DO(assertArraySize("tensor(x[3],y[],z[])", 32)); - TEST_DO(assertArraySize("tensor(x[3],y[],z[],z2[])", 64)); TEST_DO(assertArraySize("tensor(x[10],y[10])", 800)); - TEST_DO(assertArraySize("tensor(x[])", 32)); - TEST_DO(assertArraySize("tensor(x[],x2[],x3[],x4[],x5[],x6[])", 32)); - TEST_DO(assertArraySize("tensor(x[],x2[],x3[],x4[],x5[],x6[],x7[])", 64)); } TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchlib/src/vespa/searchlib/features/attributefeature.cpp b/searchlib/src/vespa/searchlib/features/attributefeature.cpp index b3ebd0f3822..56d02ce6d4e 100644 --- a/searchlib/src/vespa/searchlib/features/attributefeature.cpp +++ b/searchlib/src/vespa/searchlib/features/attributefeature.cpp @@ -295,10 +295,13 @@ AttributeBlueprint::setup(const search::fef::IIndexEnvironment & env, vespalib::string attrType = type::Attribute::lookup(env.getProperties(), _attrName); if (!attrType.empty()) { _tensorType = ValueType::from_spec(attrType); + if (_tensorType.is_error()) { + LOG(error, "%s: invalid type: '%s'", getName().c_str(), attrType.c_str()); + } } - FeatureType output_type = _tensorType.is_tensor() - ? FeatureType::object(_tensorType) - : FeatureType::number(); + FeatureType output_type = _tensorType.is_double() + ? FeatureType::number() + : FeatureType::object(_tensorType); describeOutput("value", "The value of a single value attribute, " "the value at the given index of an array attribute, " "the given key of a weighted set attribute, or" @@ -309,7 +312,7 @@ AttributeBlueprint::setup(const search::fef::IIndexEnvironment & env, describeOutput("count", "Returns the number of elements in this array or weighted set attribute."); } env.hintAttributeAccess(_attrName); - return true; + return !_tensorType.is_error(); } search::fef::Blueprint::UP diff --git a/searchlib/src/vespa/searchlib/features/constant_feature.cpp b/searchlib/src/vespa/searchlib/features/constant_feature.cpp index 4d76512ab00..ced9d95fb33 100644 --- a/searchlib/src/vespa/searchlib/features/constant_feature.cpp +++ b/searchlib/src/vespa/searchlib/features/constant_feature.cpp @@ -63,8 +63,10 @@ ConstantBlueprint::setup(const IIndexEnvironment &env, { _key = params[0].getValue(); _value = env.getConstantValue(_key); - if (!_value || _value->type().is_error()) { + if (!_value) { LOG(error, "Constant '%s' not found", _key.c_str()); + } else if (_value->type().is_error()) { + LOG(error, "Constant '%s' has invalid type", _key.c_str()); } FeatureType output_type = _value ? FeatureType::object(_value->type()) : diff --git a/searchlib/src/vespa/searchlib/features/queryfeature.cpp b/searchlib/src/vespa/searchlib/features/queryfeature.cpp index eb7eb427283..b9041901ced 100644 --- a/searchlib/src/vespa/searchlib/features/queryfeature.cpp +++ b/searchlib/src/vespa/searchlib/features/queryfeature.cpp @@ -98,12 +98,15 @@ QueryBlueprint::setup(const IIndexEnvironment &env, const ParameterList ¶ms) vespalib::string queryFeatureType = type::QueryFeature::lookup(env.getProperties(), _key); if (!queryFeatureType.empty()) { _valueType = ValueType::from_spec(queryFeatureType); + if (_valueType.is_error()) { + LOG(error, "%s: invalid type: '%s'", getName().c_str(), queryFeatureType.c_str()); + } } - FeatureType output_type = _valueType.is_tensor() - ? FeatureType::object(_valueType) - : FeatureType::number(); + FeatureType output_type = _valueType.is_double() + ? FeatureType::number() + : FeatureType::object(_valueType); describeOutput("out", "The value looked up in query properties using the given key.", output_type); - return true; + return !_valueType.is_error(); } namespace { diff --git a/searchlib/src/vespa/searchlib/features/rankingexpressionfeature.cpp b/searchlib/src/vespa/searchlib/features/rankingexpressionfeature.cpp index 72865d042e7..b2c8c64d55a 100644 --- a/searchlib/src/vespa/searchlib/features/rankingexpressionfeature.cpp +++ b/searchlib/src/vespa/searchlib/features/rankingexpressionfeature.cpp @@ -239,9 +239,6 @@ RankingExpressionBlueprint::setup(const fef::IIndexEnvironment &env, LOG(error, "rank expression contains type errors: %s\n", script.c_str()); return false; } - if (root_type.is_any()) { - LOG(warning, "rank expression could produce run-time type errors: %s\n", script.c_str()); - } auto compile_issues = CompiledFunction::detect_issues(rank_function); auto interpret_issues = InterpretedFunction::detect_issues(rank_function); if (do_compile && compile_issues && !interpret_issues) { |