#ifndef TEST_BUILTIN_FUNCTION_REGISTER_H #define TEST_BUILTIN_FUNCTION_REGISTER_H #include <language/utils/ASTNodeDataTypeTraits.hpp> #include <language/utils/BuiltinFunctionEmbedder.hpp> #include <language/utils/ParseError.hpp> #include <language/utils/TypeDescriptor.hpp> #include <utils/Exceptions.hpp> #include <unordered_map> template <> inline ASTNodeDataType ast_node_data_type_from<std::shared_ptr<const double>> = ASTNodeDataType::build<ASTNodeDataType::type_id_t>("builtin_t"); const auto builtin_data_type = ast_node_data_type_from<std::shared_ptr<const double>>; namespace test_only { class test_BuiltinFunctionRegister { private: std::unordered_map<std::string, std::shared_ptr<IBuiltinFunctionEmbedder>> m_name_builtin_function_map; void _populateNameBuiltinFunctionMap() { m_name_builtin_function_map.insert( std::make_pair("runtimeError:void", std::make_shared<BuiltinFunctionEmbedder<void(void)>>( [](void) -> void { throw NormalError("runtime error"); }))); m_name_builtin_function_map.insert( std::make_pair("RtoR:R", std::make_shared<BuiltinFunctionEmbedder<double(double)>>( [](double x) -> double { return x + 1; }))); m_name_builtin_function_map.insert( std::make_pair("ZtoR:Z", std::make_shared<BuiltinFunctionEmbedder<double(int64_t)>>( [](int64_t z) -> double { return 0.5 * z; }))); m_name_builtin_function_map.insert( std::make_pair("NtoR:N", std::make_shared<BuiltinFunctionEmbedder<double(uint64_t)>>( [](uint64_t n) -> double { return 0.5 * n; }))); m_name_builtin_function_map.insert(std::make_pair("BtoR:B", std::make_shared<BuiltinFunctionEmbedder<double(bool)>>( [](bool b) -> double { return b; }))); m_name_builtin_function_map.insert( std::make_pair("RRtoB:R*R", std::make_shared<BuiltinFunctionEmbedder<bool(double, double)>>( [](double x, double y) -> bool { return x > y; }))); m_name_builtin_function_map.insert( std::make_pair("StoB:string", std::make_shared<BuiltinFunctionEmbedder<bool(std::string)>>( [](const std::string& s) -> bool { return s.size() > 0; }))); m_name_builtin_function_map.insert( std::make_pair("RtoR1:R", std::make_shared<BuiltinFunctionEmbedder<TinyVector<1>(double)>>( [](double r) -> TinyVector<1> { return {r}; }))); m_name_builtin_function_map.insert( std::make_pair("R1toR:R^1", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<1>)>>( [](TinyVector<1> x) -> double { return x[0]; }))); m_name_builtin_function_map.insert( std::make_pair("R2toR:R^2", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<2>)>>( [](TinyVector<2> x) -> double { return x[0] + x[1]; }))); m_name_builtin_function_map.insert( std::make_pair("R3toR:R^3", std::make_shared<BuiltinFunctionEmbedder<double(const TinyVector<3>&)>>( [](const TinyVector<3>& x) -> double { return x[0] + x[1] + x[2]; }))); m_name_builtin_function_map.insert( std::make_pair("R3R2toR:R^3*R^2", std::make_shared<BuiltinFunctionEmbedder<double(TinyVector<3>, TinyVector<2>)>>( [](TinyVector<3> x, TinyVector<2> y) -> double { return x[0] * y[1] + (y[0] - x[2]) * x[1]; }))); m_name_builtin_function_map.insert( std::make_pair("RtoR11:R", std::make_shared<BuiltinFunctionEmbedder<TinyMatrix<1>(double)>>( [](double r) -> TinyMatrix<1> { return {r}; }))); m_name_builtin_function_map.insert( std::make_pair("R11toR:R^1x1", std::make_shared<BuiltinFunctionEmbedder<double(TinyMatrix<1>)>>( [](TinyMatrix<1> x) -> double { return x(0, 0); }))); m_name_builtin_function_map.insert( std::make_pair("R22toR:R^2x2", std::make_shared<BuiltinFunctionEmbedder<double(TinyMatrix<2>)>>( [](TinyMatrix<2> x) -> double { return x(0, 0) + x(0, 1) + x(1, 0) + x(1, 1); }))); m_name_builtin_function_map.insert( std::make_pair("R33toR:R^3x3", std::make_shared<BuiltinFunctionEmbedder<double(const TinyMatrix<3>&)>>( [](const TinyMatrix<3>& x) -> double { return x(0, 0) + x(1, 1) + x(2, 2); }))); m_name_builtin_function_map.insert( std::make_pair("R33R22toR:R^3x3*R^2x2", std::make_shared<BuiltinFunctionEmbedder<double(TinyMatrix<3>, TinyMatrix<2>)>>( [](TinyMatrix<3> x, TinyMatrix<2> y) -> double { return (x(0, 0) + x(1, 1) + x(2, 2)) * (y(0, 0) + y(0, 1) + y(1, 0) + y(1, 1)); }))); m_name_builtin_function_map.insert( std::make_pair("fidToR:function", std::make_shared<BuiltinFunctionEmbedder<double(const FunctionSymbolId&)>>( [](const FunctionSymbolId&) -> double { return 0; }))); m_name_builtin_function_map.insert( std::make_pair("fidTupleToR:(function...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<FunctionSymbolId>)>>( [](const std::vector<FunctionSymbolId>&) -> double { return 0; }))); m_name_builtin_function_map.insert( std::make_pair("builtinToBuiltin:builtin_t", std::make_shared< BuiltinFunctionEmbedder<std::shared_ptr<const double>(std::shared_ptr<const double>)>>( [](std::shared_ptr<const double> x) -> std::shared_ptr<const double> { return x; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_BtoR:(B...)", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<bool>)>>( [](const std::vector<bool>&) -> double { return 0.5; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_NtoR:(N...)", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<uint64_t>)>>( [](const std::vector<uint64_t>&) -> double { return 0.5; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_ZtoR:(Z...)", std::make_shared<BuiltinFunctionEmbedder<double(std::vector<int64_t>)>>( [](const std::vector<int64_t>&) -> double { return 0.5; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_RtoB:(R...)", std::make_shared<BuiltinFunctionEmbedder<bool(std::vector<double>)>>( [](const std::vector<double>&) -> bool { return false; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_stringtoB:(string...)", std::make_shared<BuiltinFunctionEmbedder<bool(std::vector<std::string>)>>( [](const std::vector<std::string>&) -> bool { return true; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_builtinToB:(builtin_t...)", std::make_shared<BuiltinFunctionEmbedder<bool(std::vector<std::shared_ptr<const double>>)>>( [](const std::vector<std::shared_ptr<const double>>&) -> bool { return true; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_R1ToR:(R^1...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyVector<1>>&)>>( [](const std::vector<TinyVector<1>>&) -> double { return 1; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_R2ToR:(R^2...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyVector<2>>&)>>( [](const std::vector<TinyVector<2>>&) -> double { return 1; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_R3ToR:(R^3...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyVector<3>>)>>( [](const std::vector<TinyVector<3>>&) -> double { return 0; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_R11ToR:(R^1x1...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyMatrix<1>>&)>>( [](const std::vector<TinyMatrix<1>>&) -> double { return 1; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_R22ToR:(R^2x2...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyMatrix<2>>&)>>( [](const std::vector<TinyMatrix<2>>&) -> double { return 1; }))); m_name_builtin_function_map.insert( std::make_pair("tuple_R33ToR:(R^3x3...)", std::make_shared<BuiltinFunctionEmbedder<double(const std::vector<TinyMatrix<3>>)>>( [](const std::vector<TinyMatrix<3>>&) -> double { return 0; }))); m_name_builtin_function_map.insert( std::make_pair("sum_vector:R*R^2", std::make_shared< BuiltinFunctionEmbedder<std::tuple<double, TinyVector<2>>(const double, const double)>>( [](const double& x, const double& y) -> std::tuple<double, TinyVector<2>> { return std::make_tuple(x + y, TinyVector<2>{x, y}); }))); } void _addBuiltinTypeAndVariables(ASTNode& ast) { SymbolTable& symbol_table = *ast.m_symbol_table; auto [i_symbol, success] = symbol_table.add(builtin_data_type.nameOfTypeId(), ast.begin()); if (not success) { throw UnexpectedError("cannot add '" + builtin_data_type.nameOfTypeId() + "' type for testing"); } i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::type_name_id_t>()); i_symbol->attributes().setIsInitialized(); i_symbol->attributes().value() = symbol_table.typeEmbedderTable().size(); symbol_table.typeEmbedderTable().add(std::make_shared<TypeDescriptor>(builtin_data_type.nameOfTypeId())); auto [i_symbol_a, success_a] = symbol_table.add("a", ast.begin()); if (not success_a) { throw UnexpectedError("cannot add 'a' of type builtin_t for testing"); } i_symbol_a->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); i_symbol_a->attributes().setIsInitialized(); auto [i_symbol_b, success_b] = symbol_table.add("b", ast.begin()); if (not success_b) { throw UnexpectedError("cannot add 'b' of type builtin_t for testing"); } i_symbol_b->attributes().setDataType(ast_node_data_type_from<std::shared_ptr<const double>>); i_symbol_b->attributes().setIsInitialized(); } public: test_BuiltinFunctionRegister(ASTNode& root_node) { SymbolTable& symbol_table = *root_node.m_symbol_table; auto& builtin_function_embedder_table = symbol_table.builtinFunctionEmbedderTable(); this->_populateNameBuiltinFunctionMap(); this->_addBuiltinTypeAndVariables(root_node); for (const auto& [symbol_name, builtin_function] : m_name_builtin_function_map) { auto [i_symbol, success] = symbol_table.add(symbol_name, root_node.begin()); if (not success) { std::ostringstream error_message; error_message << "cannot add symbol '" << symbol_name << "' it is already defined"; throw ParseError(error_message.str(), root_node.begin()); } i_symbol->attributes().setDataType(ASTNodeDataType::build<ASTNodeDataType::builtin_function_t>()); i_symbol->attributes().setIsInitialized(); i_symbol->attributes().value() = builtin_function_embedder_table.size(); builtin_function_embedder_table.add(builtin_function); } } }; } // namespace test_only #endif /* TEST_BUILTIN_FUNCTION_REGISTER_H */