From 5adca3ef1277b9e7f8f4d77e1b2ecce9ad78d76b Mon Sep 17 00:00:00 2001
From: A404M <ahmadmahmoudiprogrammer@gmail.com>
Date: Tue, 28 Jan 2025 03:40:39 +0330
Subject: clean syntax to not allowing variable definition else where

---
 src/compiler/ast-tree.c       | 178 ++++++++++++++++++++++++++++++++----------
 src/compiler/ast-tree.h       |   7 +-
 src/compiler/code-generator.c |   4 +-
 src/compiler/lexer.c          |   4 +
 src/compiler/lexer.h          |   1 +
 src/compiler/parser.c         |  65 ++++++++-------
 src/compiler/parser.h         |   2 +
 7 files changed, 179 insertions(+), 82 deletions(-)

diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 96f439d..b03754d 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -11,6 +11,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
 
     "AST_TREE_TOKEN_KEYWORD_PRINT_U64",
 
+    "AST_TREE_TOKEN_TYPE_TYPE",
     "AST_TREE_TOKEN_TYPE_FUNCTION",
     "AST_TREE_TOKEN_TYPE_VOID",
     "AST_TREE_TOKEN_TYPE_U64",
@@ -19,8 +20,6 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
     "AST_TREE_TOKEN_VARIABLE",
     "AST_TREE_TOKEN_VALUE_U64",
 
-    "AST_TREE_TOKEN_VARIABLE_DEFINE",
-
     "AST_TREE_TOKEN_NONE",
 };
 
@@ -66,6 +65,7 @@ void astTreePrint(const AstTree *tree, int indent) {
     printf("]");
   }
     goto RETURN_SUCCESS;
+  case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
   case AST_TREE_TOKEN_TYPE_U64:
     goto RETURN_SUCCESS;
@@ -118,7 +118,6 @@ void astTreePrint(const AstTree *tree, int indent) {
     printf("]");
   }
     goto RETURN_SUCCESS;
-  case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_VARIABLE: {
     AstTreeVariable *metadata = tree->metadata;
     printf(",variable.name=%.*s",
@@ -167,6 +166,7 @@ void astTreeDestroy(AstTree tree) {
     free(metadata);
   }
     return;
+  case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
   case AST_TREE_TOKEN_TYPE_U64:
   case AST_TREE_TOKEN_VALUE_U64:
@@ -196,7 +196,6 @@ void astTreeDestroy(AstTree tree) {
     free(metadata);
   }
     return;
-  case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_VARIABLE: {
     // AstTreeIdentifier *metadata = tree.metadata; // not needed
   }
@@ -242,6 +241,27 @@ AstTree *newAstTree(AstTreeToken token, void *metadata) {
   return result;
 }
 
+AstTree *copyAstTree(AstTree *tree) {
+  switch (tree->token) {
+  case AST_TREE_TOKEN_TYPE_TYPE:
+  case AST_TREE_TOKEN_TYPE_VOID:
+  case AST_TREE_TOKEN_TYPE_U64:
+    return newAstTree(tree->token, NULL);
+  case AST_TREE_TOKEN_VALUE_U64:
+    return newAstTree(AST_TREE_TOKEN_VALUE_U64,
+                      (void *)(AstTreeU64)tree->metadata);
+  case AST_TREE_TOKEN_VARIABLE:
+    return newAstTree(AST_TREE_TOKEN_VARIABLE, tree->metadata);
+  case AST_TREE_TOKEN_FUNCTION:
+  case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+  case AST_TREE_TOKEN_TYPE_FUNCTION:
+  case AST_TREE_TOKEN_FUNCTION_CALL:
+  case AST_TREE_TOKEN_NONE:
+  }
+  printLog("Bad token '%d'", tree->token);
+  exit(1);
+}
+
 AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
   if (parsedRoot->token != PARSER_TOKEN_ROOT) {
     return NULL;
@@ -278,20 +298,22 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
     }
   }
 
+  AstTreeVariables *variables = &root->variables;
+  constexpr size_t variables_size = 1;
+
   for (size_t i = 0; i < nodes->size; ++i) {
     ParserNode *node =
         (ParserNodeSingleChildMetadata *)nodes->data[i]->metadata;
     ParserNodeVariableMetadata *node_metadata = node->metadata;
 
-    AstTree *type;
-    if (node_metadata->type != NULL) {
-      AstTreeVariables *variables = &root->variables;
-      type = astTreeParse(node_metadata->type, &variables, 1);
-      if (type == NULL) {
-        goto RETURN_ERROR;
-      }
-    } else {
-      type = NULL; // TODO: change this to find type
+    if (node->token != PARSER_TOKEN_CONSTANT) {
+      printLog("Only variables are allowed here");
+      goto RETURN_ERROR;
+    }
+
+    if (node_metadata->value == NULL) {
+      printLog("Variables must be initialized");
+      goto RETURN_ERROR;
     }
 
     switch (node_metadata->value->token) {
@@ -300,6 +322,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
       goto AFTER_SWITCH;
     case PARSER_TOKEN_ROOT:
     case PARSER_TOKEN_IDENTIFIER:
+    case PARSER_TOKEN_TYPE_TYPE:
     case PARSER_TOKEN_TYPE_FUNCTION:
     case PARSER_TOKEN_TYPE_VOID:
     case PARSER_TOKEN_TYPE_U64:
@@ -318,16 +341,27 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
     goto RETURN_ERROR;
 
   AFTER_SWITCH:
-    AstTreeVariables *variables = &root->variables;
-    AstTree *value = astTreeParse(node_metadata->value, &variables, 1);
+
+    AstTree *value =
+        astTreeParse(node_metadata->value, &variables, variables_size);
     if (value == NULL) {
       goto RETURN_ERROR;
     }
 
-    // TODO: then delete type != NULL
-    if (type != NULL && !hasTypeOf(value, type)) {
-      printLog("Type mismatch");
-      goto RETURN_ERROR;
+    AstTree *type;
+    if (node_metadata->type != NULL) {
+      AstTreeVariables *variables = &root->variables;
+      type = astTreeParse(node_metadata->type, &variables, 1);
+      if (type == NULL) {
+        goto RETURN_ERROR;
+      }
+
+      if (!hasTypeOf(value, type)) {
+        printLog("Type mismatch");
+        goto RETURN_ERROR;
+      }
+    } else {
+      type = makeTypeOf(value);
     }
 
     root->variables.data[i]->type = type;
@@ -391,6 +425,8 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables,
   switch (parserNode->token) {
   case PARSER_TOKEN_FUNCTION_DEFINITION:
     return astTreeParseFunction(parserNode, variables, variables_size);
+  case PARSER_TOKEN_TYPE_TYPE:
+    return newAstTree(AST_TREE_TOKEN_TYPE_TYPE, NULL);
   case PARSER_TOKEN_TYPE_FUNCTION:
     return astTreeParseTypeFunction(parserNode, variables, variables_size);
   case PARSER_TOKEN_TYPE_VOID:
@@ -408,7 +444,6 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables,
   case PARSER_TOKEN_KEYWORD_PRINT_U64:
     return astTreeParsePrintU64(parserNode, variables, variables_size);
   case PARSER_TOKEN_CONSTANT:
-    return astTreeParseConstant(parserNode, variables, variables_size);
   case PARSER_TOKEN_SYMBOL_EOL:
   case PARSER_TOKEN_SYMBOL_PARENTHESIS:
   case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
@@ -486,24 +521,29 @@ AstTree *astTreeParseFunction(ParserNode *parserNode,
       goto RETURN_ERROR;
     }
     ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
-    AstTree *tree = astTreeParse(node, variables, variables_size);
 
-    if (tree == NULL) {
-      goto RETURN_ERROR;
-    } else if (tree->token == AST_TREE_TOKEN_VARIABLE_DEFINE) {
-      astTreeDelete(tree);
-      continue;
-    }
+    if (node->token == PARSER_TOKEN_CONSTANT) {
+      if (!astTreeParseConstant(node, variables, variables_size)) {
+        goto RETURN_ERROR;
+      }
+    } else {
+      AstTree *tree;
+      tree = astTreeParse(node, variables, variables_size);
 
-    if (expressions_size == scope.expressions_size) {
-      expressions_size += expressions_size / 2 + 1;
-      scope.expressions = a404m_realloc(
-          scope.expressions, expressions_size * sizeof(*scope.expressions));
-    }
-    scope.expressions[scope.expressions_size] = *tree;
-    scope.expressions_size += 1;
+      if (tree == NULL) {
+        goto RETURN_ERROR;
+      }
 
-    free(tree);
+      if (expressions_size == scope.expressions_size) {
+        expressions_size += expressions_size / 2 + 1;
+        scope.expressions = a404m_realloc(
+            scope.expressions, expressions_size * sizeof(*scope.expressions));
+      }
+      scope.expressions[scope.expressions_size] = *tree;
+      scope.expressions_size += 1;
+
+      free(tree);
+    }
   }
 
   scope.expressions = a404m_realloc(
@@ -639,9 +679,8 @@ AstTree *astTreeParsePrintU64(ParserNode *parserNode,
                     (AstTreeSingleChild *)operand);
 }
 
-AstTree *astTreeParseConstant(ParserNode *parserNode,
-                              AstTreeVariables **variables,
-                              size_t variables_size) {
+bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables,
+                          size_t variables_size) {
   ParserNodeVariableMetadata *node_metadata = parserNode->metadata;
 
   if (node_metadata->value == NULL || node_metadata->type == NULL ||
@@ -672,13 +711,29 @@ AstTree *astTreeParseConstant(ParserNode *parserNode,
     goto RETURN_ERROR;
   }
 
-  return newAstTree(AST_TREE_TOKEN_VARIABLE_DEFINE, variable);
+  return true;
 RETURN_ERROR:
-  return NULL;
+  return false;
 }
 
 bool hasTypeOf(AstTree *value, AstTree *type) {
   switch (type->token) {
+  case AST_TREE_TOKEN_TYPE_TYPE:
+    switch (value->token) {
+    case AST_TREE_TOKEN_TYPE_TYPE:
+    case AST_TREE_TOKEN_TYPE_FUNCTION:
+    case AST_TREE_TOKEN_TYPE_VOID:
+    case AST_TREE_TOKEN_TYPE_U64:
+      return true;
+    case AST_TREE_TOKEN_FUNCTION:
+    case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+    case AST_TREE_TOKEN_FUNCTION_CALL:
+    case AST_TREE_TOKEN_VARIABLE:
+    case AST_TREE_TOKEN_VALUE_U64:
+    case AST_TREE_TOKEN_NONE:
+      return false;
+    }
+    goto ERROR;
   case AST_TREE_TOKEN_TYPE_FUNCTION:
     AstTreeTypeFunction *typeMetadata = type->metadata;
     switch (value->token) {
@@ -697,12 +752,12 @@ bool hasTypeOf(AstTree *value, AstTree *type) {
     }
     case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
     case AST_TREE_TOKEN_VALUE_U64:
+    case AST_TREE_TOKEN_TYPE_TYPE:
     case AST_TREE_TOKEN_TYPE_FUNCTION:
     case AST_TREE_TOKEN_TYPE_VOID:
     case AST_TREE_TOKEN_TYPE_U64:
     case AST_TREE_TOKEN_FUNCTION_CALL:
     case AST_TREE_TOKEN_VARIABLE:
-    case AST_TREE_TOKEN_VARIABLE_DEFINE:
       return false;
     case AST_TREE_TOKEN_NONE:
     }
@@ -715,7 +770,6 @@ bool hasTypeOf(AstTree *value, AstTree *type) {
   case AST_TREE_TOKEN_VARIABLE:
   case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
   case AST_TREE_TOKEN_VALUE_U64:
-  case AST_TREE_TOKEN_VARIABLE_DEFINE:
     return false;
   case AST_TREE_TOKEN_NONE:
   }
@@ -724,13 +778,51 @@ ERROR:
   exit(1);
 }
 
+AstTree *makeTypeOf(AstTree *value) {
+  switch (value->token) {
+  case AST_TREE_TOKEN_TYPE_TYPE:
+  case AST_TREE_TOKEN_TYPE_FUNCTION:
+  case AST_TREE_TOKEN_TYPE_VOID:
+  case AST_TREE_TOKEN_TYPE_U64:
+    return newAstTree(AST_TREE_TOKEN_TYPE_TYPE, NULL);
+  case AST_TREE_TOKEN_FUNCTION_CALL: {
+    AstTreeFunctionCall *metadata = value->metadata;
+    AstTreeFunction *function = metadata->function->metadata;
+    return copyAstTree(function->returnType);
+  }
+  case AST_TREE_TOKEN_FUNCTION: {
+    AstTreeFunction *function = value->metadata;
+
+    AstTreeTypeFunction *type_metadata = a404m_malloc(sizeof(*type_metadata));
+    type_metadata->arguments_size = function->arguments.size;
+    type_metadata->arguments = a404m_malloc(function->arguments.size *
+                                            sizeof(*type_metadata->arguments));
+    type_metadata->returnType = copyAstTree(function->returnType);
+
+    for (size_t i = 0; i < function->arguments.size; ++i) {
+      type_metadata->arguments[i] =
+          copyAstTree(function->arguments.data[i]->type);
+    }
+
+    return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata);
+  }
+  case AST_TREE_TOKEN_VALUE_U64:
+    return newAstTree(AST_TREE_TOKEN_TYPE_U64, NULL);
+  case AST_TREE_TOKEN_VARIABLE:
+  case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+  case AST_TREE_TOKEN_NONE:
+  }
+  printLog("Bad token '%d'", value->token);
+  exit(1);
+}
+
 bool typeIsEqual(AstTree *type0, AstTree *type1) {
   switch (type0->token) {
   case AST_TREE_TOKEN_FUNCTION:
   case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
   case AST_TREE_TOKEN_VALUE_U64:
-  case AST_TREE_TOKEN_VARIABLE_DEFINE:
     return false;
+  case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
   case AST_TREE_TOKEN_TYPE_U64:
     return type1->token == type0->token;
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 8dba559..7f3e3dc 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -9,6 +9,7 @@ typedef enum AstTreeToken {
 
   AST_TREE_TOKEN_KEYWORD_PRINT_U64,
 
+  AST_TREE_TOKEN_TYPE_TYPE,
   AST_TREE_TOKEN_TYPE_FUNCTION,
   AST_TREE_TOKEN_TYPE_VOID,
   AST_TREE_TOKEN_TYPE_U64,
@@ -17,8 +18,6 @@ typedef enum AstTreeToken {
   AST_TREE_TOKEN_VARIABLE,
   AST_TREE_TOKEN_VALUE_U64,
 
-  AST_TREE_TOKEN_VARIABLE_DEFINE,
-
   AST_TREE_TOKEN_NONE,
 } AstTreeToken;
 
@@ -83,6 +82,7 @@ void astTreeDelete(AstTree *tree);
 void astTreeRootDelete(AstTreeRoot *root);
 
 AstTree *newAstTree(AstTreeToken token, void *metadata);
+AstTree *copyAstTree(AstTree *tree);
 
 AstTreeRoot *makeAstTree(ParserNode *parsedRoot);
 
@@ -114,9 +114,10 @@ AstTree *astTreeParsePrintU64(ParserNode *parserNode,
                               AstTreeVariables **variables,
                               size_t variables_size);
 
-AstTree *astTreeParseConstant(ParserNode *parserNode,
+bool astTreeParseConstant(ParserNode *parserNode,
                               AstTreeVariables **variables,
                               size_t variables_size);
 
 bool hasTypeOf(AstTree *value, AstTree *type);
+AstTree *makeTypeOf(AstTree *value);
 bool typeIsEqual(AstTree *type0, AstTree *type1);
diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c
index 61d0092..342c790 100644
--- a/src/compiler/code-generator.c
+++ b/src/compiler/code-generator.c
@@ -77,6 +77,7 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) {
         return NULL;
       }
       continue;
+    case AST_TREE_TOKEN_TYPE_TYPE:
     case AST_TREE_TOKEN_TYPE_FUNCTION:
     case AST_TREE_TOKEN_TYPE_VOID:
     case AST_TREE_TOKEN_VALUE_U64:
@@ -84,7 +85,6 @@ CodeGeneratorCodes *codeGenerator(AstTreeRoot *astTreeRoot) {
     case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
     case AST_TREE_TOKEN_FUNCTION_CALL:
     case AST_TREE_TOKEN_TYPE_U64:
-    case AST_TREE_TOKEN_VARIABLE_DEFINE:
     case AST_TREE_TOKEN_NONE:
       break;
     }
@@ -148,10 +148,10 @@ bool codeGeneratorAstTreeFunction(char *label_begin, char *label_end,
     case AST_TREE_TOKEN_VALUE_U64:
     case AST_TREE_TOKEN_VARIABLE:
     case AST_TREE_TOKEN_FUNCTION:
+    case AST_TREE_TOKEN_TYPE_TYPE:
     case AST_TREE_TOKEN_TYPE_FUNCTION:
     case AST_TREE_TOKEN_TYPE_VOID:
     case AST_TREE_TOKEN_TYPE_U64:
-    case AST_TREE_TOKEN_VARIABLE_DEFINE:
     case AST_TREE_TOKEN_NONE:
     }
     printLog("Bad token %d", tree.token);
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 2c0774e..464ec7e 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -11,6 +11,7 @@
 const char *LEXER_TOKEN_STRINGS[] = {
     "LEXER_TOKEN_IDENTIFIER",
 
+    "LEXER_TOKEN_KEYWORD_TYPE",
     "LEXER_TOKEN_KEYWORD_VOID",
     "LEXER_TOKEN_KEYWORD_U64",
     "LEXER_TOKEN_KEYWORD_PRINT_U64",
@@ -47,11 +48,13 @@ const size_t LEXER_SYMBOL_SIZE =
     sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS);
 
 const char *LEXER_KEYWORD_STRINGS[] = {
+    "type",
     "void",
     "u64",
     "print_u64",
 };
 const LexerToken LEXER_KEYWORD_TOKENS[] = {
+    LEXER_TOKEN_KEYWORD_TYPE,
     LEXER_TOKEN_KEYWORD_VOID,
     LEXER_TOKEN_KEYWORD_U64,
     LEXER_TOKEN_KEYWORD_PRINT_U64,
@@ -171,6 +174,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
   }
     // goto PUSH;
   PUSH:
+  case LEXER_TOKEN_KEYWORD_TYPE:
   case LEXER_TOKEN_KEYWORD_VOID:
   case LEXER_TOKEN_KEYWORD_U64:
   case LEXER_TOKEN_KEYWORD_PRINT_U64:
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index da3aa0f..6efeac8 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -5,6 +5,7 @@
 typedef enum LexerToken {
   LEXER_TOKEN_IDENTIFIER,
 
+  LEXER_TOKEN_KEYWORD_TYPE,
   LEXER_TOKEN_KEYWORD_VOID,
   LEXER_TOKEN_KEYWORD_U64,
   LEXER_TOKEN_KEYWORD_PRINT_U64,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index bac809f..50b8aae 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -15,8 +15,10 @@ const char *PARSER_TOKEN_STRINGS[] = {
 
     "PARSER_TOKEN_VALUE_U64",
 
+    "PARSER_TOKEN_TYPE_TYPE",
     "PARSER_TOKEN_TYPE_FUNCTION",
     "PARSER_TOKEN_TYPE_VOID",
+    "PARSER_TOKEN_TYPE_U64",
 
     "PARSER_TOKEN_KEYWORD_PRINT_U64",
 
@@ -34,52 +36,33 @@ const char *PARSER_TOKEN_STRINGS[] = {
     "PARSER_TOKEN_NONE",
 };
 
+#define ORDER_ARRAY(...)                                                       \
+  .size = sizeof((LexerToken[]){__VA_ARGS__}) / sizeof(LexerToken),            \
+  .data = {__VA_ARGS__}
+
 static constexpr ParserOrder PARSER_ORDER[] = {
     {
         .ltr = true,
-        .size = 1,
-        .data =
-            {
-                LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET,
-            },
+        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_CLOSE_CURLY_BRACKET, ),
     },
     {
         .ltr = true,
-        .size = 5,
-        .data =
-            {
-                LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS,
-                LEXER_TOKEN_IDENTIFIER,
-                LEXER_TOKEN_KEYWORD_VOID,
-                LEXER_TOKEN_KEYWORD_U64,
-                LEXER_TOKEN_NUMBER,
-            },
+        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_CLOSE_PARENTHESIS,
+                    LEXER_TOKEN_IDENTIFIER, LEXER_TOKEN_KEYWORD_TYPE,
+                    LEXER_TOKEN_KEYWORD_VOID, LEXER_TOKEN_KEYWORD_U64,
+                    LEXER_TOKEN_NUMBER, ),
     },
     {
         .ltr = false,
-        .size = 1,
-        .data =
-            {
-                LEXER_TOKEN_SYMBOL_FUNCTION_ARROW,
-            },
+        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_FUNCTION_ARROW, ),
     },
     {
         .ltr = true,
-        .size = 3,
-        .data =
-            {
-                LEXER_TOKEN_SYMBOL_COLON,
-                LEXER_TOKEN_KEYWORD_PRINT_U64,
-            },
+        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_COLON, LEXER_TOKEN_KEYWORD_PRINT_U64, ),
     },
     {
         .ltr = true,
-        .size = 2,
-        .data =
-            {
-                LEXER_TOKEN_SYMBOL_EOL,
-                LEXER_TOKEN_SYMBOL_COMMA,
-            },
+        ORDER_ARRAY(LEXER_TOKEN_SYMBOL_EOL, LEXER_TOKEN_SYMBOL_COMMA, ),
     },
 };
 
@@ -113,6 +96,7 @@ void parserNodePrint(const ParserNode *node, int indent) {
   }
     goto RETURN_SUCCESS;
   case PARSER_TOKEN_IDENTIFIER:
+  case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_U64:
     goto RETURN_SUCCESS;
@@ -242,6 +226,7 @@ void parserNodeDelete(ParserNode *node) {
   }
     goto RETURN_SUCCESS;
   case PARSER_TOKEN_IDENTIFIER:
+  case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_U64:
   case PARSER_TOKEN_VALUE_U64:
@@ -393,6 +378,8 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
   switch (node->token) {
   case LEXER_TOKEN_IDENTIFIER:
     return parserIdentifier(node, parent);
+  case LEXER_TOKEN_KEYWORD_TYPE:
+    return parserType(node, parent);
   case LEXER_TOKEN_KEYWORD_VOID:
     return parserVoid(node, parent);
   case LEXER_TOKEN_KEYWORD_U64:
@@ -435,6 +422,12 @@ ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent) {
                            node->str_end, NULL, parent);
 }
 
+ParserNode *parserType(LexerNode *node, ParserNode *parent) {
+  return node->parserNode =
+             newParserNode(PARSER_TOKEN_TYPE_TYPE, node->str_begin,
+                           node->str_end, NULL, parent);
+}
+
 ParserNode *parserVoid(LexerNode *node, ParserNode *parent) {
   return node->parserNode =
              newParserNode(PARSER_TOKEN_TYPE_VOID, node->str_begin,
@@ -751,7 +744,8 @@ ParserNode *parserVariable(LexerNode *node, LexerNode *begin, LexerNode *end,
   if (node1 != NULL) {
     LexerNode *valueNode = node1 + 1;
     if (valueNode >= end || valueNode->parserNode == NULL) {
-      printLog("No value");
+      printLog("No value for '%.*s'", (int)(name->str_end - name->str_begin),
+               name->str_begin);
       return NULL;
     } else {
       value = getUntilCommonParent(valueNode->parserNode, parent);
@@ -803,6 +797,7 @@ bool isExpression(ParserNode *node) {
   case PARSER_TOKEN_KEYWORD_PRINT_U64:
     return true;
   case PARSER_TOKEN_ROOT:
+  case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_FUNCTION:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_U64:
@@ -819,9 +814,10 @@ bool isExpression(ParserNode *node) {
 
 bool isType(ParserNode *node) {
   switch (node->token) {
+  case PARSER_TOKEN_TYPE_TYPE:
+  case PARSER_TOKEN_TYPE_FUNCTION:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_U64:
-  case PARSER_TOKEN_TYPE_FUNCTION:
     return true;
   case PARSER_TOKEN_IDENTIFIER:
   case PARSER_TOKEN_CONSTANT:
@@ -847,13 +843,14 @@ bool isValue(ParserNode *node) {
   case PARSER_TOKEN_FUNCTION_CALL:
   case PARSER_TOKEN_VALUE_U64:
     return true;
+  case PARSER_TOKEN_TYPE_FUNCTION:
+  case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_U64:
   case PARSER_TOKEN_IDENTIFIER:
   case PARSER_TOKEN_CONSTANT:
   case PARSER_TOKEN_SYMBOL_PARENTHESIS:
   case PARSER_TOKEN_ROOT:
-  case PARSER_TOKEN_TYPE_FUNCTION:
   case PARSER_TOKEN_SYMBOL_EOL:
   case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
   case PARSER_TOKEN_SYMBOL_COMMA:
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 55354fa..71aa9d8 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -11,6 +11,7 @@ typedef enum ParserToken {
 
   PARSER_TOKEN_VALUE_U64,
 
+  PARSER_TOKEN_TYPE_TYPE,
   PARSER_TOKEN_TYPE_FUNCTION,
   PARSER_TOKEN_TYPE_VOID,
   PARSER_TOKEN_TYPE_U64,
@@ -93,6 +94,7 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
 ParserNode *getUntilCommonParent(ParserNode *node, ParserNode *parent);
 
 ParserNode *parserIdentifier(LexerNode *node, ParserNode *parent);
+ParserNode *parserType(LexerNode *node, ParserNode *parent);
 ParserNode *parserVoid(LexerNode *node, ParserNode *parent);
 ParserNode *parserU64(LexerNode *node, ParserNode *parent);
 ParserNode *parserPrintU64(LexerNode *node, LexerNode *end, ParserNode *parent);
-- 
cgit v1.2.3