diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/core/Typesystem.cpp | 78 | ||||
-rw-r--r-- | src/core/Typesystem.hpp | 232 | ||||
-rw-r--r-- | src/core/common/Variant.hpp | 18 | ||||
-rw-r--r-- | src/core/model/Typesystem.cpp | 45 | ||||
-rw-r--r-- | src/core/model/Typesystem.hpp | 381 |
6 files changed, 445 insertions, 311 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 64285d1..739acd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,13 +106,13 @@ ADD_LIBRARY(ousia_core src/core/Registry src/core/ResourceLocator src/core/Tokenizer -# src/core/Typesystem src/core/common/CharReader src/core/common/Exceptions src/core/common/Logger src/core/common/Utils src/core/common/Variant src/core/common/VariantReader + src/core/model/Typesystem src/core/parser/Parser src/core/parser/ParserStack src/core/parser/Scope diff --git a/src/core/Typesystem.cpp b/src/core/Typesystem.cpp deleted file mode 100644 index a9ef61f..0000000 --- a/src/core/Typesystem.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - Ousía - Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <unordered_map> -#include <sstream> - -#include "CodeTokenizer.hpp" -#include "Typesystem.hpp" - -namespace ousia { - -/* Class EnumType */ - -EnumType::EnumType(Manager &mgr, const std::set<std::string> &names) : - Type(mgr, false, true) -{ - int value = 0; - for (const auto &name: names) { - values.insert(std::make_pair(name, value++)) - } -} - -int EnumType::valueOf(const std::string &name) -{ - auto it = values.find(name); - if (it != values.end()) { - return it->second; - } - return -1; -} - -std::string EnumType::toString(int value) { - for (const auto &p : values) { - if (p->second == value) { - return p->first; - } - } - return std::string{}; -} - -/* Class Typesystem */ - -void Typesystem::doResolve(std::vector<Rooted<Managed>> &res, - const std::vector<std::string> &path, Filter filter, - void *filterData, unsigned idx, - VisitorSet &visited) -{ - // Try to resolve the given name as a type - for (auto n: types) { - n->resolve(res, path, filter, filterData, idx, visited, nullptr); - } - - // Try to resolve the given name as a constant - const auto it = constants.find(path[idx]); - if (it != constants.cend()) { - if (filter && filter(it->second, filterData)) { - res.push_back(it->second); - } - } -} - -} - diff --git a/src/core/Typesystem.hpp b/src/core/Typesystem.hpp deleted file mode 100644 index 8ef3072..0000000 --- a/src/core/Typesystem.hpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - Ousía - Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _OUSIA_TYPESYSTEM_HPP_ -#define _OUSIA_TYPESYSTEM_HPP_ - -#include <string> -#include <vector> - -#include "BufferedCharReader.hpp" -#include "Managed.hpp" -#include "Node.hpp" - -namespace ousia { - -class Typesystem; -class Type; -class StringType; - -/** - * The TypeInstance class represents an instance of a certain type variable: - * Wheras Type only describes the type of an TypeInstance in an abstract manner, - * TypeInstance represents an instance of that type. - */ -class TypeInstance : public Managed { -public: - /** - * Reference to the underlying Type which describes this type instance. - */ - const Owned<Type> type; - - /** - * Constructor of the TypeInstance class. - * - * @param mgr is a reference to the Manager class which manages this object. - * @param type is a reference to the type this TypeInstance instance is an - * instance of. - */ - TypeInstance(Manager &mgr, Handle<Type> type) - : Managed(mgr), type(acquire(type)) - { - } -}; - -/** - * Type is an abstract describtion of a type class in the type system. The type - * class can be used to instantiate instances of the corresponding type. - */ -class Type : public Node { -public: - /** - * True, if the type cannot be extended. - */ - const bool isFinal; - - /** - * True, if the type represents a primitive type, such as an integer, - * doubles, enums and string. - */ - const bool isPrimitive; - - /** - * Constructor of the Type class. - * - * @param mgr is a reference at the underlying node manager. - * @param bool isFinal specifies whether this type is final. - * @param bool isPrimitive specifies whether this type is primitive. - * @param name specifies the internal name of the type. - * @param typesystem specifies the parent type system. - */ - Type(Manager &mgr, bool isFinal, bool isPrimitive, std::string name, - Handle<Typesystem> typesystem = nullptr) - : Node(mgr, std::move(name), typesystem), - isFinal(isFinal), - isPrimitive(isPrimitive) - { - } - - /** - * Virtual destructor. - */ - virtual ~Type(){}; - - /** - * Creates a new instance of this type. All values of this type are - * initialized to default values. - * - * @return a new instance of this type. - */ - // virtual Rooted<TypeInstance> create() = 0; - - /** - * Parses the given string and produces a new instance of the given type. - * - * TODO: Add error handler - * - * @param str is the string which should be parsed. - */ - // virtual Rooted<TypeInstance> parse(BufferedCharReader &reader) = 0; -}; - -/** - * Type which is used to represent a string. - */ -class StringType : public Type { -public: - StringType(Manager &mgr, Handle<Typesystem> typesystem) - : Type(mgr, true, true, "string", typesystem){}; -}; - -/** - * Type which is used to represent an integer. - */ -class IntegerType : public Type { -public: - IntegerType(Manager &mgr, Handle<Typesystem> typesystem) - : Type(mgr, true, true, "int", typesystem){}; -}; - -/** - * Type which is used to represent a double. - */ -class DoubleType : public Type { -public: - DoubleType(Manager &mgr, Handle<Typesystem> typesystem) - : Type(mgr, true, true, "double", typesystem){}; -}; - -/** - * Type which represents a enum. - */ -class EnumType : public Type { -private: - std::map<std::string, int> values; - -public: - EnumType(Manager &mgr, std::string name, Handle<Typesystem> typesystem, - const std::set<std::string> &names); - - /** - * Returns the integer value associated to the given name. - * - * @param name is the name of the value that should be looked up. - * @return the (non-negative) value associated to the given name or -1 if - * the value does not exist. - */ - int valueOf(const std::string &name); - - /** - * Returns the name corresponding to the given enum value or an empty string - * instead. - * - * @param value is the integer representation of an enum value that should - * be converted to the corresponding string. - * @return the string corresponding to the enum value or an empty string if - * no entry with such a value exists. - */ - std::string toString(int value); -}; - -/** - * Type which represents an array. - */ -class ArrayType : public Type { -public: - const Owned<Type> innerType; - - ArrayType(Manager &mgr, std::string name, Handle<Typesystem> typesystem, - Handle<Type> innerType) - : Type(mgr, false, true, name, typesystem), - innerType(acquire(innerType)){}; -}; - -/** - * Type which represents a structure of other types. - */ -class StructType : public Type { -private: - std::map<std::string, Type> entries; - - StructType(Manager) -} - -class Typesystem : public Node { -private: - NodeVector<Type> types; - ManagedMap<std::string, TypeInstance> constants; - -protected: - void doResolve(std::vector<Rooted<Managed>> &res, - const std::vector<std::string> &path, Filter filter, - void *filterData, unsigned idx, - VisitorSet &visited) override; - -public: - using Node::Node; - - Typesystem(Manager &mgr) : Node(mgr), types(this), constants(this) {} - - const NodeVector<Type> &getTypes() { return types; } - - const ManagedMap<std::string, TypeInstance> &getConstants() - { - return constants; - } - - void addType(Handle<Type> type) { types.push_back(type); } - - void addConstant(const std::string &name, Handle<TypeInstance> instance) - { - constants.insert(std::make_pair(name, instance)); - } -}; -} - -#endif /* _OUSIA_TYPESYSTEM_HPP_ */ - diff --git a/src/core/common/Variant.hpp b/src/core/common/Variant.hpp index d411fd3..c57ef57 100644 --- a/src/core/common/Variant.hpp +++ b/src/core/common/Variant.hpp @@ -434,6 +434,24 @@ public: bool isMap() const { return type == Type::MAP; } /** + * Checks whether this Variant instance is a primitive type. + * + * @return true if the Variant instance is a primitive type. + */ + bool isPrimitive() const { + switch(type){ + case Type::NULLPTR: + case Type::BOOL: + case Type::INT: + case Type::DOUBLE: + case Type::STRING: + return true; + default: + return false; + } + } + + /** * Returns the Variant boolean value. Performs no type conversion. Throws an * exception if the underlying type is not a boolean. * diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp new file mode 100644 index 0000000..f3c49dc --- /dev/null +++ b/src/core/model/Typesystem.cpp @@ -0,0 +1,45 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "Typesystem.hpp" + +#include <core/common/Utils.hpp> + +namespace ousia { +namespace model { + +EnumerationType EnumerationType::createValidated( + Manager &mgr, std::string name, Handle<Typesystem> system, + const std::vector<std::string> &values, Logger &logger) +{ + std::map<std::string, size_t> unique_values; + for (size_t i = 0; i < values.size(); i++) { + if (!Utils::isIdentifier(values[i])) { + logger.error(values[i] + " is no valid identifier."); + } + + if (!(unique_values.insert(std::make_pair(values[i], i))).second) { + logger.error(std::string("The value ") + values[i] + + " was duplicated."); + } + } + return std::move(EnumerationType(mgr, name, system, unique_values)); +} +} +} + diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp new file mode 100644 index 0000000..77a862b --- /dev/null +++ b/src/core/model/Typesystem.hpp @@ -0,0 +1,381 @@ +/* + Ousía + Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +/** + * @file Typesystem.hpp + * + * TODO: Docu + * + * @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de) + */ + +#ifndef _OUSIA_MODEL_TYPESYSTEM_HPP_ +#define _OUSIA_MODEL_TYPESYSTEM_HPP_ + +#include <map> +#include <vector> + +#include <core/ManagedContainers.hpp> +#include <core/Node.hpp> +#include <core/common/Exceptions.hpp> +#include <core/common/Logger.hpp> +#include <core/common/Variant.hpp> + +namespace ousia { +namespace model { + +class Typesystem; + +class Type : public Node { +protected: + Type(Manager &mgr, std::string name, Handle<Typesystem> system, + bool inheritable, bool primitive) + : Node(mgr, std::move(name), system), + inheritable(inheritable), + primitive(primitive) + { + } + + virtual bool doPrepare(Variant &var, Logger &log) = 0; + +public: + /** + * TODO: DOC + */ + const bool inheritable; + /** + * TODO: DOC + */ + const bool primitive; + + /** + * TODO: DOC + */ + virtual Variant create() = 0; + + /** + * TODO: DOC + */ + bool prepare(Variant &var, Logger &log) + { + try { + return doPrepare(var, log); + } + catch (LoggableException ex) { + log.log(ex); + var = create(); + return false; + } + } +}; + +class StringType : public Type { +protected: + /** + * TODO: DOC + */ + bool doPrepare(Variant &var, Logger &log) override + { + if (!var.isPrimitive()) { + throw LoggableException{"Expected a string or primitive input."}; + } + + if (!var.isString()) { + log.note(std::string("Implicit type conversion from ") + + var.getTypeName() + " to string."); + } + var = Variant{var.toString().c_str()}; + return true; + } + +public: + /** + * TODO: DOC + */ + StringType(Manager &mgr, Handle<Typesystem> system) + : Type(mgr, "string", system, false, true) + { + } + + /** + * TODO: DOC + */ + Variant create() override { return Variant{""}; } +}; + +class IntType : public Type { +protected: + /** + * TODO: DOC + */ + bool doPrepare(Variant &var, Logger &log) override + { + if (!var.isInt()) { + throw LoggableException{"Expected an integer value."}; + } + return true; + } + +public: + /** + * TODO: DOC + */ + IntType(Manager &mgr, Handle<Typesystem> system) + : Type(mgr, "int", system, false, true) + { + } + + /** + * TODO: DOC + */ + Variant create() override { return Variant{0}; } +}; + +class DoubleType : public Type { +protected: + /** + * TODO: DOC + */ + bool doPrepare(Variant &var, Logger &log) override + { + if (!var.isInt() && !var.isDouble()) { + throw LoggableException{"Expected a double value."}; + } + var = Variant{var.toDouble()}; + return true; + } + +public: + /** + * TODO: DOC + */ + DoubleType(Manager &mgr, Handle<Typesystem> system) + : Type(mgr, "double", system, false, true) + { + } + + /** + * TODO: DOC + */ + Variant create() override { return Variant{0.}; } +}; + +class UnknownType : public Type { +protected: + /** + * TODO: DOC + */ + bool doPrepare(Variant &var, Logger &log) override { return true; } + +public: + /** + * TODO: DOC + */ + UnknownType(Manager &mgr, Handle<Typesystem> system) + : Type(mgr, "unknown", system, false, true) + { + } + + /** + * TODO: DOC + */ + Variant create() override { return Variant{nullptr}; } +}; + +class BoolType : public Type { +protected: + /** + * TODO: DOC + */ + bool doPrepare(Variant &var, Logger &log) override + { + if (!var.isBool()) { + throw LoggableException("Expected boolean value!"); + } + return true; + } + +public: + /** + * TODO: DOC + */ + BoolType(Manager &mgr, Handle<Typesystem> system) + : Type(mgr, "bool", system, false, true) + { + } + + /** + * TODO: DOC + */ + Variant create() override { return Variant{false}; } +}; + +class EnumerationType : public Type { +private: + std::map<std::string, size_t> values; + +protected: + /** + * TODO: DOC + */ + bool doPrepare(Variant &var, Logger &log) override + { + if (var.isInt()) { + int i = var.asInt(); + if (i < 0 || i >= (int)values.size()) { + throw LoggableException("Value is out of range."); + } + } else if (var.isString()) { + } + + return true; + } + + EnumerationType(Manager &mgr, std::string name, Handle<Typesystem> system, + std::map<std::string, size_t> values) + : Type(mgr, std::move(name), system, false, false), + values(std::move(values)) + { + } + +public: + /** + * TODO: DOC + */ + EnumerationType(Manager &mgr, std::string name, Handle<Typesystem> system, + const std::vector<std::string> &values) + : Type(mgr, std::move(name), system, false, false) + { + for (size_t i = 0; i < values.size(); i++) { + this->values.insert(std::make_pair(values[i], i)); + } + } + + /** + * TODO: DOC + */ + static EnumerationType createValidated( + Manager &mgr, std::string name, Handle<Typesystem> system, + const std::vector<std::string> &values, Logger &logger); + + /** + * TODO: DOC + */ + Variant create() override { return Variant{0}; } +}; + +class StructType : public Type { +public: + struct AttributeDescriptor { + const std::string name; + const Variant defaultValue; + const bool optional; + const Owned<Type> type; + + AttributeDescriptor(std::string name, Variant defaultValue, + bool optional, Owned<Type> type) + : name(name), + defaultValue(defaultValue), + optional(optional), + type(type) + { + } + }; + +private: + std::vector<AttributeDescriptor> attrs; + + StructType(Manager &mgr, std::string name, Handle<Typesystem> system, + std::vector<AttributeDescriptor> attrs) + : Type(mgr, std::move(name), system, true, false), + attrs(std::move(attrs)) + { + } + +public: + // TODO + // static StructType createValidated( + // Manager &mgr, std::string name, Handle<Typesystem> system, + // Handle<StructType> parent, + // const std::vector<AttributeDescriptor> &attrs, Logger &logger); + + Variant create() override { return Variant{Variant::arrayType{}}; } +}; + +class ArrayType : public Type { +private: + Owned<Type> innerType; + +protected: + /** + * TODO: DOC + */ + bool doPrepare(Variant &var, Logger &log) override + { + if (!var.isArray()) { + throw LoggableException("Expected array!"); + } + bool res = true; + for (auto &v : var.asArray()) { + if (!innerType->prepare(v, log)) { + res = false; + } + } + + return res; + } + +public: + /** + * TODO: DOC + */ + ArrayType(Manager &mgr, std::string name, Handle<Typesystem> system, + Handle<Type> innerType) + : Type(mgr, std::move(name), system, false, false), + innerType(acquire(innerType)) + { + } + + /** + * TODO: DOC + */ + Variant create() override { return Variant{Variant::arrayType{}}; } + + Rooted<Type> getType() { return innerType; } +}; + +class Typesystem : public Node { +private: + ManagedVector<Type> types; + +public: + Typesystem(Manager &mgr, std::string name, Handle<Node> parent = nullptr) + : Node(mgr, name, parent), types(this) + { + } + + /** + * TODO: DOC + */ + void addType(Handle<Type> type) { types.push_back(type); } +}; +} +} + +#endif /* _OUSIA_MODEL_TYPESYSTEM_HPP_ */ + |