From 05e98e1981f9d909e81174f0cce998f83667e680 Mon Sep 17 00:00:00 2001 From: Stephane Del Pino <stephane.delpino44@gmail.com> Date: Tue, 25 Feb 2020 19:18:51 +0100 Subject: [PATCH] Continue mesh module definition --- src/language/ASTBuilder.cpp | 2 +- .../ASTNodeCFunctionExpressionBuilder.cpp | 4 +- src/language/ASTNodeDataType.cpp | 6 ++ src/language/ASTNodeDataType.hpp | 37 +++++--- src/language/ASTNodeDataTypeBuilder.cpp | 48 ++++++++-- src/language/BuiltinFunctionEmbedder.hpp | 59 ++++++++++++ src/language/BuiltinModule.cpp | 18 +++- src/language/BuiltinModule.hpp | 23 +++-- src/language/CFunctionEmbedderTable.hpp | 41 --------- src/language/CMakeLists.txt | 1 + src/language/DataHandler.hpp | 41 +++++++++ src/language/DataVariant.hpp | 3 + src/language/EmbeddedData.cpp | 14 +++ src/language/EmbeddedData.hpp | 51 ++++++++++ src/language/EmbedderTable.hpp | 41 +++++++++ src/language/IModule.hpp | 13 ++- src/language/MathModule.cpp | 92 +++++++++---------- src/language/MeshModule.cpp | 6 +- src/language/ModuleRepository.cpp | 59 +++++------- src/language/ModuleRepository.hpp | 14 +-- src/language/PEGGrammar.hpp | 6 +- src/language/SymbolTable.hpp | 69 ++++++++------ src/language/TypeTable.hpp | 30 ------ .../node_processor/OStreamProcessor.hpp | 3 +- ...test_ASTNodeCFunctionExpressionBuilder.cpp | 2 +- tests/test_CFunctionEmbedderTable.cpp | 4 +- tests/test_CFunctionProcessor.cpp | 2 +- tests/test_MathModule.cpp | 4 +- tests/test_SymbolTable.cpp | 4 +- 29 files changed, 459 insertions(+), 238 deletions(-) create mode 100644 src/language/BuiltinFunctionEmbedder.hpp delete mode 100644 src/language/CFunctionEmbedderTable.hpp create mode 100644 src/language/DataHandler.hpp create mode 100644 src/language/EmbeddedData.cpp create mode 100644 src/language/EmbeddedData.hpp create mode 100644 src/language/EmbedderTable.hpp delete mode 100644 src/language/TypeTable.hpp diff --git a/src/language/ASTBuilder.cpp b/src/language/ASTBuilder.cpp index 7692ed981..704ced95e 100644 --- a/src/language/ASTBuilder.cpp +++ b/src/language/ASTBuilder.cpp @@ -244,7 +244,7 @@ using selector = parse_tree::selector< language::N_set, language::Z_set, language::R_set, - language::type_id, + language::type_name_id, language::tuple_expression, language::vector_type, language::string_type, diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.cpp b/src/language/ASTNodeCFunctionExpressionBuilder.cpp index 99a1c8ac0..dbd1d0834 100644 --- a/src/language/ASTNodeCFunctionExpressionBuilder.cpp +++ b/src/language/ASTNodeCFunctionExpressionBuilder.cpp @@ -117,8 +117,8 @@ ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& no uint64_t c_function_id = std::get<uint64_t>(i_function_symbol->attributes().value()); - CFunctionEmbedderTable& c_function_embedder_table = node.m_symbol_table->cFunctionEbedderTable(); - std::shared_ptr c_function_embedder = c_function_embedder_table[c_function_id]; + auto& c_function_embedder_table = node.m_symbol_table->cFunctionEmbedderTable(); + std::shared_ptr c_function_embedder = c_function_embedder_table[c_function_id]; std::vector<ASTNodeDataType> c_function_parameter_type_list = c_function_embedder->getParameterDataTypes(); diff --git a/src/language/ASTNodeDataType.cpp b/src/language/ASTNodeDataType.cpp index cbbc95fe8..c6191255b 100644 --- a/src/language/ASTNodeDataType.cpp +++ b/src/language/ASTNodeDataType.cpp @@ -46,6 +46,9 @@ dataTypeName(const ASTNodeDataType& data_type) case ASTNodeDataType::typename_t: name = "typename"; break; + case ASTNodeDataType::type_name_id_t: + name = "type_name_id"; + break; case ASTNodeDataType::type_id_t: name = "type_id"; break; @@ -55,6 +58,9 @@ dataTypeName(const ASTNodeDataType& data_type) case ASTNodeDataType::c_function_t: name = "c_function"; break; + case ASTNodeDataType::builtin_function_t: + name = "builtin_function"; + break; case ASTNodeDataType::void_t: name = "void"; break; diff --git a/src/language/ASTNodeDataType.hpp b/src/language/ASTNodeDataType.hpp index af053c4d8..ee424e775 100644 --- a/src/language/ASTNodeDataType.hpp +++ b/src/language/ASTNodeDataType.hpp @@ -11,19 +11,21 @@ class ASTNodeDataType public: enum DataType : int32_t { - undefined_t = -1, - bool_t = 0, - int_t = 1, - unsigned_int_t = 2, - double_t = 3, - vector_t = 4, - list_t = 5, - string_t = 6, - typename_t = 10, - type_id_t = 20, - function_t = 21, - c_function_t = 22, - void_t = std::numeric_limits<int32_t>::max() + undefined_t = -1, + bool_t = 0, + int_t = 1, + unsigned_int_t = 2, + double_t = 3, + vector_t = 4, + list_t = 5, + string_t = 6, + typename_t = 10, + type_name_id_t = 20, + type_id_t = 21, + function_t = 22, + c_function_t = 23, + builtin_function_t = 24, + void_t = std::numeric_limits<int32_t>::max() }; private: @@ -38,12 +40,19 @@ class ASTNodeDataType return m_dimension; } + std::string_view + typeName() const + { + return m_type_name; + } + operator DataType() const { return m_data_type; } ASTNodeDataType& operator=(const ASTNodeDataType&) = default; + ASTNodeDataType& operator=(ASTNodeDataType&&) = default; constexpr ASTNodeDataType(DataType data_type) : m_data_type{data_type}, m_dimension{1} {} @@ -55,6 +64,8 @@ class ASTNodeDataType ASTNodeDataType(const ASTNodeDataType&) = default; + ASTNodeDataType(ASTNodeDataType&&) = default; + ~ASTNodeDataType() = default; }; diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp index bf6ebea68..80c24227f 100644 --- a/src/language/ASTNodeDataTypeBuilder.cpp +++ b/src/language/ASTNodeDataTypeBuilder.cpp @@ -6,6 +6,7 @@ #include <PugsAssert.hpp> #include <SymbolTable.hpp> +#include <BuiltinFunctionEmbedder.hpp> #include <CFunctionEmbedder.hpp> ASTNodeDataType @@ -41,26 +42,45 @@ ASTNodeDataTypeBuilder::_buildDeclarationNodeDataTypes(ASTNode& type_node, ASTNo data_type = getVectorDataType(type_node); } else if (type_node.is_type<language::string_type>()) { data_type = ASTNodeDataType::string_t; - } else if (type_node.is_type<language::type_id>()) { - data_type = ASTNodeDataType{ASTNodeDataType::type_id_t, type_node.string_view()}; + } else if (type_node.is_type<language::type_name_id>()) { + const std::string& type_name_id = type_node.string(); + + auto& symbol_table = *type_node.m_symbol_table; + + auto [i_type_symbol, found] = symbol_table.find(type_name_id, type_node.begin()); + if (not found) { + throw parse_error("undefined type identifier", std::vector{type_node.begin()}); + } else if (i_type_symbol->attributes().dataType() != ASTNodeDataType::type_name_id_t) { + std::ostringstream os; + os << "invalid type identifier, '" << type_name_id << "' was previously defined as a '" + << dataTypeName(i_type_symbol->attributes().dataType()) << "'" << std::ends; + throw parse_error(os.str(), std::vector{type_node.begin()}); + } + + data_type = ASTNodeDataType{ASTNodeDataType::type_name_id_t, type_name_id}; } if (name_node.is_type<language::name_list>()) { - throw parse_error("unexpected variable list for single space", name_node.begin()); + throw parse_error("unexpected variable list for single space", std::vector{name_node.begin()}); } Assert(name_node.is_type<language::name>()); - name_node.m_data_type = data_type; + if (data_type == ASTNodeDataType::type_name_id_t) { + name_node.m_data_type = ASTNodeDataType{ASTNodeDataType::type_id_t, data_type.typeName()}; + } else { + name_node.m_data_type = data_type; + } + const std::string& symbol = name_node.string(); std::shared_ptr<SymbolTable>& symbol_table = name_node.m_symbol_table; auto [i_symbol, found] = symbol_table->find(symbol, name_node.begin()); Assert(found); - i_symbol->attributes().setDataType(data_type); + i_symbol->attributes().setDataType(name_node.m_data_type); } - Assert(data_type != ASTNodeDataType::undefined_t); // LCOV_EXCL_LINE + Assert(data_type != ASTNodeDataType::undefined_t); return data_type; } @@ -397,10 +417,22 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const Assert(success); uint64_t c_function_id = std::get<uint64_t>(i_symbol->attributes().value()); - auto c_function_embedder = symbol_table.cFunctionEbedderTable()[c_function_id]; + auto c_function_embedder = symbol_table.cFunctionEmbedderTable()[c_function_id]; Assert(c_function_embedder); n.m_data_type = c_function_embedder->getReturnDataType(); + } else if (n.children[0]->m_data_type == ASTNodeDataType::builtin_function_t) { + const std::string builtin_function_name = n.children[0]->string(); + auto& symbol_table = *n.m_symbol_table; + + auto [i_symbol, success] = symbol_table.find(builtin_function_name, n.begin()); + Assert(success); + + uint64_t builtin_function_id = std::get<uint64_t>(i_symbol->attributes().value()); + auto builtin_function_embedder = symbol_table.builtinFunctionEmbedderTable()[builtin_function_id]; + Assert(builtin_function_embedder); + + n.m_data_type = builtin_function_embedder->getReturnDataType(); } else { std::ostringstream message; message << "invalid function call\n" @@ -426,7 +458,7 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n) const } } else if (n.is_type<language::B_set>() or n.is_type<language::Z_set>() or n.is_type<language::N_set>() or n.is_type<language::R_set>() or n.is_type<language::string_type>() or - n.is_type<language::vector_type>() or n.is_type<language::type_id>()) { + n.is_type<language::vector_type>() or n.is_type<language::type_name_id>()) { n.m_data_type = ASTNodeDataType::typename_t; } else if (n.is_type<language::name_list>() or n.is_type<language::lvalue_list>() or n.is_type<language::function_argument_list>()) { diff --git a/src/language/BuiltinFunctionEmbedder.hpp b/src/language/BuiltinFunctionEmbedder.hpp new file mode 100644 index 000000000..d1896ede4 --- /dev/null +++ b/src/language/BuiltinFunctionEmbedder.hpp @@ -0,0 +1,59 @@ +#ifndef BUILTIN_FUNCTION_EMBEDDER_HPP +#define BUILTIN_FUNCTION_EMBEDDER_HPP + +#include <memory> +#include <vector> + +#include <ASTNodeDataType.hpp> +#include <DataVariant.hpp> + +class IBuiltinFunctionEmbedder +{ + public: + virtual size_t numberOfParameters() const = 0; + + virtual ASTNodeDataType getReturnDataType() const = 0; + + virtual std::vector<ASTNodeDataType> getParameterDataTypes() const = 0; + + virtual DataVariant apply(const std::vector<DataVariant>& x) const = 0; + + virtual ~IBuiltinFunctionEmbedder() = default; +}; + +class BuiltinFunctionEmbedder : public IBuiltinFunctionEmbedder +{ + private: + ASTNodeDataType m_return_data_type{ASTNodeDataType::type_id_t, "mesh"}; + + public: + size_t + numberOfParameters() const + { + return 1; + } + + ASTNodeDataType + getReturnDataType() const + { + return m_return_data_type; + } + + std::vector<ASTNodeDataType> + getParameterDataTypes() const + { + return {ASTNodeDataType::string_t}; + } + + DataVariant + apply(const std::vector<DataVariant>&) const + { + std::cerr << "NIY\n"; + return {}; + } + + BuiltinFunctionEmbedder() = default; + ~BuiltinFunctionEmbedder() = default; +}; + +#endif // BUILTIN_FUNCTION_EMBEDDER_HPP diff --git a/src/language/BuiltinModule.cpp b/src/language/BuiltinModule.cpp index 88967ad75..bea61e9d7 100644 --- a/src/language/BuiltinModule.cpp +++ b/src/language/BuiltinModule.cpp @@ -6,7 +6,7 @@ #include <iostream> void -BuiltinModule::_addFunction(const std::string& name, std::shared_ptr<ICFunctionEmbedder> c_function_embedder) +BuiltinModule::_addCFunction(const std::string& name, std::shared_ptr<ICFunctionEmbedder> c_function_embedder) { auto [i_function, success] = m_name_cfunction_map.insert(std::make_pair(name, c_function_embedder)); // LCOV_EXCL_START @@ -17,10 +17,24 @@ BuiltinModule::_addFunction(const std::string& name, std::shared_ptr<ICFunctionE // LCOV_EXCL_STOP } +void +BuiltinModule::_addBuiltinFunction(const std::string& name, + std::shared_ptr<IBuiltinFunctionEmbedder> builtin_function_embedder) +{ + auto [i_builtin_function, success] = + m_name_builtin_function_map.insert(std::make_pair(name, builtin_function_embedder)); + // LCOV_EXCL_START + if (not success) { + std::cerr << "builtin function " << name << " cannot be added!\n"; + std::exit(1); + } + // LCOV_EXCL_STOP +} + void BuiltinModule::_addTypeDescriptor(std::shared_ptr<TypeDescriptor> type_descriptor) { - auto [i_type, success] = m_type_descriptor_map.insert(std::make_pair(type_descriptor->name(), type_descriptor)); + auto [i_type, success] = m_name_type_map.insert(std::make_pair(type_descriptor->name(), type_descriptor)); // LCOV_EXCL_START if (not success) { std::cerr << "type '" << type_descriptor->name() << "' cannot be added!\n"; diff --git a/src/language/BuiltinModule.hpp b/src/language/BuiltinModule.hpp index 67adb09e1..7e0d599e9 100644 --- a/src/language/BuiltinModule.hpp +++ b/src/language/BuiltinModule.hpp @@ -4,29 +4,40 @@ #include <IModule.hpp> class ICFunctionEmbedder; +class IBuiltinFunctionEmbedder; class TypeDescriptor; class BuiltinModule : public IModule { protected: NameCFunctionMap m_name_cfunction_map; - TypeDescriptorMap m_type_descriptor_map; + NameBuiltinFunctionMap m_name_builtin_function_map; + NameTypeMap m_name_type_map; - void _addFunction(const std::string& name, std::shared_ptr<ICFunctionEmbedder> c_function_embedder); + void _addCFunction(const std::string& name, std::shared_ptr<ICFunctionEmbedder> c_function_embedder); + + void _addBuiltinFunction(const std::string& name, + std::shared_ptr<IBuiltinFunctionEmbedder> builtin_function_embedder); void _addTypeDescriptor(std::shared_ptr<TypeDescriptor> type_descriptor); public: const NameCFunctionMap& - getNameCFunctionsMap() const final + getNameCFunctionMap() const final { return m_name_cfunction_map; } - const TypeDescriptorMap& - getTypeDescriptorMap() const final + const NameBuiltinFunctionMap& + getNameBuiltinFunctionMap() const final + { + return m_name_builtin_function_map; + } + + const NameTypeMap& + getNameTypeMap() const final { - return m_type_descriptor_map; + return m_name_type_map; } BuiltinModule() = default; diff --git a/src/language/CFunctionEmbedderTable.hpp b/src/language/CFunctionEmbedderTable.hpp deleted file mode 100644 index b67f2afab..000000000 --- a/src/language/CFunctionEmbedderTable.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef CFUNCTION_EMBEDDER_TABLE_HPP -#define CFUNCTION_EMBEDDER_TABLE_HPP - -#include <PugsAssert.hpp> - -#include <memory> -#include <vector> - -class ICFunctionEmbedder; -class CFunctionEmbedderTable -{ - private: - std::vector<std::shared_ptr<ICFunctionEmbedder>> m_c_function_embedder_list; - - public: - PUGS_INLINE - size_t - size() const - { - return m_c_function_embedder_list.size(); - } - - PUGS_INLINE - const std::shared_ptr<ICFunctionEmbedder>& - operator[](size_t function_id) const - { - Assert(function_id < m_c_function_embedder_list.size()); - return m_c_function_embedder_list[function_id]; - } - - void - add(std::shared_ptr<ICFunctionEmbedder> c_function_embedder) - { - m_c_function_embedder_list.push_back(c_function_embedder); - } - - CFunctionEmbedderTable() = default; - ~CFunctionEmbedderTable() = default; -}; - -#endif // CFUNCTION_EMBEDDER_TABLE_HPP diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt index 14f349b46..a68852943 100644 --- a/src/language/CMakeLists.txt +++ b/src/language/CMakeLists.txt @@ -32,6 +32,7 @@ add_library( ASTSymbolTableBuilder.cpp ASTSymbolInitializationChecker.cpp BuiltinModule.cpp + EmbeddedData.cpp MathModule.cpp MeshModule.cpp ModuleRepository.cpp diff --git a/src/language/DataHandler.hpp b/src/language/DataHandler.hpp new file mode 100644 index 000000000..78cf0587d --- /dev/null +++ b/src/language/DataHandler.hpp @@ -0,0 +1,41 @@ +#ifndef DATA_HANDLER_HPP +#define DATA_HANDLER_HPP + +#include <PugsAssert.hpp> + +#include <memory> + +class IDataHandler +{ + public: + IDataHandler() = default; + + virtual ~IDataHandler() = default; +}; + +template <typename DataT> +class DataHandler +{ + private: + std::shared_ptr<DataT> m_data; + + public: + DataT& + data() + { + Assert(m_data); + return m_data; + } + + const DataT& + data() const + { + Assert(m_data); + return m_data; + } + + DataHandler(std::shared_ptr<DataT> data) : m_data(data) {} + ~DataHandler() = default; +}; + +#endif // DATA_HANDLER_HPP diff --git a/src/language/DataVariant.hpp b/src/language/DataVariant.hpp index 54abc6692..1aacda650 100644 --- a/src/language/DataVariant.hpp +++ b/src/language/DataVariant.hpp @@ -9,6 +9,8 @@ #include <PugsAssert.hpp> +#include <EmbeddedData.hpp> + class AggregateDataVariant; using DataVariant = std::variant<std::monostate, @@ -17,6 +19,7 @@ using DataVariant = std::variant<std::monostate, int64_t, double, std::string, + EmbeddedData, AggregateDataVariant, TinyVector<1>, TinyVector<2>, diff --git a/src/language/EmbeddedData.cpp b/src/language/EmbeddedData.cpp new file mode 100644 index 000000000..bdd29bbd3 --- /dev/null +++ b/src/language/EmbeddedData.cpp @@ -0,0 +1,14 @@ +#include <EmbeddedData.hpp> + +#include <DataHandler.hpp> + +std::ostream& +operator<<(std::ostream& os, const EmbeddedData&) +{ + os << "embedded_data"; + return os; +} + +EmbeddedData::EmbeddedData() {} + +EmbeddedData::~EmbeddedData() {} diff --git a/src/language/EmbeddedData.hpp b/src/language/EmbeddedData.hpp new file mode 100644 index 000000000..10febc07a --- /dev/null +++ b/src/language/EmbeddedData.hpp @@ -0,0 +1,51 @@ +#ifndef EMBEDDED_DATA_HPP +#define EMBEDDED_DATA_HPP + +#include <iostream> +#include <memory> + +#include <PugsAssert.hpp> + +class IDataHandler; + +class EmbeddedData +{ + private: + std::shared_ptr<IDataHandler> m_data_handler{nullptr}; + + public: + [[nodiscard]] const IDataHandler& + get() const + { + Assert(m_data_handler); + return *m_data_handler; + } + + void + set(const std::shared_ptr<IDataHandler>& data_handler) + { + m_data_handler = data_handler; + } + + void + set(std::shared_ptr<IDataHandler>&& data_handler) + { + m_data_handler = std::move(data_handler); + } + + friend std::ostream& operator<<(std::ostream& os, const EmbeddedData&); + + EmbeddedData& operator=(const EmbeddedData&) = default; + EmbeddedData& operator=(EmbeddedData&&) = default; + + EmbeddedData(const EmbeddedData&) = default; + EmbeddedData(EmbeddedData&&) = default; + + EmbeddedData(const std::shared_ptr<IDataHandler>& data_handler) : m_data_handler{data_handler} {} + EmbeddedData(std::shared_ptr<IDataHandler>&& data_handler) : m_data_handler{std::move(data_handler)} {} + + EmbeddedData(); + ~EmbeddedData(); +}; + +#endif // EMBEDDED_DATA_HPP diff --git a/src/language/EmbedderTable.hpp b/src/language/EmbedderTable.hpp new file mode 100644 index 000000000..f12c1843d --- /dev/null +++ b/src/language/EmbedderTable.hpp @@ -0,0 +1,41 @@ +#ifndef EMBEDDER_TABLE_HPP +#define EMBEDDER_TABLE_HPP + +#include <PugsAssert.hpp> + +#include <memory> +#include <vector> + +template <typename EmbedderT> +class EmbedderTable +{ + private: + std::vector<std::shared_ptr<EmbedderT>> m_embedder_list; + + public: + PUGS_INLINE + size_t + size() const + { + return m_embedder_list.size(); + } + + PUGS_INLINE + const std::shared_ptr<EmbedderT>& + operator[](size_t embedder_id) const + { + Assert(embedder_id < m_embedder_list.size()); + return m_embedder_list[embedder_id]; + } + + void + add(std::shared_ptr<EmbedderT> embedder) + { + m_embedder_list.push_back(embedder); + } + + EmbedderTable() = default; + ~EmbedderTable() = default; +}; + +#endif // EMBEDDER_TABLE_HPP diff --git a/src/language/IModule.hpp b/src/language/IModule.hpp index 459a914b9..deb485714 100644 --- a/src/language/IModule.hpp +++ b/src/language/IModule.hpp @@ -7,20 +7,25 @@ #include <unordered_map> class ICFunctionEmbedder; +class IBuiltinFunctionEmbedder; class TypeDescriptor; class IModule { public: - using NameCFunctionMap = std::unordered_map<std::string, std::shared_ptr<ICFunctionEmbedder>>; - using TypeDescriptorMap = std::unordered_map<std::string, std::shared_ptr<TypeDescriptor>>; + using NameCFunctionMap = std::unordered_map<std::string, std::shared_ptr<ICFunctionEmbedder>>; + using NameBuiltinFunctionMap = std::unordered_map<std::string, std::shared_ptr<IBuiltinFunctionEmbedder>>; + using NameTypeMap = std::unordered_map<std::string, std::shared_ptr<TypeDescriptor>>; IModule() = default; IModule(IModule&&) = default; IModule& operator=(IModule&&) = default; - virtual const NameCFunctionMap& getNameCFunctionsMap() const = 0; - virtual const TypeDescriptorMap& getTypeDescriptorMap() const = 0; + virtual const NameCFunctionMap& getNameCFunctionMap() const = 0; + + virtual const NameBuiltinFunctionMap& getNameBuiltinFunctionMap() const = 0; + + virtual const NameTypeMap& getNameTypeMap() const = 0; virtual std::string_view name() const = 0; diff --git a/src/language/MathModule.cpp b/src/language/MathModule.cpp index 440ad9290..4f70162ad 100644 --- a/src/language/MathModule.cpp +++ b/src/language/MathModule.cpp @@ -4,71 +4,71 @@ MathModule::MathModule() { - this->_addFunction("sqrt", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::sqrt(x); }})); + this->_addCFunction("sqrt", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::sqrt(x); }})); - this->_addFunction("abs", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::abs(x); }})); + this->_addCFunction("abs", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::abs(x); }})); - this->_addFunction("sin", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::sin(x); }})); + this->_addCFunction("sin", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::sin(x); }})); - this->_addFunction("cos", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::cos(x); }})); + this->_addCFunction("cos", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::cos(x); }})); - this->_addFunction("tan", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::tan(x); }})); + this->_addCFunction("tan", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::tan(x); }})); - this->_addFunction("asin", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::asin(x); }})); + this->_addCFunction("asin", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::asin(x); }})); - this->_addFunction("acos", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::acos(x); }})); + this->_addCFunction("acos", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::acos(x); }})); - this->_addFunction("atan", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::atan(x); }})); + this->_addCFunction("atan", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::atan(x); }})); - this->_addFunction("atan2", - std::make_shared<CFunctionEmbedder<double, double, double>>(std::function<double(double, double)>{ - [](double x, double y) -> double { return std::atan2(x, y); }})); + this->_addCFunction("atan2", + std::make_shared<CFunctionEmbedder<double, double, double>>(std::function<double(double, double)>{ + [](double x, double y) -> double { return std::atan2(x, y); }})); - this->_addFunction("sinh", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::sinh(x); }})); + this->_addCFunction("sinh", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::sinh(x); }})); - this->_addFunction("cosh", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::cosh(x); }})); + this->_addCFunction("cosh", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::cosh(x); }})); - this->_addFunction("tanh", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::tanh(x); }})); + this->_addCFunction("tanh", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::tanh(x); }})); - this->_addFunction("asinh", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::asinh(x); }})); + this->_addCFunction("asinh", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::asinh(x); }})); - this->_addFunction("acosh", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::acosh(x); }})); + this->_addCFunction("acosh", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::acosh(x); }})); - this->_addFunction("atanh", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::atanh(x); }})); + this->_addCFunction("atanh", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::atanh(x); }})); - this->_addFunction("exp", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::exp(x); }})); + this->_addCFunction("exp", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::exp(x); }})); - this->_addFunction("log", std::make_shared<CFunctionEmbedder<double, double>>( - std::function<double(double)>{[](double x) -> double { return std::log(x); }})); + this->_addCFunction("log", std::make_shared<CFunctionEmbedder<double, double>>( + std::function<double(double)>{[](double x) -> double { return std::log(x); }})); - this->_addFunction("pow", - std::make_shared<CFunctionEmbedder<double, double, double>>(std::function<double(double, double)>{ - [](double x, double y) -> double { return std::pow(x, y); }})); + this->_addCFunction("pow", + std::make_shared<CFunctionEmbedder<double, double, double>>(std::function<double(double, double)>{ + [](double x, double y) -> double { return std::pow(x, y); }})); - this->_addFunction("ceil", std::make_shared<CFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::ceil(x); }})); + this->_addCFunction("ceil", std::make_shared<CFunctionEmbedder<int64_t, double>>( + std::function<int64_t(double)>{[](double x) -> int64_t { return std::ceil(x); }})); - this->_addFunction("floor", std::make_shared<CFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::floor(x); }})); + this->_addCFunction("floor", std::make_shared<CFunctionEmbedder<int64_t, double>>( + std::function<int64_t(double)>{[](double x) -> int64_t { return std::floor(x); }})); - this->_addFunction("trunc", std::make_shared<CFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::trunc(x); }})); + this->_addCFunction("trunc", std::make_shared<CFunctionEmbedder<int64_t, double>>( + std::function<int64_t(double)>{[](double x) -> int64_t { return std::trunc(x); }})); - this->_addFunction("round", std::make_shared<CFunctionEmbedder<int64_t, double>>( - std::function<int64_t(double)>{[](double x) -> int64_t { return std::lround(x); }})); + this->_addCFunction("round", std::make_shared<CFunctionEmbedder<int64_t, double>>( + std::function<int64_t(double)>{[](double x) -> int64_t { return std::lround(x); }})); } diff --git a/src/language/MeshModule.cpp b/src/language/MeshModule.cpp index 7edad9c35..1b33eedca 100644 --- a/src/language/MeshModule.cpp +++ b/src/language/MeshModule.cpp @@ -1,9 +1,11 @@ #include <MeshModule.hpp> -#include <TypeDescriptor.hpp> -#include <memory> +#include <BuiltinFunctionEmbedder.hpp> +#include <TypeDescriptor.hpp> MeshModule::MeshModule() { this->_addTypeDescriptor(std::make_shared<TypeDescriptor>(std::string{"mesh"})); + + this->_addBuiltinFunction("readGmsh", std::make_shared<BuiltinFunctionEmbedder>()); } diff --git a/src/language/ModuleRepository.cpp b/src/language/ModuleRepository.cpp index f6b0b0d8f..bacda2efa 100644 --- a/src/language/ModuleRepository.cpp +++ b/src/language/ModuleRepository.cpp @@ -23,16 +23,17 @@ ModuleRepository::ModuleRepository() this->_subscribe(std::make_unique<MeshModule>()); } +template <typename NameEmbedderMapT, typename EmbedderTableT> void -ModuleRepository::_populateCFunctionsEmbedderTable(const IModule& populating_module, - const ASTNode& module_name_node, - SymbolTable& symbol_table) +ModuleRepository::_populateEmbedderTableT(const ASTNode& module_name_node, + const NameEmbedderMapT& name_embedder_map, + const ASTNodeDataType& data_type, + SymbolTable& symbol_table, + EmbedderTableT& embedder_table) { const std::string& module_name = module_name_node.string(); - CFunctionEmbedderTable& c_function_embedder_table = symbol_table.cFunctionEbedderTable(); - - for (auto [symbol_name, c_function] : populating_module.getNameCFunctionsMap()) { + for (auto [symbol_name, embedded] : name_embedder_map) { auto [i_symbol, success] = symbol_table.add(symbol_name, module_name_node.begin()); if (not success) { @@ -42,38 +43,11 @@ ModuleRepository::_populateCFunctionsEmbedderTable(const IModule& populating_mod throw parse_error(error_message.str(), module_name_node.begin()); } - i_symbol->attributes().setDataType(ASTNodeDataType::c_function_t); + i_symbol->attributes().setDataType(data_type); i_symbol->attributes().setIsInitialized(); - i_symbol->attributes().value() = c_function_embedder_table.size(); + i_symbol->attributes().value() = embedder_table.size(); - c_function_embedder_table.add(c_function); - } -} - -void -ModuleRepository::_populateTypeDescriptor(const IModule& populating_module, - const ASTNode& module_name_node, - SymbolTable& symbol_table) -{ - const std::string& module_name = module_name_node.string(); - - TypeTable& type_table = symbol_table.typeTable(); - - for (auto [symbol_name, type_descriptor] : populating_module.getTypeDescriptorMap()) { - auto [i_symbol, success] = symbol_table.add(symbol_name, module_name_node.begin()); - - if (not success) { - std::ostringstream error_message; - error_message << "importing module '" << module_name << "', cannot add symbol '" << symbol_name - << "', it is already defined!"; - throw parse_error(error_message.str(), module_name_node.begin()); - } - - i_symbol->attributes().setDataType(ASTNodeDataType::type_id_t); - i_symbol->attributes().setIsInitialized(); - i_symbol->attributes().value() = type_table.size(); - - type_table.add(type_descriptor); + embedder_table.add(embedded); } } @@ -84,8 +58,17 @@ ModuleRepository::populateSymbolTable(const ASTNode& module_name_node, SymbolTab auto i_module = m_module_set.find(module_name); if (i_module != m_module_set.end()) { - this->_populateCFunctionsEmbedderTable(*i_module->second, module_name_node, symbol_table); - this->_populateTypeDescriptor(*i_module->second, module_name_node, symbol_table); + const IModule& populating_module = *i_module->second; + + this->_populateEmbedderTableT(module_name_node, populating_module.getNameCFunctionMap(), + ASTNodeDataType::c_function_t, symbol_table, symbol_table.cFunctionEmbedderTable()); + + this->_populateEmbedderTableT(module_name_node, populating_module.getNameBuiltinFunctionMap(), + ASTNodeDataType::builtin_function_t, symbol_table, + symbol_table.builtinFunctionEmbedderTable()); + + this->_populateEmbedderTableT(module_name_node, populating_module.getNameTypeMap(), ASTNodeDataType::type_name_id_t, + symbol_table, symbol_table.typeEmbedderTable()); } else { throw parse_error(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()}); } diff --git a/src/language/ModuleRepository.hpp b/src/language/ModuleRepository.hpp index e71a56587..93c4fa177 100644 --- a/src/language/ModuleRepository.hpp +++ b/src/language/ModuleRepository.hpp @@ -8,6 +8,7 @@ #include <string> class ASTNode; +class ASTNodeDataType; class SymbolTable; class ModuleRepository @@ -17,13 +18,12 @@ class ModuleRepository void _subscribe(std::unique_ptr<IModule> a); - void _populateCFunctionsEmbedderTable(const IModule& populating_module, - const ASTNode& module_name_node, - SymbolTable& symbol_table); - - void _populateTypeDescriptor(const IModule& populating_module, - const ASTNode& module_name_node, - SymbolTable& symbol_table); + template <typename NameEmbedderMapT, typename EmbedderTableT> + void _populateEmbedderTableT(const ASTNode& module_name_node, + const NameEmbedderMapT& name_embedder_map, + const ASTNodeDataType& data_type, + SymbolTable& symbol_table, + EmbedderTableT& embedder_table); public: void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table); diff --git a/src/language/PEGGrammar.hpp b/src/language/PEGGrammar.hpp index 98724f5fe..12f3bcd49 100644 --- a/src/language/PEGGrammar.hpp +++ b/src/language/PEGGrammar.hpp @@ -71,8 +71,8 @@ struct vector_type : seq< R_set, ignored, one< '^' >, ignored, integer >{}; struct basic_type : sor< scalar_type, string_type >{}; -struct type_id; -struct type_specifier : sor< vector_type, basic_type, type_id >{}; +struct type_name_id; +struct type_specifier : sor< vector_type, basic_type, type_name_id >{}; struct TYPE_SPECIFIER : seq< type_specifier, ignored >{}; @@ -125,7 +125,7 @@ struct identifier_minus_keyword : minus< identifier, keywork > {}; struct module_name : identifier_minus_keyword {}; struct MODULE_NAME : seq< module_name, ignored > {}; -struct type_id : identifier_minus_keyword {}; +struct type_name_id : identifier_minus_keyword {}; struct name : identifier_minus_keyword {}; struct NAME : seq< name, ignored > {}; diff --git a/src/language/SymbolTable.hpp b/src/language/SymbolTable.hpp index 4dbbc5b2c..3105957cc 100644 --- a/src/language/SymbolTable.hpp +++ b/src/language/SymbolTable.hpp @@ -10,10 +10,13 @@ #include <iostream> -#include <CFunctionEmbedderTable.hpp> #include <FunctionTable.hpp> -#include <TypeTable.hpp> +#include <EmbedderTable.hpp> + +class TypeDescriptor; +class ICFunctionEmbedder; +class IBuiltinFunctionEmbedder; class SymbolTable { @@ -89,8 +92,10 @@ class SymbolTable { if (attributes.m_data_type == ASTNodeDataType::function_t) { os << "function_id:"; + } else if (attributes.m_data_type == ASTNodeDataType::type_name_id_t) { + os << "type_name_id:"; } else if (attributes.m_data_type == ASTNodeDataType::type_id_t) { - os << "type_id:"; + os << attributes.m_data_type.typeName() << ':'; } std::visit( [&](const auto& value) { @@ -198,9 +203,10 @@ class SymbolTable std::shared_ptr<Context> m_context; std::shared_ptr<FunctionTable> m_function_table; - std::shared_ptr<CFunctionEmbedderTable> m_c_function_embedder_table; - std::shared_ptr<TypeTable> m_type_table; + std::shared_ptr<EmbedderTable<ICFunctionEmbedder>> m_c_function_embedder_table; + std::shared_ptr<EmbedderTable<IBuiltinFunctionEmbedder>> m_builtin_function_embedder_table; + std::shared_ptr<EmbedderTable<TypeDescriptor>> m_type_embedder_table; public: bool @@ -230,32 +236,46 @@ class SymbolTable return *m_function_table; } - const CFunctionEmbedderTable& - cFunctionEbedderTable() const + const auto& + cFunctionEmbedderTable() const { Assert(m_c_function_embedder_table); return *m_c_function_embedder_table; } - CFunctionEmbedderTable& - cFunctionEbedderTable() + auto& + cFunctionEmbedderTable() { Assert(m_c_function_embedder_table); return *m_c_function_embedder_table; } - TypeTable& - typeTable() + const auto& + builtinFunctionEmbedderTable() const + { + Assert(m_builtin_function_embedder_table); + return *m_builtin_function_embedder_table; + } + + auto& + builtinFunctionEmbedderTable() + { + Assert(m_builtin_function_embedder_table); + return *m_builtin_function_embedder_table; + } + + auto& + typeEmbedderTable() { - Assert(m_type_table); - return *m_type_table; + Assert(m_type_embedder_table); + return *m_type_embedder_table; } - const TypeTable& - typeTable() const + const auto& + typeEmbedderTable() const { - Assert(m_type_table); - return *m_type_table; + Assert(m_type_embedder_table); + return *m_type_embedder_table; } friend std::ostream& @@ -320,17 +340,13 @@ class SymbolTable m_context{context}, m_function_table{parent_table->m_function_table}, m_c_function_embedder_table{parent_table->m_c_function_embedder_table}, - m_type_table{parent_table->m_type_table} + m_builtin_function_embedder_table{parent_table->m_builtin_function_embedder_table}, + m_type_embedder_table{parent_table->m_type_embedder_table} { ; } - SymbolTable(const std::shared_ptr<SymbolTable>& parent_table) - : m_parent_table{parent_table}, - m_context{parent_table->m_context}, - m_function_table{parent_table->m_function_table}, - m_c_function_embedder_table{parent_table->m_c_function_embedder_table}, - m_type_table{parent_table->m_type_table} + SymbolTable(const std::shared_ptr<SymbolTable>& parent_table) : SymbolTable{parent_table, parent_table->m_context} { ; } @@ -339,8 +355,9 @@ class SymbolTable : m_parent_table{nullptr}, m_context{nullptr}, m_function_table{std::make_shared<FunctionTable>()}, - m_c_function_embedder_table{std::make_shared<CFunctionEmbedderTable>()}, - m_type_table{std::make_shared<TypeTable>()} + m_c_function_embedder_table{std::make_shared<EmbedderTable<ICFunctionEmbedder>>()}, + m_builtin_function_embedder_table{std::make_shared<EmbedderTable<IBuiltinFunctionEmbedder>>()}, + m_type_embedder_table{std::make_shared<EmbedderTable<TypeDescriptor>>()} { ; } diff --git a/src/language/TypeTable.hpp b/src/language/TypeTable.hpp deleted file mode 100644 index 059e686e1..000000000 --- a/src/language/TypeTable.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef TYPE_TABLE_HPP -#define TYPE_TABLE_HPP - -#include <TypeDescriptor.hpp> - -#include <vector> - -class TypeTable -{ - private: - std::vector<std::shared_ptr<TypeDescriptor>> m_type_list; - - public: - size_t - size() const - { - return m_type_list.size(); - } - - void - add(std::shared_ptr<TypeDescriptor> type_descriptor) - { - m_type_list.emplace_back(type_descriptor); - } - - TypeTable() = default; - ~TypeTable() = default; -}; - -#endif // TYPE_TABLE_HPP diff --git a/src/language/node_processor/OStreamProcessor.hpp b/src/language/node_processor/OStreamProcessor.hpp index c0fd17c92..8ef721696 100644 --- a/src/language/node_processor/OStreamProcessor.hpp +++ b/src/language/node_processor/OStreamProcessor.hpp @@ -34,7 +34,8 @@ class OStreamProcessor final : public INodeProcessor OStreamProcessor(ASTNode& node, std::ostream& os) : m_node{node}, m_os(os) { for (auto& child : m_node.children) { - if ((child->m_data_type == ASTNodeDataType::type_id_t) or (child->m_data_type == ASTNodeDataType::function_t) or + if ((child->m_data_type == ASTNodeDataType::type_name_id_t) or + (child->m_data_type == ASTNodeDataType::function_t) or (child->m_data_type == ASTNodeDataType::c_function_t)) { throw parse_error("invalid argument, cannot print a '" + dataTypeName(child->m_data_type) + "'", std::vector{child->begin()}); diff --git a/tests/test_ASTNodeCFunctionExpressionBuilder.cpp b/tests/test_ASTNodeCFunctionExpressionBuilder.cpp index 8d6534fa6..99deff5cf 100644 --- a/tests/test_ASTNodeCFunctionExpressionBuilder.cpp +++ b/tests/test_ASTNodeCFunctionExpressionBuilder.cpp @@ -63,7 +63,7 @@ class CFunctionRegister { SymbolTable& symbol_table = *root_node.m_symbol_table; - CFunctionEmbedderTable& c_function_embedder_table = symbol_table.cFunctionEbedderTable(); + auto& c_function_embedder_table = symbol_table.cFunctionEmbedderTable(); this->_populateNameCFunctionMap(); diff --git a/tests/test_CFunctionEmbedderTable.cpp b/tests/test_CFunctionEmbedderTable.cpp index 797536f42..e75155f76 100644 --- a/tests/test_CFunctionEmbedderTable.cpp +++ b/tests/test_CFunctionEmbedderTable.cpp @@ -1,13 +1,13 @@ #include <catch2/catch.hpp> #include <CFunctionEmbedder.hpp> -#include <CFunctionEmbedderTable.hpp> +#include <EmbedderTable.hpp> TEST_CASE("CFunctionEmbedderTable", "[language]") { rang::setControlMode(rang::control::Off); - CFunctionEmbedderTable table; + EmbedderTable<ICFunctionEmbedder> table; REQUIRE(table.size() == 0); diff --git a/tests/test_CFunctionProcessor.cpp b/tests/test_CFunctionProcessor.cpp index 0809ca9bd..2a19c7263 100644 --- a/tests/test_CFunctionProcessor.cpp +++ b/tests/test_CFunctionProcessor.cpp @@ -260,7 +260,7 @@ let z:Z, z = round(-1.2); MathModule math_module; bool missing_test = false; - for (auto [cmath_name, c_function] : math_module.getNameCFunctionsMap()) { + for (auto [cmath_name, c_function] : math_module.getNameCFunctionMap()) { if (tested_function_set.find(cmath_name) == tested_function_set.end()) { UNSCOPED_INFO("function '" << cmath_name << "' is NOT tested"); missing_test = true; diff --git a/tests/test_MathModule.cpp b/tests/test_MathModule.cpp index 5239387a5..69eb53643 100644 --- a/tests/test_MathModule.cpp +++ b/tests/test_MathModule.cpp @@ -1,7 +1,7 @@ #include <catch2/catch.hpp> #include <CFunctionEmbedder.hpp> -#include <CFunctionEmbedderTable.hpp> +#include <EmbedderTable.hpp> #include <MathModule.hpp> @@ -10,7 +10,7 @@ TEST_CASE("MathModule", "[language]") rang::setControlMode(rang::control::Off); MathModule math_module; - const auto& name_cfunction = math_module.getNameCFunctionsMap(); + const auto& name_cfunction = math_module.getNameCFunctionMap(); REQUIRE(name_cfunction.size() == 22); diff --git a/tests/test_SymbolTable.cpp b/tests/test_SymbolTable.cpp index 33645f9ef..14b80ee4a 100644 --- a/tests/test_SymbolTable.cpp +++ b/tests/test_SymbolTable.cpp @@ -205,10 +205,10 @@ TEST_CASE("SymbolTable", "[language]") { std::shared_ptr root_st = std::make_shared<SymbolTable>(); - auto& c_function_table = root_st->cFunctionEbedderTable(); + auto& c_function_table = root_st->cFunctionEmbedderTable(); REQUIRE(c_function_table.size() == 0); - const auto& const_c_function_table = static_cast<const SymbolTable&>(*root_st).cFunctionEbedderTable(); + const auto& const_c_function_table = static_cast<const SymbolTable&>(*root_st).cFunctionEmbedderTable(); REQUIRE(const_c_function_table.size() == 0); c_function_table.add(std::make_shared<CFunctionEmbedder<double, double>>( -- GitLab