diff options
| author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-02-18 23:42:10 +0330 | 
|---|---|---|
| committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-02-18 23:42:10 +0330 | 
| commit | df4604f27bbd8ed42ea2c7026c7e4845aafd1a8b (patch) | |
| tree | d877ced731ba28bf0ae8878d18b7eb392ff51404 | |
| parent | 9eb9be33d7623a4759b0794073bd32489b865b3d (diff) | |
add while
fix some memory leaks
| -rw-r--r-- | src/compiler/ast-tree.c | 73 | ||||
| -rw-r--r-- | src/compiler/ast-tree.h | 9 | ||||
| -rw-r--r-- | src/compiler/lexer.c | 10 | ||||
| -rw-r--r-- | src/compiler/lexer.h | 1 | ||||
| -rw-r--r-- | src/compiler/parser.c | 72 | ||||
| -rw-r--r-- | src/compiler/parser.h | 7 | ||||
| -rw-r--r-- | src/runner/runner.c | 49 | ||||
| -rw-r--r-- | test/main.felan | 11 | 
8 files changed, 205 insertions, 27 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 66a5f6b..3d7c675 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -110,6 +110,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = {      "AST_TREE_TOKEN_KEYWORD_PRINT_U64",      "AST_TREE_TOKEN_KEYWORD_RETURN",      "AST_TREE_TOKEN_KEYWORD_IF", +    "AST_TREE_TOKEN_KEYWORD_WHILE",      "AST_TREE_TOKEN_TYPE_FUNCTION",      "AST_TREE_TOKEN_TYPE_TYPE", @@ -337,6 +338,23 @@ void astTreePrint(const AstTree *tree, int indent) {        printf(" ");    }      goto RETURN_SUCCESS; +  case AST_TREE_TOKEN_KEYWORD_WHILE: { +    AstTreeWhile *metadata = tree->metadata; +    printf(",\n"); +    for (int i = 0; i < indent; ++i) +      printf(" "); +    printf("condition=\n"); +    astTreePrint(metadata->condition, indent + 1); +    printf(",\n"); +    for (int i = 0; i < indent; ++i) +      printf(" "); +    printf("body=\n"); +    astTreePrint(metadata->body, indent + 1); +    printf(",\n"); +    for (int i = 0; i < indent; ++i) +      printf(" "); +  } +    goto RETURN_SUCCESS;    case AST_TREE_TOKEN_SCOPE: {      AstTreeScope *metadata = tree->metadata;      printf(",\n"); @@ -487,6 +505,13 @@ void astTreeDestroy(AstTree tree) {      free(metadata);    }      return; +  case AST_TREE_TOKEN_KEYWORD_WHILE: { +    AstTreeWhile *metadata = tree.metadata; +    astTreeDelete(metadata->condition); +    astTreeDelete(metadata->body); +    free(metadata); +  } +    return;    case AST_TREE_TOKEN_SCOPE: {      AstTreeScope *metadata = tree.metadata;      for (size_t i = 0; i < metadata->expressions_size; ++i) { @@ -676,6 +701,7 @@ AstTree *copyAstTree(AstTree *tree) {                        tree->str_begin, tree->str_end);    }    case AST_TREE_TOKEN_KEYWORD_IF: +  case AST_TREE_TOKEN_KEYWORD_WHILE:    case AST_TREE_TOKEN_SCOPE:    case AST_TREE_TOKEN_NONE:    } @@ -802,6 +828,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {      case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL:      case PARSER_TOKEN_SYMBOL_PARENTHESIS:      case PARSER_TOKEN_KEYWORD_IF: +    case PARSER_TOKEN_KEYWORD_WHILE:        goto AFTER_SWITCH;      case PARSER_TOKEN_ROOT:      case PARSER_TOKEN_TYPE_TYPE: @@ -1036,6 +1063,8 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) {      return astTreeParseVariable(parserNode, helper);    case PARSER_TOKEN_KEYWORD_IF:      return astTreeParseIf(parserNode, helper); +  case PARSER_TOKEN_KEYWORD_WHILE: +    return astTreeParseWhile(parserNode, helper);    case PARSER_TOKEN_SYMBOL_EOL:      return astTreeParse((ParserNodeSingleChildMetadata *)parserNode->metadata,                          helper); @@ -1130,6 +1159,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) {        node = (ParserNodeSingleChildMetadata *)node->metadata;        goto OK_NODE;      case PARSER_TOKEN_KEYWORD_IF: +    case PARSER_TOKEN_KEYWORD_WHILE:        goto OK_NODE;      case PARSER_TOKEN_ROOT:      case PARSER_TOKEN_IDENTIFIER: @@ -1512,6 +1542,27 @@ AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper) {                      parserNode->str_begin, parserNode->str_end);  } +AstTree *astTreeParseWhile(ParserNode *parserNode, AstTreeHelper *helper) { +  ParserNodeWhileMetadata *node_metadata = parserNode->metadata; + +  AstTree *condition = astTreeParse(node_metadata->condition, helper); +  if (condition == NULL) { +    return NULL; +  } + +  AstTree *body = astTreeParse(node_metadata->body, helper); +  if (body == NULL) { +    return NULL; +  } + +  AstTreeWhile *metadata = a404m_malloc(sizeof(*metadata)); +  metadata->condition = condition; +  metadata->body = body; + +  return newAstTree(AST_TREE_TOKEN_KEYWORD_WHILE, metadata, NULL, +                    parserNode->str_begin, parserNode->str_end); +} +  AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,                                    AstTreeHelper *p_helper) {    ParserNodeArray *body = parserNode->metadata; @@ -2054,6 +2105,8 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper,      return setTypesVariableDefine(tree, helper);    case AST_TREE_TOKEN_KEYWORD_IF:      return setTypesIf(tree, helper, function); +  case AST_TREE_TOKEN_KEYWORD_WHILE: +    return setTypesWhile(tree, helper, function);    case AST_TREE_TOKEN_SCOPE:      return setTypesScope(tree, helper, function);    case AST_TREE_TOKEN_NONE: @@ -2448,6 +2501,25 @@ bool setTypesIf(AstTree *tree, AstTreeSetTypesHelper helper,    return true;  } +bool setTypesWhile(AstTree *tree, AstTreeSetTypesHelper helper, +                   AstTreeFunction *function) { +  AstTreeWhile *metadata = tree->metadata; + +  if (!setAllTypes(metadata->condition, helper, function) || +      !setAllTypes(metadata->body, helper, function)) { +    return false; +  } + +  if (!typeIsEqual(metadata->condition->type, &AST_TREE_BOOL_TYPE)) { +    printError(metadata->condition->str_begin, metadata->condition->str_end, +               "If condition must be boolean"); +    return false; +  } + +  tree->type = &AST_TREE_VOID_TYPE; +  return true; +} +  bool setTypesScope(AstTree *tree, AstTreeSetTypesHelper helper,                     AstTreeFunction *function) {    AstTreeScope *metadata = tree->metadata; @@ -2497,6 +2569,7 @@ bool astTreeClean(AstTree *tree) {    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_TYPE_TYPE:    case AST_TREE_TOKEN_TYPE_FUNCTION:    case AST_TREE_TOKEN_TYPE_VOID: diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index eaf8b07..b58d413 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -10,6 +10,7 @@ typedef enum AstTreeToken {    AST_TREE_TOKEN_KEYWORD_PRINT_U64,    AST_TREE_TOKEN_KEYWORD_RETURN,    AST_TREE_TOKEN_KEYWORD_IF, +  AST_TREE_TOKEN_KEYWORD_WHILE,    AST_TREE_TOKEN_TYPE_FUNCTION,    AST_TREE_TOKEN_TYPE_TYPE, @@ -149,6 +150,11 @@ typedef struct AstTreeIf {    AstTree *elseBody;  } AstTreeIf; +typedef struct AstTreeWhile { +  AstTree *condition; +  AstTree *body; +} AstTreeWhile; +  typedef struct AstTreeHelper {    AstTreeVariables **variables;    size_t variables_size; @@ -198,6 +204,7 @@ AstTree *astTreeParseUnaryOperator(ParserNode *parserNode,  bool astTreeParseConstant(ParserNode *parserNode, AstTreeHelper *helper);  AstTree *astTreeParseVariable(ParserNode *parserNode, AstTreeHelper *helper);  AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper); +AstTree *astTreeParseWhile(ParserNode *parserNode, AstTreeHelper *helper);  AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,                                    AstTreeHelper *helper);  AstTree *astTreeParseParenthesis(ParserNode *parserNode, AstTreeHelper *helper); @@ -230,6 +237,8 @@ bool setTypesOperatorUnary(AstTree *tree, AstTreeSetTypesHelper helper);  bool setTypesVariableDefine(AstTree *tree, AstTreeSetTypesHelper helper);  bool setTypesIf(AstTree *tree, AstTreeSetTypesHelper helper,                  AstTreeFunction *function); +bool setTypesWhile(AstTree *tree, AstTreeSetTypesHelper helper, +                   AstTreeFunction *function);  bool setTypesScope(AstTree *tree, AstTreeSetTypesHelper helper,                     AstTreeFunction *function); diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c index 7fef9be..6263854 100644 --- a/src/compiler/lexer.c +++ b/src/compiler/lexer.c @@ -33,6 +33,7 @@ const char *LEXER_TOKEN_STRINGS[] = {      "LEXER_TOKEN_KEYWORD_FALSE",      "LEXER_TOKEN_KEYWORD_IF",      "LEXER_TOKEN_KEYWORD_ELSE", +    "LEXER_TOKEN_KEYWORD_WHILE",      "LEXER_TOKEN_NUMBER", @@ -93,9 +94,9 @@ const size_t LEXER_SYMBOL_SIZE =      sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS);  const char *LEXER_KEYWORD_STRINGS[] = { -    "type", "void",      "i8",     "u8",   "i16",   "u16", "i32", -    "u32",  "i64",       "u64",    "f16",  "f32",   "f64", "f128", -    "bool", "print_u64", "return", "true", "false", "if",  "else", +    "type",   "void", "i8",    "u8",  "i16",  "u16",   "i32",  "u32", +    "i64",    "u64",  "f16",   "f32", "f64",  "f128",  "bool", "print_u64", +    "return", "true", "false", "if",  "else", "while",  };  const LexerToken LEXER_KEYWORD_TOKENS[] = {      LEXER_TOKEN_KEYWORD_TYPE,   LEXER_TOKEN_KEYWORD_VOID, @@ -108,7 +109,7 @@ const LexerToken LEXER_KEYWORD_TOKENS[] = {      LEXER_TOKEN_KEYWORD_BOOL,   LEXER_TOKEN_KEYWORD_PRINT_U64,      LEXER_TOKEN_KEYWORD_RETURN, LEXER_TOKEN_KEYWORD_TRUE,      LEXER_TOKEN_KEYWORD_FALSE,  LEXER_TOKEN_KEYWORD_IF, -    LEXER_TOKEN_KEYWORD_ELSE, +    LEXER_TOKEN_KEYWORD_ELSE,   LEXER_TOKEN_KEYWORD_WHILE,  };  const size_t LEXER_KEYWORD_SIZE =      sizeof(LEXER_KEYWORD_TOKENS) / sizeof(*LEXER_KEYWORD_TOKENS); @@ -255,6 +256,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,    case LEXER_TOKEN_KEYWORD_FALSE:    case LEXER_TOKEN_KEYWORD_IF:    case LEXER_TOKEN_KEYWORD_ELSE: +  case LEXER_TOKEN_KEYWORD_WHILE:    case LEXER_TOKEN_NUMBER:    case LEXER_TOKEN_SYMBOL_EOL:    case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS: diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h index 0a6da3a..92d943e 100644 --- a/src/compiler/lexer.h +++ b/src/compiler/lexer.h @@ -26,6 +26,7 @@ typedef enum LexerToken {    LEXER_TOKEN_KEYWORD_FALSE,    LEXER_TOKEN_KEYWORD_IF,    LEXER_TOKEN_KEYWORD_ELSE, +  LEXER_TOKEN_KEYWORD_WHILE,    LEXER_TOKEN_NUMBER, diff --git a/src/compiler/parser.c b/src/compiler/parser.c index 84dca1c..9f6b060 100644 --- a/src/compiler/parser.c +++ b/src/compiler/parser.c @@ -38,6 +38,7 @@ const char *PARSER_TOKEN_STRINGS[] = {      "PARSER_TOKEN_KEYWORD_PRINT_U64",      "PARSER_TOKEN_KEYWORD_RETURN",      "PARSER_TOKEN_KEYWORD_IF", +    "PARSER_TOKEN_KEYWORD_WHILE",      "PARSER_TOKEN_CONSTANT",      "PARSER_TOKEN_VARIABLE", @@ -129,7 +130,7 @@ static constexpr ParserOrder PARSER_ORDER[] = {      },      {          .ltr = true, -        ORDER_ARRAY(LEXER_TOKEN_KEYWORD_IF, ), +        ORDER_ARRAY(LEXER_TOKEN_KEYWORD_IF, LEXER_TOKEN_KEYWORD_WHILE, ),      },  }; @@ -354,7 +355,27 @@ void parserNodePrint(const ParserNode *node, int indent) {      printf("\n");      for (int i = 0; i < indent; ++i)        printf(" "); -    free(metadata); +  } +  case PARSER_TOKEN_KEYWORD_WHILE: { +    ParserNodeIfMetadata *metadata = node->metadata; +    printf(",\n"); +    for (int i = 0; i < indent; ++i) +      printf(" "); +    printf("condition=\n"); +    parserNodePrint(metadata->condition, indent + 1); +    printf(",\n"); +    for (int i = 0; i < indent; ++i) +      printf(" "); +    printf("ifBody=\n"); +    parserNodePrint(metadata->ifBody, indent + 1); +    printf("\n,"); +    for (int i = 0; i < indent; ++i) +      printf(" "); +    printf("elseBody=\n"); +    parserNodePrint(metadata->elseBody, indent + 1); +    printf("\n"); +    for (int i = 0; i < indent; ++i) +      printf(" ");    }      goto RETURN_SUCCESS;    case PARSER_TOKEN_NONE: @@ -483,6 +504,13 @@ void parserNodeDelete(ParserNode *node) {      free(metadata);    }      goto RETURN_SUCCESS; +  case PARSER_TOKEN_KEYWORD_WHILE: { +    ParserNodeWhileMetadata *metadata = node->metadata; +    parserNodeDelete(metadata->condition); +    parserNodeDelete(metadata->body); +    free(metadata); +  } +    goto RETURN_SUCCESS;    case PARSER_TOKEN_NONE:    }    UNREACHABLE; @@ -692,6 +720,8 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,    }    case LEXER_TOKEN_KEYWORD_IF:      return parserIf(node, end, parent); +  case LEXER_TOKEN_KEYWORD_WHILE: +    return parserWhile(node, end, parent);    case LEXER_TOKEN_KEYWORD_ELSE:    case LEXER_TOKEN_SYMBOL:    case LEXER_TOKEN_SYMBOL_OPEN_PARENTHESIS: @@ -1058,6 +1088,7 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,        switch (bodyArray->data[i]->token) {        case PARSER_TOKEN_SYMBOL_EOL:        case PARSER_TOKEN_KEYWORD_IF: +      case PARSER_TOKEN_KEYWORD_WHILE:          continue;        case PARSER_TOKEN_ROOT:        case PARSER_TOKEN_IDENTIFIER: @@ -1364,6 +1395,40 @@ ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent) {                                 elseBody->str_end, metadata, parent);  } +ParserNode *parserWhile(LexerNode *node, LexerNode *end, ParserNode *parent) { +  LexerNode *conditionNode = node + 1; +  if (conditionNode >= end) { +    printError(node->str_begin, node->str_end, "While has no condition"); +    return NULL; +  } + +  ParserNode *condition = +      getUntilCommonParent(conditionNode->parserNode, parent); + +  if (condition == NULL) { +    printError(conditionNode->str_begin, conditionNode->str_end, +               "While has bad condition"); +    return NULL; +  } + +  LexerNode *bodyNode = +      getNextLexerNodeUsingCommonParent(conditionNode, end, parent); +  ParserNode *body = getUntilCommonParent(bodyNode->parserNode, parent); + +  if (body == NULL) { +    printError(node->str_begin, node->str_end, "While has bad body"); +    return NULL; +  } + +  ParserNodeWhileMetadata *metadata = a404m_malloc(sizeof(*metadata)); +  metadata->condition = condition; +  metadata->body = body; + +  return condition->parent = body->parent = node->parserNode = +             newParserNode(PARSER_TOKEN_KEYWORD_WHILE, node->str_begin, +                           body->str_end, metadata, parent); +} +  bool isAllArguments(const ParserNodeArray *nodes) {    for (size_t i = 0; i < nodes->size; ++i) {      const ParserNode *node = nodes->data[i]; @@ -1402,6 +1467,7 @@ bool isExpression(ParserNode *node) {    case PARSER_TOKEN_VALUE_FLOAT:    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: @@ -1478,6 +1544,7 @@ bool isType(ParserNode *node) {    case PARSER_TOKEN_OPERATOR_GREATER_OR_EQUAL:    case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL:    case PARSER_TOKEN_KEYWORD_IF: +  case PARSER_TOKEN_KEYWORD_WHILE:      return false;    case PARSER_TOKEN_NONE:    } @@ -1533,6 +1600,7 @@ bool isValue(ParserNode *node) {    case PARSER_TOKEN_SYMBOL_COMMA:    case PARSER_TOKEN_KEYWORD_PRINT_U64:    case PARSER_TOKEN_KEYWORD_RETURN: +  case PARSER_TOKEN_KEYWORD_WHILE:      return false;    case PARSER_TOKEN_NONE:    } diff --git a/src/compiler/parser.h b/src/compiler/parser.h index 3af47e7..6fe6d6f 100644 --- a/src/compiler/parser.h +++ b/src/compiler/parser.h @@ -34,6 +34,7 @@ typedef enum ParserToken {    PARSER_TOKEN_KEYWORD_PRINT_U64,    PARSER_TOKEN_KEYWORD_RETURN,    PARSER_TOKEN_KEYWORD_IF, +  PARSER_TOKEN_KEYWORD_WHILE,    PARSER_TOKEN_CONSTANT,    PARSER_TOKEN_VARIABLE, @@ -131,6 +132,11 @@ typedef struct ParserNodeIfMetadata {    ParserNode *elseBody;  } ParserNodeIfMetadata; +typedef struct ParserNodeWhileMetadata { +  ParserNode *condition; +  ParserNode *body; +} ParserNodeWhileMetadata; +  void parserNodePrint(const ParserNode *node, int indent);  void parserNodeDelete(ParserNode *node); @@ -175,6 +181,7 @@ ParserNode *parserBinaryOrLeftOperator(LexerNode *node, LexerNode *begin,                                         ParserToken token,                                         LexerToken laterToken);  ParserNode *parserIf(LexerNode *node, LexerNode *end, ParserNode *parent); +ParserNode *parserWhile(LexerNode *node, LexerNode *end, ParserNode *parent);  bool isAllArguments(const ParserNodeArray *nodes); diff --git a/src/runner/runner.c b/src/runner/runner.c index 0c8fbdd..54d6cfc 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -17,24 +17,24 @@        (void *)(u64)((type) * (originalType *)(op0)->metadata operator(type) *  \                      (originalType *)(op1)->metadata) -#define doLogicalOperation(op0, op1, operator, originalType, _type)             \ +#define doLogicalOperation(op0, op1, operator, originalType, _type)            \    {                                                                            \ -    bool res = (bool)((_type)(originalType)(op0)                                \ +    bool res = (bool)((_type)(originalType)(op0)                               \                            ->metadata                                           \ -                          operator(_type)(originalType)(op1)                    \ +                          operator(_type)(originalType)(op1)                   \                            ->metadata);                                         \      astTreeDestroy(*(op0));                                                    \ -    (op0)->metadata = (void*)(u64)res;                                                     \ -    (op0)->type = &AST_TREE_BOOL_TYPE;                                          \ +    (op0)->metadata = (void *)(u64)res;                                        \ +    (op0)->type = &AST_TREE_BOOL_TYPE;                                         \    } -#define doLogicalOperationFloat(op0, op1, operator, originalType, _type)        \ +#define doLogicalOperationFloat(op0, op1, operator, originalType, _type)       \    {                                                                            \ -    bool res = (bool)(((_type) * ((originalType *)(op0)->metadata)) operator(   \ -        (_type) * ((originalType *)(op1)->metadata)));                          \ +    bool res = (bool)(((_type) * ((originalType *)(op0)->metadata)) operator(  \ +        (_type) * ((originalType *)(op1)->metadata)));                         \      astTreeDestroy(*(op0));                                                    \ -    (op0)->metadata = (void*)(u64)res;                                                     \ -    (op0)->type = &AST_TREE_BOOL_TYPE;                                          \ +    (op0)->metadata = (void *)(u64)res;                                        \ +    (op0)->type = &AST_TREE_BOOL_TYPE;                                         \    }  #define doLeftOperation(op0, operator, originalType, type)                     \ @@ -340,7 +340,20 @@ AstTree *runExpression(AstTree *expr, RunnerVariablePages *pages) {      astTreeDelete(tree);      return ret;    } -    return NULL; +  case AST_TREE_TOKEN_KEYWORD_WHILE: { +    AstTreeWhile *metadata = expr->metadata; +    AstTree *ret = NULL; +    while (true) { +      AstTree *tree = calcAstTreeValue(metadata->condition, pages); +      bool conti = (AstTreeBool)tree->metadata; +      astTreeDelete(tree); +      if (!conti) { +        break; +      } +      ret = runExpression(metadata->body, pages); +    } +    return ret; +  }    case AST_TREE_TOKEN_SCOPE: {      AstTreeScope *metadata = expr->metadata; @@ -365,12 +378,20 @@ AstTree *runExpression(AstTree *expr, RunnerVariablePages *pages) {        runnerVariablePush(newPages.data[newPages.size - 1], variable);      } +    AstTree *ret = NULL;      for (size_t i = 0; i < metadata->expressions_size; ++i) { -      AstTree *r = runExpression(metadata->expressions[i], &newPages); -      if (r) { -        return r; +      ret = runExpression(metadata->expressions[i], &newPages); +    } +    for (size_t i = 0; i < newPages.data[pages->size]->size; ++i) { +      if (newPages.data[pages->size]->data[i]->value) { +        astTreeDelete(newPages.data[pages->size]->data[i]->value);        } +      free(newPages.data[pages->size]->data[i]);      } +    free(newPages.data[pages->size]->data); +    free(newPages.data[pages->size]); +    free(newPages.data); +    return ret;    }      return NULL;    case AST_TREE_TOKEN_OPERATOR_PLUS: diff --git a/test/main.felan b/test/main.felan index 9d77aea..b99a284 100644 --- a/test/main.felan +++ b/test/main.felan @@ -1,10 +1,7 @@  main :: () -> void { -  a :f32 = 23; -  b :f64 = 54.5; -  c :f128 = 1.0; -  d :f16 = 5.5; -  if -a == -23.0 -    print_u64 1; -  else +  a := 10000; +  while a > 0 {      print_u64 2; +    a = a -1; +  }  };  |