diff --git a/src/language/ASTModulesImporter.cpp b/src/language/ASTModulesImporter.cpp
index edf68606681775f72d430f3ff806e3be8699e928..e15268ec1d4859342b4cf89eb22ed2d8861a54eb 100644
--- a/src/language/ASTModulesImporter.cpp
+++ b/src/language/ASTModulesImporter.cpp
@@ -17,7 +17,20 @@ ASTModulesImporter::_importModule(ASTNode& import_node)
   std::cout << " * importing '" << rang::fgB::green << module_name << rang::style::reset << "' module\n";
 
   if (module_name == "math") {
-    std::cout << rang::fgB::red << "importing math module NIY!" << rang::style::reset << '\n';
+    std::string symbol_name{"sin"};
+
+    auto [i_symbol, success] = m_symbol_table.add(symbol_name, import_node.begin());
+
+    if (not success) {
+      std::ostringstream error_message;
+      error_message << "cannot add symbol '" << symbol_name << "' it is already defined";
+      throw parse_error(error_message.str(), import_node.begin());
+    }
+
+    i_symbol->attributes().setDataType(ASTNodeDataType::c_function_t);
+    i_symbol->attributes().setIsInitialized();
+    i_symbol->attributes().value() = static_cast<uint64_t>(0);
+
   } else {
     throw parse_error(std::string{"could not find module "} + module_name, std::vector{module_name_node.begin()});
   }
@@ -35,7 +48,7 @@ ASTModulesImporter::_importAllModules(ASTNode& node)
   }
 }
 
-ASTModulesImporter::ASTModulesImporter(ASTNode& root_node)
+ASTModulesImporter::ASTModulesImporter(ASTNode& root_node) : m_symbol_table{*root_node.m_symbol_table}
 {
   Assert(root_node.is_root());
   this->_importAllModules(root_node);
diff --git a/src/language/ASTModulesImporter.hpp b/src/language/ASTModulesImporter.hpp
index 1d9c49c738e132ab8955b9e7d53b05ff6c3c1376..13e91ce5d2ad6042fb1940968978394545a48cef 100644
--- a/src/language/ASTModulesImporter.hpp
+++ b/src/language/ASTModulesImporter.hpp
@@ -3,8 +3,12 @@
 
 #include <ASTNode.hpp>
 
+class SymbolTable;
+
 class ASTModulesImporter
 {
+  SymbolTable& m_symbol_table;
+
   void _importModule(ASTNode& import_node);
   void _importAllModules(ASTNode& node);
 
diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.cpp b/src/language/ASTNodeCFunctionExpressionBuilder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..02ab715f8c0f6deb16fc97421b46553dc9c66c45
--- /dev/null
+++ b/src/language/ASTNodeCFunctionExpressionBuilder.cpp
@@ -0,0 +1,16 @@
+#include <ASTNodeCFunctionExpressionBuilder.hpp>
+#include <PEGGrammar.hpp>
+
+#include <FunctionTable.hpp>
+#include <SymbolTable.hpp>
+
+ASTNodeCFunctionExpressionBuilder::ASTNodeCFunctionExpressionBuilder(ASTNode& node)
+{
+  auto [i_function_symbol, found] = node.m_symbol_table->find(node.children[0]->string(), node.begin());
+  Assert(found);
+  Assert(i_function_symbol->attributes().dataType() == ASTNodeDataType::c_function_t);
+
+  //  uint64_t function_id = std::get<uint64_t>(i_function_symbol->attributes().value());
+
+  throw parse_error("CFunction processor not implemented yet", node.begin());
+}
diff --git a/src/language/ASTNodeCFunctionExpressionBuilder.hpp b/src/language/ASTNodeCFunctionExpressionBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ca40e4718de2a1d2a1486b963b17621b63af7e04
--- /dev/null
+++ b/src/language/ASTNodeCFunctionExpressionBuilder.hpp
@@ -0,0 +1,13 @@
+#ifndef AST_NODE_C_FUNCTION_EXPRESSION_BUILDER_HPP
+#define AST_NODE_C_FUNCTION_EXPRESSION_BUILDER_HPP
+
+#include <ASTNode.hpp>
+#include <node_processor/INodeProcessor.hpp>
+
+class ASTNodeCFunctionExpressionBuilder
+{
+ public:
+  ASTNodeCFunctionExpressionBuilder(ASTNode& node);
+};
+
+#endif   // AST_NODE_C_FUNCTION_EXPRESSION_BUILDER_HPP
diff --git a/src/language/ASTNodeDataType.cpp b/src/language/ASTNodeDataType.cpp
index 1220df563cc9ec5685bc68dfaaa791062c086efb..bd935e1fcaff79be6b648da5c452441e8a7a026d 100644
--- a/src/language/ASTNodeDataType.cpp
+++ b/src/language/ASTNodeDataType.cpp
@@ -29,6 +29,9 @@ dataTypeName(const ASTNodeDataType& data_type)
   case ASTNodeDataType::function_t:
     name = "function";
     break;
+  case ASTNodeDataType::c_function_t:
+    name = "c_function";
+    break;
   case ASTNodeDataType::void_t:
     name = "void";
     break;
diff --git a/src/language/ASTNodeDataType.hpp b/src/language/ASTNodeDataType.hpp
index daabf0c0ec78ab9bf22c4f0dc52f1f20b78bcbf9..71669327dbdf496ba630c90cc3d23cbb062d87d7 100644
--- a/src/language/ASTNodeDataType.hpp
+++ b/src/language/ASTNodeDataType.hpp
@@ -14,6 +14,7 @@ enum class ASTNodeDataType : int32_t
   string_t       = 5,
   typename_t     = 10,
   function_t     = 11,
+  c_function_t   = 12,
   void_t         = std::numeric_limits<int32_t>::max()
 };
 
diff --git a/src/language/ASTNodeDataTypeBuilder.cpp b/src/language/ASTNodeDataTypeBuilder.cpp
index b90b5b00554612a8c0b14094aa2df1fd5fd40ab1..eed6bba4660fa340a2069e6dd13297306eda5ad9 100644
--- a/src/language/ASTNodeDataTypeBuilder.cpp
+++ b/src/language/ASTNodeDataTypeBuilder.cpp
@@ -219,46 +219,51 @@ ASTNodeDataTypeBuilder::_buildNodeDataTypes(ASTNode& n)
         throw parse_error(message.str(), n.begin());
       }
     } else if (n.is<language::function_evaluation>()) {
-      if (n.children[0]->m_data_type != ASTNodeDataType::function_t) {
-        std::ostringstream message;
-        message << "invalid function call\n"
-                << "note: '" << n.children[0]->string() << "' is not a function!" << std::ends;
-        throw parse_error(message.str(), n.begin());
-      }
-
-      const std::string& function_name  = n.children[0]->string();
-      auto [i_function_symbol, success] = n.m_symbol_table->find(function_name, n.children[0]->begin());
+      if (n.children[0]->m_data_type == ASTNodeDataType::function_t) {
+        const std::string& function_name  = n.children[0]->string();
+        auto [i_function_symbol, success] = n.m_symbol_table->find(function_name, n.children[0]->begin());
 
-      auto& function_table = n.m_symbol_table->functionTable();
+        auto& function_table = n.m_symbol_table->functionTable();
 
-      uint64_t function_id                    = std::get<uint64_t>(i_function_symbol->attributes().value());
-      FunctionDescriptor& function_descriptor = function_table[function_id];
+        uint64_t function_id                    = std::get<uint64_t>(i_function_symbol->attributes().value());
+        FunctionDescriptor& function_descriptor = function_table[function_id];
 
-      ASTNode& image_domain_node = *function_descriptor.domainMappingNode().children[1];
+        ASTNode& image_domain_node = *function_descriptor.domainMappingNode().children[1];
 
-      Assert(image_domain_node.m_data_type == ASTNodeDataType::typename_t);
+        Assert(image_domain_node.m_data_type == ASTNodeDataType::typename_t);
 
-      ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
-      if (image_domain_node.children.size() > 0) {
-        std::ostringstream message;
-        throw parse_error("compound data type is not implemented yet", image_domain_node.begin());
-      } else {
-        if (image_domain_node.is<language::B_set>()) {
-          data_type = ASTNodeDataType::bool_t;
-        } else if (image_domain_node.is<language::Z_set>()) {
-          data_type = ASTNodeDataType::int_t;
-        } else if (image_domain_node.is<language::N_set>()) {
-          data_type = ASTNodeDataType::unsigned_int_t;
-        } else if (image_domain_node.is<language::R_set>()) {
-          data_type = ASTNodeDataType::double_t;
-        } else if (image_domain_node.is<language::string_type>()) {
-          data_type = ASTNodeDataType::string_t;
+        ASTNodeDataType data_type{ASTNodeDataType::undefined_t};
+        if (image_domain_node.children.size() > 0) {
+          std::ostringstream message;
+          throw parse_error("compound data type is not implemented yet", image_domain_node.begin());
+        } else {
+          if (image_domain_node.is<language::B_set>()) {
+            data_type = ASTNodeDataType::bool_t;
+          } else if (image_domain_node.is<language::Z_set>()) {
+            data_type = ASTNodeDataType::int_t;
+          } else if (image_domain_node.is<language::N_set>()) {
+            data_type = ASTNodeDataType::unsigned_int_t;
+          } else if (image_domain_node.is<language::R_set>()) {
+            data_type = ASTNodeDataType::double_t;
+          } else if (image_domain_node.is<language::string_type>()) {
+            data_type = ASTNodeDataType::string_t;
+          }
         }
-      }
 
-      Assert(data_type != ASTNodeDataType::undefined_t);   // LCOV_EXCL_LINE
+        Assert(data_type != ASTNodeDataType::undefined_t);   // LCOV_EXCL_LINE
 
-      n.m_data_type = data_type;
+        n.m_data_type = data_type;
+      } else if (n.children[0]->m_data_type == ASTNodeDataType::c_function_t) {
+        std::cout << __FILE__ << ':' << __LINE__ << ": " << rang::fgB::red << "datatype is incorrectly defined!"
+                  << rang::style::reset << '\n';
+        n.m_data_type = ASTNodeDataType::double_t;
+      } else {
+        std::ostringstream message;
+        message << "invalid function call\n"
+                << "note: '" << n.children[0]->string() << "' (type: " << dataTypeName(n.children[0]->m_data_type)
+                << ") is not a function!" << std::ends;
+        throw parse_error(message.str(), n.begin());
+      }
     } else if (n.is<language::B_set>() or n.is<language::Z_set>() or n.is<language::N_set>() or
                n.is<language::R_set>() or n.is<language::string_type>()) {
       n.m_data_type = ASTNodeDataType::typename_t;
diff --git a/src/language/ASTNodeExpressionBuilder.cpp b/src/language/ASTNodeExpressionBuilder.cpp
index 516307662a1c16b4674ed0dad2dc2f36592108e7..66aab7283864ddb01aa1007a3279fc5c40a1f128 100644
--- a/src/language/ASTNodeExpressionBuilder.cpp
+++ b/src/language/ASTNodeExpressionBuilder.cpp
@@ -2,7 +2,7 @@
 
 #include <ASTNodeAffectationExpressionBuilder.hpp>
 #include <ASTNodeBinaryOperatorExpressionBuilder.hpp>
-#include <ASTNodeFunctionExpressionBuilder.hpp>
+#include <ASTNodeFunctionEvaluationExpressionBuilder.hpp>
 #include <ASTNodeIncDecExpressionBuilder.hpp>
 #include <ASTNodeUnaryOperatorExpressionBuilder.hpp>
 
@@ -32,7 +32,7 @@ ASTNodeExpressionBuilder::_buildExpression(ASTNode& n)
     n.m_node_processor = std::make_unique<FakeProcessor>();
 
   } else if (n.is<language::function_evaluation>()) {
-    ASTNodeFunctionExpressionBuilder{n};
+    ASTNodeFunctionEvaluationExpressionBuilder{n};
 
   } else if (n.is<language::real>()) {
     n.m_node_processor = std::make_unique<FakeProcessor>();
diff --git a/src/language/ASTNodeFunctionEvaluationExpressionBuilder.cpp b/src/language/ASTNodeFunctionEvaluationExpressionBuilder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fa4798b3d3715f09eb3d0d050e09c820748cdb9d
--- /dev/null
+++ b/src/language/ASTNodeFunctionEvaluationExpressionBuilder.cpp
@@ -0,0 +1,26 @@
+#include <ASTNodeFunctionEvaluationExpressionBuilder.hpp>
+
+#include <ASTNodeCFunctionExpressionBuilder.hpp>
+#include <ASTNodeFunctionExpressionBuilder.hpp>
+
+#include <SymbolTable.hpp>
+
+ASTNodeFunctionEvaluationExpressionBuilder::ASTNodeFunctionEvaluationExpressionBuilder(ASTNode& node)
+{
+  auto [i_function_symbol, found] = node.m_symbol_table->find(node.children[0]->string(), node.begin());
+  Assert(found);
+
+  switch (i_function_symbol->attributes().dataType()) {
+  case ASTNodeDataType::function_t: {
+    ASTNodeFunctionExpressionBuilder{node};
+    break;
+  }
+  case ASTNodeDataType::c_function_t: {
+    ASTNodeCFunctionExpressionBuilder{node};
+    break;
+  }
+  default: {
+    throw parse_error("unexpected function type", node.begin());
+  }
+  }
+}
diff --git a/src/language/ASTNodeFunctionEvaluationExpressionBuilder.hpp b/src/language/ASTNodeFunctionEvaluationExpressionBuilder.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..889dd627ae0829804ed9f168654b8e596d09a269
--- /dev/null
+++ b/src/language/ASTNodeFunctionEvaluationExpressionBuilder.hpp
@@ -0,0 +1,11 @@
+#ifndef AST_NODE_FUNCTION_EVALUATION_EXPRESSION_BUILDER_HPP
+#define AST_NODE_FUNCTION_EVALUATION_EXPRESSION_BUILDER_HPP
+
+#include <ASTNode.hpp>
+
+struct ASTNodeFunctionEvaluationExpressionBuilder
+{
+  ASTNodeFunctionEvaluationExpressionBuilder(ASTNode& node);
+};
+
+#endif   // AST_NODE_FUNCTION_EVALUATION_EXPRESSION_BUILDER_HPP
diff --git a/src/language/ASTNodeFunctionExpressionBuilder.cpp b/src/language/ASTNodeFunctionExpressionBuilder.cpp
index 3f8259dab73e5e8d1b898d0bedfd6cc58dfd783f..910bd31264745164646d9e74f413961bb06b87e0 100644
--- a/src/language/ASTNodeFunctionExpressionBuilder.cpp
+++ b/src/language/ASTNodeFunctionExpressionBuilder.cpp
@@ -158,6 +158,8 @@ ASTNodeFunctionExpressionBuilder::ASTNodeFunctionExpressionBuilder(ASTNode& node
 {
   auto [i_function_symbol, found] = node.m_symbol_table->find(node.children[0]->string(), node.begin());
   Assert(found);
+  Assert(i_function_symbol->attributes().dataType() == ASTNodeDataType::function_t);
+
   uint64_t function_id = std::get<uint64_t>(i_function_symbol->attributes().value());
 
   FunctionDescriptor& function_descriptor = node.m_symbol_table->functionTable()[function_id];
diff --git a/src/language/CMakeLists.txt b/src/language/CMakeLists.txt
index 5c6cc784b1b3bfb8568c9fbd65b4b99e41e8e9db..b88c971c4fdcb1a75514f85109710d8dfa649f06 100644
--- a/src/language/CMakeLists.txt
+++ b/src/language/CMakeLists.txt
@@ -12,6 +12,7 @@ add_library(
   ASTModulesImporter.cpp
   ASTNodeAffectationExpressionBuilder.cpp
   ASTNodeBinaryOperatorExpressionBuilder.cpp
+  ASTNodeCFunctionExpressionBuilder.cpp
   ASTNodeDataType.cpp
   ASTNodeDataTypeBuilder.cpp
   ASTNodeDataTypeChecker.cpp
@@ -19,6 +20,7 @@ add_library(
   ASTNodeEmptyBlockCleaner.cpp
   ASTNodeExpressionBuilder.cpp
   ASTNodeFunctionExpressionBuilder.cpp
+  ASTNodeFunctionEvaluationExpressionBuilder.cpp
   ASTNodeIncDecExpressionBuilder.cpp
   ASTNodeJumpPlacementChecker.cpp
   ASTNodeUnaryOperatorExpressionBuilder.cpp