diff options
Diffstat (limited to 'src/compiler/ast-tree.c')
-rw-r--r-- | src/compiler/ast-tree.c | 142 |
1 files changed, 134 insertions, 8 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 4c6d36d..261e13b 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -112,6 +112,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_KEYWORD_IF", "AST_TREE_TOKEN_KEYWORD_WHILE", "AST_TREE_TOKEN_KEYWORD_COMPTIME", + "AST_TREE_TOKEN_KEYWORD_STRUCT", "AST_TREE_TOKEN_TYPE_FUNCTION", "AST_TREE_TOKEN_TYPE_TYPE", @@ -341,7 +342,6 @@ void astTreePrint(const AstTree *tree, int indent) { case AST_TREE_TOKEN_OPERATOR_SMALLER: case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL: case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: { - AstTreeInfix *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) @@ -412,6 +412,23 @@ void astTreePrint(const AstTree *tree, int indent) { printf("]"); } goto RETURN_SUCCESS; + case AST_TREE_TOKEN_KEYWORD_STRUCT: { + AstTreeStruct *metadata = tree->metadata; + printf(",\n"); + for (int i = 0; i < indent; ++i) + printf(" "); + printf("variables=[\n"); + for (size_t i = 0; i < metadata->variables.size; ++i) { + astTreeVariablePrint(metadata->variables.data[i], indent + 1); + printf(",\n"); + } + for (int i = 0; i < indent; ++i) { + printf(" "); + } + printf("]"); + + goto RETURN_SUCCESS; + } case AST_TREE_TOKEN_NONE: } @@ -421,14 +438,21 @@ RETURN_SUCCESS: printf("}"); } +void astTreeVariablePrint(const AstTreeVariable *variable, int indent) { + for (int i = 0; i < indent; ++i) { + printf(" "); + } + printf("{\nname=\"%.*s\",\nvalue=\n", + (int)(variable->name_end - variable->name_begin), + variable->name_begin); + astTreePrint(variable->value, indent); + printf("\n}"); +} + void astTreeRootPrint(const AstTreeRoot *root) { for (size_t i = 0; i < root->variables.size; ++i) { - const AstTreeVariable *variable = root->variables.data[i]; - printf("{\nname=\"%.*s\",\nvalue=\n", - (int)(variable->name_end - variable->name_begin), - variable->name_begin); - astTreePrint(variable->value, 1); - printf("\n}\n"); + astTreeVariablePrint(root->variables.data[i], 0); + printf("\n"); } } @@ -581,6 +605,15 @@ void astTreeDestroy(AstTree tree) { free(metadata); } return; + case AST_TREE_TOKEN_KEYWORD_STRUCT: { + AstTreeStruct *metadata = tree.metadata; + for (size_t i = 0; i < metadata->variables.size; ++i) { + astTreeVariableDelete(metadata->variables.data[i]); + } + free(metadata->variables.data); + free(metadata); + } + return; case AST_TREE_TOKEN_NONE: } printLog("token = %d", tree.token); @@ -908,6 +941,18 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], new_newVariables, new_variables_size), tree->str_begin, tree->str_end); } + case AST_TREE_TOKEN_KEYWORD_STRUCT: { + AstTreeStruct *metadata = tree->metadata; + AstTreeStruct *new_metadata = a404m_malloc(sizeof(*new_metadata)); + + new_metadata->variables = copyAstTreeVariables( + metadata->variables, oldVariables, newVariables, variables_size); + + 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); @@ -1078,6 +1123,7 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { case PARSER_TOKEN_OPERATOR_POINTER: case PARSER_TOKEN_OPERATOR_ADDRESS: case PARSER_TOKEN_OPERATOR_DEREFERENCE: + case PARSER_TOKEN_KEYWORD_STRUCT: goto AFTER_SWITCH; case PARSER_TOKEN_ROOT: case PARSER_TOKEN_KEYWORD_PRINT_U64: @@ -1337,6 +1383,8 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) { return astTreeParseCurlyBracket(parserNode, helper); case PARSER_TOKEN_SYMBOL_PARENTHESIS: return astTreeParseParenthesis(parserNode, helper); + case PARSER_TOKEN_KEYWORD_STRUCT: + return astTreeParseStruct(parserNode, helper); case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_NONE: @@ -1450,6 +1498,7 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) { case PARSER_TOKEN_KEYWORD_PRINT_U64: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_COMPTIME: + case PARSER_TOKEN_KEYWORD_STRUCT: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: @@ -1991,6 +2040,7 @@ AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, case PARSER_TOKEN_KEYWORD_PRINT_U64: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_KEYWORD_COMPTIME: + case PARSER_TOKEN_KEYWORD_STRUCT: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: @@ -2078,6 +2128,56 @@ AstTree *astTreeParseParenthesis(ParserNode *parserNode, } } +AstTree *astTreeParseStruct(ParserNode *parserNode, AstTreeHelper *helper) { + ParserNode *body = parserNode->metadata; + ParserNodeArray *body_metadata = body->metadata; + AstTreeVariables variables = { + .data = a404m_malloc(sizeof(*variables.data) * body_metadata->size), + .size = body_metadata->size, + }; + + for (size_t i = 0; i < body_metadata->size; ++i) { + ParserNode *node = body_metadata->data[i]; + if (node->token != PARSER_TOKEN_SYMBOL_EOL) { + printError(node->str_begin, node->str_end, + "Semicolon is required, maybe forget a semicolon?"); + return NULL; + } + node = (ParserNodeSingleChildMetadata *)node->metadata; + + if (node->token != PARSER_TOKEN_VARIABLE) { + printError(node->str_begin, node->str_end, + "Only variable definitions are allowed here"); + return NULL; + } + ParserNodeVariableMetadata *node_variable = node->metadata; + + AstTreeVariable *variable = a404m_malloc(sizeof(*variable)); + variable->name_begin = node_variable->name->str_begin; + variable->name_end = node_variable->name->str_end; + if (node_variable->type != NULL) { + variable->type = astTreeParse(node_variable->type, helper); + } else { + variable->type = NULL; + } + if (node_variable->value != NULL) { + printError(node->str_begin, node->str_end, "Can't have default values"); + NOT_IMPLEMENTED; + } + variable->value = NULL; + variable->isConst = false; + + variables.data[i] = variable; + } + + AstTreeStruct *metadata = a404m_malloc(sizeof(*metadata)); + metadata->variables = variables; + metadata->id = (size_t)metadata; // TODO: change it + + return newAstTree(AST_TREE_TOKEN_KEYWORD_STRUCT, metadata, NULL, + parserNode->str_begin, parserNode->str_end); +} + bool isFunction(AstTree *value) { return value->type->token == AST_TREE_TOKEN_TYPE_FUNCTION; } @@ -2107,6 +2207,7 @@ bool isConst(AstTree *tree, AstTreeHelper *helper) { case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_KEYWORD_COMPTIME: case AST_TREE_TOKEN_SCOPE: + case AST_TREE_TOKEN_KEYWORD_STRUCT: return true; case AST_TREE_TOKEN_KEYWORD_IF: { AstTreeIf *metadata = tree->metadata; @@ -2179,6 +2280,7 @@ AstTree *makeTypeOf(AstTree *value) { case AST_TREE_TOKEN_TYPE_F128: case AST_TREE_TOKEN_TYPE_BOOL: case AST_TREE_TOKEN_OPERATOR_POINTER: + case AST_TREE_TOKEN_KEYWORD_STRUCT: return &AST_TREE_TYPE_TYPE; case AST_TREE_TOKEN_OPERATOR_ADDRESS: { AstTreeSingleChild *metadata = value->metadata; @@ -2348,6 +2450,14 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_VARIABLE: return type1->token == AST_TREE_TOKEN_VARIABLE && type0->metadata == type1->metadata; + case AST_TREE_TOKEN_KEYWORD_STRUCT: { + if (type1->token != AST_TREE_TOKEN_KEYWORD_STRUCT) + return false; + + AstTreeStruct *type0_metadata = type0->metadata; + AstTreeStruct *type1_metadata = type1->metadata; + return type0_metadata->id == type1_metadata->id; + } case AST_TREE_TOKEN_NONE: } UNREACHABLE; @@ -2411,6 +2521,7 @@ AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper) { } return value; } + case AST_TREE_TOKEN_KEYWORD_STRUCT: case AST_TREE_TOKEN_FUNCTION: { return tree; } @@ -2437,7 +2548,6 @@ bool isCircularDependenciesBack(AstTreeHelper *helper, AstTreeVariable *variable, AstTree *tree, AstTreeVariables *checkedVariables) { switch (tree->token) { - case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_VOID: @@ -2517,9 +2627,11 @@ bool isCircularDependenciesBack(AstTreeHelper *helper, } return false; } + case AST_TREE_TOKEN_KEYWORD_STRUCT: case AST_TREE_TOKEN_FUNCTION: { return false; } + case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_VARIABLE_DEFINE: @@ -2668,6 +2780,8 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper, return setTypesScope(tree, helper, function); case AST_TREE_TOKEN_KEYWORD_COMPTIME: return setTypesComptime(tree, helper); + case AST_TREE_TOKEN_KEYWORD_STRUCT: + return setTypesStruct(tree, helper); case AST_TREE_TOKEN_NONE: break; } @@ -3302,6 +3416,18 @@ bool setTypesComptime(AstTree *tree, AstTreeSetTypesHelper helper) { return true; } +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)) { + return false; + } + } + tree->type = &AST_TREE_TYPE_TYPE; + return true; +} + bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) { if (!setAllTypes(&infix->left, helper, NULL)) { return false; |