From 30210fac06a6719a1f547a8cd1e24c159d7e7ee7 Mon Sep 17 00:00:00 2001
From: A404M <ahmadmahmoudiprogrammer@gmail.com>
Date: Fri, 21 Feb 2025 23:53:32 +0330
Subject: add a lot of goodies in types

---
 src/compiler/ast-tree.c | 135 ++++++++++++++++++++++++++++++++----------------
 src/compiler/ast-tree.h |  19 ++++---
 src/compiler/parser.c   |  10 +++-
 3 files changed, 111 insertions(+), 53 deletions(-)

(limited to 'src/compiler')

diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 4d6c3ee..7211dd4 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -1,6 +1,7 @@
 #include "ast-tree.h"
 
 #include "compiler/parser.h"
+#include "runner/runner.h"
 #include "utils/log.h"
 #include "utils/memory.h"
 #include <stdint.h>
@@ -882,7 +883,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
   }
 
   helper.variable = NULL;
-  if (!setAllTypesRoot(root, &helper) || !astTreeCleanRoot(root)) {
+  if (!setAllTypesRoot(root, &helper) || !astTreeCleanRoot(root, &helper)) {
     goto RETURN_ERROR;
   }
 
@@ -1750,9 +1751,8 @@ AstTreeFunction *getFunction(AstTree *value) {
   UNREACHABLE;
 }
 
-bool isConst(AstTree *value) {
-  switch (value->token) {
-  case AST_TREE_TOKEN_FUNCTION:
+bool isConst(AstTree *tree, AstTreeHelper *helper) {
+  switch (tree->token) {
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_FUNCTION:
   case AST_TREE_TOKEN_TYPE_VOID:
@@ -1769,10 +1769,26 @@ bool isConst(AstTree *value) {
   case AST_TREE_TOKEN_VALUE_INT:
   case AST_TREE_TOKEN_VALUE_BOOL:
     return true;
+  case AST_TREE_TOKEN_KEYWORD_IF: {
+    AstTreeIf *metadata = tree->metadata;
+    return isConst(metadata->condition, helper) &&
+           isConst(metadata->ifBody, helper) &&
+           (metadata->elseBody == NULL || isConst(metadata->elseBody, helper));
+  }
+  case AST_TREE_TOKEN_FUNCTION_CALL: {
+    AstTreeFunctionCall *metadata = tree->metadata;
+    for (size_t i = 0; i < metadata->parameters_size; ++i) {
+      if (!isConst(metadata->parameters[i], helper)) {
+        return false;
+      }
+    }
+    return isConst(metadata->function, helper);
+  }
+  case AST_TREE_TOKEN_FUNCTION: {
+    AstTreeFunction *function;
+  }
   case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
   case AST_TREE_TOKEN_KEYWORD_RETURN:
-  case AST_TREE_TOKEN_KEYWORD_IF:
-  case AST_TREE_TOKEN_FUNCTION_CALL:
   case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
   case AST_TREE_TOKEN_OPERATOR_PLUS:
@@ -1791,7 +1807,7 @@ bool isConst(AstTree *value) {
   case AST_TREE_TOKEN_SCOPE:
     return false;
   case AST_TREE_TOKEN_VARIABLE: {
-    AstTreeVariable *metadata = value->metadata;
+    AstTreeVariable *metadata = tree->metadata;
     return metadata->isConst;
   }
   case AST_TREE_TOKEN_NONE:
@@ -1947,10 +1963,13 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
   UNREACHABLE;
 }
 
-AstTree *getValue(AstTree *tree) {
+AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper) {
+  if (!isConst(tree, helper.treeHelper)) {
+    printLog("Can't get value at compile time because it is not const");
+    return NULL;
+  }
   switch (tree->token) {
   case AST_TREE_TOKEN_TYPE_FUNCTION:
-    return copyAstTree(tree);
   case AST_TREE_TOKEN_TYPE_TYPE:
   case AST_TREE_TOKEN_TYPE_VOID:
   case AST_TREE_TOKEN_TYPE_I8:
@@ -1966,24 +1985,22 @@ AstTree *getValue(AstTree *tree) {
   case AST_TREE_TOKEN_TYPE_F64:
   case AST_TREE_TOKEN_TYPE_F128:
   case AST_TREE_TOKEN_TYPE_BOOL:
-    return tree;
-  case AST_TREE_TOKEN_VARIABLE: {
-    AstTreeVariable *metadata = tree->metadata;
-    if (metadata->isConst) {
-      return getValue(metadata->value);
-    }
-  }
-  case AST_TREE_TOKEN_FUNCTION:
-  case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
-  case AST_TREE_TOKEN_KEYWORD_RETURN:
-  case AST_TREE_TOKEN_KEYWORD_IF:
-  case AST_TREE_TOKEN_KEYWORD_WHILE:
-  case AST_TREE_TOKEN_FUNCTION_CALL:
-  case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_VALUE_VOID:
   case AST_TREE_TOKEN_VALUE_INT:
   case AST_TREE_TOKEN_VALUE_FLOAT:
   case AST_TREE_TOKEN_VALUE_BOOL:
+    return copyAstTree(tree);
+  case AST_TREE_TOKEN_VARIABLE: {
+    AstTreeVariable *metadata = tree->metadata;
+    return getValue(metadata->value, helper);
+  }
+  case AST_TREE_TOKEN_FUNCTION_CALL: {
+    AstTree *value = runExpression(tree, helper.pages);
+    if (value == NULL) {
+      printError(tree->str_begin, tree->str_end, "Unknown error");
+    }
+    return value;
+  }
   case AST_TREE_TOKEN_OPERATOR_ASSIGN:
   case AST_TREE_TOKEN_OPERATOR_PLUS:
   case AST_TREE_TOKEN_OPERATOR_MINUS:
@@ -1997,7 +2014,19 @@ AstTree *getValue(AstTree *tree) {
   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_SMALLER_OR_EQUAL: {
+    AstTree *value = calcAstTreeValue(tree, helper.pages);
+    if (value == NULL) {
+      printError(tree->str_begin, tree->str_end, "Unknown error");
+    }
+    return value;
+  }
+  case AST_TREE_TOKEN_FUNCTION:
+  case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+  case AST_TREE_TOKEN_KEYWORD_RETURN:
+  case AST_TREE_TOKEN_KEYWORD_IF:
+  case AST_TREE_TOKEN_KEYWORD_WHILE:
+  case AST_TREE_TOKEN_VARIABLE_DEFINE:
   case AST_TREE_TOKEN_SCOPE:
   case AST_TREE_TOKEN_NONE:
   }
@@ -2090,8 +2119,12 @@ bool setAllTypesRoot(AstTreeRoot *root, AstTreeHelper *helper) {
     }
   }
 
+  RunnerVariablePages pages = initRootPages();
+
   AstTreeSetTypesHelper setTypesHelper = {
       .lookingType = NULL,
+      .treeHelper = helper,
+      .pages = &pages,
   };
 
   for (size_t i = 0; i < root->variables.size; ++i) {
@@ -2351,10 +2384,11 @@ bool setTypesFunction(AstTree *tree, AstTreeSetTypesHelper helper) {
 }
 
 bool setTypesPrintU64(AstTree *tree, AstTreeSetTypesHelper _helper) {
-  (void)(_helper);
   AstTreeSingleChild *metadata = tree->metadata;
   AstTreeSetTypesHelper helper = {
       .lookingType = &AST_TREE_U64_TYPE,
+      .treeHelper = _helper.treeHelper,
+      .pages = _helper.pages,
   };
   if (!setAllTypes(metadata, helper, NULL)) {
     return false;
@@ -2450,7 +2484,7 @@ bool setTypesOperatorAssign(AstTree *tree, AstTreeSetTypesHelper helper) {
   } else if (!typeIsEqual(infix->left.type, infix->right.type)) {
     printError(tree->str_begin, tree->str_end, "Type mismatch");
     return false;
-  } else if (isConst(&infix->left)) {
+  } else if (isConst(&infix->left, helper.treeHelper)) {
     printError(tree->str_begin, tree->str_end, "Constants can't be assigned");
     return false;
   } else {
@@ -2504,9 +2538,10 @@ bool setTypesVariableDefine(AstTree *tree, AstTreeSetTypesHelper helper) {
 
 bool setTypesAstVariable(AstTreeVariable *variable,
                          AstTreeSetTypesHelper _helper) {
-  (void)_helper;
   AstTreeSetTypesHelper helper = {
       .lookingType = &AST_TREE_TYPE_TYPE,
+      .treeHelper = _helper.treeHelper,
+      .pages = _helper.pages,
   };
 
   if (variable->type != NULL && !setAllTypes(variable->type, helper, NULL)) {
@@ -2515,7 +2550,10 @@ bool setTypesAstVariable(AstTreeVariable *variable,
 
   if (variable->type != NULL) {
     AstTree *type = variable->type;
-    variable->type = getValue(type);
+    variable->type = getValue(type, helper);
+    if (variable->type == NULL) {
+      return false;
+    }
     astTreeDelete(type);
   }
 
@@ -2614,25 +2652,32 @@ bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) {
   }
   AstTreeSetTypesHelper newHelper = {
       .lookingType = infix->left.type,
+      .treeHelper = helper.treeHelper,
+      .pages = helper.pages,
   };
 
   return setAllTypes(&infix->right, newHelper, NULL);
 }
 
-bool astTreeCleanRoot(AstTreeRoot *root) {
+bool astTreeCleanRoot(AstTreeRoot *root, AstTreeHelper *_helper) {
+  AstTreeSetTypesHelper helper = {
+      .lookingType = NULL,
+      .treeHelper = _helper,
+      .pages = helper.pages,
+  };
   for (size_t i = 0; i < root->variables.size; ++i) {
-    astTreeClean(root->variables.data[i]->value);
-    astTreeClean(root->variables.data[i]->type);
+    astTreeClean(root->variables.data[i]->value, helper);
+    astTreeClean(root->variables.data[i]->type, helper);
   }
   return true;
 }
 
-bool astTreeClean(AstTree *tree) {
+bool astTreeClean(AstTree *tree, AstTreeSetTypesHelper helper) {
   switch (tree->token) {
   case AST_TREE_TOKEN_VARIABLE:
-    return astTreeCleanVariable(tree);
+    return astTreeCleanVariable(tree, helper);
   case AST_TREE_TOKEN_FUNCTION:
-    return astTreeCleanFunction(tree);
+    return astTreeCleanFunction(tree, helper);
   case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
   case AST_TREE_TOKEN_KEYWORD_RETURN:
   case AST_TREE_TOKEN_KEYWORD_IF:
@@ -2681,28 +2726,28 @@ bool astTreeClean(AstTree *tree) {
   UNREACHABLE;
 }
 
-bool astTreeCleanFunction(AstTree *tree) {
+bool astTreeCleanFunction(AstTree *tree, AstTreeSetTypesHelper helper) {
   AstTreeFunction *metadata = tree->metadata;
 
   for (size_t i = 0; i < metadata->arguments.size; ++i) {
     if (metadata->arguments.data[i]->value != NULL &&
-        !astTreeClean(metadata->arguments.data[i]->value)) {
+        !astTreeClean(metadata->arguments.data[i]->value, helper)) {
       return false;
     }
   }
 
-  if (!astTreeClean(metadata->returnType)) {
+  if (!astTreeClean(metadata->returnType, helper)) {
     return false;
   }
 
   for (size_t i = 0; i < metadata->scope.expressions_size; ++i) {
-    if (!astTreeClean(metadata->scope.expressions[i])) {
+    if (!astTreeClean(metadata->scope.expressions[i], helper)) {
       return false;
     }
   }
 
   for (size_t i = 0; i < metadata->scope.variables.size; ++i) {
-    if (!astTreeCleanAstVariable(metadata->scope.variables.data[i])) {
+    if (!astTreeCleanAstVariable(metadata->scope.variables.data[i], helper)) {
       return false;
     }
   }
@@ -2710,12 +2755,14 @@ bool astTreeCleanFunction(AstTree *tree) {
   return true;
 }
 
-bool astTreeCleanVariable(AstTree *tree) {
-  return astTreeCleanAstVariable(tree->metadata);
+bool astTreeCleanVariable(AstTree *tree, AstTreeSetTypesHelper helper) {
+  return astTreeCleanAstVariable(tree->metadata, helper);
 }
 
-bool astTreeCleanAstVariable(AstTreeVariable *variable) {
-  if (!astTreeClean(variable->value) || !astTreeClean(variable->type)) {
+bool astTreeCleanAstVariable(AstTreeVariable *variable,
+                             AstTreeSetTypesHelper helper) {
+  if (!astTreeClean(variable->value, helper) ||
+      !astTreeClean(variable->type, helper)) {
     return false;
   }
   AstTree *value = variable->value;
@@ -2734,7 +2781,7 @@ bool astTreeCleanAstVariable(AstTreeVariable *variable) {
     variable->value = copyAstTree(value);
   }
 
-  if (variable->isConst && !isConst(value)) {
+  if (variable->isConst && !isConst(value, helper.treeHelper)) {
     return false;
   }
 
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index c8f5f75..18703c8 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -162,8 +162,12 @@ typedef struct AstTreeHelper {
   AstTreeVariables *globalDeps;
 } AstTreeHelper;
 
+struct RunnerVariablePages;
+
 typedef struct AstTreeSetTypesHelper {
   AstTree *lookingType;
+  AstTreeHelper *treeHelper;
+  struct RunnerVariablePages *pages;
 } AstTreeSetTypesHelper;
 
 void astTreePrint(const AstTree *tree, int indent);
@@ -210,10 +214,10 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,
 AstTree *astTreeParseParenthesis(ParserNode *parserNode, AstTreeHelper *helper);
 
 AstTreeFunction *getFunction(AstTree *value);
-bool isConst(AstTree *value);
+bool isConst(AstTree *tree, AstTreeHelper *helper);
 AstTree *makeTypeOf(AstTree *value);
 bool typeIsEqual(const AstTree *type0, const AstTree *type1);
-AstTree *getValue(AstTree *tree);
+AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper);
 
 bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable,
                             AstTree *tree);
@@ -247,10 +251,11 @@ bool setTypesAstVariable(AstTreeVariable *variable,
                          AstTreeSetTypesHelper helper);
 bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper);
 
-bool astTreeCleanRoot(AstTreeRoot *root);
-bool astTreeClean(AstTree *tree);
-bool astTreeCleanFunction(AstTree *tree);
-bool astTreeCleanVariable(AstTree *tree);
-bool astTreeCleanAstVariable(AstTreeVariable *variable);
+bool astTreeCleanRoot(AstTreeRoot *root, AstTreeHelper *helper);
+bool astTreeClean(AstTree *tree, AstTreeSetTypesHelper helper);
+bool astTreeCleanFunction(AstTree *tree, AstTreeSetTypesHelper helper);
+bool astTreeCleanVariable(AstTree *tree, AstTreeSetTypesHelper helper);
+bool astTreeCleanAstVariable(AstTreeVariable *variable,
+                             AstTreeSetTypesHelper helper);
 
 size_t astTreeTypeSize(AstTree tree);
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index c5721f1..b2cfd2b 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -56,6 +56,12 @@ const char *PARSER_TOKEN_STRINGS[] = {
     "PARSER_TOKEN_OPERATOR_MULTIPLY",
     "PARSER_TOKEN_OPERATOR_DIVIDE",
     "PARSER_TOKEN_OPERATOR_MODULO",
+    "PARSER_TOKEN_OPERATOR_EQUAL",
+    "PARSER_TOKEN_OPERATOR_NOT_EQUAL",
+    "PARSER_TOKEN_OPERATOR_GREATER",
+    "PARSER_TOKEN_OPERATOR_SMALLER",
+    "PARSER_TOKEN_OPERATOR_GREATER_OR_EQUAL",
+    "PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL",
 
     "PARSER_TOKEN_FUNCTION_DEFINITION",
 
@@ -1468,8 +1474,6 @@ bool isExpression(ParserNode *node) {
   case PARSER_TOKEN_VALUE_BOOL:
   case PARSER_TOKEN_KEYWORD_IF:
   case PARSER_TOKEN_KEYWORD_WHILE:
-    return true;
-  case PARSER_TOKEN_ROOT:
   case PARSER_TOKEN_TYPE_TYPE:
   case PARSER_TOKEN_TYPE_FUNCTION:
   case PARSER_TOKEN_TYPE_VOID:
@@ -1486,6 +1490,8 @@ bool isExpression(ParserNode *node) {
   case PARSER_TOKEN_TYPE_F32:
   case PARSER_TOKEN_TYPE_F64:
   case PARSER_TOKEN_TYPE_F128:
+    return true;
+  case PARSER_TOKEN_ROOT:
   case PARSER_TOKEN_SYMBOL_EOL:
   case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
   case PARSER_TOKEN_SYMBOL_COMMA:
-- 
cgit v1.2.3