From e9fd42f02245ffbca0580d102e8a3c5c4ea81498 Mon Sep 17 00:00:00 2001
From: Stephane Del Pino <stephane.delpino44@gmail.com>
Date: Fri, 22 Jul 2022 09:21:14 +0200
Subject: [PATCH] Simplify registration of builtin functions (a lot!)

---
 src/language/modules/BuiltinModule.hpp        |  13 +
 src/language/modules/CoreModule.cpp           |  24 +-
 src/language/modules/DevUtilsModule.cpp       |  27 +-
 src/language/modules/LinearSolverModule.cpp   |  16 +-
 .../modules/MathFunctionRegisterForVh.cpp     | 656 +++++++++---------
 src/language/modules/MathModule.cpp           |  98 +--
 src/language/modules/MeshModule.cpp           |  97 ++-
 src/language/modules/SchemeModule.cpp         | 251 +++----
 src/language/modules/SocketModule.cpp         | 222 +++---
 src/language/modules/WriterModule.cpp         |  94 ++-
 tests/test_BuiltinFunctionEmbedder.cpp        |   6 +-
 tests/test_BuiltinFunctionEmbedderTable.cpp   |   3 +-
 12 files changed, 701 insertions(+), 806 deletions(-)

diff --git a/src/language/modules/BuiltinModule.hpp b/src/language/modules/BuiltinModule.hpp
index 3dd9ad1db..ae36c3510 100644
--- a/src/language/modules/BuiltinModule.hpp
+++ b/src/language/modules/BuiltinModule.hpp
@@ -8,6 +8,9 @@ class IBuiltinFunctionEmbedder;
 class TypeDescriptor;
 class ValueDescriptor;
 
+template <typename FX, typename... Args>
+class BuiltinFunctionEmbedder;
+
 class BuiltinModule : public IModule
 {
  protected:
@@ -15,9 +18,19 @@ class BuiltinModule : public IModule
   NameTypeMap m_name_type_map;
   NameValueMap m_name_value_map;
 
+  template <typename FX, typename... Args>
+  void
+  _addBuiltinFunction(const std::string& name, std::function<FX(Args...)>&& f)
+  {
+    this->_addBuiltinFunction(name, std::make_shared<BuiltinFunctionEmbedder<FX(Args...)>>(
+                                      std::forward<std::function<FX(Args...)>>(f)));
+  }
+
+ private:
   void _addBuiltinFunction(const std::string& name,
                            std::shared_ptr<IBuiltinFunctionEmbedder> builtin_function_embedder);
 
+ protected:
   void _addTypeDescriptor(const ASTNodeDataType& type);
 
   void _addNameValue(const std::string& name, const ASTNodeDataType& type, const DataVariant& data);
diff --git a/src/language/modules/CoreModule.cpp b/src/language/modules/CoreModule.cpp
index 966953add..ff07fc9da 100644
--- a/src/language/modules/CoreModule.cpp
+++ b/src/language/modules/CoreModule.cpp
@@ -37,19 +37,19 @@
 
 CoreModule::CoreModule() : BuiltinModule(true)
 {
-  this->_addBuiltinFunction("getPugsVersion", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>(
+  this->_addBuiltinFunction("getPugsVersion", std::function(
 
                                                 []() -> std::string { return pugsVersion(); }
 
                                                 ));
 
-  this->_addBuiltinFunction("getPugsBuildInfo", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>(
+  this->_addBuiltinFunction("getPugsBuildInfo", std::function(
 
                                                   []() -> std::string { return pugsBuildInfo(); }
 
                                                   ));
 
-  this->_addBuiltinFunction("getAvailableModules", std::make_shared<BuiltinFunctionEmbedder<std::string()>>(
+  this->_addBuiltinFunction("getAvailableModules", std::function(
 
                                                      []() -> std::string {
                                                        const ModuleRepository& repository =
@@ -60,7 +60,7 @@ CoreModule::CoreModule() : BuiltinModule(true)
 
                                                      ));
 
-  this->_addBuiltinFunction("getModuleInfo", std::make_shared<BuiltinFunctionEmbedder<std::string(const std::string&)>>(
+  this->_addBuiltinFunction("getModuleInfo", std::function(
 
                                                [](const std::string& module_name) -> std::string {
                                                  const ModuleRepository& repository =
@@ -71,7 +71,7 @@ CoreModule::CoreModule() : BuiltinModule(true)
 
                                                ));
 
-  this->_addBuiltinFunction("setRandomSeed", std::make_shared<BuiltinFunctionEmbedder<void(const int64_t&)>>(
+  this->_addBuiltinFunction("setRandomSeed", std::function(
 
                                                [](const int64_t& random_seed) -> void {
                                                  RandomEngine::instance().setRandomSeed(random_seed);
@@ -79,21 +79,21 @@ CoreModule::CoreModule() : BuiltinModule(true)
 
                                                ));
 
-  this->_addBuiltinFunction("resetRandomSeed", std::make_shared<BuiltinFunctionEmbedder<void(void)>>(
+  this->_addBuiltinFunction("resetRandomSeed", std::function(
 
-                                                 []() { RandomEngine::instance().resetRandomSeed(); }
+                                                 []() -> void { RandomEngine::instance().resetRandomSeed(); }
 
                                                  ));
 
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const OStream>>);
 
-  this
-    ->_addBuiltinFunction("ofstream",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const OStream>(const std::string&)>>(
+  this->_addBuiltinFunction("ofstream", std::function(
 
-                            [](const std::string& filename) { return std::make_shared<const OFStream>(filename); }
+                                          [](const std::string& filename) -> std::shared_ptr<const OStream> {
+                                            return std::make_shared<const OFStream>(filename);
+                                          }
 
-                            ));
+                                          ));
 
   this->_addNameValue("cout", ast_node_data_type_from<std::shared_ptr<const OStream>>,
                       EmbeddedData{std::make_shared<DataHandler<const OStream>>(std::make_shared<OStream>(std::cout))});
diff --git a/src/language/modules/DevUtilsModule.cpp b/src/language/modules/DevUtilsModule.cpp
index f0d0d31f3..2dace9adf 100644
--- a/src/language/modules/DevUtilsModule.cpp
+++ b/src/language/modules/DevUtilsModule.cpp
@@ -10,7 +10,7 @@
 
 DevUtilsModule::DevUtilsModule()
 {
-  this->_addBuiltinFunction("getAST", std::make_shared<BuiltinFunctionEmbedder<std::string(void)>>(
+  this->_addBuiltinFunction("getAST", std::function(
 
                                         []() -> std::string {
                                           const auto& root_node = ASTExecutionInfo::current().rootNode();
@@ -23,7 +23,7 @@ DevUtilsModule::DevUtilsModule()
 
                                         ));
 
-  this->_addBuiltinFunction("saveASTDot", std::make_shared<BuiltinFunctionEmbedder<void(const std::string&)>>(
+  this->_addBuiltinFunction("saveASTDot", std::function(
 
                                             [](const std::string& dot_filename) -> void {
                                               const auto& root_node = ASTExecutionInfo::current().rootNode();
@@ -48,22 +48,21 @@ DevUtilsModule::DevUtilsModule()
 
                                             ));
 
-  this->_addBuiltinFunction("getFunctionAST",
-                            std::make_shared<BuiltinFunctionEmbedder<std::string(const FunctionSymbolId&)>>(
+  this->_addBuiltinFunction("getFunctionAST", std::function(
 
-                              [](const FunctionSymbolId& function_symbol_id) -> std::string {
-                                const auto& function_descriptor = function_symbol_id.descriptor();
+                                                [](const FunctionSymbolId& function_symbol_id) -> std::string {
+                                                  const auto& function_descriptor = function_symbol_id.descriptor();
 
-                                std::ostringstream os;
-                                os << function_descriptor.name() << ": domain mapping\n";
-                                os << ASTPrinter(function_descriptor.domainMappingNode());
-                                os << function_descriptor.name() << ": definition\n";
-                                os << ASTPrinter(function_descriptor.definitionNode());
+                                                  std::ostringstream os;
+                                                  os << function_descriptor.name() << ": domain mapping\n";
+                                                  os << ASTPrinter(function_descriptor.domainMappingNode());
+                                                  os << function_descriptor.name() << ": definition\n";
+                                                  os << ASTPrinter(function_descriptor.definitionNode());
 
-                                return os.str();
-                              }
+                                                  return os.str();
+                                                }
 
-                              ));
+                                                ));
 }
 
 void
diff --git a/src/language/modules/LinearSolverModule.cpp b/src/language/modules/LinearSolverModule.cpp
index 5dafbadcf..123a93007 100644
--- a/src/language/modules/LinearSolverModule.cpp
+++ b/src/language/modules/LinearSolverModule.cpp
@@ -6,7 +6,7 @@
 
 LinearSolverModule::LinearSolverModule()
 {
-  this->_addBuiltinFunction("setLSVerbosity", std::make_shared<BuiltinFunctionEmbedder<void(const bool&)>>(
+  this->_addBuiltinFunction("setLSVerbosity", std::function(
 
                                                 [](const bool& verbose) -> void {
                                                   LinearSolverOptions::default_options.verbose() = verbose;
@@ -14,7 +14,7 @@ LinearSolverModule::LinearSolverModule()
 
                                                 ));
 
-  this->_addBuiltinFunction("setLSEpsilon", std::make_shared<BuiltinFunctionEmbedder<void(const double&)>>(
+  this->_addBuiltinFunction("setLSEpsilon", std::function(
 
                                               [](const double& epsilon) -> void {
                                                 LinearSolverOptions::default_options.epsilon() = epsilon;
@@ -22,7 +22,7 @@ LinearSolverModule::LinearSolverModule()
 
                                               ));
 
-  this->_addBuiltinFunction("setLSMaxIter", std::make_shared<BuiltinFunctionEmbedder<void(const uint64_t&)>>(
+  this->_addBuiltinFunction("setLSMaxIter", std::function(
 
                                               [](const uint64_t& max_iter) -> void {
                                                 LinearSolverOptions::default_options.maximumIteration() = max_iter;
@@ -30,7 +30,7 @@ LinearSolverModule::LinearSolverModule()
 
                                               ));
 
-  this->_addBuiltinFunction("setLSLibrary", std::make_shared<BuiltinFunctionEmbedder<void(const std::string&)>>(
+  this->_addBuiltinFunction("setLSLibrary", std::function(
 
                                               [](const std::string& library_name) -> void {
                                                 LinearSolverOptions::default_options.library() =
@@ -39,7 +39,7 @@ LinearSolverModule::LinearSolverModule()
 
                                               ));
 
-  this->_addBuiltinFunction("setLSMethod", std::make_shared<BuiltinFunctionEmbedder<void(const std::string&)>>(
+  this->_addBuiltinFunction("setLSMethod", std::function(
 
                                              [](const std::string& method_name) -> void {
                                                LinearSolverOptions::default_options.method() =
@@ -48,7 +48,7 @@ LinearSolverModule::LinearSolverModule()
 
                                              ));
 
-  this->_addBuiltinFunction("setLSPrecond", std::make_shared<BuiltinFunctionEmbedder<void(const std::string&)>>(
+  this->_addBuiltinFunction("setLSPrecond", std::function(
 
                                               [](const std::string& precond_name) -> void {
                                                 LinearSolverOptions::default_options.precond() =
@@ -57,7 +57,7 @@ LinearSolverModule::LinearSolverModule()
 
                                               ));
 
-  this->_addBuiltinFunction("getLSOptions", std::make_shared<BuiltinFunctionEmbedder<std::string()>>(
+  this->_addBuiltinFunction("getLSOptions", std::function(
 
                                               []() -> std::string {
                                                 std::ostringstream os;
@@ -69,7 +69,7 @@ LinearSolverModule::LinearSolverModule()
 
                                               ));
 
-  this->_addBuiltinFunction("getLSAvailable", std::make_shared<BuiltinFunctionEmbedder<std::string()>>(
+  this->_addBuiltinFunction("getLSAvailable", std::function(
 
                                                 []() -> std::string {
                                                   std::ostringstream os;
diff --git a/src/language/modules/MathFunctionRegisterForVh.cpp b/src/language/modules/MathFunctionRegisterForVh.cpp
index 22f7866bd..b15e9796f 100644
--- a/src/language/modules/MathFunctionRegisterForVh.cpp
+++ b/src/language/modules/MathFunctionRegisterForVh.cpp
@@ -8,342 +8,380 @@
 
 MathFunctionRegisterForVh::MathFunctionRegisterForVh(SchemeModule& scheme_module)
 {
-  scheme_module._addBuiltinFunction("sqrt",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return sqrt(a); }));
-
-  scheme_module._addBuiltinFunction("abs",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return abs(a); }));
-
-  scheme_module._addBuiltinFunction("sin",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return sin(a); }));
-
-  scheme_module._addBuiltinFunction("cos",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return cos(a); }));
-
-  scheme_module._addBuiltinFunction("tan",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return tan(a); }));
-
-  scheme_module._addBuiltinFunction("asin",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return asin(a); }));
-
-  scheme_module._addBuiltinFunction("acos",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return acos(a); }));
-
-  scheme_module._addBuiltinFunction("atan",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return atan(a); }));
-
-  scheme_module
-    ._addBuiltinFunction("atan2",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>,
-                                                                    std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("atan2",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(double, std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](double a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("atan2",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, double)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a,
-                              double b) -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); }));
-
-  scheme_module._addBuiltinFunction("sinh",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return sinh(a); }));
-
-  scheme_module._addBuiltinFunction("cosh",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return cosh(a); }));
-
-  scheme_module._addBuiltinFunction("tanh",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return tanh(a); }));
-
-  scheme_module._addBuiltinFunction("asinh",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return asinh(a); }));
-
-  scheme_module._addBuiltinFunction("acosh",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return acosh(a); }));
-
-  scheme_module._addBuiltinFunction("atanh",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return atanh(a); }));
-
-  scheme_module._addBuiltinFunction("exp",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return exp(a); }));
-
-  scheme_module._addBuiltinFunction("log",
-                                    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                                      std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a)
-                                        -> std::shared_ptr<const IDiscreteFunction> { return log(a); }));
-
-  scheme_module
-    ._addBuiltinFunction("pow",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(double, std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](double a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("pow",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, double)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a,
-                              double b) -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("pow",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>,
-                                                                    std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("dot",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>,
-                                                                    std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("dot",
-                         std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                           const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, const TinyVector<1>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<1> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("dot",
-                         std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                           const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, const TinyVector<2>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<2> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("dot",
-                         std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                           const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, const TinyVector<3>&)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<3>& b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("dot",
-                         std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                           const IDiscreteFunction>(const TinyVector<1>, std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](const TinyVector<1> a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("dot",
-                         std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                           const IDiscreteFunction>(const TinyVector<2>, std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](const TinyVector<2> a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("dot",
-                         std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                           const IDiscreteFunction>(const TinyVector<3>&, std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](const TinyVector<3>& a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("min",
-                         std::make_shared<BuiltinFunctionEmbedder<double(std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a) -> double { return min(a); }));
-
-  scheme_module
-    ._addBuiltinFunction("min",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>,
-                                                                    std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("min",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(double, std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](double a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("min",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, double)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a,
-                              double b) -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("max",
-                         std::make_shared<BuiltinFunctionEmbedder<double(std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a) -> double { return max(a); }));
-
-  scheme_module
-    ._addBuiltinFunction("max",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>,
-                                                                    std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("max",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(double, std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](double a, std::shared_ptr<const IDiscreteFunction> b)
-                             -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("max",
-                         std::make_shared<BuiltinFunctionEmbedder<
-                           std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>, double)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a,
-                              double b) -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); }));
-
-  scheme_module
-    ._addBuiltinFunction("sum_of_R",
-                         std::make_shared<BuiltinFunctionEmbedder<double(std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a) -> double { return sum_of<double>(a); }));
-
-  scheme_module._addBuiltinFunction("sum_of_R1",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyVector<1>(std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<1> {
-                                        return sum_of<TinyVector<1>>(a);
-                                      }));
+  scheme_module._addBuiltinFunction("sqrt", std::function(
 
-  scheme_module._addBuiltinFunction("sum_of_R2",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyVector<2>(std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<2> {
-                                        return sum_of<TinyVector<2>>(a);
-                                      }));
+                                              [](std::shared_ptr<const IDiscreteFunction> a)
+                                                -> std::shared_ptr<const IDiscreteFunction> { return sqrt(a); }
 
-  scheme_module._addBuiltinFunction("sum_of_R3",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyVector<3>(std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<3> {
-                                        return sum_of<TinyVector<3>>(a);
-                                      }));
+                                              ));
 
-  scheme_module._addBuiltinFunction("sum_of_R1x1",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyMatrix<1>(std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<1> {
-                                        return sum_of<TinyMatrix<1>>(a);
-                                      }));
+  scheme_module._addBuiltinFunction("abs", std::function(
 
-  scheme_module._addBuiltinFunction("sum_of_R2x2",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyMatrix<2>(std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<2> {
-                                        return sum_of<TinyMatrix<2>>(a);
-                                      }));
+                                             [](std::shared_ptr<const IDiscreteFunction> a)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return abs(a); }
 
-  scheme_module._addBuiltinFunction("sum_of_R3x3",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyMatrix<3>(std::shared_ptr<const IDiscreteFunction>)>>(
-                                      [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<3> {
-                                        return sum_of<TinyMatrix<3>>(a);
-                                      }));
-  scheme_module
-    ._addBuiltinFunction("integral_of_R",
-                         std::make_shared<BuiltinFunctionEmbedder<double(std::shared_ptr<const IDiscreteFunction>)>>(
-                           [](std::shared_ptr<const IDiscreteFunction> a) -> double {
-                             return integral_of<double>(a);
-                           }));
+                                             ));
+
+  scheme_module._addBuiltinFunction("sin", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return sin(a); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("cos", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return cos(a); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("tan", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return tan(a); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("asin", std::function(
+
+                                              [](std::shared_ptr<const IDiscreteFunction> a)
+                                                -> std::shared_ptr<const IDiscreteFunction> { return asin(a); }
+
+                                              ));
+
+  scheme_module._addBuiltinFunction("acos", std::function(
+
+                                              [](std::shared_ptr<const IDiscreteFunction> a)
+                                                -> std::shared_ptr<const IDiscreteFunction> { return acos(a); }
+
+                                              ));
+
+  scheme_module._addBuiltinFunction("atan", std::function(
+
+                                              [](std::shared_ptr<const IDiscreteFunction> a)
+                                                -> std::shared_ptr<const IDiscreteFunction> { return atan(a); }
+
+                                              ));
+
+  scheme_module._addBuiltinFunction("atan2", std::function(
+
+                                               [](std::shared_ptr<const IDiscreteFunction> a,
+                                                  std::shared_ptr<const IDiscreteFunction> b)
+                                                 -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); }
+
+                                               ));
+
+  scheme_module._addBuiltinFunction("atan2", std::function(
+
+                                               [](double a, std::shared_ptr<const IDiscreteFunction> b)
+                                                 -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); }
+
+                                               ));
+
+  scheme_module._addBuiltinFunction("atan2",
+                                    std::function(
+
+                                      [](std::shared_ptr<const IDiscreteFunction> a,
+                                         double b) -> std::shared_ptr<const IDiscreteFunction> { return atan2(a, b); }
+
+                                      ));
+
+  scheme_module._addBuiltinFunction("sinh", std::function(
+
+                                              [](std::shared_ptr<const IDiscreteFunction> a)
+                                                -> std::shared_ptr<const IDiscreteFunction> { return sinh(a); }
+
+                                              ));
+
+  scheme_module._addBuiltinFunction("std::function", std::function(
+
+                                                       [](std::shared_ptr<const IDiscreteFunction> a)
+                                                         -> std::shared_ptr<const IDiscreteFunction> { return tanh(a); }
+
+                                                       ));
+
+  scheme_module._addBuiltinFunction("asinh", std::function(
+
+                                               [](std::shared_ptr<const IDiscreteFunction> a)
+                                                 -> std::shared_ptr<const IDiscreteFunction> { return asinh(a); }
+
+                                               ));
+
+  scheme_module._addBuiltinFunction("acosh", std::function(
+
+                                               [](std::shared_ptr<const IDiscreteFunction> a)
+                                                 -> std::shared_ptr<const IDiscreteFunction> { return acosh(a); }
+
+                                               ));
+
+  scheme_module._addBuiltinFunction("atanh", std::function(
+
+                                               [](std::shared_ptr<const IDiscreteFunction> a)
+                                                 -> std::shared_ptr<const IDiscreteFunction> { return atanh(a); }
+
+                                               ));
+
+  scheme_module._addBuiltinFunction("exp", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return exp(a); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("log", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return log(a); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("pow", std::function(
+
+                                             [](double a, std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("pow",
+                                    std::function(
+
+                                      [](std::shared_ptr<const IDiscreteFunction> a,
+                                         double b) -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); }
+
+                                      ));
+
+  scheme_module._addBuiltinFunction("pow", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a,
+                                                std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return pow(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("dot", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a,
+                                                std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("dot", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<1> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("dot", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<2> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("dot", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a, const TinyVector<3>& b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("dot", std::function(
+
+                                             [](const TinyVector<1> a, std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("dot", std::function(
+
+                                             [](const TinyVector<2> a, std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("dot", std::function(
+
+                                             [](const TinyVector<3>& a, std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return dot(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("min", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a) -> double { return min(a); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("min", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a,
+                                                std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("min", std::function(
+
+                                             [](double a, std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("min",
+                                    std::function(
+
+                                      [](std::shared_ptr<const IDiscreteFunction> a,
+                                         double b) -> std::shared_ptr<const IDiscreteFunction> { return min(a, b); }
+
+                                      ));
+
+  scheme_module._addBuiltinFunction("max", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a) -> double { return max(a); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("max", std::function(
+
+                                             [](std::shared_ptr<const IDiscreteFunction> a,
+                                                std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("max", std::function(
+
+                                             [](double a, std::shared_ptr<const IDiscreteFunction> b)
+                                               -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); }
+
+                                             ));
+
+  scheme_module._addBuiltinFunction("max",
+                                    std::function(
+
+                                      [](std::shared_ptr<const IDiscreteFunction> a,
+                                         double b) -> std::shared_ptr<const IDiscreteFunction> { return max(a, b); }
+
+                                      ));
+
+  scheme_module._addBuiltinFunction("sum_of_R", std::function(
+
+                                                  [](std::shared_ptr<const IDiscreteFunction> a) -> double {
+                                                    return sum_of<double>(a);
+                                                  }
+
+                                                  ));
+
+  scheme_module._addBuiltinFunction("sum_of_R1", std::function(
+
+                                                   [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<1> {
+                                                     return sum_of<TinyVector<1>>(a);
+                                                   }
+
+                                                   ));
+
+  scheme_module._addBuiltinFunction("sum_of_R2", std::function(
+
+                                                   [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<2> {
+                                                     return sum_of<TinyVector<2>>(a);
+                                                   }
+
+                                                   ));
+
+  scheme_module._addBuiltinFunction("sum_of_R3", std::function(
+
+                                                   [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<3> {
+                                                     return sum_of<TinyVector<3>>(a);
+                                                   }
+
+                                                   ));
+
+  scheme_module._addBuiltinFunction("sum_of_R1x1", std::function(
+
+                                                     [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<1> {
+                                                       return sum_of<TinyMatrix<1>>(a);
+                                                     }
+
+                                                     ));
+
+  scheme_module._addBuiltinFunction("sum_of_R2x2", std::function(
+
+                                                     [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<2> {
+                                                       return sum_of<TinyMatrix<2>>(a);
+                                                     }
+
+                                                     ));
+
+  scheme_module._addBuiltinFunction("sum_of_R3x3", std::function(
+
+                                                     [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<3> {
+                                                       return sum_of<TinyMatrix<3>>(a);
+                                                     }
+
+                                                     ));
+
+  scheme_module._addBuiltinFunction("integral_of_R", std::function(
+
+                                                       [](std::shared_ptr<const IDiscreteFunction> a) -> double {
+                                                         return integral_of<double>(a);
+                                                       }
+
+                                                       ));
 
   scheme_module._addBuiltinFunction("integral_of_R1",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyVector<1>(std::shared_ptr<const IDiscreteFunction>)>>(
+                                    std::function(
+
                                       [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<1> {
                                         return integral_of<TinyVector<1>>(a);
-                                      }));
+                                      }
+
+                                      ));
 
   scheme_module._addBuiltinFunction("integral_of_R2",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyVector<2>(std::shared_ptr<const IDiscreteFunction>)>>(
+                                    std::function(
+
                                       [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<2> {
                                         return integral_of<TinyVector<2>>(a);
-                                      }));
+                                      }
+
+                                      ));
 
   scheme_module._addBuiltinFunction("integral_of_R3",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyVector<3>(std::shared_ptr<const IDiscreteFunction>)>>(
+                                    std::function(
+
                                       [](std::shared_ptr<const IDiscreteFunction> a) -> TinyVector<3> {
                                         return integral_of<TinyVector<3>>(a);
-                                      }));
+                                      }
+
+                                      ));
 
   scheme_module._addBuiltinFunction("integral_of_R1x1",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyMatrix<1>(std::shared_ptr<const IDiscreteFunction>)>>(
+                                    std::function(
+
                                       [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<1> {
                                         return integral_of<TinyMatrix<1>>(a);
-                                      }));
+                                      }
+
+                                      ));
 
   scheme_module._addBuiltinFunction("integral_of_R2x2",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyMatrix<2>(std::shared_ptr<const IDiscreteFunction>)>>(
+                                    std::function(
+
                                       [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<2> {
                                         return integral_of<TinyMatrix<2>>(a);
-                                      }));
+                                      }
+
+                                      ));
 
   scheme_module._addBuiltinFunction("integral_of_R3x3",
-                                    std::make_shared<
-                                      BuiltinFunctionEmbedder<TinyMatrix<3>(std::shared_ptr<const IDiscreteFunction>)>>(
+                                    std::function(
+
                                       [](std::shared_ptr<const IDiscreteFunction> a) -> TinyMatrix<3> {
                                         return integral_of<TinyMatrix<3>>(a);
-                                      }));
+                                      }
+
+                                      ));
 }
diff --git a/src/language/modules/MathModule.cpp b/src/language/modules/MathModule.cpp
index e73bfc4f5..4e8e10d15 100644
--- a/src/language/modules/MathModule.cpp
+++ b/src/language/modules/MathModule.cpp
@@ -7,99 +7,69 @@
 
 MathModule::MathModule()
 {
-  this->_addBuiltinFunction("sqrt", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                      [](double x) -> double { return std::sqrt(x); }));
+  this->_addBuiltinFunction("sqrt", std::function([](double x) -> double { return std::sqrt(x); }));
 
-  this->_addBuiltinFunction("abs", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                     [](double x) -> double { return std::abs(x); }));
+  this->_addBuiltinFunction("abs", std::function([](double x) -> double { return std::abs(x); }));
 
-  this->_addBuiltinFunction("abs", std::make_shared<BuiltinFunctionEmbedder<uint64_t(int64_t)>>(
-                                     [](int64_t x) -> uint64_t { return std::abs(x); }));
+  this->_addBuiltinFunction("abs", std::function([](int64_t x) -> uint64_t { return std::abs(x); }));
 
-  this->_addBuiltinFunction("sin", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                     [](double x) -> double { return std::sin(x); }));
+  this->_addBuiltinFunction("sin", std::function([](double x) -> double { return std::sin(x); }));
 
-  this->_addBuiltinFunction("cos", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                     [](double x) -> double { return std::cos(x); }));
+  this->_addBuiltinFunction("cos", std::function([](double x) -> double { return std::cos(x); }));
 
-  this->_addBuiltinFunction("tan", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                     [](double x) -> double { return std::tan(x); }));
+  this->_addBuiltinFunction("tan", std::function([](double x) -> double { return std::tan(x); }));
 
-  this->_addBuiltinFunction("asin", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                      [](double x) -> double { return std::asin(x); }));
+  this->_addBuiltinFunction("asin", std::function([](double x) -> double { return std::asin(x); }));
 
-  this->_addBuiltinFunction("acos", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                      [](double x) -> double { return std::acos(x); }));
+  this->_addBuiltinFunction("acos", std::function([](double x) -> double { return std::acos(x); }));
 
-  this->_addBuiltinFunction("atan", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                      [](double x) -> double { return std::atan(x); }));
+  this->_addBuiltinFunction("atan", std::function([](double x) -> double { return std::atan(x); }));
 
-  this->_addBuiltinFunction("atan2", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
-                                       [](double x, double y) -> double { return std::atan2(x, y); }));
+  this->_addBuiltinFunction("atan2", std::function([](double x, double y) -> double { return std::atan2(x, y); }));
 
-  this->_addBuiltinFunction("sinh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                      [](double x) -> double { return std::sinh(x); }));
+  this->_addBuiltinFunction("sinh", std::function([](double x) -> double { return std::sinh(x); }));
 
-  this->_addBuiltinFunction("cosh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                      [](double x) -> double { return std::cosh(x); }));
+  this->_addBuiltinFunction("cosh", std::function([](double x) -> double { return std::cosh(x); }));
 
-  this->_addBuiltinFunction("tanh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                      [](double x) -> double { return std::tanh(x); }));
+  this->_addBuiltinFunction("tanh", std::function([](double x) -> double { return std::tanh(x); }));
 
-  this->_addBuiltinFunction("asinh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                       [](double x) -> double { return std::asinh(x); }));
+  this->_addBuiltinFunction("asinh", std::function([](double x) -> double { return std::asinh(x); }));
 
-  this->_addBuiltinFunction("acosh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                       [](double x) -> double { return std::acosh(x); }));
+  this->_addBuiltinFunction("acosh", std::function([](double x) -> double { return std::acosh(x); }));
 
-  this->_addBuiltinFunction("atanh", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                       [](double x) -> double { return std::atanh(x); }));
+  this->_addBuiltinFunction("atanh", std::function([](double x) -> double { return std::atanh(x); }));
 
-  this->_addBuiltinFunction("exp", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                     [](double x) -> double { return std::exp(x); }));
+  this->_addBuiltinFunction("exp", std::function([](double x) -> double { return std::exp(x); }));
 
-  this->_addBuiltinFunction("log", std::make_shared<BuiltinFunctionEmbedder<double(double)>>(
-                                     [](double x) -> double { return std::log(x); }));
+  this->_addBuiltinFunction("log", std::function([](double x) -> double { return std::log(x); }));
 
-  this->_addBuiltinFunction("pow", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
-                                     [](double x, double y) -> double { return std::pow(x, y); }));
+  this->_addBuiltinFunction("pow", std::function([](double x, double y) -> double { return std::pow(x, y); }));
 
-  this->_addBuiltinFunction("ceil", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
-                                      [](double x) -> int64_t { return std::ceil(x); }));
+  this->_addBuiltinFunction("ceil", std::function([](double x) -> int64_t { return std::ceil(x); }));
 
-  this->_addBuiltinFunction("floor", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
-                                       [](double x) -> int64_t { return std::floor(x); }));
+  this->_addBuiltinFunction("floor", std::function([](double x) -> int64_t { return std::floor(x); }));
 
-  this->_addBuiltinFunction("trunc", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
-                                       [](double x) -> int64_t { return std::trunc(x); }));
+  this->_addBuiltinFunction("trunc", std::function([](double x) -> int64_t { return std::trunc(x); }));
 
-  this->_addBuiltinFunction("round", std::make_shared<BuiltinFunctionEmbedder<int64_t(double)>>(
-                                       [](double x) -> int64_t { return std::lround(x); }));
+  this->_addBuiltinFunction("round", std::function([](double x) -> int64_t { return std::lround(x); }));
 
-  this->_addBuiltinFunction("min", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
-                                     [](double x, double y) -> double { return std::min(x, y); }));
+  this->_addBuiltinFunction("min", std::function([](double x, double y) -> double { return std::min(x, y); }));
 
-  this->_addBuiltinFunction("min", std::make_shared<BuiltinFunctionEmbedder<int64_t(int64_t, int64_t)>>(
-                                     [](int64_t x, int64_t y) -> int64_t { return std::min(x, y); }));
+  this->_addBuiltinFunction("min", std::function([](int64_t x, int64_t y) -> int64_t { return std::min(x, y); }));
 
-  this->_addBuiltinFunction("max", std::make_shared<BuiltinFunctionEmbedder<double(double, double)>>(
-                                     [](double x, double y) -> double { return std::max(x, y); }));
+  this->_addBuiltinFunction("max", std::function([](double x, double y) -> double { return std::max(x, y); }));
 
-  this->_addBuiltinFunction("max", std::make_shared<BuiltinFunctionEmbedder<int64_t(int64_t, int64_t)>>(
-                                     [](int64_t x, int64_t y) -> int64_t { return std::max(x, y); }));
+  this->_addBuiltinFunction("max", std::function([](int64_t x, int64_t y) -> int64_t { return std::max(x, y); }));
 
-  this->_addBuiltinFunction("dot",
-                            std::make_shared<BuiltinFunctionEmbedder<double(const TinyVector<1>, const TinyVector<1>)>>(
-                              [](const TinyVector<1> x, const TinyVector<1> y) -> double { return dot(x, y); }));
+  this->_addBuiltinFunction("dot", std::function(
+                                     [](const TinyVector<1> x, const TinyVector<1> y) -> double { return dot(x, y); }));
 
-  this->_addBuiltinFunction("dot",
-                            std::make_shared<BuiltinFunctionEmbedder<double(const TinyVector<2>, const TinyVector<2>)>>(
-                              [](const TinyVector<2> x, const TinyVector<2> y) -> double { return dot(x, y); }));
+  this->_addBuiltinFunction("dot", std::function(
+                                     [](const TinyVector<2> x, const TinyVector<2> y) -> double { return dot(x, y); }));
 
-  this
-    ->_addBuiltinFunction("dot",
-                          std::make_shared<BuiltinFunctionEmbedder<double(const TinyVector<3>&, const TinyVector<3>&)>>(
-                            [](const TinyVector<3>& x, const TinyVector<3>& y) -> double { return dot(x, y); }));
+  this->_addBuiltinFunction("dot", std::function([](const TinyVector<3>& x, const TinyVector<3>& y) -> double {
+                              return dot(x, y);
+                            }));
 }
 
 void
diff --git a/src/language/modules/MeshModule.cpp b/src/language/modules/MeshModule.cpp
index 485886fdc..4fc75f4f2 100644
--- a/src/language/modules/MeshModule.cpp
+++ b/src/language/modules/MeshModule.cpp
@@ -32,19 +32,17 @@ MeshModule::MeshModule()
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IBoundaryDescriptor>>);
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IZoneDescriptor>>);
 
-  this->_addBuiltinFunction("readGmsh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>(const std::string&)>>(
+  this->_addBuiltinFunction("readGmsh", std::function(
 
-                              [](const std::string& file_name) -> std::shared_ptr<const IMesh> {
-                                GmshReader gmsh_reader(file_name);
-                                return gmsh_reader.mesh();
-                              }
+                                          [](const std::string& file_name) -> std::shared_ptr<const IMesh> {
+                                            GmshReader gmsh_reader(file_name);
+                                            return gmsh_reader.mesh();
+                                          }
 
-                              ));
+                                          ));
 
   this->_addBuiltinFunction("boundaryName",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>(const std::string&)>>(
+                            std::function(
 
                               [](const std::string& boundary_name) -> std::shared_ptr<const IBoundaryDescriptor> {
                                 return std::make_shared<NamedBoundaryDescriptor>(boundary_name);
@@ -52,62 +50,51 @@ MeshModule::MeshModule()
 
                               ));
 
-  this->_addBuiltinFunction("zoneTag",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IZoneDescriptor>(int64_t)>>(
+  this->_addBuiltinFunction("zoneTag", std::function(
 
-                              [](int64_t zone_tag) -> std::shared_ptr<const IZoneDescriptor> {
-                                return std::make_shared<NumberedZoneDescriptor>(zone_tag);
-                              }
+                                         [](int64_t zone_tag) -> std::shared_ptr<const IZoneDescriptor> {
+                                           return std::make_shared<NumberedZoneDescriptor>(zone_tag);
+                                         }
 
-                              ));
+                                         ));
 
-  this->_addBuiltinFunction("zoneName",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IZoneDescriptor>(const std::string&)>>(
+  this->_addBuiltinFunction("zoneName", std::function(
 
-                              [](const std::string& zone_name) -> std::shared_ptr<const IZoneDescriptor> {
-                                return std::make_shared<NamedZoneDescriptor>(zone_name);
-                              }
+                                          [](const std::string& zone_name) -> std::shared_ptr<const IZoneDescriptor> {
+                                            return std::make_shared<NamedZoneDescriptor>(zone_name);
+                                          }
 
-                              ));
+                                          ));
 
-  this->_addBuiltinFunction("boundaryTag",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryDescriptor>(int64_t)>>(
+  this->_addBuiltinFunction("boundaryTag", std::function(
 
-                              [](int64_t boundary_tag) -> std::shared_ptr<const IBoundaryDescriptor> {
-                                return std::make_shared<NumberedBoundaryDescriptor>(boundary_tag);
-                              }
+                                             [](int64_t boundary_tag) -> std::shared_ptr<const IBoundaryDescriptor> {
+                                               return std::make_shared<NumberedBoundaryDescriptor>(boundary_tag);
+                                             }
 
-                              ));
+                                             ));
 
-  this->_addBuiltinFunction("transform",
-                            std::make_shared<BuiltinFunctionEmbedder<
-                              std::shared_ptr<const IMesh>(std::shared_ptr<const IMesh>, const FunctionSymbolId&)>>(
+  this->_addBuiltinFunction("transform", std::function(
 
-                              [](std::shared_ptr<const IMesh> p_mesh,
-                                 const FunctionSymbolId& function_id) -> std::shared_ptr<const IMesh> {
-                                return MeshTransformer{}.transform(function_id, p_mesh);
-                              }
+                                           [](std::shared_ptr<const IMesh> p_mesh,
+                                              const FunctionSymbolId& function_id) -> std::shared_ptr<const IMesh> {
+                                             return MeshTransformer{}.transform(function_id, p_mesh);
+                                           }
 
-                              ));
+                                           ));
 
-  this->_addBuiltinFunction("relax",
-                            std::make_shared<BuiltinFunctionEmbedder<
-                              std::shared_ptr<const IMesh>(const std::shared_ptr<const IMesh>&,
-                                                           const std::shared_ptr<const IMesh>&, const double&)>>(
+  this->_addBuiltinFunction("relax", std::function(
 
-                              [](const std::shared_ptr<const IMesh>& source_mesh,
-                                 const std::shared_ptr<const IMesh>& destination_mesh,
-                                 const double& theta) -> std::shared_ptr<const IMesh> {
-                                return MeshRelaxer{}.relax(source_mesh, destination_mesh, theta);
-                              }
+                                       [](const std::shared_ptr<const IMesh>& source_mesh,
+                                          const std::shared_ptr<const IMesh>& destination_mesh,
+                                          const double& theta) -> std::shared_ptr<const IMesh> {
+                                         return MeshRelaxer{}.relax(source_mesh, destination_mesh, theta);
+                                       }
 
-                              ));
+                                       ));
 
   this->_addBuiltinFunction("cartesianMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IMesh>(const TinyVector<1>, const TinyVector<1>, const std::vector<uint64_t>&)>>(
+                            std::function(
 
                               [](const TinyVector<1> a, const TinyVector<1> b,
                                  const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
@@ -133,8 +120,7 @@ MeshModule::MeshModule()
                               ));
 
   this->_addBuiltinFunction("cartesianMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IMesh>(const TinyVector<2>, const TinyVector<2>, const std::vector<uint64_t>&)>>(
+                            std::function(
 
                               [](const TinyVector<2> a, const TinyVector<2> b,
                                  const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
@@ -160,8 +146,7 @@ MeshModule::MeshModule()
                               ));
 
   this->_addBuiltinFunction("cartesianMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IMesh>(const TinyVector<3>&, const TinyVector<3>&, const std::vector<uint64_t>&)>>(
+                            std::function(
 
                               [](const TinyVector<3>& a, const TinyVector<3>& b,
                                  const std::vector<uint64_t>& box_sizes) -> std::shared_ptr<const IMesh> {
@@ -187,8 +172,7 @@ MeshModule::MeshModule()
                               ));
 
   this->_addBuiltinFunction("diamondDual",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>(
-                              const std::shared_ptr<const IMesh>&)>>(
+                            std::function(
 
                               [](const std::shared_ptr<const IMesh>& i_mesh) -> std::shared_ptr<const IMesh> {
                                 switch (i_mesh->dimension()) {
@@ -219,8 +203,7 @@ MeshModule::MeshModule()
                               ));
 
   this->_addBuiltinFunction("medianDual",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IMesh>(
-                              const std::shared_ptr<const IMesh>&)>>(
+                            std::function(
 
                               [](const std::shared_ptr<const IMesh>& i_mesh) -> std::shared_ptr<const IMesh> {
                                 switch (i_mesh->dimension()) {
diff --git a/src/language/modules/SchemeModule.cpp b/src/language/modules/SchemeModule.cpp
index bc744e4d3..01dcc66eb 100644
--- a/src/language/modules/SchemeModule.cpp
+++ b/src/language/modules/SchemeModule.cpp
@@ -48,56 +48,49 @@ SchemeModule::SchemeModule()
 
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IBoundaryConditionDescriptor>>);
 
-  this->_addBuiltinFunction("P0", std::make_shared<
-                                    BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunctionDescriptor>()>>(
+  this->_addBuiltinFunction("P0", std::function(
+
                                     []() -> std::shared_ptr<const IDiscreteFunctionDescriptor> {
                                       return std::make_shared<DiscreteFunctionDescriptorP0>();
                                     }
 
                                     ));
 
-  this->_addBuiltinFunction("P0Vector",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunctionDescriptor>()>>(
-                              []() -> std::shared_ptr<const IDiscreteFunctionDescriptor> {
-                                return std::make_shared<DiscreteFunctionDescriptorP0Vector>();
-                              }
+  this->_addBuiltinFunction("P0Vector", std::function(
 
-                              ));
+                                          []() -> std::shared_ptr<const IDiscreteFunctionDescriptor> {
+                                            return std::make_shared<DiscreteFunctionDescriptorP0Vector>();
+                                          }
+
+                                          ));
+
+  this->_addBuiltinFunction("Gauss", std::function(
 
-  this->_addBuiltinFunction("Gauss", std::make_shared<
-                                       BuiltinFunctionEmbedder<std::shared_ptr<const IQuadratureDescriptor>(uint64_t)>>(
                                        [](uint64_t degree) -> std::shared_ptr<const IQuadratureDescriptor> {
                                          return std::make_shared<GaussQuadratureDescriptor>(degree);
                                        }
 
                                        ));
 
-  this->_addBuiltinFunction("GaussLobatto",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IQuadratureDescriptor>(uint64_t)>>(
-                              [](uint64_t degree) -> std::shared_ptr<const IQuadratureDescriptor> {
-                                return std::make_shared<GaussLobattoQuadratureDescriptor>(degree);
-                              }
+  this->_addBuiltinFunction("GaussLobatto", std::function(
 
-                              ));
+                                              [](uint64_t degree) -> std::shared_ptr<const IQuadratureDescriptor> {
+                                                return std::make_shared<GaussLobattoQuadratureDescriptor>(degree);
+                                              }
 
-  this->_addBuiltinFunction("GaussLegendre",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const IQuadratureDescriptor>(uint64_t)>>(
-                              [](uint64_t degree) -> std::shared_ptr<const IQuadratureDescriptor> {
-                                return std::make_shared<GaussLegendreQuadratureDescriptor>(degree);
-                              }
+                                              ));
 
-                              ));
+  this->_addBuiltinFunction("GaussLegendre", std::function(
+
+                                               [](uint64_t degree) -> std::shared_ptr<const IQuadratureDescriptor> {
+                                                 return std::make_shared<GaussLegendreQuadratureDescriptor>(degree);
+                                               }
+
+                                               ));
 
   this->_addBuiltinFunction("integrate",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IDiscreteFunction>(std::shared_ptr<const IMesh>,
-                                                       const std::vector<std::shared_ptr<const IZoneDescriptor>>&,
-                                                       std::shared_ptr<const IQuadratureDescriptor>,
-                                                       std::shared_ptr<const IDiscreteFunctionDescriptor>,
-                                                       const std::vector<FunctionSymbolId>&)>>(
+                            std::function(
+
                               [](std::shared_ptr<const IMesh> mesh,
                                  const std::vector<std::shared_ptr<const IZoneDescriptor>>& integration_zone_list,
                                  std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor,
@@ -112,30 +105,25 @@ SchemeModule::SchemeModule()
 
                               ));
 
-  this
-    ->_addBuiltinFunction("integrate",
-                          std::make_shared<BuiltinFunctionEmbedder<
-                            std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IMesh>,
-                                                                     std::shared_ptr<const IQuadratureDescriptor>,
-                                                                     std::shared_ptr<const IDiscreteFunctionDescriptor>,
-                                                                     const std::vector<FunctionSymbolId>&)>>(
-                            [](std::shared_ptr<const IMesh> mesh,
-                               std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor,
-                               std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor,
-                               const std::vector<FunctionSymbolId>& function_id_list)
-                              -> std::shared_ptr<const IDiscreteFunction> {
-                              return DiscreteFunctionVectorIntegrator{mesh, quadrature_descriptor,
-                                                                      discrete_function_descriptor, function_id_list}
-                                .integrate();
-                            }
+  this->_addBuiltinFunction("integrate",
+                            std::function(
 
-                            ));
+                              [](std::shared_ptr<const IMesh> mesh,
+                                 std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor,
+                                 std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor,
+                                 const std::vector<FunctionSymbolId>& function_id_list)
+                                -> std::shared_ptr<const IDiscreteFunction> {
+                                return DiscreteFunctionVectorIntegrator{mesh, quadrature_descriptor,
+                                                                        discrete_function_descriptor, function_id_list}
+                                  .integrate();
+                              }
+
+                              ));
 
   this->_addBuiltinFunction(
     "integrate",
-    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-      const IDiscreteFunction>(std::shared_ptr<const IMesh>, const std::vector<std::shared_ptr<const IZoneDescriptor>>&,
-                               std::shared_ptr<const IQuadratureDescriptor>, const FunctionSymbolId&)>>(
+    std::function(
+
       [](std::shared_ptr<const IMesh> mesh,
          const std::vector<std::shared_ptr<const IZoneDescriptor>>& integration_zone_list,
          std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor,
@@ -146,10 +134,8 @@ SchemeModule::SchemeModule()
       ));
 
   this->_addBuiltinFunction("integrate",
-                            std::make_shared<BuiltinFunctionEmbedder<
-                              std::shared_ptr<const IDiscreteFunction>(std::shared_ptr<const IMesh>,
-                                                                       std::shared_ptr<const IQuadratureDescriptor>,
-                                                                       const FunctionSymbolId&)>>(
+                            std::function(
+
                               [](std::shared_ptr<const IMesh> mesh,
                                  std::shared_ptr<const IQuadratureDescriptor> quadrature_descriptor,
                                  const FunctionSymbolId& function_id) -> std::shared_ptr<const IDiscreteFunction> {
@@ -159,11 +145,8 @@ SchemeModule::SchemeModule()
                               ));
 
   this->_addBuiltinFunction("interpolate",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IDiscreteFunction>(std::shared_ptr<const IMesh>,
-                                                       const std::vector<std::shared_ptr<const IZoneDescriptor>>&,
-                                                       std::shared_ptr<const IDiscreteFunctionDescriptor>,
-                                                       const std::vector<FunctionSymbolId>&)>>(
+                            std::function(
+
                               [](std::shared_ptr<const IMesh> mesh,
                                  const std::vector<std::shared_ptr<const IZoneDescriptor>>& interpolation_zone_list,
                                  std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor,
@@ -194,9 +177,8 @@ SchemeModule::SchemeModule()
 
   this->_addBuiltinFunction(
     "interpolate",
-    std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-      const IDiscreteFunction>(std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunctionDescriptor>,
-                               const std::vector<FunctionSymbolId>&)>>(
+    std::function(
+
       [](std::shared_ptr<const IMesh> mesh,
          std::shared_ptr<const IDiscreteFunctionDescriptor> discrete_function_descriptor,
          const std::vector<FunctionSymbolId>& function_id_list) -> std::shared_ptr<const IDiscreteFunction> {
@@ -219,9 +201,7 @@ SchemeModule::SchemeModule()
       ));
 
   this->_addBuiltinFunction("randomizeMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IMesh>(std::shared_ptr<const IMesh>,
-                                           const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&)>>(
+                            std::function(
 
                               [](std::shared_ptr<const IMesh> p_mesh,
                                  const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
@@ -233,10 +213,7 @@ SchemeModule::SchemeModule()
                               ));
 
   this->_addBuiltinFunction("randomizeMesh",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IMesh>(std::shared_ptr<const IMesh>,
-                                           const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&,
-                                           const FunctionSymbolId&)>>(
+                            std::function(
 
                               [](std::shared_ptr<const IMesh> p_mesh,
                                  const std::vector<std::shared_ptr<const IBoundaryConditionDescriptor>>&
@@ -248,74 +225,59 @@ SchemeModule::SchemeModule()
 
                               ));
 
-  this
-    ->_addBuiltinFunction("fixed",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryConditionDescriptor>(
-                            std::shared_ptr<const IBoundaryDescriptor>)>>(
+  this->_addBuiltinFunction("fixed", std::function(
 
-                            [](std::shared_ptr<const IBoundaryDescriptor> boundary)
-                              -> std::shared_ptr<const IBoundaryConditionDescriptor> {
-                              return std::make_shared<FixedBoundaryConditionDescriptor>(boundary);
-                            }
+                                       [](std::shared_ptr<const IBoundaryDescriptor> boundary)
+                                         -> std::shared_ptr<const IBoundaryConditionDescriptor> {
+                                         return std::make_shared<FixedBoundaryConditionDescriptor>(boundary);
+                                       }
 
-                            ));
+                                       ));
 
-  this
-    ->_addBuiltinFunction("axis",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryConditionDescriptor>(
-                            std::shared_ptr<const IBoundaryDescriptor>)>>(
+  this->_addBuiltinFunction("axis", std::function(
 
-                            [](std::shared_ptr<const IBoundaryDescriptor> boundary)
-                              -> std::shared_ptr<const IBoundaryConditionDescriptor> {
-                              return std::make_shared<AxisBoundaryConditionDescriptor>(boundary);
-                            }
+                                      [](std::shared_ptr<const IBoundaryDescriptor> boundary)
+                                        -> std::shared_ptr<const IBoundaryConditionDescriptor> {
+                                        return std::make_shared<AxisBoundaryConditionDescriptor>(boundary);
+                                      }
 
-                            ));
+                                      ));
 
-  this
-    ->_addBuiltinFunction("symmetry",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IBoundaryConditionDescriptor>(
-                            std::shared_ptr<const IBoundaryDescriptor>)>>(
+  this->_addBuiltinFunction("symmetry", std::function(
 
-                            [](std::shared_ptr<const IBoundaryDescriptor> boundary)
-                              -> std::shared_ptr<const IBoundaryConditionDescriptor> {
-                              return std::make_shared<SymmetryBoundaryConditionDescriptor>(boundary);
-                            }
+                                          [](std::shared_ptr<const IBoundaryDescriptor> boundary)
+                                            -> std::shared_ptr<const IBoundaryConditionDescriptor> {
+                                            return std::make_shared<SymmetryBoundaryConditionDescriptor>(boundary);
+                                          }
 
-                            ));
+                                          ));
 
-  this->_addBuiltinFunction("pressure",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IBoundaryConditionDescriptor>(std::shared_ptr<const IBoundaryDescriptor>,
-                                                                  const FunctionSymbolId&)>>(
+  this->_addBuiltinFunction("pressure", std::function(
 
-                              [](std::shared_ptr<const IBoundaryDescriptor> boundary,
-                                 const FunctionSymbolId& pressure_id)
-                                -> std::shared_ptr<const IBoundaryConditionDescriptor> {
-                                return std::make_shared<DirichletBoundaryConditionDescriptor>("pressure", boundary,
-                                                                                              pressure_id);
-                              }
+                                          [](std::shared_ptr<const IBoundaryDescriptor> boundary,
+                                             const FunctionSymbolId& pressure_id)
+                                            -> std::shared_ptr<const IBoundaryConditionDescriptor> {
+                                            return std::make_shared<DirichletBoundaryConditionDescriptor>("pressure",
+                                                                                                          boundary,
+                                                                                                          pressure_id);
+                                          }
 
-                              ));
+                                          ));
 
-  this->_addBuiltinFunction("velocity",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IBoundaryConditionDescriptor>(std::shared_ptr<const IBoundaryDescriptor>,
-                                                                  const FunctionSymbolId&)>>(
+  this->_addBuiltinFunction("velocity", std::function(
 
-                              [](std::shared_ptr<const IBoundaryDescriptor> boundary,
-                                 const FunctionSymbolId& velocity_id)
-                                -> std::shared_ptr<const IBoundaryConditionDescriptor> {
-                                return std::make_shared<DirichletBoundaryConditionDescriptor>("velocity", boundary,
-                                                                                              velocity_id);
-                              }
+                                          [](std::shared_ptr<const IBoundaryDescriptor> boundary,
+                                             const FunctionSymbolId& velocity_id)
+                                            -> std::shared_ptr<const IBoundaryConditionDescriptor> {
+                                            return std::make_shared<DirichletBoundaryConditionDescriptor>("velocity",
+                                                                                                          boundary,
+                                                                                                          velocity_id);
+                                          }
 
-                              ));
+                                          ));
 
   this->_addBuiltinFunction("external_fsi_velocity",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<
-                              const IBoundaryConditionDescriptor>(std::shared_ptr<const IBoundaryDescriptor>,
-                                                                  const std::shared_ptr<const Socket>&)>>(
+                            std::function(
 
                               [](std::shared_ptr<const IBoundaryDescriptor> boundary,
                                  const std::shared_ptr<const Socket>& socket)
@@ -327,17 +289,7 @@ SchemeModule::SchemeModule()
                               ));
 
   this->_addBuiltinFunction("glace_solver",
-                            std::make_shared<BuiltinFunctionEmbedder<std::tuple<
-                              std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunction>,
-                              std::shared_ptr<const IDiscreteFunction>,
-                              std::shared_ptr<const IDiscreteFunction>>(const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::vector<std::shared_ptr<
-                                                                          const IBoundaryConditionDescriptor>>&,
-                                                                        const double&)>>(
+                            std::function(
 
                               [](const std::shared_ptr<const IDiscreteFunction>& rho,
                                  const std::shared_ptr<const IDiscreteFunction>& u,
@@ -363,17 +315,7 @@ SchemeModule::SchemeModule()
                               ));
 
   this->_addBuiltinFunction("eucclhyd_solver",
-                            std::make_shared<BuiltinFunctionEmbedder<std::tuple<
-                              std::shared_ptr<const IMesh>, std::shared_ptr<const IDiscreteFunction>,
-                              std::shared_ptr<const IDiscreteFunction>,
-                              std::shared_ptr<const IDiscreteFunction>>(const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::shared_ptr<const IDiscreteFunction>&,
-                                                                        const std::vector<std::shared_ptr<
-                                                                          const IBoundaryConditionDescriptor>>&,
-                                                                        const double&)>>(
+                            std::function(
 
                               [](const std::shared_ptr<const IDiscreteFunction>& rho,
                                  const std::shared_ptr<const IDiscreteFunction>& u,
@@ -398,21 +340,17 @@ SchemeModule::SchemeModule()
 
                               ));
 
-  this
-    ->_addBuiltinFunction("lagrangian",
-                          std::make_shared<BuiltinFunctionEmbedder<
-                            std::shared_ptr<const IDiscreteFunction>(const std::shared_ptr<const IMesh>&,
-                                                                     const std::shared_ptr<const IDiscreteFunction>&)>>(
+  this->_addBuiltinFunction("lagrangian",
+                            std::function(
 
-                            [](const std::shared_ptr<const IMesh>& mesh,
-                               const std::shared_ptr<const IDiscreteFunction>& v)
-                              -> std::shared_ptr<const IDiscreteFunction> { return shallowCopy(mesh, v); }
+                              [](const std::shared_ptr<const IMesh>& mesh,
+                                 const std::shared_ptr<const IDiscreteFunction>& v)
+                                -> std::shared_ptr<const IDiscreteFunction> { return shallowCopy(mesh, v); }
 
-                            ));
+                              ));
 
   this->_addBuiltinFunction("acoustic_dt",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<double(const std::shared_ptr<const IDiscreteFunction>&)>>(
+                            std::function(
 
                               [](const std::shared_ptr<const IDiscreteFunction>& c) -> double { return acoustic_dt(c); }
 
@@ -420,8 +358,7 @@ SchemeModule::SchemeModule()
 
   this
     ->_addBuiltinFunction("cell_volume",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IDiscreteFunction>(
-                            const std::shared_ptr<const IMesh>&)>>(
+                          std::function(
 
                             [](const std::shared_ptr<const IMesh>& i_mesh) -> std::shared_ptr<const IDiscreteFunction> {
                               switch (i_mesh->dimension()) {
diff --git a/src/language/modules/SocketModule.cpp b/src/language/modules/SocketModule.cpp
index 0540af2b6..426a56137 100644
--- a/src/language/modules/SocketModule.cpp
+++ b/src/language/modules/SocketModule.cpp
@@ -11,7 +11,7 @@ SocketModule::SocketModule()
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const Socket>>);
 
   this->_addBuiltinFunction("createSocketServer",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const Socket>(const uint64_t&)>>(
+                            std::function(
 
                               [](const uint64_t& port_number) -> std::shared_ptr<const Socket> {
                                 return std::make_shared<const Socket>(createServerSocket(port_number));
@@ -20,8 +20,7 @@ SocketModule::SocketModule()
                               ));
 
   this->_addBuiltinFunction("acceptSocketClient",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<std::shared_ptr<const Socket>(std::shared_ptr<const Socket>)>>(
+                            std::function(
 
                               [](std::shared_ptr<const Socket> server_socket) -> std::shared_ptr<const Socket> {
                                 return std::make_shared<const Socket>(acceptClientSocket(*server_socket));
@@ -30,8 +29,7 @@ SocketModule::SocketModule()
                               ));
 
   this->_addBuiltinFunction("connectSocketServer",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const Socket>(const std::string&,
-                                                                                                   const uint64_t&)>>(
+                            std::function(
 
                               [](const std::string& hostname,
                                  const uint64_t& port_number) -> std::shared_ptr<const Socket> {
@@ -40,88 +38,74 @@ SocketModule::SocketModule()
 
                               ));
 
-  this->_addBuiltinFunction("write",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const bool&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket, const bool& value) -> void {
-                                write(*socket, value);
-                              }
+                                       [](const std::shared_ptr<const Socket>& socket, const bool& value) -> void {
+                                         write(*socket, value);
+                                       }
 
-                              ));
+                                       ));
 
-  this->_addBuiltinFunction("write",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const uint64_t&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket, const uint64_t& value) -> void {
-                                write(*socket, value);
-                              }
+                                       [](const std::shared_ptr<const Socket>& socket, const uint64_t& value) -> void {
+                                         write(*socket, value);
+                                       }
 
-                              ));
+                                       ));
 
-  this->_addBuiltinFunction("write",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const int64_t&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket, const int64_t& value) -> void {
-                                write(*socket, value);
-                              }
+                                       [](const std::shared_ptr<const Socket>& socket, const int64_t& value) -> void {
+                                         write(*socket, value);
+                                       }
 
-                              ));
+                                       ));
 
-  this->_addBuiltinFunction("write",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const double&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket, const double& value) -> void {
-                                write(*socket, value);
-                              }
+                                       [](const std::shared_ptr<const Socket>& socket, const double& value) -> void {
+                                         write(*socket, value);
+                                       }
 
-                              ));
+                                       ));
 
-  this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
-                                                                                   const TinyVector<1>&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
                                        [](const std::shared_ptr<const Socket>& socket,
                                           const TinyVector<1>& value) -> void { write(*socket, value); }
 
                                        ));
 
-  this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
-                                                                                   const TinyVector<2>&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
                                        [](const std::shared_ptr<const Socket>& socket,
                                           const TinyVector<2>& value) -> void { write(*socket, value); }
 
                                        ));
 
-  this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
-                                                                                   const TinyVector<3>&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
                                        [](const std::shared_ptr<const Socket>& socket,
                                           const TinyVector<3>& value) -> void { write(*socket, value); }
 
                                        ));
 
-  this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
-                                                                                   const TinyMatrix<1>&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
                                        [](const std::shared_ptr<const Socket>& socket,
                                           const TinyMatrix<1>& value) -> void { write(*socket, value); }
 
                                        ));
 
-  this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
-                                                                                   const TinyMatrix<2>&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
                                        [](const std::shared_ptr<const Socket>& socket,
                                           const TinyMatrix<2>& value) -> void { write(*socket, value); }
 
                                        ));
 
-  this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&,
-                                                                                   const TinyMatrix<3>&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
                                        [](const std::shared_ptr<const Socket>& socket,
                                           const TinyMatrix<3>& value) -> void { write(*socket, value); }
@@ -129,8 +113,7 @@ SocketModule::SocketModule()
                                        ));
 
   this->_addBuiltinFunction("write",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<void(const std::shared_ptr<const Socket>&, const std::string&)>>(
+                            std::function(
 
                               [](const std::shared_ptr<const Socket>& socket, const std::string& value) -> void {
                                 write(*socket, value.size());
@@ -139,56 +122,51 @@ SocketModule::SocketModule()
 
                               ));
 
-  this->_addBuiltinFunction("read_B",
-                            std::make_shared<BuiltinFunctionEmbedder<bool(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_B", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket) -> bool {
-                                bool value;
-                                read(*socket, value);
+                                        [](const std::shared_ptr<const Socket>& socket) -> bool {
+                                          bool value;
+                                          read(*socket, value);
 
-                                return value;
-                              }
+                                          return value;
+                                        }
 
-                              ));
+                                        ));
 
-  this->_addBuiltinFunction("read_N",
-                            std::make_shared<BuiltinFunctionEmbedder<uint64_t(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_N", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket) -> uint64_t {
-                                uint64_t value;
-                                read(*socket, value);
+                                        [](const std::shared_ptr<const Socket>& socket) -> uint64_t {
+                                          uint64_t value;
+                                          read(*socket, value);
 
-                                return value;
-                              }
+                                          return value;
+                                        }
 
-                              ));
+                                        ));
 
-  this->_addBuiltinFunction("read_Z",
-                            std::make_shared<BuiltinFunctionEmbedder<int64_t(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_Z", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket) -> int64_t {
-                                int64_t value;
-                                read(*socket, value);
+                                        [](const std::shared_ptr<const Socket>& socket) -> int64_t {
+                                          int64_t value;
+                                          read(*socket, value);
 
-                                return value;
-                              }
+                                          return value;
+                                        }
 
-                              ));
+                                        ));
 
-  this->_addBuiltinFunction("read_R",
-                            std::make_shared<BuiltinFunctionEmbedder<double(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_R", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket) -> double {
-                                double value;
-                                read(*socket, value);
+                                        [](const std::shared_ptr<const Socket>& socket) -> double {
+                                          double value;
+                                          read(*socket, value);
 
-                                return value;
-                              }
+                                          return value;
+                                        }
 
-                              ));
+                                        ));
 
-  this->_addBuiltinFunction("read_R1", std::make_shared<
-                                         BuiltinFunctionEmbedder<TinyVector<1>(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_R1", std::function(
 
                                          [](const std::shared_ptr<const Socket>& socket) -> TinyVector<1> {
                                            TinyVector<1> value;
@@ -199,8 +177,7 @@ SocketModule::SocketModule()
 
                                          ));
 
-  this->_addBuiltinFunction("read_R2", std::make_shared<
-                                         BuiltinFunctionEmbedder<TinyVector<2>(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_R2", std::function(
 
                                          [](const std::shared_ptr<const Socket>& socket) -> TinyVector<2> {
                                            TinyVector<2> value;
@@ -211,8 +188,7 @@ SocketModule::SocketModule()
 
                                          ));
 
-  this->_addBuiltinFunction("read_R3", std::make_shared<
-                                         BuiltinFunctionEmbedder<TinyVector<3>(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_R3", std::function(
 
                                          [](const std::shared_ptr<const Socket>& socket) -> TinyVector<3> {
                                            TinyVector<3> value;
@@ -223,61 +199,53 @@ SocketModule::SocketModule()
 
                                          ));
 
-  this->_addBuiltinFunction("read_R1x1",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<TinyMatrix<1>(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_R1x1", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<1> {
-                                TinyMatrix<1> value;
-                                read(*socket, value);
+                                           [](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<1> {
+                                             TinyMatrix<1> value;
+                                             read(*socket, value);
 
-                                return value;
-                              }
+                                             return value;
+                                           }
 
-                              ));
+                                           ));
 
-  this->_addBuiltinFunction("read_R2x2",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<TinyMatrix<2>(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_R2x2", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<2> {
-                                TinyMatrix<2> value;
-                                read(*socket, value);
+                                           [](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<2> {
+                                             TinyMatrix<2> value;
+                                             read(*socket, value);
 
-                                return value;
-                              }
+                                             return value;
+                                           }
 
-                              ));
+                                           ));
 
-  this->_addBuiltinFunction("read_R3x3",
-                            std::make_shared<
-                              BuiltinFunctionEmbedder<TinyMatrix<3>(const std::shared_ptr<const Socket>&)>>(
+  this->_addBuiltinFunction("read_R3x3", std::function(
 
-                              [](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<3> {
-                                TinyMatrix<3> value;
-                                read(*socket, value);
+                                           [](const std::shared_ptr<const Socket>& socket) -> TinyMatrix<3> {
+                                             TinyMatrix<3> value;
+                                             read(*socket, value);
 
-                                return value;
-                              }
+                                             return value;
+                                           }
 
-                              ));
+                                           ));
 
-  this
-    ->_addBuiltinFunction("read_string",
-                          std::make_shared<BuiltinFunctionEmbedder<std::string(const std::shared_ptr<const Socket>&)>>(
-
-                            [](const std::shared_ptr<const Socket>& socket) -> std::string {
-                              size_t size;
-                              read(*socket, size);
-                              std::string value;
-                              if (size > 0) {
-                                value.resize(size);
-                                read(*socket, value);
-                              }
-                              return value;
-                            }
+  this->_addBuiltinFunction("read_string", std::function(
+
+                                             [](const std::shared_ptr<const Socket>& socket) -> std::string {
+                                               size_t size;
+                                               read(*socket, size);
+                                               std::string value;
+                                               if (size > 0) {
+                                                 value.resize(size);
+                                                 read(*socket, value);
+                                               }
+                                               return value;
+                                             }
 
-                            ));
+                                             ));
 }
 
 void
diff --git a/src/language/modules/WriterModule.cpp b/src/language/modules/WriterModule.cpp
index a1eebb3ed..89d25001b 100644
--- a/src/language/modules/WriterModule.cpp
+++ b/src/language/modules/WriterModule.cpp
@@ -20,64 +20,59 @@ WriterModule::WriterModule()
 
   this->_addTypeDescriptor(ast_node_data_type_from<std::shared_ptr<const IWriter>>);
 
-  this
-    ->_addBuiltinFunction("vtk_writer",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IWriter>(const std::string&)>>(
+  this->_addBuiltinFunction("vtk_writer", std::function(
 
-                            [](const std::string& filename) { return std::make_shared<VTKWriter>(filename); }
+                                            [](const std::string& filename) -> std::shared_ptr<const IWriter> {
+                                              return std::make_shared<VTKWriter>(filename);
+                                            }
 
-                            ));
+                                            ));
 
   this->_addBuiltinFunction("vtk_writer",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IWriter>(const std::string&,
-                                                                                                    const double&)>>(
+                            std::function(
 
-                              [](const std::string& filename, const double& period) {
+                              [](const std::string& filename, const double& period) -> std::shared_ptr<const IWriter> {
                                 return std::make_shared<VTKWriter>(filename, period);
                               }
 
                               ));
 
-  this
-    ->_addBuiltinFunction("gnuplot_writer",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IWriter>(const std::string&)>>(
+  this->_addBuiltinFunction("gnuplot_writer", std::function(
 
-                            [](const std::string& filename) { return std::make_shared<GnuplotWriter>(filename); }
+                                                [](const std::string& filename) -> std::shared_ptr<const IWriter> {
+                                                  return std::make_shared<GnuplotWriter>(filename);
+                                                }
 
-                            ));
+                                                ));
 
   this->_addBuiltinFunction("gnuplot_writer",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IWriter>(const std::string&,
-                                                                                                    const double&)>>(
+                            std::function(
 
-                              [](const std::string& filename, const double& period) {
+                              [](const std::string& filename, const double& period) -> std::shared_ptr<const IWriter> {
                                 return std::make_shared<GnuplotWriter>(filename, period);
                               }
 
                               ));
 
-  this
-    ->_addBuiltinFunction("gnuplot_1d_writer",
-                          std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IWriter>(const std::string&)>>(
+  this->_addBuiltinFunction("gnuplot_1d_writer", std::function(
 
-                            [](const std::string& filename) { return std::make_shared<GnuplotWriter1D>(filename); }
+                                                   [](const std::string& filename) -> std::shared_ptr<const IWriter> {
+                                                     return std::make_shared<GnuplotWriter1D>(filename);
+                                                   }
 
-                            ));
+                                                   ));
 
   this->_addBuiltinFunction("gnuplot_1d_writer",
-                            std::make_shared<BuiltinFunctionEmbedder<std::shared_ptr<const IWriter>(const std::string&,
-                                                                                                    const double&)>>(
+                            std::function(
 
-                              [](const std::string& filename, const double& period) {
+                              [](const std::string& filename, const double& period) -> std::shared_ptr<const IWriter> {
                                 return std::make_shared<GnuplotWriter1D>(filename, period);
                               }
 
                               ));
 
   this->_addBuiltinFunction("name_output",
-                            std::make_shared<BuiltinFunctionEmbedder<
-                              std::shared_ptr<const NamedDiscreteFunction>(std::shared_ptr<const IDiscreteFunction>,
-                                                                           const std::string&)>>(
+                            std::function(
 
                               [](std::shared_ptr<const IDiscreteFunction> discrete_function,
                                  const std::string& name) -> std::shared_ptr<const NamedDiscreteFunction> {
@@ -87,8 +82,7 @@ WriterModule::WriterModule()
                               ));
 
   this->_addBuiltinFunction("write_mesh",
-                            std::make_shared<BuiltinFunctionEmbedder<void(std::shared_ptr<const IWriter>,
-                                                                          std::shared_ptr<const IMesh>)>>(
+                            std::function(
 
                               [](std::shared_ptr<const IWriter> writer, std::shared_ptr<const IMesh> p_mesh) -> void {
                                 writer->writeMesh(p_mesh);
@@ -96,9 +90,7 @@ WriterModule::WriterModule()
 
                               ));
 
-  this->_addBuiltinFunction("write", std::make_shared<BuiltinFunctionEmbedder<
-                                       void(std::shared_ptr<const IWriter>,
-                                            const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
                                        [](std::shared_ptr<const IWriter> writer,
                                           const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&
@@ -108,33 +100,27 @@ WriterModule::WriterModule()
 
                                        ));
 
-  this->_addBuiltinFunction("write",
-                            std::make_shared<BuiltinFunctionEmbedder<
-                              void(std::shared_ptr<const IWriter>,
-                                   const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&, const double&)>>(
+  this->_addBuiltinFunction("write", std::function(
 
-                              [](std::shared_ptr<const IWriter> writer,
-                                 const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&
-                                   named_discrete_function_list,
-                                 const double& time) -> void {
-                                writer->writeIfNeeded(named_discrete_function_list, time);
-                              }
+                                       [](std::shared_ptr<const IWriter> writer,
+                                          const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&
+                                            named_discrete_function_list,
+                                          const double& time) -> void {
+                                         writer->writeIfNeeded(named_discrete_function_list, time);
+                                       }
 
-                              ));
+                                       ));
 
-  this->_addBuiltinFunction("force_write",
-                            std::make_shared<BuiltinFunctionEmbedder<
-                              void(std::shared_ptr<const IWriter>,
-                                   const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&, const double&)>>(
+  this->_addBuiltinFunction("force_write", std::function(
 
-                              [](std::shared_ptr<const IWriter> writer,
-                                 const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&
-                                   named_discrete_function_list,
-                                 const double& time) -> void {
-                                writer->writeForced(named_discrete_function_list, time);
-                              }
+                                             [](std::shared_ptr<const IWriter> writer,
+                                                const std::vector<std::shared_ptr<const NamedDiscreteFunction>>&
+                                                  named_discrete_function_list,
+                                                const double& time) -> void {
+                                               writer->writeForced(named_discrete_function_list, time);
+                                             }
 
-                              ));
+                                             ));
 }
 
 void
diff --git a/tests/test_BuiltinFunctionEmbedder.cpp b/tests/test_BuiltinFunctionEmbedder.cpp
index 51b2462b4..3e9b5192e 100644
--- a/tests/test_BuiltinFunctionEmbedder.cpp
+++ b/tests/test_BuiltinFunctionEmbedder.cpp
@@ -293,7 +293,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
     };
 
     std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c = std::make_unique<
-      BuiltinFunctionEmbedder<std::tuple<double, TinyVector<2>, std::shared_ptr<double>>(double, double)>>(c);
+      BuiltinFunctionEmbedder<std::tuple<double, TinyVector<2>, std::shared_ptr<const double>>(double, double)>>(c);
 
     const double a = 3.2;
     const double b = 1.5;
@@ -323,7 +323,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
     };
 
     std::unique_ptr<IBuiltinFunctionEmbedder> i_embedded_c =
-      std::make_unique<BuiltinFunctionEmbedder<std::tuple<uint64_t, double, std::shared_ptr<double>>(void)>>(c);
+      std::make_unique<BuiltinFunctionEmbedder<std::tuple<uint64_t, double, std::shared_ptr<const double>>(void)>>(c);
 
     REQUIRE(1ul == std::get<0>(c()));
     REQUIRE(3.5 == std::get<1>(c()));
@@ -339,7 +339,7 @@ TEST_CASE("BuiltinFunctionEmbedder", "[language]")
 
     REQUIRE(*data_type.contentTypeList()[0] == ASTNodeDataType::unsigned_int_t);
     REQUIRE(*data_type.contentTypeList()[1] == ASTNodeDataType::double_t);
-    REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<double>>);
+    REQUIRE(*data_type.contentTypeList()[2] == ast_node_data_type_from<std::shared_ptr<const double>>);
   }
 
   SECTION("void(void) BuiltinFunctionEmbedder")
diff --git a/tests/test_BuiltinFunctionEmbedderTable.cpp b/tests/test_BuiltinFunctionEmbedderTable.cpp
index e07875526..17a51370c 100644
--- a/tests/test_BuiltinFunctionEmbedderTable.cpp
+++ b/tests/test_BuiltinFunctionEmbedderTable.cpp
@@ -21,7 +21,8 @@ TEST_CASE("BuiltinFunctionEmbedderTable", "[language]")
   REQUIRE(table.size() == 1);
 
   std::shared_ptr<IBuiltinFunctionEmbedder> embedded_greater =
-    std::make_shared<BuiltinFunctionEmbedder<bool(int, int)>>([](int i, int j) -> bool { return i > j; });
+    std::make_shared<BuiltinFunctionEmbedder<bool(int64_t, int64_t)>>(
+      [](int64_t i, int64_t j) -> bool { return i > j; });
   table.add(embedded_greater);
 
   REQUIRE(table.size() == 2);
-- 
GitLab