From c654793a3a513a9c8ffcd1aa9c3962b6a72e61bd Mon Sep 17 00:00:00 2001 From: Andreas Stöckel Date: Mon, 20 Oct 2014 23:22:56 +0000 Subject: started to implement Function class which represents functions and methods, both on the host and the client side git-svn-id: file:///var/local/svn/basicwriter@73 daaaf23c-2e50-4459-9457-1e69db5a47bf --- src/core/script/Function.cpp | 31 ++++++++ src/core/script/Function.hpp | 161 +++++++++++++++++++++++++++++++++++++++ src/core/script/ScriptEngine.hpp | 2 +- src/core/script/Variant.cpp | 43 +++++++++++ src/core/script/Variant.hpp | 82 ++++++++++++++++---- 5 files changed, 304 insertions(+), 15 deletions(-) create mode 100644 src/core/script/Function.cpp create mode 100644 src/core/script/Function.hpp (limited to 'src') diff --git a/src/core/script/Function.cpp b/src/core/script/Function.cpp new file mode 100644 index 0000000..d72df4c --- /dev/null +++ b/src/core/script/Function.cpp @@ -0,0 +1,31 @@ +/* + 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 . +*/ + +#include "Function.hpp" + +namespace ousia { +namespace script { + +std::pair> validate(const std::vector &args) +{ + return std::make_pair(true, std::vector{}); +} + +} +} + diff --git a/src/core/script/Function.hpp b/src/core/script/Function.hpp new file mode 100644 index 0000000..35e2205 --- /dev/null +++ b/src/core/script/Function.hpp @@ -0,0 +1,161 @@ +/* + 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 . +*/ + +#ifndef _OUSIA_FUNCTION_HPP_ +#define _OUSIA_FUNCTION_HPP_ + +#include +#include +#include + +#include "Variant.hpp" + +namespace ousia { +namespace script { + +/** + * The abstract Function class is most basic version of a function handle -- + * just a virtual "call" function which calls the underlying code. + */ +class Function { + +public: + + /** + * Abstract function which is meant to call the underlying function (be it + * a host or a script function) with the given arguments. + * + * @param args is a vector containing all arguments that shall be passed to + * the function. + * @return a Variant containing the return value. + */ + virtual Variant call(const std::vector &args) const = 0; + +}; + +/** + * The ArgumentDescriptor class is used to describe the type of a function + * argument. + */ +struct ArgumentDescriptor { + + const VariantType type; + const bool hasDefault; + const Variant defaultValue; + + ArgumentDescriptor(VariantType type) : + type(type), hasDefault(false) {}; + + ArgumentDescriptor(VariantType type, const Variant &defaultValue) : + type(type), hasDefault(true), defaultValue(defaultValue) {}; + +}; + +/** + * ArgumentValidatorError is an exception type used to represent argument + * validator errors. + */ +class ArgumentValidatorError : std::exception { + +public: + + const int index; + + const std::string msg; + + ArgumentValidatorError(int index, const std::string &msg) : + index(index), msg(msg) {}; + + virtual const char* what() const noexcept override + { + return msg.c_str(); + } + +}; + +/** + * The ArgumentValidator class is responsible for checking whether the given + * arguments passed to a function match the description. + */ +class ArgumentValidator { + +private: + /** + * List containing the argument descriptors. + */ + const std::vector descriptors; + + /** + * Argument index in the input array, at which the last error occured. + */ + int errorIndex = -1; + + /** + * Error message for the last validation error. + */ + std::string errorMessage; + +public: + + /** + * Constructor of the argument validator class. + * + * @param descriptors is a list of ArgumentDescriptors which should be used + * for the validation. + */ + ArgumentValidator(const std::vector &descriptors) : + descriptors(descriptors) {} + + /** + * Validates and augments the given argument list (e.g. adds the default + * values). + * + * @param args contains the input arguments. + * @return a pair, where the first element specifies whether the arguments + * were validated sucessfully and the second argument contains the augmented + * list of arguments. If false is returned, use the error function to get + * more information about the error. + */ + std::pair> validate(const std::vector &args); + + /** + * Returns an ArgumentValidatorError instance containing the argument index + * in the input array, at which the error occured and an explaining error + * message. As ArgumentValidatorError is derived from std::exception, + * the result of this function is throwable. + * + * @return an ArgumentValidatorError instance containing information about + * the last error. If no error occurred, the message will be empty and + * the argument index will be set to -1. + */ + ArgumentValidatorError error() + { + return ArgumentValidatorError(errorIndex, errorMessage); + } + +}; + +/** + * The HostFunction class represents a function that resides in the script host. + */ + +} +} + +#endif /* _OUSIA_FUNCTION_HPP_ */ + diff --git a/src/core/script/ScriptEngine.hpp b/src/core/script/ScriptEngine.hpp index 3a53791..5443460 100644 --- a/src/core/script/ScriptEngine.hpp +++ b/src/core/script/ScriptEngine.hpp @@ -67,7 +67,7 @@ public: /** * Returns the error message. */ - virtual const char* what() const noexcept; + virtual const char* what() const noexcept override; }; diff --git a/src/core/script/Variant.cpp b/src/core/script/Variant.cpp index a379735..b70f361 100644 --- a/src/core/script/Variant.cpp +++ b/src/core/script/Variant.cpp @@ -21,6 +21,49 @@ namespace ousia { namespace script { +/* Class VariantTypeException */ + +static const char* getVariantTypeName(VariantType type) +{ + switch (type) { + case VariantType::null: + return "null"; + case VariantType::boolean: + return "boolean"; + case VariantType::integer: + return "integer"; + case VariantType::number: + return "number"; + case VariantType::string: + return "string"; + case VariantType::array: + return "array"; + case VariantType::map: + return "map"; + case VariantType::function: + return "function"; + case VariantType::object: + return "object"; + case VariantType::buffer: + return "buffer"; + } + return "unknown"; +} + +VariantTypeException::VariantTypeException(VariantType actualType, + VariantType requestedType) : + msg(std::string("Cannot get value of variant of type \"") + + getVariantTypeName(actualType) + + std::string("\" as \"") + getVariantTypeName(requestedType)), + actualType(actualType), requestedType(requestedType) {} + +const char* VariantTypeException::what() const noexcept +{ + return msg.c_str(); +} + +/* Global scope operator */ + std::ostream& operator<< (std::ostream& os, const Variant &v) { switch (v.type) { diff --git a/src/core/script/Variant.hpp b/src/core/script/Variant.hpp index faa5bad..ee4a97a 100644 --- a/src/core/script/Variant.hpp +++ b/src/core/script/Variant.hpp @@ -19,13 +19,12 @@ #ifndef _OUSIA_VARIANT_HPP_ #define _OUSIA_VARIANT_HPP_ -#include - #include +#include +#include #include #include #include -#include namespace ousia { namespace script { @@ -33,17 +32,68 @@ namespace script { /** * Enum containing the possible types a variant may have. */ -enum class VariantType { - null, boolean, integer, number, string, array, map, function, object, buffer +enum class VariantType : int16_t { + null = 0x0001, + boolean = 0x0002, + integer = 0x0004, + number = 0x0008, + string = 0x0010, + array = 0x0020, + map = 0x0040, + function = 0x0080, + object = 0x0100, + buffer = 0x0200 +}; + +/** + * Exception thrown whenever a variant is accessed via a getter function that + * is not supported for the current variant type. + */ +class VariantTypeException : std::exception { + +private: + /** + * Internally used string holding the exception message. + */ + const std::string msg; + +public: + /** + * Contains the actual type of the variant. + */ + const VariantType actualType; + + /** + * Contains the requested type of the variant. + */ + const VariantType requestedType; + + /** + * Constructor of the VariantTypeException. + * + * @param actualType describes the actual type of the variant. + * @param requestedType describes the type in which the variant was + * requested. + */ + VariantTypeException(VariantType actualType, VariantType requestedType); + + /** + * Returns the error message of the exception. + * + * @return the error message as C string. + */ + virtual const char* what() const noexcept override; + }; /** * Instances of the Variant class represent any kind of data that is exchanged - * between the host application and the script engine. + * between the host application and the script engine. Variants are immutable. */ class Variant { private: + const VariantType type; union { @@ -55,8 +105,6 @@ private: public: - class EBadEntry {}; - Variant(const Variant &v) : type(v.type) { @@ -189,7 +237,7 @@ public: case VariantType::map: return !getMapValue().empty(); default: - throw EBadEntry{}; + throw VariantTypeException{type, VariantType::boolean}; } } @@ -203,7 +251,7 @@ public: case VariantType::number: return static_cast(numberValue); default: - throw EBadEntry{}; + throw VariantTypeException{type, VariantType::integer}; } } @@ -217,7 +265,7 @@ public: case VariantType::number: return numberValue; default: - throw EBadEntry{}; + throw VariantTypeException{type, VariantType::number}; } } @@ -227,7 +275,7 @@ public: case VariantType::string: return *(static_cast(objectValue)); default: - throw EBadEntry {}; + throw VariantTypeException{type, VariantType::string}; } } @@ -237,7 +285,7 @@ public: case VariantType::array: return *(static_cast*>(objectValue)); default: - throw EBadEntry {}; + throw VariantTypeException{type, VariantType::array}; } } @@ -247,7 +295,7 @@ public: case VariantType::map: return *(static_cast*>(objectValue)); default: - throw EBadEntry {}; + throw VariantTypeException{type, VariantType::map}; } } @@ -255,6 +303,12 @@ public: }; + +/** + * Shorthand for a constant representing a "null" as a variant. + */ +static const Variant VarNull; + } } -- cgit v1.2.3