summaryrefslogtreecommitdiff
path: root/src/compiler/ast-tree.c
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-01-28 03:40:39 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-01-28 03:44:01 +0330
commit5adca3ef1277b9e7f8f4d77e1b2ecce9ad78d76b (patch)
tree1abc6fe5850b90b6c3956538e8be93ce1ebdb672 /src/compiler/ast-tree.c
parentaa69d90b4f0d8bb0d320c245ebf9b47741f655fe (diff)
clean syntax to not allowing variable definition else where
Diffstat (limited to 'src/compiler/ast-tree.c')
-rw-r--r--src/compiler/ast-tree.c178
1 files changed, 135 insertions, 43 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 96f439d..b03754d 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -11,6 +11,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
"AST_TREE_TOKEN_KEYWORD_PRINT_U64",
+ "AST_TREE_TOKEN_TYPE_TYPE",
"AST_TREE_TOKEN_TYPE_FUNCTION",
"AST_TREE_TOKEN_TYPE_VOID",
"AST_TREE_TOKEN_TYPE_U64",
@@ -19,8 +20,6 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
"AST_TREE_TOKEN_VARIABLE",
"AST_TREE_TOKEN_VALUE_U64",
- "AST_TREE_TOKEN_VARIABLE_DEFINE",
-
"AST_TREE_TOKEN_NONE",
};
@@ -66,6 +65,7 @@ void astTreePrint(const AstTree *tree, int indent) {
printf("]");
}
goto RETURN_SUCCESS;
+ case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
goto RETURN_SUCCESS;
@@ -118,7 +118,6 @@ void astTreePrint(const AstTree *tree, int indent) {
printf("]");
}
goto RETURN_SUCCESS;
- case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_VARIABLE: {
AstTreeVariable *metadata = tree->metadata;
printf(",variable.name=%.*s",
@@ -167,6 +166,7 @@ void astTreeDestroy(AstTree tree) {
free(metadata);
}
return;
+ case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_VALUE_U64:
@@ -196,7 +196,6 @@ void astTreeDestroy(AstTree tree) {
free(metadata);
}
return;
- case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_VARIABLE: {
// AstTreeIdentifier *metadata = tree.metadata; // not needed
}
@@ -242,6 +241,27 @@ AstTree *newAstTree(AstTreeToken token, void *metadata) {
return result;
}
+AstTree *copyAstTree(AstTree *tree) {
+ switch (tree->token) {
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ case AST_TREE_TOKEN_TYPE_VOID:
+ case AST_TREE_TOKEN_TYPE_U64:
+ return newAstTree(tree->token, NULL);
+ case AST_TREE_TOKEN_VALUE_U64:
+ return newAstTree(AST_TREE_TOKEN_VALUE_U64,
+ (void *)(AstTreeU64)tree->metadata);
+ case AST_TREE_TOKEN_VARIABLE:
+ return newAstTree(AST_TREE_TOKEN_VARIABLE, tree->metadata);
+ case AST_TREE_TOKEN_FUNCTION:
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+ case AST_TREE_TOKEN_TYPE_FUNCTION:
+ case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_NONE:
+ }
+ printLog("Bad token '%d'", tree->token);
+ exit(1);
+}
+
AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
if (parsedRoot->token != PARSER_TOKEN_ROOT) {
return NULL;
@@ -278,20 +298,22 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
}
}
+ AstTreeVariables *variables = &root->variables;
+ constexpr size_t variables_size = 1;
+
for (size_t i = 0; i < nodes->size; ++i) {
ParserNode *node =
(ParserNodeSingleChildMetadata *)nodes->data[i]->metadata;
ParserNodeVariableMetadata *node_metadata = node->metadata;
- AstTree *type;
- if (node_metadata->type != NULL) {
- AstTreeVariables *variables = &root->variables;
- type = astTreeParse(node_metadata->type, &variables, 1);
- if (type == NULL) {
- goto RETURN_ERROR;
- }
- } else {
- type = NULL; // TODO: change this to find type
+ if (node->token != PARSER_TOKEN_CONSTANT) {
+ printLog("Only variables are allowed here");
+ goto RETURN_ERROR;
+ }
+
+ if (node_metadata->value == NULL) {
+ printLog("Variables must be initialized");
+ goto RETURN_ERROR;
}
switch (node_metadata->value->token) {
@@ -300,6 +322,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
goto AFTER_SWITCH;
case PARSER_TOKEN_ROOT:
case PARSER_TOKEN_IDENTIFIER:
+ case PARSER_TOKEN_TYPE_TYPE:
case PARSER_TOKEN_TYPE_FUNCTION:
case PARSER_TOKEN_TYPE_VOID:
case PARSER_TOKEN_TYPE_U64:
@@ -318,16 +341,27 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
goto RETURN_ERROR;
AFTER_SWITCH:
- AstTreeVariables *variables = &root->variables;
- AstTree *value = astTreeParse(node_metadata->value, &variables, 1);
+
+ AstTree *value =
+ astTreeParse(node_metadata->value, &variables, variables_size);
if (value == NULL) {
goto RETURN_ERROR;
}
- // TODO: then delete type != NULL
- if (type != NULL && !hasTypeOf(value, type)) {
- printLog("Type mismatch");
- goto RETURN_ERROR;
+ AstTree *type;
+ if (node_metadata->type != NULL) {
+ AstTreeVariables *variables = &root->variables;
+ type = astTreeParse(node_metadata->type, &variables, 1);
+ if (type == NULL) {
+ goto RETURN_ERROR;
+ }
+
+ if (!hasTypeOf(value, type)) {
+ printLog("Type mismatch");
+ goto RETURN_ERROR;
+ }
+ } else {
+ type = makeTypeOf(value);
}
root->variables.data[i]->type = type;
@@ -391,6 +425,8 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables,
switch (parserNode->token) {
case PARSER_TOKEN_FUNCTION_DEFINITION:
return astTreeParseFunction(parserNode, variables, variables_size);
+ case PARSER_TOKEN_TYPE_TYPE:
+ return newAstTree(AST_TREE_TOKEN_TYPE_TYPE, NULL);
case PARSER_TOKEN_TYPE_FUNCTION:
return astTreeParseTypeFunction(parserNode, variables, variables_size);
case PARSER_TOKEN_TYPE_VOID:
@@ -408,7 +444,6 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables,
case PARSER_TOKEN_KEYWORD_PRINT_U64:
return astTreeParsePrintU64(parserNode, variables, variables_size);
case PARSER_TOKEN_CONSTANT:
- return astTreeParseConstant(parserNode, variables, variables_size);
case PARSER_TOKEN_SYMBOL_EOL:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
@@ -486,24 +521,29 @@ AstTree *astTreeParseFunction(ParserNode *parserNode,
goto RETURN_ERROR;
}
ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata;
- AstTree *tree = astTreeParse(node, variables, variables_size);
- if (tree == NULL) {
- goto RETURN_ERROR;
- } else if (tree->token == AST_TREE_TOKEN_VARIABLE_DEFINE) {
- astTreeDelete(tree);
- continue;
- }
+ if (node->token == PARSER_TOKEN_CONSTANT) {
+ if (!astTreeParseConstant(node, variables, variables_size)) {
+ goto RETURN_ERROR;
+ }
+ } else {
+ AstTree *tree;
+ tree = astTreeParse(node, variables, variables_size);
- if (expressions_size == scope.expressions_size) {
- expressions_size += expressions_size / 2 + 1;
- scope.expressions = a404m_realloc(
- scope.expressions, expressions_size * sizeof(*scope.expressions));
- }
- scope.expressions[scope.expressions_size] = *tree;
- scope.expressions_size += 1;
+ if (tree == NULL) {
+ goto RETURN_ERROR;
+ }
- free(tree);
+ if (expressions_size == scope.expressions_size) {
+ expressions_size += expressions_size / 2 + 1;
+ scope.expressions = a404m_realloc(
+ scope.expressions, expressions_size * sizeof(*scope.expressions));
+ }
+ scope.expressions[scope.expressions_size] = *tree;
+ scope.expressions_size += 1;
+
+ free(tree);
+ }
}
scope.expressions = a404m_realloc(
@@ -639,9 +679,8 @@ AstTree *astTreeParsePrintU64(ParserNode *parserNode,
(AstTreeSingleChild *)operand);
}
-AstTree *astTreeParseConstant(ParserNode *parserNode,
- AstTreeVariables **variables,
- size_t variables_size) {
+bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables,
+ size_t variables_size) {
ParserNodeVariableMetadata *node_metadata = parserNode->metadata;
if (node_metadata->value == NULL || node_metadata->type == NULL ||
@@ -672,13 +711,29 @@ AstTree *astTreeParseConstant(ParserNode *parserNode,
goto RETURN_ERROR;
}
- return newAstTree(AST_TREE_TOKEN_VARIABLE_DEFINE, variable);
+ return true;
RETURN_ERROR:
- return NULL;
+ return false;
}
bool hasTypeOf(AstTree *value, AstTree *type) {
switch (type->token) {
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ switch (value->token) {
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ case AST_TREE_TOKEN_TYPE_FUNCTION:
+ case AST_TREE_TOKEN_TYPE_VOID:
+ case AST_TREE_TOKEN_TYPE_U64:
+ return true;
+ case AST_TREE_TOKEN_FUNCTION:
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+ case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_VARIABLE:
+ case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_NONE:
+ return false;
+ }
+ goto ERROR;
case AST_TREE_TOKEN_TYPE_FUNCTION:
AstTreeTypeFunction *typeMetadata = type->metadata;
switch (value->token) {
@@ -697,12 +752,12 @@ bool hasTypeOf(AstTree *value, AstTree *type) {
}
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_VALUE_U64:
+ case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_FUNCTION:
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
case AST_TREE_TOKEN_FUNCTION_CALL:
case AST_TREE_TOKEN_VARIABLE:
- case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -715,7 +770,6 @@ bool hasTypeOf(AstTree *value, AstTree *type) {
case AST_TREE_TOKEN_VARIABLE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_VALUE_U64:
- case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
case AST_TREE_TOKEN_NONE:
}
@@ -724,13 +778,51 @@ ERROR:
exit(1);
}
+AstTree *makeTypeOf(AstTree *value) {
+ switch (value->token) {
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ case AST_TREE_TOKEN_TYPE_FUNCTION:
+ case AST_TREE_TOKEN_TYPE_VOID:
+ case AST_TREE_TOKEN_TYPE_U64:
+ return newAstTree(AST_TREE_TOKEN_TYPE_TYPE, NULL);
+ case AST_TREE_TOKEN_FUNCTION_CALL: {
+ AstTreeFunctionCall *metadata = value->metadata;
+ AstTreeFunction *function = metadata->function->metadata;
+ return copyAstTree(function->returnType);
+ }
+ case AST_TREE_TOKEN_FUNCTION: {
+ AstTreeFunction *function = value->metadata;
+
+ AstTreeTypeFunction *type_metadata = a404m_malloc(sizeof(*type_metadata));
+ type_metadata->arguments_size = function->arguments.size;
+ type_metadata->arguments = a404m_malloc(function->arguments.size *
+ sizeof(*type_metadata->arguments));
+ type_metadata->returnType = copyAstTree(function->returnType);
+
+ for (size_t i = 0; i < function->arguments.size; ++i) {
+ type_metadata->arguments[i] =
+ copyAstTree(function->arguments.data[i]->type);
+ }
+
+ return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata);
+ }
+ case AST_TREE_TOKEN_VALUE_U64:
+ return newAstTree(AST_TREE_TOKEN_TYPE_U64, NULL);
+ case AST_TREE_TOKEN_VARIABLE:
+ case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
+ case AST_TREE_TOKEN_NONE:
+ }
+ printLog("Bad token '%d'", value->token);
+ exit(1);
+}
+
bool typeIsEqual(AstTree *type0, AstTree *type1) {
switch (type0->token) {
case AST_TREE_TOKEN_FUNCTION:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_VALUE_U64:
- case AST_TREE_TOKEN_VARIABLE_DEFINE:
return false;
+ case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
case AST_TREE_TOKEN_TYPE_U64:
return type1->token == type0->token;