summaryrefslogtreecommitdiff
path: root/src/compiler/ast-tree.c
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-04-05 15:09:23 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-04-05 15:09:23 +0330
commitb5772e1c6961dd4b99b91b060b57584d4868aa2b (patch)
tree0b2d3c4f9b4d58981439e027423129ff0f427572 /src/compiler/ast-tree.c
parent5d43a23a42725d9e88be76ce04260dbd4b57d370 (diff)
working on access operator
Diffstat (limited to 'src/compiler/ast-tree.c')
-rw-r--r--src/compiler/ast-tree.c211
1 files changed, 207 insertions, 4 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c
index 4c37703..ef5e6a7 100644
--- a/src/compiler/ast-tree.c
+++ b/src/compiler/ast-tree.c
@@ -158,6 +158,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = {
"AST_TREE_TOKEN_OPERATOR_POINTER",
"AST_TREE_TOKEN_OPERATOR_ADDRESS",
"AST_TREE_TOKEN_OPERATOR_DEREFERENCE",
+ "AST_TREE_TOKEN_OPERATOR_ACCESS",
"AST_TREE_TOKEN_SCOPE",
@@ -428,9 +429,26 @@ void astTreePrint(const AstTree *tree, int indent) {
printf(" ");
}
printf("]");
-
+ }
goto RETURN_SUCCESS;
+ case AST_TREE_TOKEN_OPERATOR_ACCESS: {
+ AstTreeAccess *metadata = tree->metadata;
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("left=\n");
+ astTreePrint(metadata->object, indent + 1);
+ printf(",\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
+ printf("right=%.*s",
+ (int)(metadata->member.name.end - metadata->member.name.begin),
+ metadata->member.name.begin);
+ printf("\n");
+ for (int i = 0; i < indent; ++i)
+ printf(" ");
}
+ goto RETURN_SUCCESS;
case AST_TREE_TOKEN_NONE:
}
@@ -447,7 +465,11 @@ void astTreeVariablePrint(const AstTreeVariable *variable, int indent) {
printf("{\nname=\"%.*s\",\nvalue=\n",
(int)(variable->name_end - variable->name_begin),
variable->name_begin);
- astTreePrint(variable->value, indent);
+ if (variable->value == NULL) {
+ printf("null");
+ } else {
+ astTreePrint(variable->value, indent);
+ }
printf("\n}");
}
@@ -617,6 +639,12 @@ void astTreeDestroy(AstTree tree) {
free(metadata);
}
return;
+ case AST_TREE_TOKEN_OPERATOR_ACCESS: {
+ AstTreeAccess *metadata = tree.metadata;
+ astTreeDelete(metadata->object);
+ free(metadata);
+ }
+ return;
case AST_TREE_TOKEN_NONE:
}
printLog("token = %d", tree.token);
@@ -958,6 +986,18 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[],
copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size),
tree->str_begin, tree->str_end);
}
+ case AST_TREE_TOKEN_OPERATOR_ACCESS: {
+ AstTreeAccess *metadata = tree->metadata;
+ AstTreeAccess *new_metadata = a404m_malloc(sizeof(*new_metadata));
+
+ new_metadata->object = metadata->object;
+ new_metadata->member = metadata->member;
+
+ return newAstTree(
+ tree->token, new_metadata,
+ copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size),
+ tree->str_begin, tree->str_end);
+ }
case AST_TREE_TOKEN_NONE:
}
printLog("Bad token %d", tree->token);
@@ -1087,6 +1127,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) {
case PARSER_TOKEN_FUNCTION_DEFINITION:
case PARSER_TOKEN_FUNCTION_CALL:
case PARSER_TOKEN_IDENTIFIER:
+ case PARSER_TOKEN_OPERATOR_ACCESS:
case PARSER_TOKEN_OPERATOR_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUM_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUB_ASSIGN:
@@ -1361,6 +1402,9 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) {
case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL:
return astTreeParseBinaryOperator(parserNode, helper,
AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL);
+ case PARSER_TOKEN_OPERATOR_ACCESS:
+ return astTreeParseAccessOperator(parserNode, helper,
+ AST_TREE_TOKEN_OPERATOR_ACCESS);
case PARSER_TOKEN_OPERATOR_PLUS:
return astTreeParseUnaryOperator(parserNode, helper,
AST_TREE_TOKEN_OPERATOR_PLUS);
@@ -1538,6 +1582,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) {
case PARSER_TOKEN_OPERATOR_POINTER:
case PARSER_TOKEN_OPERATOR_ADDRESS:
case PARSER_TOKEN_OPERATOR_DEREFERENCE:
+ case PARSER_TOKEN_OPERATOR_ACCESS:
printError(node->str_begin, node->str_end, "Unexpected %s",
PARSER_TOKEN_STRINGS[node->token]);
goto RETURN_ERROR;
@@ -2081,6 +2126,7 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,
case PARSER_TOKEN_OPERATOR_POINTER:
case PARSER_TOKEN_OPERATOR_ADDRESS:
case PARSER_TOKEN_OPERATOR_DEREFERENCE:
+ case PARSER_TOKEN_OPERATOR_ACCESS:
printError(node->str_begin, node->str_end, "Unexpected %s",
PARSER_TOKEN_STRINGS[node->token]);
goto RETURN_ERROR;
@@ -2188,6 +2234,33 @@ AstTree *astTreeParseStruct(ParserNode *parserNode, AstTreeHelper *helper) {
parserNode->str_begin, parserNode->str_end);
}
+AstTree *astTreeParseAccessOperator(ParserNode *parserNode,
+ AstTreeHelper *helper, AstTreeToken token) {
+ ParserNodeInfixMetadata *node_metadata = parserNode->metadata;
+
+ AstTree *object = astTreeParse(node_metadata->left, helper);
+ if (object == NULL) {
+ return NULL;
+ }
+
+ ParserNode *right_node = node_metadata->right;
+ if (right_node->token != PARSER_TOKEN_IDENTIFIER) {
+ printError(right_node->str_begin, right_node->str_end,
+ "Should be an identifier but got `%s`",
+ PARSER_TOKEN_STRINGS[right_node->token]);
+ return NULL;
+ }
+
+ AstTreeAccess *metadata = a404m_malloc(sizeof(*metadata));
+
+ metadata->object = object;
+ metadata->member.name.begin = right_node->str_begin;
+ metadata->member.name.end = right_node->str_end;
+
+ return newAstTree(token, metadata, NULL, parserNode->str_begin,
+ parserNode->str_end);
+}
+
bool isFunction(AstTree *value) {
return value->type->token == AST_TREE_TOKEN_TYPE_FUNCTION;
}
@@ -2267,6 +2340,10 @@ bool isConst(AstTree *tree, AstTreeHelper *helper) {
AstTreeSingleChild *metadata = tree->metadata;
return isConst(metadata, helper);
}
+ case AST_TREE_TOKEN_OPERATOR_ACCESS: {
+ AstTreeAccess *metadata = tree->metadata;
+ return isConst(metadata->object, helper);
+ }
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
@@ -2368,6 +2445,22 @@ AstTree *makeTypeOf(AstTree *value) {
case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: {
return &AST_TREE_BOOL_TYPE;
}
+ case AST_TREE_TOKEN_OPERATOR_ACCESS: {
+ AstTreeAccess *metadata = value->metadata;
+
+ AstTreeStruct *struc = metadata->object->type->metadata;
+ const size_t size = metadata->member.name.end - metadata->member.name.begin;
+ const char *str = metadata->member.name.begin;
+
+ for (size_t i = 0; i < struc->variables.size; ++i) {
+ AstTreeVariable *member = struc->variables.data[i];
+ const size_t member_size = member->name_end - member->name_begin;
+ if (member_size == size && strncmp(member->name_begin, str, size)) {
+ return copyAstTree(member->type);
+ }
+ }
+ UNREACHABLE;
+ }
case AST_TREE_TOKEN_VARIABLE_DEFINE:
case AST_TREE_TOKEN_KEYWORD_PRINT_U64:
case AST_TREE_TOKEN_KEYWORD_RETURN:
@@ -2413,6 +2506,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) {
case AST_TREE_TOKEN_SCOPE:
case AST_TREE_TOKEN_OPERATOR_DEREFERENCE:
case AST_TREE_TOKEN_OPERATOR_ADDRESS:
+ case AST_TREE_TOKEN_OPERATOR_ACCESS:
return false;
case AST_TREE_TOKEN_TYPE_TYPE:
case AST_TREE_TOKEN_TYPE_VOID:
@@ -2524,12 +2618,13 @@ AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper) {
case AST_TREE_TOKEN_OPERATOR_POINTER:
case AST_TREE_TOKEN_OPERATOR_ADDRESS:
case AST_TREE_TOKEN_OPERATOR_DEREFERENCE:
+ case AST_TREE_TOKEN_OPERATOR_ACCESS:
case AST_TREE_TOKEN_KEYWORD_IF:
case AST_TREE_TOKEN_KEYWORD_WHILE:
case AST_TREE_TOKEN_KEYWORD_COMPTIME:
case AST_TREE_TOKEN_SCOPE: {
bool shouldRet = false;
- AstTree *value = runExpression(tree, &shouldRet);
+ AstTree *value = runExpression(tree, &shouldRet, false);
if (value == NULL) {
printError(tree->str_begin, tree->str_end, "Unknown error");
}
@@ -2584,6 +2679,7 @@ bool isCircularDependenciesBack(AstTreeHelper *helper,
case AST_TREE_TOKEN_VALUE_INT:
case AST_TREE_TOKEN_VALUE_FLOAT:
case AST_TREE_TOKEN_VALUE_BOOL:
+ case AST_TREE_TOKEN_OPERATOR_ACCESS:
return false;
case AST_TREE_TOKEN_OPERATOR_POINTER:
case AST_TREE_TOKEN_OPERATOR_ADDRESS:
@@ -2799,6 +2895,8 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper,
return setTypesComptime(tree, helper);
case AST_TREE_TOKEN_KEYWORD_STRUCT:
return setTypesStruct(tree, helper);
+ case AST_TREE_TOKEN_OPERATOR_ACCESS:
+ return setTypesOperatorAccess(tree, helper);
case AST_TREE_TOKEN_NONE:
break;
}
@@ -3451,7 +3549,7 @@ bool setTypesStruct(AstTree *tree, AstTreeSetTypesHelper helper) {
AstTreeStruct *metadata = tree->metadata;
for (size_t i = 0; i < metadata->variables.size; ++i) {
- if (!setAllTypes(metadata->variables.data[i]->type, helper, NULL)) {
+ if (!setTypesAstVariable(metadata->variables.data[i], helper)) {
return false;
}
}
@@ -3459,6 +3557,38 @@ bool setTypesStruct(AstTree *tree, AstTreeSetTypesHelper helper) {
return true;
}
+bool setTypesOperatorAccess(AstTree *tree, AstTreeSetTypesHelper helper) {
+ AstTreeAccess *metadata = tree->metadata;
+ if (!setAllTypes(metadata->object, helper, NULL)) {
+ return false;
+ } else if (metadata->object->type->token != AST_TREE_TOKEN_KEYWORD_STRUCT) {
+ printError(metadata->object->str_begin, metadata->object->str_end,
+ "The object is not a struct");
+ return false;
+ }
+
+ AstTreeStruct *struc = metadata->object->type->metadata;
+ const size_t size = metadata->member.name.end - metadata->member.name.begin;
+ const char *str = metadata->member.name.begin;
+
+ size_t index = 0;
+
+ for (size_t i = 0; i < struc->variables.size; ++i) {
+ AstTreeVariable *member = struc->variables.data[i];
+ const size_t member_size = member->name_end - member->name_begin;
+ if (member_size == size && strncmp(member->name_begin, str, size)) {
+ metadata->member.index = index;
+ tree->type = copyAstTree(member->type);
+ return true;
+ }
+ index += sizeOfType(member->type);
+ }
+
+ printError(metadata->member.name.begin, metadata->member.name.end,
+ "Member not found");
+ return false;
+}
+
bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) {
if (!setAllTypes(&infix->left, helper, NULL)) {
return false;
@@ -3470,3 +3600,76 @@ bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) {
return setAllTypes(&infix->right, newHelper, NULL);
}
+
+size_t sizeOfType(AstTree *type) {
+ switch (type->token) {
+ case AST_TREE_TOKEN_TYPE_TYPE:
+ UNREACHABLE;
+ case AST_TREE_TOKEN_TYPE_VOID:
+ return 0;
+ case AST_TREE_TOKEN_TYPE_I8:
+ case AST_TREE_TOKEN_TYPE_U8:
+ case AST_TREE_TOKEN_TYPE_BOOL:
+ return 1;
+ case AST_TREE_TOKEN_TYPE_I16:
+ case AST_TREE_TOKEN_TYPE_U16:
+ case AST_TREE_TOKEN_TYPE_F16:
+ return 2;
+ case AST_TREE_TOKEN_TYPE_I32:
+ case AST_TREE_TOKEN_TYPE_U32:
+ case AST_TREE_TOKEN_TYPE_F32:
+ return 4;
+ case AST_TREE_TOKEN_TYPE_I64:
+ case AST_TREE_TOKEN_TYPE_U64:
+ case AST_TREE_TOKEN_TYPE_F64:
+ case AST_TREE_TOKEN_TYPE_FUNCTION:
+ return 8;
+ case AST_TREE_TOKEN_TYPE_F128:
+ return 16;
+ case AST_TREE_TOKEN_KEYWORD_STRUCT: {
+ AstTreeStruct *metadata = type->metadata;
+ size_t size = 0;
+ for (size_t i = 0; i < metadata->variables.size; ++i) {
+ size += sizeOfType(metadata->variables.data[i]->type);
+ }
+ return size;
+ }
+ case AST_TREE_TOKEN_VALUE_VOID:
+ case AST_TREE_TOKEN_FUNCTION_CALL:
+ case AST_TREE_TOKEN_VARIABLE:
+ case AST_TREE_TOKEN_VARIABLE_DEFINE:
+ case AST_TREE_TOKEN_VALUE_NULL:
+ case AST_TREE_TOKEN_VALUE_UNDEFINED:
+ case AST_TREE_TOKEN_VALUE_INT:
+ case AST_TREE_TOKEN_VALUE_FLOAT:
+ case AST_TREE_TOKEN_VALUE_BOOL:
+ case AST_TREE_TOKEN_OPERATOR_ASSIGN:
+ case AST_TREE_TOKEN_OPERATOR_PLUS:
+ case AST_TREE_TOKEN_OPERATOR_MINUS:
+ 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_POINTER:
+ case AST_TREE_TOKEN_OPERATOR_ADDRESS:
+ case AST_TREE_TOKEN_OPERATOR_DEREFERENCE:
+ case AST_TREE_TOKEN_OPERATOR_ACCESS:
+ case AST_TREE_TOKEN_SCOPE:
+ 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_KEYWORD_COMPTIME:
+ case AST_TREE_TOKEN_NONE:
+ }
+ printError(type->str_begin, type->str_end, "Bad token %d", type->token);
+ UNREACHABLE;
+}