From e6e44774556bf6172c1577268cf9f013a4157ae2 Mon Sep 17 00:00:00 2001
From: A404M <ahmadmahmoudiprogrammer@gmail.com>
Date: Sun, 27 Apr 2025 02:11:41 +0330
Subject: add operator overloading

---
 code/basic.felan        |  91 ++++---
 code/main.felan         |  14 +-
 src/compiler/ast-tree.c | 535 +++++++++++++++++++++++++-----------
 src/compiler/ast-tree.h |  77 ++++--
 src/compiler/lexer.c    |  17 +-
 src/compiler/lexer.h    |   2 +
 src/compiler/parser.c   |  18 ++
 src/compiler/parser.h   |   2 +
 src/runner/runner.c     | 706 ++++--------------------------------------------
 src/utils/log.c         |   2 +-
 src/utils/log.h         |   2 +-
 11 files changed, 573 insertions(+), 893 deletions(-)

diff --git a/code/basic.felan b/code/basic.felan
index 9d93ef8..c9e8b61 100644
--- a/code/basic.felan
+++ b/code/basic.felan
@@ -1,40 +1,53 @@
-string :: []u8;
-
-print :: (value:[]u8)->void{
-  i :u64= 0;
-  while i < value.length {
-    putc value[i];
-    i += 1;
-  }
-};
-
-print :: (value:u64)->void{
-  value := value;
-  result :[20]u8 = undefined;
-  i := 0;
-  while {
-    result[i] = '0' + @cast(value % 10,u8);
-    i += 1;
-    value /= 10;
-    value != 0;
-  } {}
-
-  j := 0;
-  while j < i {
-    putc result[j];
-    j += 1;
-  }
-};
-
-to_u64 :: (value:string) -> u64 {
-  i := value.length;
-  result :u64= 0;
-
-  while i > 0 {
-    c := value[i-1];
-    result *= 10;
-    result += @cast(c - '0',u64);
-    i -= 1;
-  }
-  return result;
+__plus__ :: (a:u8) -> u8 {
+  return a;
 };
+
+__plus__ :: (a:i8) -> i8 {
+  return a;
+};
+
+__plus__ :: (a:u16) -> u16 {
+  return a;
+};
+
+__plus__ :: (a:i16) -> i16 {
+  return a;
+};
+
+__plus__ :: (a:u32) -> u32 {
+  return a;
+};
+
+__plus__ :: (a:i32) -> i32 {
+  return a;
+};
+
+__plus__ :: (a:u64) -> u64 {
+  return a;
+};
+
+__plus__ :: (a:i64) -> i64 {
+  return a;
+};
+
+__minus__ :: (a:i8) -> i8 {
+  return a;
+};
+
+__minus__ :: (a:i16) -> i16 {
+  return a;
+};
+
+__minus__ :: (a:i32) -> i32 {
+  return a;
+};
+
+__minus__ :: (a:i64) -> i64 {
+  return a;
+};
+
+__logical_not__ :: (a:bool) -> bool {
+  return a;
+};
+
+
diff --git a/code/main.felan b/code/main.felan
index aeb4da9..b135110 100644
--- a/code/main.felan
+++ b/code/main.felan
@@ -1,9 +1,15 @@
-@import("lib/print.felan");
+@import("basic.felan");
 
 main :: () -> void {
-  print(@isComptime);
+  a : u8 = 65;
+  b : u8 = 70;
+  a + b;
 };
 
-comptime {
-  print(@isComptime);
+__sum__ :: (a:u8,b:u8)->void{
+  putc 'h';
+  putc a;
+  putc '\n';
+  putc b;
 };
+
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 6b68a75..2372feb 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -8,6 +8,7 @@
 #include "utils/string.h"
 #include "utils/time.h"
 #include "utils/type.h"
+#include <stdlib.h>
 
 AstTree AST_TREE_TYPE_TYPE = {
     .token = AST_TREE_TOKEN_TYPE_TYPE,
@@ -120,6 +121,8 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
     "AST_TREE_TOKEN_BUILTIN_TYPE_OF",
     "AST_TREE_TOKEN_BUILTIN_IMPORT",
     "AST_TREE_TOKEN_BUILTIN_IS_COMPTIME",
+    "AST_TREE_TOKEN_BUILTIN_STACK_ALLOC",
+    "AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC",
 
     "AST_TREE_TOKEN_KEYWORD_PUTC",
     "AST_TREE_TOKEN_KEYWORD_RETURN",
@@ -237,6 +240,8 @@ void astTreePrint(const AstTree *tree, int indent) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
   case AST_TREE_TOKEN_TYPE_I8:
@@ -261,11 +266,22 @@ void astTreePrint(const AstTree *tree, int indent) {
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
     goto RETURN_SUCCESS;
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
+  case AST_TREE_TOKEN_OPERATOR_PLUS:
+  case AST_TREE_TOKEN_OPERATOR_MINUS: {
+    AstTreeUnary *metadata = tree->metadata;
+    printf(",\n");
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+    printf("child=\n");
+    astTreePrint(metadata->operand, indent + 1);
+    printf(",\n");
+    for (int i = 0; i < indent; ++i)
+      printf(" ");
+    printf("function=%p", metadata->function);
+  }
   case AST_TREE_TOKEN_OPERATOR_POINTER:
   case AST_TREE_TOKEN_OPERATOR_ADDRESS:
   case AST_TREE_TOKEN_OPERATOR_DEREFERENCE:
-  case AST_TREE_TOKEN_OPERATOR_PLUS:
-  case AST_TREE_TOKEN_OPERATOR_MINUS:
   case AST_TREE_TOKEN_KEYWORD_PUTC:
   case AST_TREE_TOKEN_KEYWORD_COMPTIME: {
     AstTreeSingleChild *metadata = tree->metadata;
@@ -624,6 +640,8 @@ void astTreeDestroy(AstTree tree) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
   case AST_TREE_TOKEN_TYPE_I8:
@@ -673,11 +691,16 @@ void astTreeDestroy(AstTree tree) {
     return;
   }
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
+  case AST_TREE_TOKEN_OPERATOR_PLUS:
+  case AST_TREE_TOKEN_OPERATOR_MINUS: {
+    AstTreeUnary *metadata = tree.metadata;
+    astTreeDelete(metadata->operand);
+    free(metadata);
+  }
+    return;
   case AST_TREE_TOKEN_OPERATOR_POINTER:
   case AST_TREE_TOKEN_OPERATOR_ADDRESS:
   case AST_TREE_TOKEN_OPERATOR_DEREFERENCE:
-  case AST_TREE_TOKEN_OPERATOR_PLUS:
-  case AST_TREE_TOKEN_OPERATOR_MINUS:
   case AST_TREE_TOKEN_KEYWORD_PUTC:
   case AST_TREE_TOKEN_KEYWORD_COMPTIME: {
     AstTreeSingleChild *metadata = tree.metadata;
@@ -896,6 +919,8 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
     return newAstTree(
         tree->token, NULL,
         copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size),
@@ -942,15 +967,11 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
   case AST_TREE_TOKEN_VARIABLE:
   case AST_TREE_TOKEN_VARIABLE_DEFINE: {
     AstTreeVariable *variable = tree->metadata;
-    for (size_t i = 0; i < variables_size; ++i) {
-      for (size_t j = 0; j < oldVariables[i].size; ++j) {
-        if (oldVariables[i].data[j] == variable) {
-          variable = newVariables[i].data[j];
-        }
-      }
-    }
+
     return newAstTree(
-        tree->token, variable,
+        tree->token,
+        copyAstTreeBackFindVariable(variable, oldVariables, newVariables,
+                                    variables_size),
         copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size),
         tree->str_begin, tree->str_end);
   }
@@ -995,6 +1016,8 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
                                          newVariables, variables_size);
     new_metadata->right = copyAstTreeBack(metadata->right, oldVariables,
                                           newVariables, variables_size);
+    new_metadata->function = copyAstTreeBackFindVariable(
+        metadata->function, oldVariables, newVariables, variables_size);
     return newAstTree(
         tree->token, new_metadata,
         copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size),
@@ -1049,11 +1072,23 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
                       tree->str_begin, tree->str_end);
   }
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
+  case AST_TREE_TOKEN_OPERATOR_PLUS:
+  case AST_TREE_TOKEN_OPERATOR_MINUS: {
+    AstTreeUnary *metadata = tree->metadata;
+    AstTreeUnary *new_metadata = a404m_malloc(sizeof(*new_metadata));
+    new_metadata->operand = copyAstTreeBack(metadata->operand, oldVariables,
+                                            newVariables, variables_size);
+    new_metadata->function = copyAstTreeBackFindVariable(
+        metadata->function, oldVariables, newVariables, variables_size);
+
+    return newAstTree(
+        tree->token, new_metadata,
+        copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size),
+        tree->str_begin, tree->str_end);
+  }
   case AST_TREE_TOKEN_OPERATOR_POINTER:
   case AST_TREE_TOKEN_OPERATOR_ADDRESS:
   case AST_TREE_TOKEN_OPERATOR_DEREFERENCE:
-  case AST_TREE_TOKEN_OPERATOR_PLUS:
-  case AST_TREE_TOKEN_OPERATOR_MINUS:
   case AST_TREE_TOKEN_KEYWORD_PUTC:
   case AST_TREE_TOKEN_KEYWORD_COMPTIME: {
     AstTreeSingleChild *metadata = tree->metadata;
@@ -1219,6 +1254,20 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
   UNREACHABLE;
 }
 
+AstTreeVariable *copyAstTreeBackFindVariable(AstTreeVariable *variable,
+                                             AstTreeVariables oldVariables[],
+                                             AstTreeVariables newVariables[],
+                                             size_t variables_size) {
+  for (size_t i = 0; i < variables_size; ++i) {
+    for (size_t j = 0; j < oldVariables[i].size; ++j) {
+      if (oldVariables[i].data[j] == variable) {
+        return newVariables[i].data[j];
+      }
+    }
+  }
+  return variable;
+}
+
 AstTreeVariables copyAstTreeVariables(AstTreeVariables variables,
                                       AstTreeVariables oldVariables[],
                                       AstTreeVariables newVariables[],
@@ -1587,6 +1636,8 @@ AstTreeRoot *makeAstRoot(const ParserNode *parsedRoot, char *filePath) {
       case PARSER_TOKEN_BUILTIN_TYPE_OF:
       case PARSER_TOKEN_BUILTIN_IMPORT:
       case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+      case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+      case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
       case PARSER_TOKEN_SYMBOL_BRACKET_LEFT:
       case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT:
         goto AFTER_SWITCH;
@@ -1692,6 +1743,10 @@ AstTree *astTreeParse(const ParserNode *parserNode, AstTreeHelper *helper) {
     return astTreeParseKeyword(parserNode, AST_TREE_TOKEN_BUILTIN_IMPORT);
   case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
     return astTreeParseKeyword(parserNode, AST_TREE_TOKEN_BUILTIN_IS_COMPTIME);
+  case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+    return astTreeParseKeyword(parserNode, AST_TREE_TOKEN_BUILTIN_STACK_ALLOC);
+  case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
+    return astTreeParseKeyword(parserNode, AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC);
   case PARSER_TOKEN_TYPE_TYPE:
     return &AST_TREE_TYPE_TYPE;
   case PARSER_TOKEN_TYPE_FUNCTION:
@@ -2012,6 +2067,8 @@ AstTree *astTreeParseFunction(const ParserNode *parserNode,
     case PARSER_TOKEN_BUILTIN_TYPE_OF:
     case PARSER_TOKEN_BUILTIN_IMPORT:
     case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+    case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+    case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
     case PARSER_TOKEN_SYMBOL_BRACKET_LEFT:
     case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT:
       printError(node->str_begin, node->str_end, "Unexpected %s",
@@ -2299,6 +2356,7 @@ AstTree *astTreeParseBinaryOperator(const ParserNode *parserNode,
 
   metadata->left = left;
   metadata->right = right;
+  metadata->function = NULL;
 
   return newAstTree(token, metadata, NULL, parserNode->str_begin,
                     parserNode->str_end);
@@ -2308,10 +2366,13 @@ AstTree *astTreeParseUnaryOperator(const ParserNode *parserNode,
                                    AstTreeHelper *helper, AstTreeToken token) {
   ParserNodeSingleChildMetadata *node_metadata = parserNode->metadata;
 
-  AstTreeSingleChild *metadata = astTreeParse(node_metadata, helper);
-  if (metadata == NULL) {
+  AstTreeUnary *metadata = a404m_malloc(sizeof(*metadata));
+  metadata->operand = astTreeParse(node_metadata, helper);
+  if (metadata->operand == NULL) {
+    free(metadata);
     return NULL;
   }
+  metadata->function = NULL;
 
   return newAstTree(token, metadata, NULL, parserNode->str_begin,
                     parserNode->str_end);
@@ -2335,6 +2396,7 @@ AstTree *astTreeParseOperateAssignOperator(const ParserNode *parserNode,
 
   metadata->left = left;
   metadata->right = right;
+  metadata->function = NULL;
 
   AstTreeInfix *assignMetadata = a404m_malloc(sizeof(*assignMetadata));
 
@@ -2344,6 +2406,7 @@ AstTree *astTreeParseOperateAssignOperator(const ParserNode *parserNode,
 
   assignMetadata->left = assignLeft;
   assignMetadata->right = assignRight;
+  assignMetadata->function = NULL;
 
   return newAstTree(AST_TREE_TOKEN_OPERATOR_ASSIGN, assignMetadata, NULL,
                     parserNode->str_begin, parserNode->str_end);
@@ -2607,6 +2670,8 @@ AstTree *astTreeParseCurlyBracket(const ParserNode *parserNode,
     case PARSER_TOKEN_BUILTIN_TYPE_OF:
     case PARSER_TOKEN_BUILTIN_IMPORT:
     case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+    case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+    case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
     case PARSER_TOKEN_SYMBOL_BRACKET_LEFT:
     case PARSER_TOKEN_SYMBOL_BRACKET_RIGHT:
       printError(node->str_begin, node->str_end, "Unexpected %s",
@@ -2796,6 +2861,8 @@ bool isConst(AstTree *tree) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_FUNCTION:
   case AST_TREE_TOKEN_TYPE_VOID:
@@ -2914,6 +2981,8 @@ bool isConstByValue(AstTree *tree) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_FUNCTION:
   case AST_TREE_TOKEN_TYPE_VOID:
@@ -3100,22 +3169,25 @@ AstTree *makeTypeOf(AstTree *value) {
     AstTreeVariable *variable = value->metadata;
     return copyAstTree(variable->type);
   }
-  case AST_TREE_TOKEN_KEYWORD_COMPTIME:
+  case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
   case AST_TREE_TOKEN_OPERATOR_PLUS:
   case AST_TREE_TOKEN_OPERATOR_MINUS: {
+    AstTreeUnary *metadata = value->metadata;
+    AstTreeTypeFunction *function = metadata->function->type->metadata;
+    return copyAstTree(function->returnType);
+  }
+  case AST_TREE_TOKEN_KEYWORD_COMPTIME: {
     AstTreeSingleChild *metadata = value->metadata;
     return copyAstTree(metadata->type);
   }
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
+    AstTreeInfix *metadata = value->metadata;
+    return copyAstTree(metadata->left->type);
   case AST_TREE_TOKEN_OPERATOR_SUM:
   case AST_TREE_TOKEN_OPERATOR_SUB:
   case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
   case AST_TREE_TOKEN_OPERATOR_DIVIDE:
-  case AST_TREE_TOKEN_OPERATOR_MODULO: {
-    AstTreeInfix *metadata = value->metadata;
-    return copyAstTree(metadata->left->type);
-  }
-  case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND:
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_OR:
   case AST_TREE_TOKEN_OPERATOR_EQUAL:
@@ -3124,7 +3196,9 @@ AstTree *makeTypeOf(AstTree *value) {
   case AST_TREE_TOKEN_OPERATOR_SMALLER:
   case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL:
   case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: {
-    return &AST_TREE_BOOL_TYPE;
+    AstTreeInfix *metadata = value->metadata;
+    AstTreeTypeFunction *function = metadata->function->type->metadata;
+    return copyAstTree(function->returnType);
   }
   case AST_TREE_TOKEN_OPERATOR_ACCESS: {
     AstTreeAccess *metadata = value->metadata;
@@ -3151,6 +3225,8 @@ AstTree *makeTypeOf(AstTree *value) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_VALUE_OBJECT:
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_KEYWORD_PUTC:
@@ -3191,6 +3267,8 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_FUNCTION:
   case AST_TREE_TOKEN_KEYWORD_PUTC:
   case AST_TREE_TOKEN_KEYWORD_RETURN:
@@ -3338,6 +3416,8 @@ AstTree *getValue(AstTree *tree) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_TYPE_FUNCTION:
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
@@ -3445,6 +3525,8 @@ bool isIntType(AstTree *type) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_KEYWORD_PUTC:
   case AST_TREE_TOKEN_KEYWORD_RETURN:
   case AST_TREE_TOKEN_KEYWORD_IF:
@@ -3545,6 +3627,8 @@ bool isEqual(AstTree *left, AstTree *right) {
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
   case AST_TREE_TOKEN_KEYWORD_PUTC:
   case AST_TREE_TOKEN_KEYWORD_RETURN:
   case AST_TREE_TOKEN_KEYWORD_IF:
@@ -3681,6 +3765,59 @@ RETURN_ERROR:
   return false;
 }
 
+static const char STR_PLUS[] = "__plus__";
+static const size_t STR_PLUS_SIZE =
+    sizeof(STR_PLUS) / sizeof(*STR_PLUS) - sizeof(*STR_PLUS);
+static const char STR_MINUS[] = "__minus__";
+static const size_t STR_MINUS_SIZE =
+    sizeof(STR_MINUS) / sizeof(*STR_MINUS) - sizeof(*STR_PLUS);
+static const char STR_LOGICAL_NOT[] = "__logical_not__";
+static const size_t STR_LOGICAL_NOT_SIZE =
+    sizeof(STR_LOGICAL_NOT) / sizeof(*STR_LOGICAL_NOT) - sizeof(*STR_PLUS);
+
+static const char STR_SUM[] = "__sum__";
+static const size_t STR_SUM_SIZE =
+    sizeof(STR_SUM) / sizeof(*STR_SUM) - sizeof(*STR_SUM);
+static const char STR_SUB[] = "__sub__";
+static const size_t STR_SUB_SIZE =
+    sizeof(STR_SUB) / sizeof(*STR_SUB) - sizeof(*STR_SUB);
+static const char STR_MUL[] = "__mul__";
+static const size_t STR_MUL_SIZE =
+    sizeof(STR_MUL) / sizeof(*STR_MUL) - sizeof(*STR_MUL);
+static const char STR_DIV[] = "__div__";
+static const size_t STR_DIV_SIZE =
+    sizeof(STR_DIV) / sizeof(*STR_DIV) - sizeof(*STR_DIV);
+static const char STR_MOD[] = "__mod__";
+static const size_t STR_MOD_SIZE =
+    sizeof(STR_MOD) / sizeof(*STR_MOD) - sizeof(*STR_MOD);
+static const char STR_LOGICAL_AND[] = "__logical_and__";
+static const size_t STR_LOGICAL_AND_SIZE =
+    sizeof(STR_LOGICAL_AND) / sizeof(*STR_LOGICAL_AND) -
+    sizeof(*STR_LOGICAL_AND);
+static const char STR_LOGICAL_OR[] = "__logical_or__";
+static const size_t STR_LOGICAL_OR_SIZE =
+    sizeof(STR_LOGICAL_OR) / sizeof(*STR_LOGICAL_OR) - sizeof(*STR_LOGICAL_OR);
+static const char STR_EQUAL[] = "__equal__";
+static const size_t STR_EQUAL_SIZE =
+    sizeof(STR_EQUAL) / sizeof(*STR_EQUAL) - sizeof(*STR_EQUAL);
+static const char STR_NOT_EQUAL[] = "__not_equal__";
+static const size_t STR_NOT_EQUAL_SIZE =
+    sizeof(STR_NOT_EQUAL) / sizeof(*STR_NOT_EQUAL) - sizeof(*STR_NOT_EQUAL);
+static const char STR_GREATER[] = "__greater__";
+static const size_t STR_GREATER_SIZE =
+    sizeof(STR_GREATER) / sizeof(*STR_GREATER) - sizeof(*STR_GREATER);
+static const char STR_SMALLER[] = "__smaller__";
+static const size_t STR_SMALLER_SIZE =
+    sizeof(STR_SMALLER) / sizeof(*STR_SMALLER) - sizeof(*STR_SMALLER);
+static const char STR_GREATER_OR_EQUAL[] = "__greater_or_equal__";
+static const size_t STR_GREATER_OR_EQUAL_SIZE =
+    sizeof(STR_GREATER_OR_EQUAL) / sizeof(*STR_GREATER_OR_EQUAL) -
+    sizeof(*STR_GREATER_OR_EQUAL);
+static const char STR_SMALLER_OR_EQUAL[] = "__smaller_or_equal__";
+static const size_t STR_SMALLER_OR_EQUAL_SIZE =
+    sizeof(STR_SMALLER_OR_EQUAL) / sizeof(*STR_SMALLER_OR_EQUAL) -
+    sizeof(*STR_SMALLER_OR_EQUAL);
+
 bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper,
                  AstTreeFunction *function, AstTreeFunctionCall *functionCall) {
   if (tree->type != NULL) {
@@ -3734,28 +3871,43 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper,
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
     return setTypesOperatorAssign(tree, helper);
   case AST_TREE_TOKEN_OPERATOR_PLUS:
+    return setTypesOperatorUnary(tree, helper, STR_PLUS, STR_PLUS_SIZE);
   case AST_TREE_TOKEN_OPERATOR_MINUS:
-    return setTypesOperatorUnary(tree, helper);
+    return setTypesOperatorUnary(tree, helper, STR_MINUS, STR_MINUS_SIZE);
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
-    return setTypesOperatorUnaryWithRetAndLooking(tree, &AST_TREE_BOOL_TYPE,
-                                                  &AST_TREE_BOOL_TYPE, helper);
+    return setTypesOperatorUnary(tree, helper, STR_LOGICAL_NOT,
+                                 STR_LOGICAL_NOT_SIZE);
   case AST_TREE_TOKEN_OPERATOR_SUM:
+    return setTypesOperatorInfix(tree, helper, STR_SUM, STR_SUM_SIZE);
   case AST_TREE_TOKEN_OPERATOR_SUB:
+    return setTypesOperatorInfix(tree, helper, STR_SUB, STR_SUB_SIZE);
   case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+    return setTypesOperatorInfix(tree, helper, STR_MUL, STR_MUL_SIZE);
   case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+    return setTypesOperatorInfix(tree, helper, STR_DIV, STR_DIV_SIZE);
   case AST_TREE_TOKEN_OPERATOR_MODULO:
-    return setTypesOperatorInfix(tree, helper);
+    return setTypesOperatorInfix(tree, helper, STR_MOD, STR_MOD_SIZE);
   case AST_TREE_TOKEN_OPERATOR_EQUAL:
+    return setTypesOperatorInfix(tree, helper, STR_EQUAL, STR_EQUAL_SIZE);
   case AST_TREE_TOKEN_OPERATOR_NOT_EQUAL:
+    return setTypesOperatorInfix(tree, helper, STR_NOT_EQUAL,
+                                 STR_NOT_EQUAL_SIZE);
   case AST_TREE_TOKEN_OPERATOR_GREATER:
+    return setTypesOperatorInfix(tree, helper, STR_GREATER, STR_GREATER_SIZE);
   case AST_TREE_TOKEN_OPERATOR_SMALLER:
+    return setTypesOperatorInfix(tree, helper, STR_SMALLER, STR_SMALLER_SIZE);
   case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL:
+    return setTypesOperatorInfix(tree, helper, STR_GREATER_OR_EQUAL,
+                                 STR_GREATER_OR_EQUAL_SIZE);
   case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL:
-    return setTypesOperatorInfixWithRet(tree, &AST_TREE_BOOL_TYPE, helper);
+    return setTypesOperatorInfix(tree, helper, STR_SMALLER_OR_EQUAL,
+                                 STR_SMALLER_OR_EQUAL_SIZE);
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND:
+    return setTypesOperatorInfix(tree, helper, STR_LOGICAL_AND,
+                                 STR_LOGICAL_AND_SIZE);
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_OR:
-    return setTypesOperatorInfixWithRetAndLooking(tree, &AST_TREE_BOOL_TYPE,
-                                                  &AST_TREE_BOOL_TYPE, helper);
+    return setTypesOperatorInfix(tree, helper, STR_LOGICAL_OR,
+                                 STR_LOGICAL_OR_SIZE);
   case AST_TREE_TOKEN_OPERATOR_POINTER:
     return setTypesOperatorPointer(tree, helper);
   case AST_TREE_TOKEN_OPERATOR_ADDRESS:
@@ -3784,6 +3936,10 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper,
     return setTypesBuiltinImport(tree, helper, functionCall);
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME:
     return setTypesBuiltinIsComptime(tree, helper);
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+    return setTypesBuiltinStackAlloc(tree, helper, functionCall);
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
+    return setTypesBuiltinHeapAlloc(tree, helper, functionCall);
   case AST_TREE_TOKEN_TYPE_ARRAY:
     return setTypesTypeArray(tree, helper);
   case AST_TREE_TOKEN_OPERATOR_ARRAY_ACCESS:
@@ -4229,108 +4385,8 @@ bool setTypesFunctionCall(AstTree *tree, AstTreeSetTypesHelper _helper) {
 
 bool setTypesVariable(AstTree *tree, AstTreeSetTypesHelper helper,
                       AstTreeFunctionCall *functionCall) {
-  AstTreeVariable *variable = NULL;
-
-  const char *str = tree->str_begin;
-  const size_t str_size = tree->str_end - tree->str_begin;
-
-  if (functionCall == NULL) {
-    for (size_t i = helper.variables.size - 1; i != -1ULL; --i) {
-      AstTreeVariable *var = helper.variables.data[i];
-
-      const char *var_str = var->name_begin;
-      const size_t var_str_size = var->name_end - var->name_begin;
-
-      if (var_str_size != str_size || !strnEquals(var_str, str, str_size)) {
-        continue;
-      }
-
-      if (!setTypesAstVariable(var, helper)) {
-        goto RETURN_ERROR;
-      }
-
-      variable = var;
-      break;
-    }
-  } else {
-    for (size_t i = helper.variables.size - 1; i != -1ULL; --i) {
-      AstTreeVariable *var = helper.variables.data[i];
-
-      const char *var_str = var->name_begin;
-      const size_t var_str_size = var->name_end - var->name_begin;
-
-      if (var_str_size != str_size || !strnEquals(var_str, str, str_size)) {
-        continue;
-      }
-
-      if (!setTypesAstVariable(var, helper)) {
-        goto RETURN_ERROR;
-      }
-
-      if (var->type->token != AST_TREE_TOKEN_TYPE_FUNCTION) {
-        continue;
-      }
-
-      AstTreeTypeFunction *function = var->type->metadata;
-
-      AstTreeFunctionCallParam initedArguments[function->arguments_size];
-      size_t initedArguments_size = function->arguments_size;
-
-      for (size_t i = 0; i < initedArguments_size; ++i) {
-        initedArguments[i].value = NULL;
-      }
-
-      for (size_t i = 0; i < functionCall->parameters_size; ++i) {
-        AstTreeFunctionCallParam param = functionCall->parameters[i];
-        if (param.nameBegin != param.nameEnd) {
-          const size_t param_name_size = param.nameEnd - param.nameBegin;
-          for (size_t j = 0; j < function->arguments_size; ++j) {
-            AstTreeTypeFunctionArgument arg = function->arguments[j];
-            if ((size_t)(arg.name_end - arg.name_begin) == param_name_size &&
-                strnEquals(arg.name_begin, param.nameBegin, param_name_size)) {
-              if (!typeIsEqual(arg.type, param.value->type)) {
-                goto CONTINUE_OUTER;
-              }
-              initedArguments[j] = param;
-              goto END_OF_NAMED_FOR;
-            }
-          }
-          goto CONTINUE_OUTER;
-        }
-      END_OF_NAMED_FOR:
-      }
-
-      for (size_t i = 0; i < functionCall->parameters_size; ++i) {
-        AstTreeFunctionCallParam param = functionCall->parameters[i];
-        if (param.nameBegin == param.nameEnd) {
-          for (size_t j = 0; j < function->arguments_size; ++j) {
-            AstTreeTypeFunctionArgument arg = function->arguments[j];
-            if (initedArguments[j].value == NULL) {
-              if (!typeIsEqual(arg.type, param.value->type)) {
-                goto CONTINUE_OUTER;
-              }
-              initedArguments[j] = param;
-              goto END_OF_UNNAMED_FOR;
-            }
-          }
-          goto CONTINUE_OUTER;
-        }
-      END_OF_UNNAMED_FOR:
-      }
-
-      for (size_t i = 0; i < function->arguments_size; ++i) {
-        if (initedArguments[i].value == NULL) {
-          goto CONTINUE_OUTER;
-        }
-      }
-      if (variable != NULL) {
-        printError(tree->str_begin, tree->str_end, "Multiple candidates found");
-        goto RETURN_ERROR;
-      }
-      variable = var;
-    CONTINUE_OUTER:
-    }
-  }
+  AstTreeVariable *variable = setTypesFindVariable(
+      tree->str_begin, tree->str_end, helper, functionCall);
   if (variable == NULL) {
     printError(tree->str_begin, tree->str_end, "No candidate found");
     goto RETURN_ERROR;
@@ -4365,17 +4421,51 @@ bool setTypesOperatorAssign(AstTree *tree, AstTreeSetTypesHelper helper) {
   }
 }
 
-bool setTypesOperatorInfix(AstTree *tree, AstTreeSetTypesHelper helper) {
-  AstTreeInfix *infix = tree->metadata;
-  if (!setTypesAstInfix(infix, helper)) {
+bool setTypesOperatorInfix(AstTree *tree, AstTreeSetTypesHelper _helper,
+                           const char *str, size_t str_size) {
+  AstTreeInfix *metadata = tree->metadata;
+
+  AstTreeSetTypesHelper helper = {
+      .lookingType = NULL,
+      .dependencies = _helper.dependencies,
+      .variables = _helper.variables,
+  };
+
+  if (!setAllTypes(metadata->left, helper, NULL, NULL) ||
+      !setAllTypes(metadata->right, helper, NULL, NULL)) {
     return false;
-  } else if (!typeIsEqual(infix->left->type, infix->right->type)) {
-    printError(tree->str_begin, tree->str_end, "Type mismatch");
+  }
+
+  AstTreeFunctionCallParam parameters[] = {
+      (AstTreeFunctionCallParam){
+          .nameBegin = NULL,
+          .nameEnd = NULL,
+          .value = metadata->left,
+      },
+      (AstTreeFunctionCallParam){
+          .nameBegin = NULL,
+          .nameEnd = NULL,
+          .value = metadata->right,
+      },
+  };
+
+  AstTreeFunctionCall functionCall = {
+      .function = NULL,
+      .parameters = parameters,
+      .parameters_size = 2,
+  };
+
+  AstTreeVariable *variable =
+      setTypesFindVariable(str, str + str_size, helper, &functionCall);
+  if (variable == NULL) {
     return false;
-  } else {
-    tree->type = copyAstTree(infix->left->type);
-    return true;
   }
+
+  metadata->function = variable;
+  AstTreeTypeFunction *function = metadata->function->type->metadata;
+
+  tree->type = copyAstTree(function->returnType);
+  return true;
 }
 
 bool setTypesOperatorInfixWithRet(AstTree *tree, AstTree *retType,
@@ -4403,31 +4493,38 @@ bool setTypesOperatorInfixWithRetAndLooking(AstTree *tree, AstTree *lookingType,
   return setTypesOperatorInfixWithRet(tree, retType, helper);
 }
 
-bool setTypesOperatorUnary(AstTree *tree, AstTreeSetTypesHelper helper) {
-  AstTreeSingleChild *operand = tree->metadata;
-  if (!setAllTypes(operand, helper, NULL, NULL)) {
+bool setTypesOperatorUnary(AstTree *tree, AstTreeSetTypesHelper helper,
+                           const char *funcStr, size_t funcStr_size) {
+  AstTreeUnary *metadata = tree->metadata;
+  if (!setAllTypes(metadata->operand, helper, NULL, NULL)) {
     return false;
-  } else {
-    tree->type = copyAstTree(operand->type);
-    return true;
   }
-}
 
-bool setTypesOperatorUnaryWithRetAndLooking(AstTree *tree, AstTree *lookingType,
-                                            AstTree *retType,
-                                            AstTreeSetTypesHelper _helper) {
-  AstTreeSetTypesHelper helper = {
-      .lookingType = lookingType,
-      .dependencies = _helper.dependencies,
-      .variables = _helper.variables,
+  AstTreeFunctionCallParam parameters[] = {
+      (AstTreeFunctionCallParam){
+          .nameBegin = NULL,
+          .nameEnd = NULL,
+          .value = metadata->operand,
+      },
   };
-  AstTreeSingleChild *operand = tree->metadata;
-  if (!setAllTypes(operand, helper, NULL, NULL)) {
+
+  AstTreeFunctionCall functionCall = {
+      .function = NULL,
+      .parameters = parameters,
+      .parameters_size = 1,
+  };
+
+  AstTreeVariable *variable = setTypesFindVariable(
+      funcStr, funcStr + funcStr_size, helper, &functionCall);
+  if (variable == NULL) {
     return false;
-  } else {
-    tree->type = retType;
-    return true;
   }
+
+  metadata->function = variable;
+  AstTreeTypeFunction *function = metadata->function->type->metadata;
+
+  tree->type = copyAstTree(function->returnType);
+  return true;
 }
 
 bool setTypesOperatorPointer(AstTree *tree, AstTreeSetTypesHelper helper) {
@@ -4960,6 +5057,16 @@ bool setTypesBuiltinIsComptime(AstTree *tree, AstTreeSetTypesHelper helper) {
   return true;
 }
 
+bool setTypesBuiltinStackAlloc(AstTree *tree, AstTreeSetTypesHelper helper,
+                               AstTreeFunctionCall *functionCall) {
+  NOT_IMPLEMENTED;
+}
+
+bool setTypesBuiltinHeapAlloc(AstTree *tree, AstTreeSetTypesHelper helper,
+                              AstTreeFunctionCall *functionCall) {
+  NOT_IMPLEMENTED;
+}
+
 bool setTypesTypeArray(AstTree *tree, AstTreeSetTypesHelper helper) {
   AstTreeBracket *metadata = tree->metadata;
 
@@ -5056,6 +5163,116 @@ bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper _helper) {
   return setAllTypes(infix->right, helper, NULL, NULL);
 }
 
+AstTreeVariable *setTypesFindVariable(const char *name_begin,
+                                      const char *name_end,
+                                      AstTreeSetTypesHelper helper,
+                                      AstTreeFunctionCall *functionCall) {
+  AstTreeVariable *variable = NULL;
+
+  const char *str = name_begin;
+  const size_t str_size = name_end - name_begin;
+
+  if (functionCall == NULL) {
+    for (size_t i = helper.variables.size - 1; i != -1ULL; --i) {
+      AstTreeVariable *var = helper.variables.data[i];
+
+      const char *var_str = var->name_begin;
+      const size_t var_str_size = var->name_end - var->name_begin;
+
+      if (var_str_size != str_size || !strnEquals(var_str, str, str_size)) {
+        continue;
+      }
+
+      if (!setTypesAstVariable(var, helper)) {
+        return NULL;
+      }
+
+      variable = var;
+      break;
+    }
+  } else {
+    for (size_t i = helper.variables.size - 1; i != -1ULL; --i) {
+      AstTreeVariable *var = helper.variables.data[i];
+
+      const char *var_str = var->name_begin;
+      const size_t var_str_size = var->name_end - var->name_begin;
+
+      if (var_str_size != str_size || !strnEquals(var_str, str, str_size)) {
+        continue;
+      }
+
+      if (!setTypesAstVariable(var, helper)) {
+        return NULL;
+      }
+
+      if (var->type->token != AST_TREE_TOKEN_TYPE_FUNCTION) {
+        continue;
+      }
+
+      AstTreeTypeFunction *function = var->type->metadata;
+
+      AstTreeFunctionCallParam initedArguments[function->arguments_size];
+      size_t initedArguments_size = function->arguments_size;
+
+      for (size_t i = 0; i < initedArguments_size; ++i) {
+        initedArguments[i].value = NULL;
+      }
+
+      for (size_t i = 0; i < functionCall->parameters_size; ++i) {
+        AstTreeFunctionCallParam param = functionCall->parameters[i];
+        if (param.nameBegin != param.nameEnd) {
+          const size_t param_name_size = param.nameEnd - param.nameBegin;
+          for (size_t j = 0; j < function->arguments_size; ++j) {
+            AstTreeTypeFunctionArgument arg = function->arguments[j];
+            if ((size_t)(arg.name_end - arg.name_begin) == param_name_size &&
+                strnEquals(arg.name_begin, param.nameBegin, param_name_size)) {
+              if (!typeIsEqual(arg.type, param.value->type)) {
+                goto CONTINUE_OUTER;
+              }
+              initedArguments[j] = param;
+              goto END_OF_NAMED_FOR;
+            }
+          }
+          goto CONTINUE_OUTER;
+        }
+      END_OF_NAMED_FOR:
+      }
+
+      for (size_t i = 0; i < functionCall->parameters_size; ++i) {
+        AstTreeFunctionCallParam param = functionCall->parameters[i];
+        if (param.nameBegin == param.nameEnd) {
+          for (size_t j = 0; j < function->arguments_size; ++j) {
+            AstTreeTypeFunctionArgument arg = function->arguments[j];
+            if (initedArguments[j].value == NULL) {
+              if (!typeIsEqual(arg.type, param.value->type)) {
+                goto CONTINUE_OUTER;
+              }
+              initedArguments[j] = param;
+              goto END_OF_UNNAMED_FOR;
+            }
+          }
+          goto CONTINUE_OUTER;
+        }
+      END_OF_UNNAMED_FOR:
+      }
+
+      for (size_t i = 0; i < function->arguments_size; ++i) {
+        if (initedArguments[i].value == NULL) {
+          goto CONTINUE_OUTER;
+        }
+      }
+      if (variable != NULL) {
+        printError(name_begin, name_end, "Multiple candidates found");
+        return NULL;
+      }
+      variable = var;
+    CONTINUE_OUTER:
+    }
+  }
+
+  return variable;
+}
+
 char *u8ArrayToCString(AstTree *tree) {
   AstTreeObject *object = tree->metadata;
   char *str = a404m_malloc((object->variables.size + 1) * sizeof(*str));
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 39df36d..b454217 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -10,6 +10,8 @@ typedef enum AstTreeToken {
   AST_TREE_TOKEN_BUILTIN_TYPE_OF,
   AST_TREE_TOKEN_BUILTIN_IMPORT,
   AST_TREE_TOKEN_BUILTIN_IS_COMPTIME,
+  AST_TREE_TOKEN_BUILTIN_STACK_ALLOC,
+  AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC,
 
   AST_TREE_TOKEN_KEYWORD_PUTC,
   AST_TREE_TOKEN_KEYWORD_RETURN,
@@ -194,9 +196,15 @@ typedef struct AstTreeObject {
 
 typedef AstTree AstTreeSingleChild;
 
+typedef struct AstTreeUnary {
+  AstTree *operand;
+  AstTreeVariable *function;
+} AstTreeUnary;
+
 typedef struct AstTreeInfix {
   AstTree *left;
   AstTree *right;
+  AstTreeVariable *function;
 } AstTreeInfix;
 
 typedef struct AstTreeReturn {
@@ -268,6 +276,10 @@ AstTree *copyAstTree(AstTree *tree);
 AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
                          AstTreeVariables newVariables[],
                          size_t variables_size);
+AstTreeVariable *copyAstTreeBackFindVariable(AstTreeVariable *variable,
+                                             AstTreeVariables oldVariables[],
+                                             AstTreeVariables newVariables[],
+                                             size_t variables_size);
 AstTreeVariables copyAstTreeVariables(AstTreeVariables variables,
                                       AstTreeVariables oldVariables[],
                                       AstTreeVariables newVariables[],
@@ -276,33 +288,40 @@ AstTreeVariables copyAstTreeVariables(AstTreeVariables variables,
 AstTreeRoots makeAstTree(const char *filePath
 #ifdef PRINT_STATISTICS
                          ,
-                         struct timespec *lexingTime, struct timespec* parsingTime
+                         struct timespec *lexingTime,
+                         struct timespec *parsingTime
 #endif
 );
 AstTreeRoot *getAstTreeRoot(char *filePath, AstTreeRoots *roots
 #ifdef PRINT_STATISTICS
-                         ,
-                         struct timespec *lexingTime, struct timespec *parsingTime
+                            ,
+                            struct timespec *lexingTime,
+                            struct timespec *parsingTime
 #endif
-                            );
+);
 AstTreeRoot *makeAstRoot(const ParserNode *parsedRoot, char *filePath);
 
 bool pushVariable(AstTreeHelper *helper, AstTreeVariables *variables,
                   AstTreeVariable *variable);
 
 AstTree *astTreeParse(const ParserNode *parserNode, AstTreeHelper *helper);
-AstTree *astTreeParseFunction(const ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseFunction(const ParserNode *parserNode,
+                              AstTreeHelper *helper);
 AstTree *astTreeParseTypeFunction(const ParserNode *parserNode,
                                   AstTreeHelper *helper);
 AstTree *astTreeParseFunctionCall(const ParserNode *parserNode,
                                   AstTreeHelper *helper);
-AstTree *astTreeParseIdentifier(const ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseIdentifier(const ParserNode *parserNode,
+                                AstTreeHelper *helper);
 AstTree *astTreeParseValue(const ParserNode *parserNode, AstTreeToken token,
                            size_t metadata_size, AstTree *type);
-AstTree *astTreeParseString(const ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseString(const ParserNode *parserNode,
+                            AstTreeHelper *helper);
 AstTree *astTreeParseKeyword(const ParserNode *parserNode, AstTreeToken token);
-AstTree *astTreeParsePrintU64(const ParserNode *parserNode, AstTreeHelper *helper);
-AstTree *astTreeParseReturn(const ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParsePrintU64(const ParserNode *parserNode,
+                              AstTreeHelper *helper);
+AstTree *astTreeParseReturn(const ParserNode *parserNode,
+                            AstTreeHelper *helper);
 AstTree *astTreeParseBinaryOperator(const ParserNode *parserNode,
                                     AstTreeHelper *helper, AstTreeToken token);
 AstTree *astTreeParseUnaryOperator(const ParserNode *parserNode,
@@ -311,18 +330,22 @@ AstTree *astTreeParseOperateAssignOperator(const ParserNode *parserNode,
                                            AstTreeHelper *helper,
                                            AstTreeToken token);
 bool astTreeParseConstant(const ParserNode *parserNode, AstTreeHelper *helper);
-AstTree *astTreeParseVariable(const ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseVariable(const ParserNode *parserNode,
+                              AstTreeHelper *helper);
 AstTree *astTreeParseIf(const ParserNode *parserNode, AstTreeHelper *helper);
 AstTree *astTreeParseWhile(const ParserNode *parserNode, AstTreeHelper *helper);
-AstTree *astTreeParseComptime(const ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseComptime(const ParserNode *parserNode,
+                              AstTreeHelper *helper);
 AstTree *astTreeParseCurlyBracket(const ParserNode *parserNode,
                                   AstTreeHelper *helper);
-AstTree *astTreeParseParenthesis(const ParserNode *parserNode, AstTreeHelper *helper);
-AstTree *astTreeParseStruct(const ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseParenthesis(const ParserNode *parserNode,
+                                 AstTreeHelper *helper);
+AstTree *astTreeParseStruct(const ParserNode *parserNode,
+                            AstTreeHelper *helper);
 AstTree *astTreeParseAccessOperator(const ParserNode *parserNode,
                                     AstTreeHelper *helper, AstTreeToken token);
-AstTree *astTreeParseBracket(const ParserNode *parserNode, AstTreeHelper *helper,
-                             AstTreeToken token);
+AstTree *astTreeParseBracket(const ParserNode *parserNode,
+                             AstTreeHelper *helper, AstTreeToken token);
 
 bool isFunction(AstTree *value);
 bool isConst(AstTree *tree);
@@ -355,16 +378,15 @@ bool setTypesFunctionCall(AstTree *tree, AstTreeSetTypesHelper helper);
 bool setTypesVariable(AstTree *tree, AstTreeSetTypesHelper helper,
                       AstTreeFunctionCall *functionCall);
 bool setTypesOperatorAssign(AstTree *tree, AstTreeSetTypesHelper helper);
-bool setTypesOperatorInfix(AstTree *tree, AstTreeSetTypesHelper helper);
+bool setTypesOperatorInfix(AstTree *tree, AstTreeSetTypesHelper helper,
+                           const char *str, size_t str_size);
 bool setTypesOperatorInfixWithRet(AstTree *tree, AstTree *retType,
                                   AstTreeSetTypesHelper helper);
 bool setTypesOperatorInfixWithRetAndLooking(AstTree *tree, AstTree *lookingType,
                                             AstTree *retType,
                                             AstTreeSetTypesHelper helper);
-bool setTypesOperatorUnary(AstTree *tree, AstTreeSetTypesHelper helper);
-bool setTypesOperatorUnaryWithRetAndLooking(AstTree *tree, AstTree *lookingType,
-                                            AstTree *retType,
-                                            AstTreeSetTypesHelper helper);
+bool setTypesOperatorUnary(AstTree *tree, AstTreeSetTypesHelper helper,
+                           const char *funcStr, size_t funcStr_size);
 bool setTypesOperatorPointer(AstTree *tree, AstTreeSetTypesHelper helper);
 bool setTypesOperatorAddress(AstTree *tree, AstTreeSetTypesHelper helper);
 bool setTypesOperatorDereference(AstTree *tree, AstTreeSetTypesHelper helper);
@@ -379,12 +401,16 @@ bool setTypesComptime(AstTree *tree, AstTreeSetTypesHelper helper);
 bool setTypesStruct(AstTree *tree, AstTreeSetTypesHelper helper);
 bool setTypesOperatorAccess(AstTree *tree, AstTreeSetTypesHelper helper);
 bool setTypesBuiltinCast(AstTree *tree, AstTreeSetTypesHelper helper,
-                     AstTreeFunctionCall *functionCall);
+                         AstTreeFunctionCall *functionCall);
 bool setTypesBuiltinTypeOf(AstTree *tree, AstTreeSetTypesHelper helper,
-                     AstTreeFunctionCall *functionCall);
+                           AstTreeFunctionCall *functionCall);
 bool setTypesBuiltinImport(AstTree *tree, AstTreeSetTypesHelper helper,
-                     AstTreeFunctionCall *functionCall);
+                           AstTreeFunctionCall *functionCall);
 bool setTypesBuiltinIsComptime(AstTree *tree, AstTreeSetTypesHelper helper);
+bool setTypesBuiltinStackAlloc(AstTree *tree, AstTreeSetTypesHelper helper,
+                               AstTreeFunctionCall *functionCall);
+bool setTypesBuiltinHeapAlloc(AstTree *tree, AstTreeSetTypesHelper helper,
+                              AstTreeFunctionCall *functionCall);
 bool setTypesTypeArray(AstTree *tree, AstTreeSetTypesHelper helper);
 bool setTypesArrayAccess(AstTree *tree, AstTreeSetTypesHelper helper);
 
@@ -392,6 +418,11 @@ bool setTypesAstVariable(AstTreeVariable *variable,
                          AstTreeSetTypesHelper helper);
 bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper);
 
+AstTreeVariable *setTypesFindVariable(const char *name_begin,
+                                      const char *name_end,
+                                      AstTreeSetTypesHelper helper,
+                                      AstTreeFunctionCall *functionCall);
+
 char *u8ArrayToCString(AstTree *tree);
 
 AstTree *makeStringType();
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 378e480..651f1df 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -14,6 +14,8 @@ const char *LEXER_TOKEN_STRINGS[] = {
     "LEXER_TOKEN_BUILTIN_TYPE_OF",
     "LEXER_TOKEN_BUILTIN_IMPORT",
     "LEXER_TOKEN_BUILTIN_IS_COMPTIME",
+    "LEXER_TOKEN_BUILTIN_STACK_ALLOC",
+    "LEXER_TOKEN_BUILTIN_HEAP_ALLOC",
     "LEXER_TOKEN_KEYWORD_TYPE",
     "LEXER_TOKEN_KEYWORD_VOID",
     "LEXER_TOKEN_KEYWORD_I8",
@@ -173,16 +175,13 @@ static const size_t LEXER_KEYWORD_SIZE =
     sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS);
 
 static const char *LEXER_BUILTIN_STRINGS[] = {
-    "cast",
-    "typeOf",
-    "import",
-    "isComptime",
+    "cast", "typeOf", "import", "isComptime", "stackAlloc", "heapAlloc",
+
 };
 static const LexerToken LEXER_BUILTIN_TOKENS[] = {
-    LEXER_TOKEN_BUILTIN_CAST,
-    LEXER_TOKEN_BUILTIN_TYPE_OF,
-    LEXER_TOKEN_BUILTIN_IMPORT,
-    LEXER_TOKEN_BUILTIN_IS_COMPTIME,
+    LEXER_TOKEN_BUILTIN_CAST,        LEXER_TOKEN_BUILTIN_TYPE_OF,
+    LEXER_TOKEN_BUILTIN_IMPORT,      LEXER_TOKEN_BUILTIN_IS_COMPTIME,
+    LEXER_TOKEN_BUILTIN_STACK_ALLOC, LEXER_TOKEN_BUILTIN_HEAP_ALLOC,
 };
 static const size_t LEXER_BUILTIN_SIZE =
     sizeof(LEXER_BUILTIN_TOKENS) / sizeof(*LEXER_BUILTIN_TOKENS);
@@ -429,6 +428,8 @@ lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
   case LEXER_TOKEN_BUILTIN_TYPE_OF:
   case LEXER_TOKEN_BUILTIN_IMPORT:
   case LEXER_TOKEN_BUILTIN_IS_COMPTIME:
+  case LEXER_TOKEN_BUILTIN_STACK_ALLOC:
+  case LEXER_TOKEN_BUILTIN_HEAP_ALLOC:
   case LEXER_TOKEN_SYMBOL_CLOSE_BRACKET:
   case LEXER_TOKEN_SYMBOL_OPEN_BRACKET:
     if (*array_size == array->size) {
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index 7cceae7..91eff63 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -17,6 +17,8 @@ typedef enum LexerToken {
   LEXER_TOKEN_BUILTIN_TYPE_OF,
   LEXER_TOKEN_BUILTIN_IMPORT,
   LEXER_TOKEN_BUILTIN_IS_COMPTIME,
+  LEXER_TOKEN_BUILTIN_STACK_ALLOC,
+  LEXER_TOKEN_BUILTIN_HEAP_ALLOC,
   LEXER_TOKEN_KEYWORD_TYPE,
   LEXER_TOKEN_KEYWORD_VOID,
   LEXER_TOKEN_KEYWORD_I8,
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index c4cbfee..8ca259f 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -16,6 +16,8 @@ const char *PARSER_TOKEN_STRINGS[] = {
     "PARSER_TOKEN_BUILTIN_TYPE_OF",
     "PARSER_TOKEN_BUILTIN_IMPORT",
     "PARSER_TOKEN_BUILTIN_IS_COMPTIME",
+    "PARSER_TOKEN_BUILTIN_STACK_ALLOC",
+    "PARSER_TOKEN_BUILTIN_HEAP_ALLOC",
 
     "PARSER_TOKEN_VALUE_INT",
     "PARSER_TOKEN_VALUE_FLOAT",
@@ -228,6 +230,8 @@ void parserNodePrint(const ParserNode *node, int indent) {
   case PARSER_TOKEN_BUILTIN_TYPE_OF:
   case PARSER_TOKEN_BUILTIN_IMPORT:
   case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+  case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+  case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
   case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_BOOL:
@@ -515,6 +519,8 @@ void parserNodeDelete(ParserNode *node) {
   case PARSER_TOKEN_BUILTIN_TYPE_OF:
   case PARSER_TOKEN_BUILTIN_IMPORT:
   case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+  case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+  case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
   case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_VOID:
   case PARSER_TOKEN_TYPE_BOOL:
@@ -801,6 +807,10 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
     return parserNoMetadata(node, parent, PARSER_TOKEN_BUILTIN_IMPORT);
   case LEXER_TOKEN_BUILTIN_IS_COMPTIME:
     return parserNoMetadata(node, parent, PARSER_TOKEN_BUILTIN_IS_COMPTIME);
+  case LEXER_TOKEN_BUILTIN_STACK_ALLOC:
+    return parserNoMetadata(node, parent, PARSER_TOKEN_BUILTIN_STACK_ALLOC);
+  case LEXER_TOKEN_BUILTIN_HEAP_ALLOC:
+    return parserNoMetadata(node, parent, PARSER_TOKEN_BUILTIN_HEAP_ALLOC);
   case LEXER_TOKEN_KEYWORD_TYPE:
     return parserNoMetadata(node, parent, PARSER_TOKEN_TYPE_TYPE);
   case LEXER_TOKEN_KEYWORD_VOID:
@@ -1537,6 +1547,8 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,
       case PARSER_TOKEN_BUILTIN_TYPE_OF:
       case PARSER_TOKEN_BUILTIN_IMPORT:
       case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+  case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+  case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
       case PARSER_TOKEN_VALUE_INT:
       case PARSER_TOKEN_VALUE_FLOAT:
       case PARSER_TOKEN_VALUE_BOOL:
@@ -2001,6 +2013,8 @@ bool isExpression(ParserNode *node) {
   case PARSER_TOKEN_BUILTIN_TYPE_OF:
   case PARSER_TOKEN_BUILTIN_IMPORT:
   case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+  case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+  case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
   case PARSER_TOKEN_CONSTANT:
   case PARSER_TOKEN_VARIABLE:
   case PARSER_TOKEN_SYMBOL_PARENTHESIS:
@@ -2114,6 +2128,8 @@ bool isType(ParserNode *node) {
   case PARSER_TOKEN_BUILTIN_TYPE_OF:
   case PARSER_TOKEN_BUILTIN_IMPORT:
   case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+  case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+  case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
   case PARSER_TOKEN_OPERATOR_ADDRESS:
   case PARSER_TOKEN_KEYWORD_NULL:
   case PARSER_TOKEN_KEYWORD_UNDEFINED:
@@ -2174,6 +2190,8 @@ bool isValue(ParserNode *node) {
   case PARSER_TOKEN_BUILTIN_TYPE_OF:
   case PARSER_TOKEN_BUILTIN_IMPORT:
   case PARSER_TOKEN_BUILTIN_IS_COMPTIME:
+  case PARSER_TOKEN_BUILTIN_STACK_ALLOC:
+  case PARSER_TOKEN_BUILTIN_HEAP_ALLOC:
   case PARSER_TOKEN_OPERATOR_ACCESS:
   case PARSER_TOKEN_OPERATOR_ASSIGN:
   case PARSER_TOKEN_OPERATOR_SUM_ASSIGN:
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index 271cc13..ac729f9 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -13,6 +13,8 @@ typedef enum ParserToken {
   PARSER_TOKEN_BUILTIN_TYPE_OF,
   PARSER_TOKEN_BUILTIN_IMPORT,
   PARSER_TOKEN_BUILTIN_IS_COMPTIME,
+  PARSER_TOKEN_BUILTIN_STACK_ALLOC,
+  PARSER_TOKEN_BUILTIN_HEAP_ALLOC,
 
   PARSER_TOKEN_VALUE_INT,
   PARSER_TOKEN_VALUE_FLOAT,
diff --git a/src/runner/runner.c b/src/runner/runner.c
index 4f788e7..dc3e655 100644
--- a/src/runner/runner.c
+++ b/src/runner/runner.c
@@ -506,668 +506,56 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
     }
     return ret;
   }
+  case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT:
+  case AST_TREE_TOKEN_OPERATOR_MINUS:
   case AST_TREE_TOKEN_OPERATOR_PLUS: {
-    AstTreeSingleChild *operand =
-        runExpression(expr->metadata, scope, shouldRet, false, isComptime);
-    if (operand->type == &AST_TREE_U64_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, u64);
-    } else if (operand->type == &AST_TREE_I64_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, i64);
-    } else if (operand->type == &AST_TREE_U32_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, u32);
-    } else if (operand->type == &AST_TREE_I32_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, i32);
-    } else if (operand->type == &AST_TREE_U16_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, u16);
-    } else if (operand->type == &AST_TREE_I16_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, i16);
-    } else if (operand->type == &AST_TREE_U8_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, u8);
-    } else if (operand->type == &AST_TREE_I8_TYPE) {
-      doLeftOperation(operand, +, AstTreeInt, i8);
-    } else if (operand->type == &AST_TREE_F128_TYPE) {
-      doLeftOperation(operand, +, AstTreeFloat, f128);
-    } else if (operand->type == &AST_TREE_F64_TYPE) {
-      doLeftOperation(operand, +, AstTreeFloat, f64);
-    } else if (operand->type == &AST_TREE_F32_TYPE) {
-      doLeftOperation(operand, +, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (operand->type == &AST_TREE_F16_TYPE) {
-      doLeftOperation(operand, +, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    return operand;
-  }
-  case AST_TREE_TOKEN_OPERATOR_MINUS: {
-    AstTreeSingleChild *operand =
-        runExpression(expr->metadata, scope, shouldRet, false, isComptime);
-    if (operand->type == &AST_TREE_U64_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, u64);
-    } else if (operand->type == &AST_TREE_I64_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, i64);
-    } else if (operand->type == &AST_TREE_U32_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, u32);
-    } else if (operand->type == &AST_TREE_I32_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, i32);
-    } else if (operand->type == &AST_TREE_U16_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, u16);
-    } else if (operand->type == &AST_TREE_I16_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, i16);
-    } else if (operand->type == &AST_TREE_U8_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, u8);
-    } else if (operand->type == &AST_TREE_I8_TYPE) {
-      doLeftOperation(operand, -, AstTreeInt, i8);
-    } else if (operand->type == &AST_TREE_F128_TYPE) {
-      doLeftOperation(operand, -, AstTreeFloat, f128);
-    } else if (operand->type == &AST_TREE_F64_TYPE) {
-      doLeftOperation(operand, -, AstTreeFloat, f64);
-    } else if (operand->type == &AST_TREE_F32_TYPE) {
-      doLeftOperation(operand, -, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (operand->type == &AST_TREE_F16_TYPE) {
-      doLeftOperation(operand, -, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    return operand;
-  }
-  case AST_TREE_TOKEN_OPERATOR_LOGICAL_NOT: {
-    AstTreeSingleChild *operand =
-        runExpression(expr->metadata, scope, shouldRet, false, isComptime);
-
-    *(AstTreeBool *)operand->metadata = !*((AstTreeBool *)operand->metadata);
-    return operand;
-  }
-  case AST_TREE_TOKEN_OPERATOR_SUM: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doOperation(left, right, +, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doOperation(left, right, +, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doOperation(left, right, +, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doOperation(left, right, +, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doOperation(left, right, +, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doOperation(left, right, +, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doOperation(left, right, +, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doOperation(left, right, +, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doOperation(left, right, +, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doOperation(left, right, +, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doOperation(left, right, +, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doOperation(left, right, +, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_SUB: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doOperation(left, right, -, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doOperation(left, right, -, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doOperation(left, right, -, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doOperation(left, right, -, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doOperation(left, right, -, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doOperation(left, right, -, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doOperation(left, right, -, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doOperation(left, right, -, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doOperation(left, right, -, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doOperation(left, right, -, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doOperation(left, right, -, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doOperation(left, right, -, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_MULTIPLY: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doOperation(left, right, *, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doOperation(left, right, *, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doOperation(left, right, *, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doOperation(left, right, *, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doOperation(left, right, *, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doOperation(left, right, *, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doOperation(left, right, *, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doOperation(left, right, *, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doOperation(left, right, *, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doOperation(left, right, *, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doOperation(left, right, *, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doOperation(left, right, *, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_DIVIDE: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doOperation(left, right, /, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doOperation(left, right, /, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doOperation(left, right, /, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doOperation(left, right, /, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doOperation(left, right, /, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doOperation(left, right, /, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doOperation(left, right, /, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doOperation(left, right, /, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doOperation(left, right, /, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doOperation(left, right, /, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doOperation(left, right, /, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doOperation(left, right, /, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_MODULO: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doOperation(left, right, %, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doOperation(left, right, %, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doOperation(left, right, %, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doOperation(left, right, %, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doOperation(left, right, %, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doOperation(left, right, %, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doOperation(left, right, %, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doOperation(left, right, %, AstTreeInt, i8);
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported %s",
-                 AST_TREE_TOKEN_STRINGS[right->type->token]);
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_EQUAL: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doLogicalOperation(left, right, ==, AstTreeFloat, f16);
-#endif
-    } else if (left->type == &AST_TREE_TYPE_TYPE) {
-      bool *res = a404m_malloc(sizeof(*res));
-      *res = typeIsEqual(left, right);
-      astTreeDelete(left);
-      left = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, res, &AST_TREE_BOOL_TYPE,
-                        NULL, NULL);
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_NOT_EQUAL: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doLogicalOperation(left, right, !=, AstTreeFloat, f16);
-#endif
-    } else if (left->type == &AST_TREE_TYPE_TYPE) {
-      bool *res = a404m_malloc(sizeof(*res));
-      *res = !typeIsEqual(left, right);
-      astTreeDelete(left);
-      left = newAstTree(AST_TREE_TOKEN_VALUE_BOOL, res, &AST_TREE_BOOL_TYPE,
-                        NULL, NULL);
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_GREATER: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doLogicalOperation(left, right, >, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_SMALLER: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doLogicalOperation(left, right, <, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doLogicalOperation(left, right, >=, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, u64);
-    } else if (left->type == &AST_TREE_I64_TYPE &&
-               right->type == &AST_TREE_I64_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, i64);
-    } else if (left->type == &AST_TREE_U32_TYPE &&
-               right->type == &AST_TREE_U32_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, u32);
-    } else if (left->type == &AST_TREE_I32_TYPE &&
-               right->type == &AST_TREE_I32_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, i32);
-    } else if (left->type == &AST_TREE_U16_TYPE &&
-               right->type == &AST_TREE_U16_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, u16);
-    } else if (left->type == &AST_TREE_I16_TYPE &&
-               right->type == &AST_TREE_I16_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, i16);
-    } else if (left->type == &AST_TREE_U8_TYPE &&
-               right->type == &AST_TREE_U8_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, u8);
-    } else if (left->type == &AST_TREE_I8_TYPE &&
-               right->type == &AST_TREE_I8_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeInt, i8);
-    } else if (left->type == &AST_TREE_F128_TYPE &&
-               right->type == &AST_TREE_F128_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeFloat, f128);
-    } else if (left->type == &AST_TREE_F64_TYPE &&
-               right->type == &AST_TREE_F64_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeFloat, f64);
-    } else if (left->type == &AST_TREE_F32_TYPE &&
-               right->type == &AST_TREE_F32_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeFloat, f32);
-#ifdef FLOAT_16_SUPPORT
-    } else if (left->type == &AST_TREE_F16_TYPE &&
-               right->type == &AST_TREE_F16_TYPE) {
-      doLogicalOperation(left, right, <=, AstTreeFloat, f16);
-#endif
-    } else {
-      printError(expr->str_begin, expr->str_end, "Not supported");
-      UNREACHABLE;
-    }
-    astTreeDelete(right);
-    return left;
-  }
-  case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND: {
-    AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    *(AstTreeBool *)left->metadata =
-        *(AstTreeBool *)left->metadata && *(AstTreeBool *)right->metadata;
-
-    astTreeDelete(right);
-    return left;
+    AstTreeUnary *metadata = expr->metadata;
+    AstTree *function = runExpression(metadata->function->value, scope,
+                                      shouldRet, false, isComptime);
+    AstTreeFunctionCallParam arguments[] = {
+        (AstTreeFunctionCallParam){
+            .nameBegin = NULL,
+            .nameEnd = NULL,
+            .value = metadata->operand,
+        },
+    };
+    AstTree *ret = runAstTreeFunction(function, arguments, 1, isComptime);
+    astTreeDelete(function);
+    return ret;
   }
+  case AST_TREE_TOKEN_OPERATOR_SUM:
+  case AST_TREE_TOKEN_OPERATOR_SUB:
+  case AST_TREE_TOKEN_OPERATOR_MULTIPLY:
+  case AST_TREE_TOKEN_OPERATOR_DIVIDE:
+  case AST_TREE_TOKEN_OPERATOR_MODULO:
+  case AST_TREE_TOKEN_OPERATOR_EQUAL:
+  case AST_TREE_TOKEN_OPERATOR_NOT_EQUAL:
+  case AST_TREE_TOKEN_OPERATOR_GREATER:
+  case AST_TREE_TOKEN_OPERATOR_SMALLER:
+  case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL:
+  case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL:
+  case AST_TREE_TOKEN_OPERATOR_LOGICAL_AND:
   case AST_TREE_TOKEN_OPERATOR_LOGICAL_OR: {
     AstTreeInfix *metadata = expr->metadata;
-    AstTree *left =
-        runExpression(metadata->left, scope, shouldRet, false, isComptime);
-    AstTree *right =
-        runExpression(metadata->right, scope, shouldRet, false, isComptime);
-
-    *(AstTreeBool *)left->metadata =
-        *(AstTreeBool *)left->metadata || *(AstTreeBool *)right->metadata;
-
-    astTreeDelete(right);
-    return left;
+    AstTree *function = runExpression(metadata->function->value, scope,
+                                      shouldRet, false, isComptime);
+
+    AstTreeFunctionCallParam arguments[] = {
+        (AstTreeFunctionCallParam){
+            .nameBegin = NULL,
+            .nameEnd = NULL,
+            .value = metadata->left,
+        },
+        (AstTreeFunctionCallParam){
+            .nameBegin = NULL,
+            .nameEnd = NULL,
+            .value = metadata->right,
+        },
+    };
+
+    AstTree *ret = runAstTreeFunction(function, arguments, 2, isComptime);
+    astTreeDelete(function);
+    return ret;
   }
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_FUNCTION:
@@ -1200,6 +588,8 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet,
   case AST_TREE_TOKEN_BUILTIN_CAST:
   case AST_TREE_TOKEN_BUILTIN_TYPE_OF:
   case AST_TREE_TOKEN_BUILTIN_IMPORT:
+  case AST_TREE_TOKEN_BUILTIN_STACK_ALLOC:
+  case AST_TREE_TOKEN_BUILTIN_HEAP_ALLOC:
     return copyAstTree(expr);
   case AST_TREE_TOKEN_BUILTIN_IS_COMPTIME: {
     AstTreeBool *metadata = a404m_malloc(sizeof(*metadata));
diff --git a/src/utils/log.c b/src/utils/log.c
index cab0c48..54253de 100644
--- a/src/utils/log.c
+++ b/src/utils/log.c
@@ -15,7 +15,7 @@ void _printLogBack(const char *format, const char *file, int line, ...) {
   free(errorStr);
 }
 
-void _printErrorWarningBack(const char *file, int line, char *begin, char *end,
+void _printErrorWarningBack(const char *file, int line, const char *begin, const char *end,
                             bool isError, const char *format, ...) {
   va_list args;
   va_start(args, end);
diff --git a/src/utils/log.h b/src/utils/log.h
index f9fb7ed..b89876a 100644
--- a/src/utils/log.h
+++ b/src/utils/log.h
@@ -22,4 +22,4 @@
 
 extern void _printLogBack(const char *format, const char *file, int line, ...);
 
-extern void _printErrorWarningBack(const char *file, int line, char *begin, char *end,bool isError,const char *format,  ...);
+extern void _printErrorWarningBack(const char *file, int line, const char *begin, const char *end,bool isError,const char *format,  ...);
-- 
cgit v1.2.3