diff options
author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-04-07 16:53:53 +0330 |
---|---|---|
committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-04-07 16:53:53 +0330 |
commit | 92bf7bf5de203eac51befc914dfddbc29d49351b (patch) | |
tree | 645448cbedf2d0cc9b3b39651daf1d069c80015a | |
parent | 62b7af496f2c694ff5361cf21042bbe14f969c64 (diff) |
add a way to make generic structs
-rw-r--r-- | code/main.felan | 14 | ||||
-rw-r--r-- | src/compiler/ast-tree.c | 183 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 1 | ||||
-rw-r--r-- | src/runner/runner.c | 26 |
4 files changed, 198 insertions, 26 deletions
diff --git a/code/main.felan b/code/main.felan index 52c8933..667adbe 100644 --- a/code/main.felan +++ b/code/main.felan @@ -24,10 +24,18 @@ array :: (t:type) -> type { }; }; +array2 :: (t:type) -> type { + return struct { + ptr : *t; + length : usize; + }; +}; + array_int :: array(u64); +array_int1 :: array(u64); +array_int2 :: array2(u64); main :: () -> void { - a : array_int = undefined; - b :u64 =2; - a.length = 1; + print_u64 (if array_int == array_int1 1 else 0); + print_u64 (if array_int == array_int2 1 else 0); }; diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 55209c4..d014f4a 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -481,18 +481,42 @@ RETURN_SUCCESS: } void astTreeVariablePrint(const AstTreeVariable *variable, int indent) { - for (int i = 0; i < indent; ++i) { + for (int i = 0; i < indent; ++i) printf(" "); - } - printf("{\nname=\"%.*s\",\nvalue=\n", - (int)(variable->name_end - variable->name_begin), + + printf("{\n"); + + for (int i = 0; i < indent; ++i) + printf(" "); + + printf("name=\"%.*s\",\n", (int)(variable->name_end - variable->name_begin), variable->name_begin); + + for (int i = 0; i < indent; ++i) + printf(" "); + + printf("type=\n"); + astTreePrint(variable->type, indent); + printf(",\n"); + + for (int i = 0; i < indent; ++i) + printf(" "); + + printf("value=\n"); + if (variable->value == NULL) { - printf("null"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("null\n"); } else { astTreePrint(variable->value, indent); + printf("\n"); } - printf("\n}"); + + for (int i = 0; i < indent; ++i) + printf(" "); + + printf("}"); } void astTreeRootPrint(const AstTreeRoot *root) { @@ -2346,8 +2370,17 @@ bool isConst(AstTree *tree) { case AST_TREE_TOKEN_VALUE_OBJECT: case AST_TREE_TOKEN_KEYWORD_COMPTIME: case AST_TREE_TOKEN_SCOPE: - case AST_TREE_TOKEN_KEYWORD_STRUCT: return true; + case AST_TREE_TOKEN_KEYWORD_STRUCT: { + AstTreeStruct *metadata = tree->metadata; + for (size_t i = 0; i < metadata->variables.size; ++i) { + AstTreeVariable *member = metadata->variables.data[i]; + if (!isConst(member->type)) { + return false; + } + } + return true; + } case AST_TREE_TOKEN_KEYWORD_IF: { AstTreeIf *metadata = tree->metadata; return isConst(metadata->condition) && isConst(metadata->ifBody) && @@ -2403,6 +2436,103 @@ bool isConst(AstTree *tree) { UNREACHABLE; } +bool isConstByValue(AstTree *tree) { + if (tree->type == NULL) { + UNREACHABLE; + } + switch (tree->token) { + case AST_TREE_TOKEN_TYPE_TYPE: + case AST_TREE_TOKEN_TYPE_FUNCTION: + case AST_TREE_TOKEN_TYPE_VOID: + case AST_TREE_TOKEN_TYPE_I8: + case AST_TREE_TOKEN_TYPE_U8: + case AST_TREE_TOKEN_TYPE_I16: + case AST_TREE_TOKEN_TYPE_U16: + case AST_TREE_TOKEN_TYPE_I32: + case AST_TREE_TOKEN_TYPE_U32: + case AST_TREE_TOKEN_TYPE_I64: + case AST_TREE_TOKEN_TYPE_U64: + case AST_TREE_TOKEN_TYPE_F16: + case AST_TREE_TOKEN_TYPE_F32: + case AST_TREE_TOKEN_TYPE_F64: + case AST_TREE_TOKEN_TYPE_F128: + case AST_TREE_TOKEN_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_NULL: + case AST_TREE_TOKEN_VALUE_UNDEFINED: + case AST_TREE_TOKEN_VALUE_VOID: + case AST_TREE_TOKEN_VALUE_INT: + case AST_TREE_TOKEN_VALUE_FLOAT: + case AST_TREE_TOKEN_VALUE_BOOL: + case AST_TREE_TOKEN_VALUE_OBJECT: + case AST_TREE_TOKEN_KEYWORD_COMPTIME: + case AST_TREE_TOKEN_SCOPE: + return true; + case AST_TREE_TOKEN_KEYWORD_STRUCT: { + AstTreeStruct *metadata = tree->metadata; + for (size_t i = 0; i < metadata->variables.size; ++i) { + AstTreeVariable *member = metadata->variables.data[i]; + if (!isConstByValue(member->type)) { + return false; + } + } + return true; + } + case AST_TREE_TOKEN_KEYWORD_IF: { + AstTreeIf *metadata = tree->metadata; + return isConstByValue(metadata->condition) && + isConstByValue(metadata->ifBody) && + (metadata->elseBody == NULL || isConstByValue(metadata->elseBody)); + } + case AST_TREE_TOKEN_FUNCTION_CALL: { + AstTreeFunctionCall *metadata = tree->metadata; + for (size_t i = 0; i < metadata->parameters_size; ++i) { + if (!isConstByValue(metadata->parameters[i].value)) { + return false; + } + } + return isConstByValue(metadata->function); + } + case AST_TREE_TOKEN_FUNCTION: { + return true; + } + case AST_TREE_TOKEN_KEYWORD_WHILE: + case AST_TREE_TOKEN_KEYWORD_PRINT_U64: + case AST_TREE_TOKEN_KEYWORD_RETURN: + case AST_TREE_TOKEN_VARIABLE_DEFINE: + 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: + return false; + case AST_TREE_TOKEN_VARIABLE: { + AstTreeVariable *metadata = tree->metadata; + return metadata->isConst && metadata->value != NULL; + } + case AST_TREE_TOKEN_OPERATOR_DEREFERENCE: + case AST_TREE_TOKEN_OPERATOR_ADDRESS: + case AST_TREE_TOKEN_OPERATOR_POINTER: { + AstTreeSingleChild *metadata = tree->metadata; + return isConstByValue(metadata); + } + case AST_TREE_TOKEN_OPERATOR_ACCESS: { + AstTreeAccess *metadata = tree->metadata; + return isConstByValue(metadata->object); + } + case AST_TREE_TOKEN_NONE: + } + UNREACHABLE; +} + AstTree *makeTypeOf(AstTree *value) { switch (value->token) { case AST_TREE_TOKEN_TYPE_TYPE: @@ -2635,7 +2765,20 @@ bool typeIsEqualBack(const AstTree *type0, const AstTree *type1) { AstTreeStruct *type0_metadata = type0->metadata; AstTreeStruct *type1_metadata = type1->metadata; - return type0_metadata->id == type1_metadata->id; + + if (type0_metadata->id != type1_metadata->id || + type0_metadata->variables.size != type1_metadata->variables.size) { + return false; + } + + for (size_t i = 0; i < type0_metadata->variables.size; ++i) { + AstTreeVariable *member0 = type0_metadata->variables.data[i]; + AstTreeVariable *member1 = type1_metadata->variables.data[i]; + if (!typeIsEqual(member0->type, member1->type)) { + return false; + } + } + return true; } case AST_TREE_TOKEN_NONE: } @@ -3496,18 +3639,20 @@ bool setTypesAstVariable(AstTreeVariable *variable, .treeHelper = _helper.treeHelper, }; - if (variable->type != NULL && !setAllTypes(variable->type, helper, NULL)) { - return false; - } - if (variable->type != NULL) { - AstTree *type = variable->type; - variable->type = getValue(type); - if (variable->type == NULL) { + if (!setAllTypes(variable->type, helper, NULL)) { return false; } - if (type != variable->type) { - astTreeDelete(type); + + if (isConstByValue(variable->type)) { + AstTree *type = variable->type; + variable->type = getValue(type); + if (variable->type == NULL) { + return false; + } + if (type != variable->type) { + astTreeDelete(type); + } } } @@ -3545,10 +3690,6 @@ bool setTypesAstVariable(AstTreeVariable *variable, if (variable->value != value) { astTreeDelete(value); } - - if (variable->value == NULL) { - return false; - } } } diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index f29ce11..d4bf807 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -275,6 +275,7 @@ AstTree *astTreeParseAccessOperator(ParserNode *parserNode, bool isFunction(AstTree *value); bool isConst(AstTree *tree); +bool isConstByValue(AstTree *tree); AstTree *makeTypeOf(AstTree *value); bool typeIsEqual(AstTree *type0,AstTree *type1); bool typeIsEqualBack(const AstTree *type0, const AstTree *type1); diff --git a/src/runner/runner.c b/src/runner/runner.c index 984af3f..a407204 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -787,9 +787,7 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) { case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_VALUE_FLOAT: case AST_TREE_TOKEN_VALUE_OBJECT: - 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; @@ -820,6 +818,9 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) { if (isLeft) { return copyAstTree(expr); } else { + if (variable->value == NULL) { + UNREACHABLE; + } return copyAstTree(variable->value); } } @@ -862,6 +863,27 @@ AstTree *runExpression(AstTree *expr, bool *shouldRet, bool isLeft) { return copyAstTree(var->value); } } + case AST_TREE_TOKEN_KEYWORD_STRUCT: { + expr = copyAstTree(expr); + AstTreeStruct *metadata = expr->metadata; + for (size_t i = 0; i < metadata->variables.size; ++i) { + AstTreeVariable *member = metadata->variables.data[i]; + AstTree *type = member->type; + member->type = runExpression(member->type, shouldRet, isLeft); + if (type != member->type) { + astTreeDelete(type); + } + } + return expr; + } + case AST_TREE_TOKEN_OPERATOR_POINTER: { + AstTreeSingleChild *metadata = expr->metadata; + AstTreeSingleChild *newMetadata = + runExpression(metadata, shouldRet, isLeft); + + return newAstTree(AST_TREE_TOKEN_OPERATOR_POINTER, newMetadata, + copyAstTree(expr->type), expr->str_begin, expr->str_end); + } case AST_TREE_TOKEN_NONE: } UNREACHABLE; |