From b945815a225c3efdef5df03af52f921f98f9ed90 Mon Sep 17 00:00:00 2001
From: A404M <ahmadmahmoudiprogrammer@gmail.com>
Date: Sat, 25 Jan 2025 20:53:59 +0330
Subject: add function call

---
 src/compiler/ast-tree.c       | 133 ++++++++++++++++++++++++++++++++++++++++--
 src/compiler/ast-tree.h       |  20 +++++++
 src/compiler/code-generator.c |  59 +++++++++++++++----
 src/compiler/code-generator.h |  14 ++++-
 src/compiler/parser.c         | 109 ++++++++++++++++++++++++++--------
 src/compiler/parser.h         |   9 ++-
 src/main.c                    |   2 +-
 test/main.felan               |   9 ++-
 8 files changed, 309 insertions(+), 46 deletions(-)

diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 0a8811c..8cbfaf5 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -4,6 +4,7 @@
 #include "utils/memory.h"
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 const char *AST_TREE_TOKEN_STRINGS[] = {
     "AST_TREE_TOKEN_FUNCTION",  "AST_TREE_TOKEN_KEYWORD_PRINT",
@@ -71,6 +72,33 @@ void astTreePrint(const AstTree *tree, int indent) {
     printf("]");
   }
     goto RETURN_SUCCESS;
+  case AST_TREE_TOKEN_FUNCTION_CALL: {
+    AstTreeFunctionCall *metadata = tree->metadata;
+    printf(",\n");
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+    printf("function=\n");
+    astTreePrint(metadata->function, indent + 1);
+    printf(",\n");
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+    printf("paramters=[\n");
+    for (size_t i = 0; i < metadata->parameters_size; ++i) {
+      astTreePrint(metadata->parameters[i], indent + 1);
+      printf(",\n");
+    }
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+    printf("]");
+  }
+    goto RETURN_SUCCESS;
+  case AST_TREE_TOKEN_IDENTIFIER: {
+    AstTreeIdentifier *metadata = tree->metadata;
+    printf(",variable.name=%.*s",
+           (int)(metadata->name_end - metadata->name_begin),
+           metadata->name_begin);
+  }
+    goto RETURN_SUCCESS;
   case AST_TREE_TOKEN_NONE:
   }
 
@@ -105,6 +133,7 @@ void astTreeDestroy(AstTree tree) {
     return;
   case AST_TREE_TOKEN_KEYWORD_PRINT:
   case AST_TREE_TOKEN_TYPE_VOID:
+  case AST_TREE_TOKEN_IDENTIFIER:
     return;
   case AST_TREE_TOKEN_TYPE_FUNCTION: {
     AstTreeTypeFunction *metadata = tree.metadata;
@@ -116,6 +145,15 @@ void astTreeDestroy(AstTree tree) {
     free(metadata);
   }
     return;
+  case AST_TREE_TOKEN_FUNCTION_CALL: {
+    AstTreeFunctionCall *metadata = tree.metadata;
+    for (size_t i = 0; i < metadata->parameters_size; ++i) {
+      astTreeDelete(metadata->parameters[i]);
+    }
+    free(metadata->parameters);
+    free(metadata);
+  }
+    return;
   case AST_TREE_TOKEN_NONE:
     break;
   }
@@ -182,9 +220,14 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
     ParserNode *node = (ParserNodeEOLMetadata *)nodes->data[i]->metadata;
     ParserNodeVariableMetadata *node_metadata = node->metadata;
 
-    AstTree *type = astTreeParse(node_metadata->type, &root->variables, 1);
-    if (type == NULL) {
-      goto RETURN_ERROR;
+    AstTree *type;
+    if (node_metadata->type != NULL) {
+      type = astTreeParse(node_metadata->type, &root->variables, 1);
+      if (type == NULL) {
+        goto RETURN_ERROR;
+      }
+    } else {
+      type = NULL; // TODO: change this to find type
     }
 
     AstTree *value = astTreeParse(node_metadata->value, &root->variables, 1);
@@ -192,7 +235,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
       goto RETURN_ERROR;
     }
 
-    if (!hasTypeOf(value, type)) {
+    // TODO: then delete type != NULL
+    if (type != NULL && !hasTypeOf(value, type)) {
       printLog("Type mismatch");
       goto RETURN_ERROR;
     }
@@ -220,6 +264,24 @@ void pushVariable(AstTreeVariables *variables, size_t *variables_size,
   variables->size += 1;
 }
 
+AstTreeVariable *getVariable(AstTreeVariables *variables, size_t variables_size,
+                             char *name_begin, char *name_end) {
+  for (size_t i = 0; i < variables_size; ++i) {
+    AstTreeVariables vars = variables[i];
+    for (size_t j = 0; j < vars.size; ++j) {
+      char *var_begin = vars.data[j]->name_begin;
+      char *var_end = vars.data[j]->name_end;
+
+      if (name_end - name_begin == var_end - var_begin &&
+          strncmp(var_begin, name_begin, name_end - name_begin) == 0) {
+        return vars.data[j];
+      }
+    }
+  }
+
+  return NULL;
+}
+
 AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables,
                       size_t variables_size) {
   switch (parserNode->token) {
@@ -231,12 +293,15 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables,
     return astTreeParseTypeFunction(parserNode, variables, variables_size);
   case PARSER_TOKEN_TYPE_VOID:
     return newAstTree(AST_TREE_TOKEN_TYPE_VOID, NULL);
+  case PARSER_TOKEN_FUNCTION_CALL:
+    return astTreeParseFunctionCall(parserNode, variables, variables_size);
+  case PARSER_TOKEN_IDENTIFIER:
+    return astTreeParseIdentifier(parserNode, variables, variables_size);
   case PARSER_TOKEN_SYMBOL_EOL:
   case PARSER_TOKEN_SYMBOL_PARENTHESIS:
   case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
   case PARSER_TOKEN_SYMBOL_COMMA:
   case PARSER_TOKEN_CONSTANT:
-  case PARSER_TOKEN_IDENTIFIER:
   case PARSER_TOKEN_NONE:
   case PARSER_TOKEN_ROOT:
   }
@@ -390,6 +455,60 @@ RETURN_ERROR:
   return NULL;
 }
 
+AstTree *astTreeParseFunctionCall(ParserNode *parserNode,
+                                  AstTreeVariables *variables,
+                                  size_t variables_size) {
+  ParserNodeFunctionCall *node_metadata = parserNode->metadata;
+  AstTree *function =
+      astTreeParse(node_metadata->function, variables, variables_size);
+  if (function == NULL) {
+    return NULL;
+  }
+  if (function->token != AST_TREE_TOKEN_IDENTIFIER) {
+    printLog("Not yet supported");
+    return NULL;
+  }
+  // TODO: check types here
+
+  AstTreeFunctionCall *metadata = a404m_malloc(sizeof(*metadata));
+  metadata->function = function;
+
+  metadata->parameters =
+      a404m_malloc(sizeof(*metadata->parameters) * node_metadata->params->size);
+  metadata->parameters_size = node_metadata->params->size;
+
+  for (size_t i = 0; i < metadata->parameters_size; ++i) {
+    printLog("Not impelemented yet");
+    exit(1);
+    if ((metadata->parameters[i] = astTreeParse(node_metadata->params->data[i],
+                                                variables, variables_size)) ==
+            NULL ||
+        hasTypeOf(metadata->parameters[i], function->metadata)) {
+      goto RETURN_ERROR;
+    }
+  }
+
+  return newAstTree(AST_TREE_TOKEN_FUNCTION_CALL, metadata);
+RETURN_ERROR:
+  for (size_t i = 0; i < metadata->parameters_size; ++i) {
+    astTreeDelete(metadata->parameters[i]);
+  }
+  free(metadata->parameters);
+  return NULL;
+}
+
+AstTree *astTreeParseIdentifier(ParserNode *parserNode,
+                                AstTreeVariables *variables,
+                                size_t variables_size) {
+  AstTreeVariable *var = getVariable(
+      variables, variables_size, parserNode->str_begin, parserNode->str_end);
+  if (var == NULL) {
+    printLog("Variable not found");
+    return NULL;
+  }
+  return newAstTree(AST_TREE_TOKEN_IDENTIFIER, (AstTreeIdentifier *)var);
+}
+
 bool hasTypeOf(AstTree *value, AstTree *type) {
   switch (type->token) {
   case AST_TREE_TOKEN_TYPE_FUNCTION:
@@ -411,6 +530,8 @@ bool hasTypeOf(AstTree *value, AstTree *type) {
     case AST_TREE_TOKEN_KEYWORD_PRINT:
     case AST_TREE_TOKEN_TYPE_FUNCTION:
     case AST_TREE_TOKEN_TYPE_VOID:
+    case AST_TREE_TOKEN_FUNCTION_CALL:
+    case AST_TREE_TOKEN_IDENTIFIER:
       return false;
     case AST_TREE_TOKEN_NONE:
     }
@@ -418,6 +539,8 @@ bool hasTypeOf(AstTree *value, AstTree *type) {
   case AST_TREE_TOKEN_FUNCTION:
   case AST_TREE_TOKEN_KEYWORD_PRINT:
   case AST_TREE_TOKEN_TYPE_VOID:
+  case AST_TREE_TOKEN_FUNCTION_CALL:
+  case AST_TREE_TOKEN_IDENTIFIER:
     return false;
   case AST_TREE_TOKEN_NONE:
   }
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 23f0b9c..ae97ca2 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -8,6 +8,8 @@ typedef enum AstTreeToken {
   AST_TREE_TOKEN_KEYWORD_PRINT,
   AST_TREE_TOKEN_TYPE_FUNCTION,
   AST_TREE_TOKEN_TYPE_VOID,
+  AST_TREE_TOKEN_FUNCTION_CALL,
+  AST_TREE_TOKEN_IDENTIFIER,
   AST_TREE_TOKEN_NONE,
 } AstTreeToken;
 
@@ -52,6 +54,14 @@ typedef struct AstTreeTypeFunction {
   AstTree *returnType;
 } AstTreeTypeFunction;
 
+typedef struct AstTreeFunctionCall {
+  AstTree *function;
+  AstTree **parameters;
+  size_t parameters_size;
+} AstTreeFunctionCall;
+
+typedef AstTreeVariable AstTreeIdentifier;
+
 extern const char *AST_TREE_TOKEN_STRINGS[];
 
 void astTreePrint(const AstTree *tree, int indent);
@@ -67,6 +77,8 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot);
 
 void pushVariable(AstTreeVariables *variables, size_t *variables_size,
                   AstTreeVariable *variable);
+AstTreeVariable *getVariable(AstTreeVariables *variables, size_t variables_size,
+                             char *name_begin, char *name_end);
 
 AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables *variables,
                       size_t variables_size);
@@ -79,5 +91,13 @@ AstTree *astTreeParseTypeFunction(ParserNode *parserNode,
                                   AstTreeVariables *variables,
                                   size_t variables_size);
 
+AstTree *astTreeParseFunctionCall(ParserNode *parserNode,
+                                  AstTreeVariables *variables,
+                                  size_t variables_size);
+
+AstTree *astTreeParseIdentifier(ParserNode *parserNode,
+                                AstTreeVariables *variables,
+                                size_t variables_size);
+
 bool hasTypeOf(AstTree *value, AstTree *type);
 bool typeIsEqual(AstTree *type0, AstTree *type1);
diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c
index 035a471..c07bab5 100644
--- a/src/compiler/code-generator.c
+++ b/src/compiler/code-generator.c
@@ -2,6 +2,7 @@
 #include "compiler/ast-tree.h"
 #include "utils/log.h"
 #include "utils/memory.h"
+#include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -15,11 +16,13 @@ void codeGeneratorDelete(CodeGeneratorCodes *code) {
 }
 
 CodeGeneratorCode createGenerateCode(char *label_begin, char *label_end,
-                                     CodeGeneratorInstruction instruction) {
+                                     CodeGeneratorInstruction instruction,
+                                     void *metadata) {
   CodeGeneratorCode code = {
       .label_begin = label_begin,
       .label_end = label_end,
       .instruction = instruction,
+      .metadata = metadata,
   };
   return code;
 }
@@ -55,19 +58,19 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) {
     AstTreeVariable *variable = astTreeRoot->variables.data[i];
     switch (variable->value->token) {
     case AST_TREE_TOKEN_FUNCTION:
-      codeGeneratorAstTreeFunction(variable->name_begin, variable->name_end,
-                                   *variable->value, codes);
+      if (!codeGeneratorAstTreeFunction(variable->name_begin,
+                                        variable->name_end, *variable->value,
+                                        codes)) {
+        return NULL;
+      }
       continue;
     case AST_TREE_TOKEN_KEYWORD_PRINT:
-      generateCodePushCode(
-          codes,
-          createGenerateCode(NULL, NULL, CODE_GENERATOR_INSTRUCTION_PRINT));
-      continue;
     case AST_TREE_TOKEN_TYPE_FUNCTION:
     case AST_TREE_TOKEN_TYPE_VOID:
     case AST_TREE_TOKEN_NONE:
     }
     printLog("Bad token %d", variable->value->token);
+    return NULL;
   }
 
   return codes;
@@ -84,8 +87,30 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end,
     case AST_TREE_TOKEN_KEYWORD_PRINT:
       generateCodePushCode(
           codes, createGenerateCode(label_begin, label_end,
-                                    CODE_GENERATOR_INSTRUCTION_PRINT));
+                                    CODE_GENERATOR_INSTRUCTION_PRINT, NULL));
+      goto OK;
+    case AST_TREE_TOKEN_FUNCTION_CALL: {
+      AstTreeFunctionCall *metadata = tree.metadata;
+      AstTree *function = metadata->function;
+      if (metadata->parameters_size != 0) {
+        printLog("Not implemented");
+        exit(0);
+      }
+      if (function->token != AST_TREE_TOKEN_IDENTIFIER) {
+        printLog("Not implemented");
+        exit(0);
+      }
+      AstTreeIdentifier *function_metadata = function->metadata;
+      CodeGeneratorCall *callMetadata = a404m_malloc(sizeof(*callMetadata));
+      callMetadata->label_begin = function_metadata->name_begin;
+      callMetadata->label_end = function_metadata->name_end;
+      generateCodePushCode(codes,
+                           createGenerateCode(label_begin, label_end,
+                                              CODE_GENERATOR_INSTRUCTION_CALL,
+                                              callMetadata));
+    }
       goto OK;
+    case AST_TREE_TOKEN_IDENTIFIER:
     case AST_TREE_TOKEN_FUNCTION:
     case AST_TREE_TOKEN_TYPE_FUNCTION:
     case AST_TREE_TOKEN_TYPE_VOID:
@@ -98,9 +123,9 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end,
     label_end = NULL;
   }
 
-  generateCodePushCode(codes,
-                       createGenerateCode(label_begin, label_end,
-                                          CODE_GENERATOR_INSTRUCTION_RET));
+  generateCodePushCode(codes, createGenerateCode(label_begin, label_end,
+                                                 CODE_GENERATOR_INSTRUCTION_RET,
+                                                 NULL));
 
   return true;
 }
@@ -154,6 +179,18 @@ char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes) {
                                         strlen(INST));
     }
       continue;
+    case CODE_GENERATOR_INSTRUCTION_CALL: {
+      CodeGeneratorCall *metadata = code.metadata;
+      constexpr char CALL_INST[] = "call ";
+      codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted,
+                                        CALL_INST, strlen(CALL_INST));
+      codeGeneratorAppendFlatASMCommand(
+          &fasm, &fasm_size, &fasm_inserted, metadata->label_begin,
+          metadata->label_end - metadata->label_begin);
+      codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, "\n",
+                                        1);
+    }
+      continue;
     case CODE_GENERATOR_INSTRUCTION_RET: {
       constexpr char INST[] = "ret\n";
       codeGeneratorAppendFlatASMCommand(&fasm, &fasm_size, &fasm_inserted, INST,
diff --git a/src/compiler/code-generator.h b/src/compiler/code-generator.h
index f9ac6c9..94552ed 100644
--- a/src/compiler/code-generator.h
+++ b/src/compiler/code-generator.h
@@ -6,6 +6,7 @@
 
 typedef enum CodeGeneratorInstruction : uint8_t {
   CODE_GENERATOR_INSTRUCTION_PRINT,
+  CODE_GENERATOR_INSTRUCTION_CALL,
   CODE_GENERATOR_INSTRUCTION_RET,
 } CodeGeneratorInstruction;
 
@@ -13,8 +14,14 @@ typedef struct CodeGeneratorCode {
   char *label_begin;
   char *label_end;
   CodeGeneratorInstruction instruction;
+  void *metadata;
 } CodeGeneratorCode;
 
+typedef struct CodeGeneratorCall {
+  char *label_begin;
+  char *label_end;
+} CodeGeneratorCall;
+
 typedef struct CodeGeneratorCodes {
   CodeGeneratorCode *codes;
   size_t codes_size;
@@ -23,7 +30,7 @@ typedef struct CodeGeneratorCodes {
 void codeGeneratorDelete(CodeGeneratorCodes *code);
 
 CodeGeneratorCode createGenerateCode(char *label_begin, char *label_end,
-                                   CodeGeneratorInstruction instruction);
+                                     CodeGeneratorInstruction instruction,void *metadata);
 
 CodeGeneratorCode *newGenerateCode(char *label_begin, char *label_end,
                                    CodeGeneratorInstruction instruction);
@@ -32,8 +39,9 @@ void generateCodePushCode(CodeGeneratorCodes *codes, CodeGeneratorCode code);
 
 CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot);
 
-bool codeGeneratorAstTreeFunction(char *label_begin,char *label_end,AstTree astTree, CodeGeneratorCodes *codes);
+bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end,
+                                  AstTree astTree, CodeGeneratorCodes *codes);
 
 char *codeGeneratorToFlatASM(const CodeGeneratorCodes *codes);
 
-bool codeGeneratorFlatASMExec(const char *filePath,const char *fasm);
+bool codeGeneratorFlatASMExec(const char *filePath, const char *fasm);
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index 7ec9e1c..14125cc 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -26,24 +26,26 @@ const char *PARSER_TOKEN_STRINGS[] = {
 
     "PARSER_TOKEN_FUNCTION_DEFINITION",
 
+    "PARSER_TOKEN_FUNCTION_CALL",
+
     "PARSER_TOKEN_NONE",
 };
 
 static constexpr ParserOrder PARSER_ORDER[] = {
     {
         .ltr = true,
-        .size = 2,
+        .size = 1,
         .data =
             {
-                LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS,
                 LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET,
             },
     },
     {
         .ltr = true,
-        .size = 2,
+        .size = 3,
         .data =
             {
+                LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS,
                 LEXER_TOKEN_IDENTIFIER,
                 LEXER_TOKEN_KEYWORD_VOID,
             },
@@ -183,6 +185,26 @@ void parserNodePrint(const ParserNode *node, int indent) {
       printf(" ");
   }
     goto RETURN_SUCCESS;
+  case PARSER_TOKEN_FUNCTION_CALL: {
+    const ParserNodeFunctionCall *metadata = node->metadata;
+    printf(",\n");
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+    printf("function=\n");
+    parserNodePrint(metadata->function, indent + 1);
+    printf(",\n");
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+    printf("params=[\n");
+    for (size_t i = 0; i < metadata->params->size; ++i) {
+      parserNodePrint(metadata->params->data[i], indent + 1);
+      printf(",\n");
+    }
+    printf("]\n");
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+  }
+    goto RETURN_SUCCESS;
   case PARSER_TOKEN_NONE:
   }
   printLog("Bad token '%d'", node->token);
@@ -241,6 +263,17 @@ void parserNodeDelete(ParserNode *node) {
     free(metadata);
   }
     goto RETURN_SUCCESS;
+  case PARSER_TOKEN_FUNCTION_CALL: {
+    ParserNodeFunctionCall *metadata = node->metadata;
+    parserNodeDelete(metadata->function);
+    for (size_t i = 0; i < metadata->params->size; ++i) {
+      parserNodeDelete(metadata->params->data[i]);
+    }
+    free(metadata->params->data);
+    free(metadata->params);
+    free(metadata);
+  }
+    goto RETURN_SUCCESS;
 
   case PARSER_TOKEN_NONE:
   }
@@ -381,24 +414,21 @@ ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent) {
 }
 
 ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent) {
-  ParserNode *parserNode = newParserNode(
-      PARSER_TOKEN_IDENTIFIER, node->str_begin, node->str_end, NULL, parent);
-  node->parserNode = parserNode;
-  return parserNode;
+  return node->parserNode =
+             newParserNode(PARSER_TOKEN_IDENTIFIER, node->str_begin,
+                           node->str_end, NULL, parent);
 }
 
 ParserNode *parserVoid(LexerNode *node, ParserNode *parent) {
-  ParserNode *parserNode = newParserNode(
-      PARSER_TOKEN_TYPE_VOID, node->str_begin, node->str_end, NULL, parent);
-  node->parserNode = parserNode;
-  return parserNode;
+  return node->parserNode =
+             newParserNode(PARSER_TOKEN_TYPE_VOID, node->str_begin,
+                           node->str_end, NULL, parent);
 }
 
 ParserNode *parserPrint(LexerNode *node, ParserNode *parent) {
-  ParserNode *parserNode = newParserNode(
-      PARSER_TOKEN_KEYWORD_PRINT, node->str_begin, node->str_end, NULL, parent);
-  node->parserNode = parserNode;
-  return parserNode;
+  return node->parserNode =
+             newParserNode(PARSER_TOKEN_KEYWORD_PRINT, node->str_begin,
+                           node->str_end, NULL, parent);
 }
 
 ParserNode *parserEol(LexerNode *node, LexerNode *begin, ParserNode *parent) {
@@ -461,17 +491,45 @@ ParserNode *parserParenthesis(LexerNode *closing, LexerNode *begin,
     return NULL;
   }
 
-  ParserNode *parserNode =
-      newParserNode(PARSER_TOKEN_SYMBOL_PARENTHESIS, opening->str_begin,
-                    closing->str_end, NULL, parent);
+  LexerNode *beforeNode = opening - 1;
+  ParserNode *before;
+  if (beforeNode < begin || beforeNode->parserNode == NULL ||
+      (before = getUntilCommonParent(beforeNode->parserNode, parent)) == NULL ||
+      !isExpression(before)) {
+    before = NULL;
+  }
 
-  opening->parserNode = parserNode;
-  closing->parserNode = parserNode;
-  if (parserNodeArray(opening + 1, closing, parserNode)) {
-    return parserNode;
+  if (before == NULL) {
+    ParserNode *parserNode =
+        newParserNode(PARSER_TOKEN_SYMBOL_PARENTHESIS, opening->str_begin,
+                      closing->str_end, NULL, parent);
+
+    opening->parserNode = parserNode;
+    closing->parserNode = parserNode;
+    if (parserNodeArray(opening + 1, closing, parserNode)) {
+      return parserNode;
+    } else {
+      free(parserNode);
+      return NULL;
+    }
   } else {
-    free(parserNode);
-    return NULL;
+    ParserNode *parserNode =
+        newParserNode(PARSER_TOKEN_FUNCTION_CALL, before->str_begin,
+                      closing->str_end, NULL, parent);
+
+    before->parent = parserNode;
+    opening->parserNode = parserNode;
+    closing->parserNode = parserNode;
+    if (parserNodeArray(opening + 1, closing, parserNode)) {
+      ParserNodeFunctionCall *metadata = malloc(sizeof(*metadata));
+      metadata->function = before;
+      metadata->params = parserNode->metadata;
+      parserNode->metadata = metadata;
+      return parserNode;
+    } else {
+      free(parserNode);
+      return NULL;
+    }
   }
 }
 
@@ -683,6 +741,7 @@ bool isExpression(ParserNode *node) {
   case PARSER_TOKEN_SYMBOL_PARENTHESIS:
   case PARSER_TOKEN_FUNCTION_DEFINITION:
   case PARSER_TOKEN_KEYWORD_PRINT:
+  case PARSER_TOKEN_FUNCTION_CALL:
     return true;
   case PARSER_TOKEN_ROOT:
   case PARSER_TOKEN_TYPE_FUNCTION:
@@ -711,6 +770,7 @@ bool isType(ParserNode *node) {
   case PARSER_TOKEN_SYMBOL_EOL:
   case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
   case PARSER_TOKEN_SYMBOL_COMMA:
+  case PARSER_TOKEN_FUNCTION_CALL:
     return false;
   case PARSER_TOKEN_NONE:
   }
@@ -721,6 +781,7 @@ bool isType(ParserNode *node) {
 bool isValue(ParserNode *node) {
   switch (node->token) {
   case PARSER_TOKEN_FUNCTION_DEFINITION:
+  case PARSER_TOKEN_FUNCTION_CALL:
     return true;
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_IDENTIFIER:
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 7d98074..fb65358 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -22,6 +22,8 @@ typedef enum ParserToken {
 
   PARSER_TOKEN_FUNCTION_DEFINITION,
 
+  PARSER_TOKEN_FUNCTION_CALL,
+
   PARSER_TOKEN_NONE,
 } ParserToken;
 
@@ -63,9 +65,14 @@ typedef struct ParserNodeArray {
   size_t size;
 } ParserNodeArray;
 
+typedef struct ParserNodeFunctionCall {
+  ParserNode *function;
+  ParserNodeArray *params;
+} ParserNodeFunctionCall;
+
 typedef ParserNode ParserNodeEOLMetadata;
 
-void parserNodePrint(const ParserNode *node,int indent);
+void parserNodePrint(const ParserNode *node, int indent);
 void parserNodeDelete(ParserNode *node);
 
 ParserNode *parser(LexerNodeArray lexed);
diff --git a/src/main.c b/src/main.c
index 86d8858..90478a3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -77,5 +77,5 @@ int main(int argc, char *argv[]) {
     return 1;
   }
 
-  return runWithPrint(argv[1], argv[2]);
+  return run(argv[1], argv[2]);
 }
diff --git a/test/main.felan b/test/main.felan
index 626bd50..9c39bc6 100644
--- a/test/main.felan
+++ b/test/main.felan
@@ -1,3 +1,10 @@
-main : (a:void)->void : (a:void) -> void {
+main : ()->void : () -> void {
+  a();
+  a();
+};
+
+a :: () -> void {
+  print;
+  print;
   print;
 };
-- 
cgit v1.2.3