From 66e382e4ea55932b1843efdfe2fd8c0fbcb1f405 Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Mon, 22 Dec 2014 23:09:07 +0100 Subject: some more Typesystem documentation and unit tests --- src/core/model/Typesystem.cpp | 12 ++++ src/core/model/Typesystem.hpp | 115 ++++++++++++++++++++++++------------- test/core/model/TypesystemTest.cpp | 82 ++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 40 deletions(-) diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index 9be78d1..79157f6 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -64,6 +64,17 @@ bool IntType::doBuild(Variant &var, Logger &logger) const return true; } +/* Class DoubleType */ + +bool DoubleType::doBuild(Variant &var, Logger &logger) const +{ + if (!var.isInt() && !var.isDouble()) { + throw LoggableException{"Expected a double value."}; + } + var = Variant{var.toDouble()}; + return true; +} + /* Class EnumType */ EnumType EnumType::createValidated(Manager &mgr, std::string name, @@ -113,6 +124,7 @@ const Rtti BoolType{"BoolType", {&Type}}; const Rtti EnumType{"EnumType", {&Type}}; const Rtti StructType{"StructType", {&Type}}; const Rtti ArrayType{"ArrayType", {&Type}}; +const Rtti UnknownType{"UnknownType", {&Type}}; const Rtti Constant{"Constant", {&Node}}; const Rtti Typesystem{"Typesystem", {&Node}}; } diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index 195cf00..1711f75 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -122,8 +122,7 @@ public: /** * The StringType class represents the primitive string type. There should - * exactly be a single instance of this class available in a preloaded type - * system. + * be exactly one instance of this class available in a preloaded type system. */ class StringType : public Type { protected: @@ -161,14 +160,14 @@ public: }; /** - * The IntType class represents the primitive integer type. There should exactly - * be a single instance of this class available in a preloaded type system. + * The IntType class represents the primitive integer type. There should be + * exactly one instance of this class available in a preloaded type system. */ class IntType : public Type { protected: /** - * Simply expects the given variant to be an integer. Does not perform any - * type conversion. + * Expects the given variant to be an integer. Does not perform any type + * conversion. * * @param var is a variant containing the data that should be checked. * @param logger is the Logger instance into which errors should be written. @@ -198,23 +197,31 @@ public: Variant create() const override { return Variant{0}; } }; +/** + * The DoubleType class represents the primitive double type. There should + * exactly be a single instance of this class available in a preloaded type + * system. + */ class DoubleType : public Type { protected: /** - * TODO: DOC + * Expects the given variant to be a double or an integer. Converts integers + * to doubles. + * + * @param var is a variant containing the data that should be checked. + * @param logger is the Logger instance into which errors should be written. + * @return true if the conversion was successful, false otherwise. */ - bool doBuild(Variant &var, Logger &logger) const override - { - if (!var.isInt() && !var.isDouble()) { - throw LoggableException{"Expected a double value."}; - } - var = Variant{var.toDouble()}; - return true; - } + bool doBuild(Variant &var, Logger &logger) const override; public: /** - * TODO: DOC + * Constructor of the DoubleType class. Only one instance of DoubleType + * should exist per project graph. + * + * @param mgr is the Manager instance to be used for the Node. + * @param name is the name of the type. + * @param system is a reference to the parent Typesystem instance. */ DoubleType(Manager &mgr, Handle system) : Type(mgr, "double", system, true) @@ -222,31 +229,11 @@ public: } /** - * TODO: DOC - */ - Variant create() const override { return Variant{0.}; } -}; - -class UnknownType : public Type { -protected: - /** - * TODO: DOC - */ - bool doBuild(Variant &var, Logger &logger) const override { return true; } - -public: - /** - * TODO: DOC - */ - UnknownType(Manager &mgr, Handle system) - : Type(mgr, "unknown", system, true) - { - } - - /** - * TODO: DOC + * Returns a variant containing the double value zero. + * + * @return the double value zero. */ - Variant create() const override { return Variant{nullptr}; } + Variant create() const override { return Variant{0.0}; } }; class BoolType : public Type { @@ -462,6 +449,49 @@ public: Rooted getInnerType() { return innerType; } }; +/** + * The UnknownType class represents a type whose type could not be resolved. + * This class may also be used while constructing the Typesystem tree, if a + * type has not yet been fully created. UnknownType instances are not part of a + * typesystem, but merely placeholders which may once be replaced by an actual + * reference to an actual Type node. + * + * TODO: Implement generic object for unresolved Nodes, not only types. For this + * implement Manager.replace, which replaces all references to a certain object + * with a new one. + */ +class UnknownType : public Type { +protected: + /** + * As the UnknownType carries no type information, it does not modify the + * given variant and always succeeds (returns true). + * + * @return always true. + */ + bool doBuild(Variant &, Logger &) const override { return true; } + +public: + /** + * Creates a new UnknownType instance, which is a place holder for a not + * (yet) resolved type. + * + * @param mgr is the Manager instance to be used for the Node. + * @param name is the name of the unresolved type which may be used later + * to perform a complete resolution. + */ + UnknownType(Manager &mgr, std::string name) + : Type(mgr, std::move(name), nullptr, false) + { + } + + /** + * Returns a nullptr variant. + * + * @return a Variant instance with nullptr value. + */ + Variant create() const override { return Variant{nullptr}; } +}; + /** * The Constant type represents a constant stored in a typesystem. A typical * application of a constant is e.g. to define predefined color values. @@ -616,6 +646,11 @@ extern const Rtti StructType; */ extern const Rtti ArrayType; +/** + * Type information for the UnknownType class. + */ +extern const Rtti UnknownType; + /** * Type information for the Constant class. */ diff --git a/test/core/model/TypesystemTest.cpp b/test/core/model/TypesystemTest.cpp index b388fe0..0e2dc8a 100644 --- a/test/core/model/TypesystemTest.cpp +++ b/test/core/model/TypesystemTest.cpp @@ -144,6 +144,54 @@ TEST(IntType, conversion) } } +/* Class IntType */ + +TEST(DoubleType, rtti) +{ + Manager mgr; + Rooted doubleType{new DoubleType(mgr, nullptr)}; + ASSERT_TRUE(doubleType->isa(RttiTypes::DoubleType)); + ASSERT_TRUE(doubleType->isa(typeOf())); + ASSERT_TRUE(doubleType->isa(typeOf())); +} + +TEST(DoubleType, creation) +{ + Manager mgr; + Rooted doubleType{new DoubleType(mgr, nullptr)}; + Variant val = doubleType->create(); + ASSERT_TRUE(val.isDouble()); + ASSERT_EQ(0.0, val.asDouble()); +} + +TEST(DoubleType, conversion) +{ + Logger logger; + Manager mgr; + Rooted doubleType{new DoubleType(mgr, nullptr)}; + + { + Variant val{3.14}; + ASSERT_TRUE(doubleType->build(val, logger)); + ASSERT_TRUE(val.isDouble()); + ASSERT_EQ(3.14, val.asDouble()); + } + + { + Variant val{314}; + ASSERT_TRUE(doubleType->build(val, logger)); + ASSERT_TRUE(val.isDouble()); + ASSERT_EQ(314.0, val.asDouble()); + } + + { + Variant val{"1"}; + ASSERT_FALSE(doubleType->build(val, logger)); + ASSERT_TRUE(val.isDouble()); + ASSERT_EQ(0.0, val.asDouble()); + } +} + /* Class ArrayType */ TEST(ArrayType, rtti) @@ -198,5 +246,39 @@ TEST(ArrayType, conversion) } } +/* Class UnknownType */ + +TEST(UnknownType, rtti) +{ + Manager mgr; + Rooted unknownType{new UnknownType(mgr, "unknown")}; + ASSERT_TRUE(unknownType->isa(RttiTypes::UnknownType)); + ASSERT_TRUE(unknownType->isa(typeOf())); + ASSERT_TRUE(unknownType->isa(typeOf())); +} + +TEST(UnknownType, creation) +{ + Manager mgr; + Rooted unknownType{new UnknownType(mgr, "unknown")}; + + Variant val = unknownType->create(); + ASSERT_TRUE(val.isNull()); +} + +TEST(UnknownType, conversion) +{ + Logger logger; + Manager mgr; + Rooted unknownType{new UnknownType(mgr, "unknown")}; + + { + Variant val1{{1, "test", false, 42.5}}; + Variant val2 = val1; + ASSERT_TRUE(unknownType->build(val1, logger)); + ASSERT_EQ(val1, val2); + } +} + } } -- cgit v1.2.3