summaryrefslogtreecommitdiff
path: root/src/compiler/ast-tree.c
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-02-12 11:55:38 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-02-12 11:55:38 +0330
commit5c336962d3d0a885a870708076f154ee422fee12 (patch)
tree6f24bf2de914d94fd309d34c7c82e8025692154b /src/compiler/ast-tree.c
parent217b2c70adfd60756591dd6b06b60279f805a596 (diff)
add if
Diffstat (limited to 'src/compiler/ast-tree.c')
-rw-r--r--src/compiler/ast-tree.c131
1 files changed, 118 insertions, 13 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 4976750..f92b95c 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -211,7 +211,23 @@ void astTreePrint(const AstTree *tree, int indent) {
printf(" ");
}
goto RETURN_SUCCESS;
-
+ case AST_TREE_TOKEN_KEYWORD_IF: {
+ AstTreeIf *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_NONE:
}
@@ -313,6 +329,13 @@ void astTreeDestroy(AstTree tree) {
free(metadata);
}
return;
+ case AST_TREE_TOKEN_KEYWORD_IF: {
+ AstTreeIf *metadata = tree.metadata;
+ astTreeDelete(metadata->condition);
+ astTreeDelete(metadata->body);
+ free(metadata);
+ }
+ return;
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -582,6 +605,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
case PARSER_TOKEN_OPERATOR_DIVIDE:
case PARSER_TOKEN_OPERATOR_MODULO:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
+ case PARSER_TOKEN_KEYWORD_IF:
goto AFTER_SWITCH;
case PARSER_TOKEN_ROOT:
case PARSER_TOKEN_TYPE_TYPE:
@@ -764,8 +788,12 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) {
AST_TREE_TOKEN_OPERATOR_MINUS);
case PARSER_TOKEN_VARIABLE:
return astTreeParseVariable(parserNode, helper);
- case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_KEYWORD_IF:
+ return astTreeParseIf(parserNode, helper);
case PARSER_TOKEN_SYMBOL_EOL:
+ return astTreeParse((ParserNodeSingleChildMetadata *)parserNode->metadata,
+ helper);
+ case PARSER_TOKEN_CONSTANT:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_COMMA:
@@ -848,13 +876,46 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) {
}
for (size_t i = 0; i < body->size; ++i) {
- ParserNode *eol = body->data[i];
- if (eol->token != PARSER_TOKEN_SYMBOL_EOL) {
- printError(eol->str_begin, eol->str_end, "Unexpected %s",
- PARSER_TOKEN_STRINGS[eol->token]);
+ ParserNode *node = body->data[i];
+ switch (node->token) {
+ case PARSER_TOKEN_SYMBOL_EOL:
+ node = (ParserNodeSingleChildMetadata *)node->metadata;
+ goto OK_NODE;
+ case PARSER_TOKEN_KEYWORD_IF:
+ goto OK_NODE;
+ case PARSER_TOKEN_ROOT:
+ case PARSER_TOKEN_IDENTIFIER:
+ case PARSER_TOKEN_VALUE_U64:
+ case PARSER_TOKEN_VALUE_BOOL:
+ case PARSER_TOKEN_TYPE_TYPE:
+ case PARSER_TOKEN_TYPE_FUNCTION:
+ case PARSER_TOKEN_TYPE_VOID:
+ case PARSER_TOKEN_TYPE_U64:
+ case PARSER_TOKEN_TYPE_BOOL:
+ case PARSER_TOKEN_KEYWORD_PRINT_U64:
+ case PARSER_TOKEN_KEYWORD_RETURN:
+ case PARSER_TOKEN_CONSTANT:
+ case PARSER_TOKEN_VARIABLE:
+ case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
+ case PARSER_TOKEN_SYMBOL_PARENTHESIS:
+ case PARSER_TOKEN_SYMBOL_COMMA:
+ case PARSER_TOKEN_OPERATOR_ASSIGN:
+ case PARSER_TOKEN_OPERATOR_PLUS:
+ case PARSER_TOKEN_OPERATOR_MINUS:
+ case PARSER_TOKEN_OPERATOR_SUM:
+ case PARSER_TOKEN_OPERATOR_SUB:
+ case PARSER_TOKEN_OPERATOR_MULTIPLY:
+ case PARSER_TOKEN_OPERATOR_DIVIDE:
+ case PARSER_TOKEN_OPERATOR_MODULO:
+ case PARSER_TOKEN_FUNCTION_DEFINITION:
+ case PARSER_TOKEN_FUNCTION_CALL:
+ printError(node->str_begin, node->str_end, "Unexpected %s",
+ PARSER_TOKEN_STRINGS[node->token]);
goto RETURN_ERROR;
+ case PARSER_TOKEN_NONE:
}
- ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
+ UNREACHABLE;
+ OK_NODE:
if (node->token == PARSER_TOKEN_CONSTANT) {
if (!astTreeParseConstant(node, &helper)) {
@@ -1147,15 +1208,31 @@ RETURN_ERROR:
return NULL;
}
+AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper) {
+ ParserNodeIfMetadata *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;
+ }
+
+ AstTreeIf *metadata = a404m_malloc(sizeof(*metadata));
+ metadata->condition = condition;
+ metadata->body = body;
+
+ return newAstTree(AST_TREE_TOKEN_KEYWORD_IF, metadata, NULL,
+ parserNode->str_begin, parserNode->str_end);
+}
+
AstTreeFunction *getFunction(AstTree *value) {
switch (value->token) {
case AST_TREE_TOKEN_FUNCTION:
return value->metadata;
- case AST_TREE_TOKEN_FUNCTION_CALL: {
- AstTreeFunctionCall *metadata = value->metadata;
- AstTreeFunction *function = metadata->function->metadata;
- return getFunction(function->returnType);
- }
case AST_TREE_TOKEN_VARIABLE: {
AstTreeVariable *metadata = value->metadata;
if (metadata->value->token == AST_TREE_TOKEN_FUNCTION) {
@@ -1164,8 +1241,10 @@ AstTreeFunction *getFunction(AstTree *value) {
return NULL;
}
}
+ case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -1203,6 +1282,7 @@ bool isConst(AstTree *value) {
return true;
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:
@@ -1280,6 +1360,7 @@ AstTree *makeTypeOf(AstTree *value) {
case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -1290,6 +1371,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
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_VALUE_VOID:
case AST_TREE_TOKEN_VALUE_U64:
case AST_TREE_TOKEN_VALUE_BOOL:
@@ -1392,10 +1474,11 @@ bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable,
case AST_TREE_TOKEN_FUNCTION: {
return false;
}
- case AST_TREE_TOKEN_NONE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
case AST_TREE_TOKEN_VARIABLE_DEFINE:
+ case AST_TREE_TOKEN_KEYWORD_IF:
+ case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
}
@@ -1458,6 +1541,8 @@ bool setAllTypes(AstTree *tree, AstTreeFunction *function) {
return setTypesOperatorInfix(tree);
case AST_TREE_TOKEN_VARIABLE_DEFINE:
return setTypesVariableDefine(tree);
+ case AST_TREE_TOKEN_KEYWORD_IF:
+ return setTypesIf(tree, function);
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -1644,6 +1729,25 @@ bool setTypesAstVariable(AstTreeVariable *variable) {
return true;
}
+bool setTypesIf(AstTree *tree, AstTreeFunction *function) {
+ AstTreeIf *metadata = tree->metadata;
+
+ if (!setAllTypes(metadata->condition, function) ||
+ !setAllTypes(metadata->body, 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 setTypesAstInfix(AstTreeInfix *infix) {
return setAllTypes(&infix->left, NULL) && setAllTypes(&infix->right, NULL);
}
@@ -1664,6 +1768,7 @@ bool astTreeClean(AstTree *tree) {
return astTreeCleanFunction(tree);
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
+ case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_TYPE_VOID: