summaryrefslogtreecommitdiff
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
parent5d43a23a42725d9e88be76ce04260dbd4b57d370 (diff)
working on access operator
-rw-r--r--code/main.felan5
-rw-r--r--src/compiler/ast-tree.c211
-rw-r--r--src/compiler/ast-tree.h19
-rw-r--r--src/compiler/lexer.c5
-rw-r--r--src/compiler/lexer.h1
-rw-r--r--src/compiler/parser.c13
-rw-r--r--src/compiler/parser.h1
-rw-r--r--src/main.c2
-rw-r--r--src/runner/runner.c131
-rw-r--r--src/runner/runner.h2
10 files changed, 327 insertions, 63 deletions
diff --git a/code/main.felan b/code/main.felan
index 7428511..f4b7608 100644
--- a/code/main.felan
+++ b/code/main.felan
@@ -11,6 +11,11 @@ st :: struct {
};
main :: () -> void {
+ b :u64= 2;
+ c := &b;
+ c.* = 4;
+ print_u64 b;
a : st = undefined;
+ a.a = 5;
};
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;
+}
diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h
index 00f477c..fdc797e 100644
--- a/src/compiler/ast-tree.h
+++ b/src/compiler/ast-tree.h
@@ -61,6 +61,7 @@ typedef enum AstTreeToken {
AST_TREE_TOKEN_OPERATOR_POINTER,
AST_TREE_TOKEN_OPERATOR_ADDRESS,
AST_TREE_TOKEN_OPERATOR_DEREFERENCE,
+ AST_TREE_TOKEN_OPERATOR_ACCESS,
AST_TREE_TOKEN_SCOPE,
@@ -194,6 +195,19 @@ typedef struct AstTreeStruct {
AstTreeVariables variables;
} AstTreeStruct;
+typedef struct AstTreeName {
+ char *begin;
+ char *end;
+} AstTreeName;
+
+typedef struct AstTreeAccess {
+ AstTree *object;
+ struct {
+ AstTreeName name;
+ size_t index;
+ } member;
+} AstTreeAccess;
+
void astTreePrint(const AstTree *tree, int indent);
void astTreeVariablePrint(const AstTreeVariable *variable, int indent);
void astTreeRootPrint(const AstTreeRoot *root);
@@ -251,6 +265,8 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode,
AstTreeHelper *helper);
AstTree *astTreeParseParenthesis(ParserNode *parserNode, AstTreeHelper *helper);
AstTree *astTreeParseStruct(ParserNode *parserNode, AstTreeHelper *helper);
+AstTree *astTreeParseAccessOperator(ParserNode *parserNode,
+ AstTreeHelper *helper, AstTreeToken token);
bool isFunction(AstTree *value);
bool isConst(AstTree *tree, AstTreeHelper *helper);
@@ -299,7 +315,10 @@ bool setTypesScope(AstTree *tree, AstTreeSetTypesHelper helper,
AstTreeFunction *function);
bool setTypesComptime(AstTree *tree, AstTreeSetTypesHelper helper);
bool setTypesStruct(AstTree *tree, AstTreeSetTypesHelper helper);
+bool setTypesOperatorAccess(AstTree *tree, AstTreeSetTypesHelper helper);
bool setTypesAstVariable(AstTreeVariable *variable,
AstTreeSetTypesHelper helper);
bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper);
+
+size_t sizeOfType(AstTree *type);
diff --git a/src/compiler/lexer.c b/src/compiler/lexer.c
index 16e8ee5..6feb77e 100644
--- a/src/compiler/lexer.c
+++ b/src/compiler/lexer.c
@@ -72,13 +72,14 @@ const char *LEXER_TOKEN_STRINGS[] = {
"LEXER_TOKEN_SYMBOL_POINTER",
"LEXER_TOKEN_SYMBOL_ADDRESS",
"LEXER_TOKEN_SYMBOL_DEREFERENCE",
+ "LEXER_TOKEN_SYMBOL_ACCESS",
"LEXER_TOKEN_NONE",
};
const char *LEXER_SYMBOL_STRINGS[] = {
";", "(", ")", "{", "}", "->", ":", "=", "+=", "-=", "*=", "/=", "%=", ",",
- "+", "-", "*", "/", "%", "==", "!=", ">", ">=", "<", "<=", "&", ".*",
+ "+", "-", "*", "/", "%", "==", "!=", ">", ">=", "<", "<=", "&", ".*", ".",
};
const LexerToken LEXER_SYMBOL_TOKENS[] = {
LEXER_TOKEN_SYMBOL_EOL,
@@ -108,6 +109,7 @@ const LexerToken LEXER_SYMBOL_TOKENS[] = {
LEXER_TOKEN_SYMBOL_SMALLER_OR_EQUAL,
LEXER_TOKEN_SYMBOL_ADDRESS,
LEXER_TOKEN_SYMBOL_DEREFERENCE,
+ LEXER_TOKEN_SYMBOL_ACCESS,
};
const size_t LEXER_SYMBOL_SIZE =
sizeof(LEXER_SYMBOL_TOKENS) / sizeof(*LEXER_SYMBOL_TOKENS);
@@ -318,6 +320,7 @@ void lexerPushClear(LexerNodeArray *array, size_t *array_size, char *iter,
case LEXER_TOKEN_SYMBOL_POINTER:
case LEXER_TOKEN_SYMBOL_ADDRESS:
case LEXER_TOKEN_SYMBOL_DEREFERENCE:
+ case LEXER_TOKEN_SYMBOL_ACCESS:
if (*array_size == array->size) {
*array_size += 1 + *array_size / 2;
array->data =
diff --git a/src/compiler/lexer.h b/src/compiler/lexer.h
index 6862c0d..4b59dff 100644
--- a/src/compiler/lexer.h
+++ b/src/compiler/lexer.h
@@ -65,6 +65,7 @@ typedef enum LexerToken {
LEXER_TOKEN_SYMBOL_POINTER,
LEXER_TOKEN_SYMBOL_ADDRESS,
LEXER_TOKEN_SYMBOL_DEREFERENCE,
+ LEXER_TOKEN_SYMBOL_ACCESS,
LEXER_TOKEN_NONE,
} LexerToken;
diff --git a/src/compiler/parser.c b/src/compiler/parser.c
index 2c7e6a6..ad06a7f 100644
--- a/src/compiler/parser.c
+++ b/src/compiler/parser.c
@@ -74,6 +74,7 @@ const char *PARSER_TOKEN_STRINGS[] = {
"PARSER_TOKEN_OPERATOR_POINTER",
"PARSER_TOKEN_OPERATOR_ADDRESS",
"PARSER_TOKEN_OPERATOR_DEREFERENCE",
+ "PARSER_TOKEN_OPERATOR_ACCESS",
"PARSER_TOKEN_FUNCTION_DEFINITION",
@@ -113,7 +114,8 @@ static constexpr ParserOrder PARSER_ORDER[] = {
},
{
.ltr = true,
- ORDER_ARRAY(LEXER_TOKEN_SYMBOL_DEREFERENCE, ),
+ ORDER_ARRAY(LEXER_TOKEN_SYMBOL_DEREFERENCE,
+ LEXER_TOKEN_SYMBOL_ACCESS, ),
},
{
.ltr = false,
@@ -343,6 +345,7 @@ void parserNodePrint(const ParserNode *node, int indent) {
printf(" ");
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_OPERATOR_ACCESS:
case PARSER_TOKEN_OPERATOR_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUM_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUB_ASSIGN:
@@ -536,6 +539,7 @@ void parserNodeDelete(ParserNode *node) {
free(metadata);
}
goto RETURN_SUCCESS;
+ case PARSER_TOKEN_OPERATOR_ACCESS:
case PARSER_TOKEN_OPERATOR_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUM_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUB_ASSIGN:
@@ -786,6 +790,9 @@ ParserNode *parseNode(LexerNode *node, LexerNode *begin, LexerNode *end,
case LEXER_TOKEN_SYMBOL_SMALLER_OR_EQUAL:
return parserBinaryOperator(node, begin, end, parent,
PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL);
+ case LEXER_TOKEN_SYMBOL_ACCESS:
+ return parserBinaryOperator(node, begin, end, parent,
+ PARSER_TOKEN_OPERATOR_ACCESS);
case LEXER_TOKEN_SYMBOL_PLUS: {
ParserNode *result = parserBinaryOrLeftOperator(node, begin, end, parent,
PARSER_TOKEN_OPERATOR_PLUS,
@@ -1227,6 +1234,7 @@ ParserNode *parserFunction(LexerNode *node, LexerNode *begin, LexerNode *end,
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_SYMBOL_PARENTHESIS:
case PARSER_TOKEN_SYMBOL_COMMA:
+ case PARSER_TOKEN_OPERATOR_ACCESS:
case PARSER_TOKEN_OPERATOR_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUM_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUB_ASSIGN:
@@ -1654,6 +1662,7 @@ bool isExpression(ParserNode *node) {
case PARSER_TOKEN_FUNCTION_CALL:
case PARSER_TOKEN_KEYWORD_PRINT_U64:
case PARSER_TOKEN_KEYWORD_RETURN:
+ case PARSER_TOKEN_OPERATOR_ACCESS:
case PARSER_TOKEN_OPERATOR_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUM_ASSIGN:
case PARSER_TOKEN_OPERATOR_SUB_ASSIGN:
@@ -1738,6 +1747,7 @@ bool isType(ParserNode *node) {
case PARSER_TOKEN_OPERATOR_POINTER:
case PARSER_TOKEN_SYMBOL_CURLY_BRACKET:
case PARSER_TOKEN_KEYWORD_STRUCT:
+ case PARSER_TOKEN_OPERATOR_ACCESS:
return true;
case PARSER_TOKEN_OPERATOR_ADDRESS:
case PARSER_TOKEN_KEYWORD_NULL:
@@ -1788,6 +1798,7 @@ bool isValue(ParserNode *node) {
case PARSER_TOKEN_VALUE_FLOAT:
case PARSER_TOKEN_VALUE_BOOL:
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:
diff --git a/src/compiler/parser.h b/src/compiler/parser.h
index bb843e2..2df35b9 100644
--- a/src/compiler/parser.h
+++ b/src/compiler/parser.h
@@ -70,6 +70,7 @@ typedef enum ParserToken {
PARSER_TOKEN_OPERATOR_POINTER,
PARSER_TOKEN_OPERATOR_ADDRESS,
PARSER_TOKEN_OPERATOR_DEREFERENCE,
+ PARSER_TOKEN_OPERATOR_ACCESS,
PARSER_TOKEN_FUNCTION_DEFINITION,
diff --git a/src/main.c b/src/main.c
index 3513ff3..71f6384 100644
--- a/src/main.c
+++ b/src/main.c
@@ -61,7 +61,7 @@ int main(int argc, char *argv[]) {
return 1;
}
- const int ret = run(argv[1], false);
+ const int ret = run(argv[1], true);
fileDelete();
return ret;
}
diff --git a/src/runner/runner.c b/src/runner/runner.c
index 94907a7..a335f85 100644
--- a/src/runner/runner.c
+++ b/src/runner/runner.c
@@ -70,7 +70,7 @@ AstTree *runAstTreeFunction(AstTree *tree, AstTreeFunctionCallParam *arguments,
for (size_t i = 0; i < arguments_size; ++i) {
AstTreeFunctionCallParam param = arguments[i];
AstTreeVariable *arg = function->arguments.data[i];
- AstTree *value = runExpression(param.value, &shouldRet);
+ AstTree *value = runExpression(param.value, &shouldRet, false);
runnerVariableSetValue(arg, value);
}
@@ -80,7 +80,7 @@ AstTree *runAstTreeFunction(AstTree *tree, AstTreeFunctionCallParam *arguments,
for (size_t i = 0; i < function->scope.expressions_size; ++i) {
astTreeDelete(ret);
- ret = runExpression(function->scope.expressions[i], &shouldRet);
+ ret = runExpression(function->scope.expressions[i], &shouldRet, false);
if (shouldRet) {
break;
}
@@ -89,11 +89,11 @@ AstTree *runAstTreeFunction(AstTree *tree, AstTreeFunctionCallParam *arguments,
return ret;
}
-AstTree *runExpression(AstTree *expr, bool *shouldRet) {
+AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) {
switch (expr->token) {
case AST_TREE_TOKEN_KEYWORD_PRINT_U64: {
AstTreeSingleChild *metadata = expr->metadata;
- AstTree *tree = runExpression(metadata, shouldRet);
+ AstTree *tree = runExpression(metadata, shouldRet, false);
printf("%lu", *(AstTreeInt *)tree->metadata);
astTreeDelete(tree);
return &AST_TREE_VOID_VALUE;
@@ -113,43 +113,38 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_ASSIGN: {
AstTreeInfix *metadata = expr->metadata;
- AstTreeVariable *left;
- if (metadata->left.token == AST_TREE_TOKEN_VARIABLE) {
- left = metadata->left.metadata;
- } else {
- AstTree *left_metadata = metadata->left.metadata;
- AstTree *var = runExpression(left_metadata, shouldRet);
- if (var->token != AST_TREE_TOKEN_VARIABLE) {
- UNREACHABLE;
- }
- left = var->metadata;
- astTreeDelete(var);
+ AstTree *l = runExpression(&metadata->left, shouldRet, true);
+ if (l->token != AST_TREE_TOKEN_VARIABLE) {
+ UNREACHABLE;
}
- runnerVariableSetValue(left, runExpression(&metadata->right, shouldRet));
+ AstTreeVariable *left = l->metadata;
+ runnerVariableSetValue(left,
+ runExpression(&metadata->right, shouldRet, false));
return copyAstTree(left->value);
}
case AST_TREE_TOKEN_KEYWORD_RETURN: {
AstTreeReturn *metadata = expr->metadata;
*shouldRet = true;
if (metadata->value != NULL) {
- return runExpression(metadata->value, shouldRet);
+ return runExpression(metadata->value, shouldRet, false);
} else {
return &AST_TREE_VOID_VALUE;
}
}
case AST_TREE_TOKEN_VARIABLE_DEFINE: {
AstTreeVariable *variable = expr->metadata;
- runnerVariableSetValue(variable, runExpression(variable->value, shouldRet));
+ runnerVariableSetValue(variable,
+ runExpression(variable->value, shouldRet, false));
return &AST_TREE_VOID_VALUE;
}
case AST_TREE_TOKEN_KEYWORD_IF: {
AstTreeIf *metadata = expr->metadata;
- AstTree *condition = runExpression(metadata->condition, shouldRet);
+ AstTree *condition = runExpression(metadata->condition, shouldRet, false);
AstTree *ret;
if (*(AstTreeBool *)condition->metadata) {
- ret = runExpression(metadata->ifBody, shouldRet);
+ ret = runExpression(metadata->ifBody, shouldRet, isLeft);
} else if (metadata->elseBody != NULL) {
- ret = runExpression(metadata->elseBody, shouldRet);
+ ret = runExpression(metadata->elseBody, shouldRet, isLeft);
} else {
ret = &AST_TREE_VOID_VALUE;
}
@@ -160,19 +155,19 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
AstTreeWhile *metadata = expr->metadata;
AstTree *ret = NULL;
while (!*shouldRet) {
- AstTree *tree = runExpression(metadata->condition, shouldRet);
+ AstTree *tree = runExpression(metadata->condition, shouldRet, false);
bool conti = *(AstTreeBool *)tree->metadata;
astTreeDelete(tree);
if (!conti) {
break;
}
- ret = runExpression(metadata->body, shouldRet);
+ ret = runExpression(metadata->body, shouldRet, isLeft);
}
return ret;
}
case AST_TREE_TOKEN_KEYWORD_COMPTIME: {
AstTreeSingleChild *operand = expr->metadata;
- return runExpression((AstTree *)operand, shouldRet);
+ return runExpression((AstTree *)operand, shouldRet, isLeft);
}
case AST_TREE_TOKEN_SCOPE: {
AstTreeScope *metadata = expr->metadata;
@@ -180,12 +175,14 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
AstTree *ret = &AST_TREE_VOID_VALUE;
for (size_t i = 0; i < metadata->expressions_size && !*shouldRet; ++i) {
astTreeDelete(ret);
- ret = runExpression(metadata->expressions[i], shouldRet);
+ ret = runExpression(metadata->expressions[i], shouldRet,
+ i == metadata->expressions_size - 1 && isLeft);
}
return ret;
}
case AST_TREE_TOKEN_OPERATOR_PLUS: {
- AstTreeSingleChild *operand = runExpression(expr->metadata, shouldRet);
+ AstTreeSingleChild *operand =
+ runExpression(expr->metadata, shouldRet, false);
if (operand->type == &AST_TREE_U64_TYPE) {
doLeftOperation(operand, +, AstTreeInt, u64);
} else if (operand->type == &AST_TREE_I64_TYPE) {
@@ -217,7 +214,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
return operand;
}
case AST_TREE_TOKEN_OPERATOR_MINUS: {
- AstTreeSingleChild *operand = runExpression(expr->metadata, shouldRet);
+ AstTreeSingleChild *operand =
+ runExpression(expr->metadata, shouldRet, false);
if (operand->type == &AST_TREE_U64_TYPE) {
doLeftOperation(operand, -, AstTreeInt, u64);
} else if (operand->type == &AST_TREE_I64_TYPE) {
@@ -250,8 +248,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_SUM: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doOperation(left, right, +, AstTreeInt, u64);
@@ -297,8 +295,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_SUB: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doOperation(left, right, -, AstTreeInt, u64);
@@ -344,8 +342,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_MULTIPLY: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doOperation(left, right, *, AstTreeInt, u64);
@@ -391,8 +389,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_DIVIDE: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doOperation(left, right, /, AstTreeInt, u64);
@@ -438,8 +436,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_MODULO: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doOperation(left, right, %, AstTreeInt, u64);
@@ -473,8 +471,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_EQUAL: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doLogicalOperation(left, right, ==, AstTreeInt, u64);
@@ -526,8 +524,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_NOT_EQUAL: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doLogicalOperation(left, right, !=, AstTreeInt, u64);
@@ -579,8 +577,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_GREATER: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doLogicalOperation(left, right, >, AstTreeInt, u64);
@@ -626,8 +624,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_SMALLER: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doLogicalOperation(left, right, <, AstTreeInt, u64);
@@ -673,8 +671,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doLogicalOperation(left, right, >=, AstTreeInt, u64);
@@ -720,8 +718,8 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: {
AstTreeInfix *metadata = expr->metadata;
- AstTree *left = runExpression(&metadata->left, shouldRet);
- AstTree *right = runExpression(&metadata->right, shouldRet);
+ AstTree *left = runExpression(&metadata->left, shouldRet, false);
+ AstTree *right = runExpression(&metadata->right, shouldRet, false);
if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) {
doLogicalOperation(left, right, <=, AstTreeInt, u64);
@@ -789,6 +787,7 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
case AST_TREE_TOKEN_VALUE_FLOAT:
case AST_TREE_TOKEN_OPERATOR_POINTER:
case AST_TREE_TOKEN_FUNCTION:
+ case AST_TREE_TOKEN_KEYWORD_STRUCT:
return copyAstTree(expr);
case AST_TREE_TOKEN_OPERATOR_ADDRESS: {
AstTreeSingleChild *metadata = expr->metadata;
@@ -799,21 +798,43 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet) {
}
case AST_TREE_TOKEN_OPERATOR_DEREFERENCE: {
AstTreeSingleChild *metadata = expr->metadata;
- AstTree *operand = runExpression(metadata, shouldRet);
+ AstTree *operand = runExpression(metadata, shouldRet, false);
if (operand->token != AST_TREE_TOKEN_VARIABLE) {
printLog("%s", AST_TREE_TOKEN_STRINGS[operand->token]);
UNREACHABLE;
}
- AstTreeVariable *variable = operand->metadata;
- AstTree *ret = copyAstTree(variable->value);
- astTreeDelete(operand);
+ AstTree *ret;
+ if (isLeft) {
+ ret = operand;
+ } else {
+ AstTreeVariable *variable = operand->metadata;
+ ret = copyAstTree(variable->value);
+ astTreeDelete(operand);
+ }
return ret;
}
case AST_TREE_TOKEN_VARIABLE: {
AstTreeVariable *variable = expr->metadata;
- return copyAstTree(variable->value);
+ if (isLeft) {
+ return copyAstTree(expr);
+ } else {
+ return copyAstTree(variable->value);
+ }
+ }
+ case AST_TREE_TOKEN_OPERATOR_ACCESS: {
+ NOT_IMPLEMENTED;
+ AstTreeAccess *metadata = expr->metadata;
+ AstTree *tree = runExpression(metadata->object, shouldRet, true);
+ if (tree->token != AST_TREE_TOKEN_VARIABLE) {
+ UNREACHABLE;
+ }
+ AstTreeVariable *variable = tree->metadata;
+ astTreeDelete(variable->type);
+ variable->type = copyAstTree(expr->type);
+ variable->value->metadata =
+ ((u8 *)variable->value->metadata) + metadata->member.index;
+ return tree;
}
- case AST_TREE_TOKEN_KEYWORD_STRUCT:
case AST_TREE_TOKEN_NONE:
}
UNREACHABLE;
diff --git a/src/runner/runner.h b/src/runner/runner.h
index efb3eb8..10fd8dc 100644
--- a/src/runner/runner.h
+++ b/src/runner/runner.h
@@ -10,4 +10,4 @@ bool runAstTree(AstTreeRoot *root);
AstTree *runAstTreeFunction(AstTree *tree, AstTreeFunctionCallParam *arguments,
size_t arguments_size);
-AstTree *runExpression(AstTree *expr, bool *shouldRet);
+AstTree *runExpression(AstTree *expr, bool *shouldRet,bool isLeft);