#include "ast-tree.h" #include "compiler/parser.h" #include "runner/runner.h" #include "utils/log.h" #include "utils/memory.h" #include #include #include #include AstTree AST_TREE_TYPE_TYPE = { .token = AST_TREE_TOKEN_TYPE_TYPE, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_VOID_TYPE = { .token = AST_TREE_TOKEN_TYPE_VOID, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_BOOL_TYPE = { .token = AST_TREE_TOKEN_TYPE_BOOL, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_I8_TYPE = { .token = AST_TREE_TOKEN_TYPE_I8, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_U8_TYPE = { .token = AST_TREE_TOKEN_TYPE_U8, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_I16_TYPE = { .token = AST_TREE_TOKEN_TYPE_I16, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_U16_TYPE = { .token = AST_TREE_TOKEN_TYPE_U16, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_I32_TYPE = { .token = AST_TREE_TOKEN_TYPE_I32, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_U32_TYPE = { .token = AST_TREE_TOKEN_TYPE_U32, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_I64_TYPE = { .token = AST_TREE_TOKEN_TYPE_I64, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_U64_TYPE = { .token = AST_TREE_TOKEN_TYPE_U64, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_F16_TYPE = { .token = AST_TREE_TOKEN_TYPE_F16, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_F32_TYPE = { .token = AST_TREE_TOKEN_TYPE_F32, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_F64_TYPE = { .token = AST_TREE_TOKEN_TYPE_F64, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_F128_TYPE = { .token = AST_TREE_TOKEN_TYPE_F128, .metadata = NULL, .type = &AST_TREE_TYPE_TYPE, }; AstTree AST_TREE_VOID_VALUE = { .token = AST_TREE_TOKEN_VALUE_VOID, .metadata = NULL, .type = &AST_TREE_VOID_TYPE, }; const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_FUNCTION", "AST_TREE_TOKEN_KEYWORD_PRINT_U64", "AST_TREE_TOKEN_KEYWORD_RETURN", "AST_TREE_TOKEN_KEYWORD_IF", "AST_TREE_TOKEN_KEYWORD_WHILE", "AST_TREE_TOKEN_TYPE_FUNCTION", "AST_TREE_TOKEN_TYPE_TYPE", "AST_TREE_TOKEN_TYPE_VOID", "AST_TREE_TOKEN_TYPE_I8", "AST_TREE_TOKEN_TYPE_U8", "AST_TREE_TOKEN_TYPE_I16", "AST_TREE_TOKEN_TYPE_U16", "AST_TREE_TOKEN_TYPE_I32", "AST_TREE_TOKEN_TYPE_U32", "AST_TREE_TOKEN_TYPE_I64", "AST_TREE_TOKEN_TYPE_U64", "AST_TREE_TOKEN_TYPE_F16", "AST_TREE_TOKEN_TYPE_F32", "AST_TREE_TOKEN_TYPE_F64", "AST_TREE_TOKEN_TYPE_F128", "AST_TREE_TOKEN_TYPE_BOOL", "AST_TREE_TOKEN_FUNCTION_CALL", "AST_TREE_TOKEN_VARIABLE", "AST_TREE_TOKEN_VARIABLE_DEFINE", "AST_TREE_TOKEN_VALUE_VOID", "AST_TREE_TOKEN_VALUE_INT", "AST_TREE_TOKEN_VALUE_FLOAT", "AST_TREE_TOKEN_VALUE_BOOL", "AST_TREE_TOKEN_OPERATOR_ASSIGN", "AST_TREE_TOKEN_OPERATOR_PLUS", "AST_TREE_TOKEN_OPERATOR_MINUS", "AST_TREE_TOKEN_OPERATOR_SUM", "AST_TREE_TOKEN_OPERATOR_SUB", "AST_TREE_TOKEN_OPERATOR_MULTIPLY", "AST_TREE_TOKEN_OPERATOR_DIVIDE", "AST_TREE_TOKEN_OPERATOR_MODULO", "AST_TREE_TOKEN_OPERATOR_EQUAL", "AST_TREE_TOKEN_OPERATOR_NOT_EQUAL", "AST_TREE_TOKEN_OPERATOR_GREATER", "AST_TREE_TOKEN_OPERATOR_SMALLER", "AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL", "AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL", "AST_TREE_TOKEN_SCOPE", "AST_TREE_TOKEN_NONE", }; void astTreePrint(const AstTree *tree, int indent) { for (int i = 0; i < indent; ++i) printf(" "); printf("{token=\"%s\"", AST_TREE_TOKEN_STRINGS[tree->token]); switch (tree->token) { case AST_TREE_TOKEN_FUNCTION: { AstTreeFunction *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("arguments=[\n"); for (size_t i = 0; i < metadata->arguments.size; ++i) { for (int i = 0; i < indent + 1; ++i) printf(" "); printf("{name=%.*s,\n", (int)(metadata->arguments.data[i]->name_end - metadata->arguments.data[i]->name_begin), metadata->arguments.data[i]->name_begin); for (int i = 0; i < indent + 1; ++i) printf(" "); printf("type=\n"); astTreePrint(metadata->arguments.data[i]->type, indent + 2); printf("\n"); for (int i = 0; i < indent + 1; ++i) printf(" "); printf("},\n"); } for (int i = 0; i < indent; ++i) printf(" "); printf("],\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("expressions=[\n"); for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { astTreePrint(metadata->scope.expressions[i], indent + 1); printf(",\n"); } for (int i = 0; i < indent; ++i) printf(" "); printf("]"); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_TYPE_TYPE: 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_BOOL: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VARIABLE_DEFINE: goto RETURN_SUCCESS; case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { AstTreeSingleChild *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("child=\n"); astTreePrint(metadata, indent + 1); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_KEYWORD_RETURN: { AstTreeReturn *metadata = tree->metadata; if (metadata->value != NULL) { printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("value=\n"); astTreePrint(metadata->value, indent + 1); } } goto RETURN_SUCCESS; case AST_TREE_TOKEN_VALUE_INT: { AstTreeInt metadata = (AstTreeInt)tree->metadata; printf(",value=%lu", metadata); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_VALUE_BOOL: { AstTreeBool metadata = (AstTreeBool)tree->metadata; printf(",value=%b", metadata); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_TYPE_FUNCTION: { AstTreeTypeFunction *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("arguments=[\n"); for (size_t i = 0; i < metadata->arguments_size; ++i) { astTreePrint(metadata->arguments[i], indent + 1); printf(",\n"); } for (int i = 0; i < indent; ++i) printf(" "); printf("]"); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("function=\n"); astTreePrint(metadata->function, indent + 1); printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("paramters=[\n"); for (size_t i = 0; i < metadata->parameters_size; ++i) { astTreePrint(metadata->parameters[i], indent + 1); printf(",\n"); } for (int i = 0; i < indent; ++i) printf(" "); printf("]"); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *metadata = tree->metadata; printf(",variable.name=%.*s", (int)(metadata->name_end - metadata->name_begin), metadata->name_begin); } goto RETURN_SUCCESS; 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_ASSIGN: 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: { AstTreeInfix *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("left=\n"); astTreePrint(&metadata->left, indent + 1); printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("right=\n"); astTreePrint(&metadata->right, indent + 1); printf("\n"); for (int i = 0; i < indent; ++i) printf(" "); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_KEYWORD_IF: { AstTreeIf *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("condition=\n"); astTreePrint(metadata->condition, indent + 1); printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("ifBody=\n"); astTreePrint(metadata->ifBody, indent + 1); printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("elseBody=\n"); astTreePrint(metadata->elseBody, indent + 1); printf("\n"); for (int i = 0; i < indent; ++i) printf(" "); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_KEYWORD_WHILE: { AstTreeWhile *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("condition=\n"); astTreePrint(metadata->condition, indent + 1); printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("body=\n"); astTreePrint(metadata->body, indent + 1); printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_SCOPE: { AstTreeScope *metadata = tree->metadata; printf(",\n"); for (int i = 0; i < indent; ++i) printf(" "); printf("expressions=[\n"); for (size_t i = 0; i < metadata->expressions_size; ++i) { astTreePrint(metadata->expressions[i], indent + 1); printf(",\n"); } for (int i = 0; i < indent; ++i) printf(" "); printf("]"); } goto RETURN_SUCCESS; case AST_TREE_TOKEN_NONE: } UNREACHABLE; RETURN_SUCCESS: printf("}"); } 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"); } } void astTreeDestroy(AstTree tree) { if (tree.type != NULL) { astTreeDelete(tree.type); } switch (tree.token) { case AST_TREE_TOKEN_FUNCTION: { AstTreeFunction *metadata = tree.metadata; for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { astTreeDelete(metadata->scope.expressions[i]); } for (size_t i = 0; i < metadata->scope.variables.size; ++i) { astTreeVariableDelete(metadata->scope.variables.data[i]); } for (size_t i = 0; i < metadata->arguments.size; ++i) { astTreeVariableDelete(metadata->arguments.data[i]); } astTreeDelete(metadata->returnType); free(metadata->scope.expressions); free(metadata->scope.variables.data); free(metadata->arguments.data); free(metadata); } return; case AST_TREE_TOKEN_TYPE_TYPE: 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_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_VARIABLE_DEFINE: return; case AST_TREE_TOKEN_VALUE_FLOAT: { AstTreeFloat *metadata = tree.metadata; free(metadata); return; } case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { AstTreeSingleChild *metadata = tree.metadata; astTreeDelete(metadata); } return; case AST_TREE_TOKEN_KEYWORD_RETURN: { AstTreeReturn *metadata = tree.metadata; if (metadata->value != NULL) { astTreeDelete(metadata->value); } free(metadata); } return; case AST_TREE_TOKEN_TYPE_FUNCTION: { AstTreeTypeFunction *metadata = tree.metadata; for (size_t i = 0; i < metadata->arguments_size; ++i) { astTreeDelete(metadata->arguments[i]); } astTreeDelete(metadata->returnType); free(metadata->arguments); free(metadata); } return; case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = tree.metadata; astTreeDelete(metadata->function); for (size_t i = 0; i < metadata->parameters_size; ++i) { astTreeDelete(metadata->parameters[i]); } free(metadata->parameters); free(metadata); } return; case AST_TREE_TOKEN_VARIABLE: { // AstTreeIdentifier *metadata = tree.metadata; // not needed } return; 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_ASSIGN: 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: { AstTreeInfix *metadata = tree.metadata; astTreeDestroy(metadata->left); astTreeDestroy(metadata->right); free(metadata); } return; case AST_TREE_TOKEN_KEYWORD_IF: { AstTreeIf *metadata = tree.metadata; astTreeDelete(metadata->condition); astTreeDelete(metadata->ifBody); if (metadata->elseBody != NULL) { astTreeDelete(metadata->elseBody); } free(metadata); } return; case AST_TREE_TOKEN_KEYWORD_WHILE: { AstTreeWhile *metadata = tree.metadata; astTreeDelete(metadata->condition); astTreeDelete(metadata->body); free(metadata); } return; case AST_TREE_TOKEN_SCOPE: { AstTreeScope *metadata = tree.metadata; for (size_t i = 0; i < metadata->expressions_size; ++i) { astTreeDelete(metadata->expressions[i]); } for (size_t i = 0; i < metadata->variables.size; ++i) { astTreeVariableDelete(metadata->variables.data[i]); } free(metadata->expressions); free(metadata->variables.data); free(metadata); } return; case AST_TREE_TOKEN_NONE: } printLog("token = %d", tree.token); UNREACHABLE; } void astTreeVariableDestroy(AstTreeVariable variable) { if (variable.value != NULL) { astTreeDelete(variable.value); } if (variable.type != NULL) { astTreeDelete(variable.type); } } void astTreeVariableDelete(AstTreeVariable *variable) { astTreeVariableDestroy(*variable); free(variable); } void astTreeDelete(AstTree *tree) { if (AST_TREE_TOKEN_STATIC_VARS_BEGIN > tree->token || tree->token > AST_TREE_TOKEN_STATIC_VARS_END) { astTreeDestroy(*tree); free(tree); } } void astTreeRootDelete(AstTreeRoot *root) { for (size_t i = 0; i < root->variables.size; ++i) { astTreeVariableDelete(root->variables.data[i]); } free(root->variables.data); free(root); } AstTree *newAstTree(AstTreeToken token, void *metadata, AstTree *type, char *str_begin, char *str_end) { AstTree *result = a404m_malloc(sizeof(*result)); result->token = token; result->metadata = metadata; result->type = type; result->str_begin = str_begin; result->str_end = str_end; 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_BOOL: 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_VALUE_VOID: return tree; case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_BOOL: return newAstTree(tree->token, tree->metadata, tree->type, tree->str_begin, tree->str_end); case AST_TREE_TOKEN_VALUE_FLOAT: { AstTreeFloat *metadata = tree->metadata; AstTreeFloat *newMetadata = a404m_malloc(sizeof(*newMetadata)); *newMetadata = *metadata; return newAstTree(tree->token, newMetadata, tree->type, tree->str_begin, tree->str_end); } case AST_TREE_TOKEN_VARIABLE: case AST_TREE_TOKEN_VARIABLE_DEFINE: return newAstTree(tree->token, tree->metadata, copyAstTree(tree->type), tree->str_begin, tree->str_end); case AST_TREE_TOKEN_TYPE_FUNCTION: { AstTreeTypeFunction *metadata = tree->metadata; AstTreeTypeFunction *new_metadata = a404m_malloc(sizeof(*new_metadata)); new_metadata->returnType = copyAstTree(metadata->returnType); new_metadata->arguments_size = metadata->arguments_size; new_metadata->arguments = a404m_malloc(sizeof(*new_metadata) * new_metadata->arguments_size); for (size_t i = 0; i < metadata->arguments_size; ++i) { new_metadata->arguments[i] = copyAstTree(metadata->arguments[i]); } return newAstTree(tree->token, new_metadata, &AST_TREE_TYPE_TYPE, tree->str_begin, tree->str_end); } case AST_TREE_TOKEN_OPERATOR_ASSIGN: 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: { AstTreeInfix *metadata = tree->metadata; AstTreeInfix *new_metadata = a404m_malloc(sizeof(*new_metadata)); AstTree *left = copyAstTree(&metadata->left); AstTree *right = copyAstTree(&metadata->right); new_metadata->left = *left; new_metadata->right = *right; free(left); free(right); return newAstTree(tree->token, new_metadata, copyAstTree(tree->type), tree->str_begin, tree->str_end); } case AST_TREE_TOKEN_FUNCTION: { AstTreeFunction *metadata = tree->metadata; AstTreeFunction *new_metadata = a404m_malloc(sizeof(*new_metadata)); new_metadata->scope.variables = copyAstTreeVariables(metadata->scope.variables); new_metadata->scope.expressions_size = metadata->scope.expressions_size; new_metadata->scope.expressions = a404m_malloc(new_metadata->scope.expressions_size * sizeof(*new_metadata->scope.expressions)); for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { new_metadata->scope.expressions[i] = copyAstTree(metadata->scope.expressions[i]); } new_metadata->returnType = copyAstTree(metadata->returnType); new_metadata->arguments = copyAstTreeVariables(metadata->arguments); return newAstTree(tree->token, new_metadata, copyAstTree(tree->type), tree->str_begin, tree->str_end); } case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { AstTreeSingleChild *metadata = tree->metadata; AstTreeSingleChild *new_metadata = copyAstTree(metadata); return newAstTree(tree->token, new_metadata, copyAstTree(tree->type), tree->str_begin, tree->str_end); } case AST_TREE_TOKEN_KEYWORD_RETURN: { AstTreeReturn *metadata = tree->metadata; AstTreeReturn *new_metadata = a404m_malloc(sizeof(*new_metadata)); if (metadata->value != NULL) { new_metadata->value = copyAstTree(metadata->value); } else { new_metadata->value = NULL; } return newAstTree(tree->token, new_metadata, copyAstTree(tree->type), tree->str_begin, tree->str_end); } case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = tree->metadata; AstTreeFunctionCall *new_metadata = a404m_malloc(sizeof(*new_metadata)); new_metadata->function = copyAstTree(metadata->function); new_metadata->parameters_size = metadata->parameters_size; new_metadata->parameters = a404m_malloc(metadata->parameters_size * sizeof(*new_metadata->parameters)); for (size_t i = 0; i < metadata->parameters_size; ++i) { new_metadata->parameters[i] = copyAstTree(metadata->parameters[i]); } return newAstTree(tree->token, new_metadata, copyAstTree(tree->type), tree->str_begin, tree->str_end); } case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_NONE: } printLog("Bad token %ld", tree->token); UNREACHABLE; } AstTreeVariables copyAstTreeVariables(AstTreeVariables variables) { AstTreeVariables result = { .data = a404m_malloc(variables.size * sizeof(*variables.data)), .size = variables.size, }; for (size_t i = 0; i < result.size; ++i) { result.data[i] = a404m_malloc(sizeof(*result.data[i])); if (variables.data[i]->value != NULL) { result.data[i]->value = copyAstTree(variables.data[i]->value); } else { result.data[i]->value = NULL; } result.data[i]->type = copyAstTree(variables.data[i]->type); result.data[i]->isConst = variables.data[i]->isConst; result.data[i]->name_begin = variables.data[i]->name_begin; result.data[i]->name_end = variables.data[i]->name_end; } return result; } AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { if (parsedRoot->token != PARSER_TOKEN_ROOT) { return NULL; } ParserNodeArray *nodes = parsedRoot->metadata; AstTreeRoot *root = a404m_malloc(sizeof(*root)); root->variables.data = a404m_malloc(nodes->size * sizeof(*root->variables.data)); root->variables.size = 0; for (size_t i = 0; i < nodes->size; ++i) { ParserNode *eol = nodes->data[i]; if (eol->token != PARSER_TOKEN_SYMBOL_EOL) { printError(eol->str_begin, eol->str_end, "Did you forgot semicolon?", PARSER_TOKEN_STRINGS[eol->token]); goto RETURN_ERROR; } ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata; if (node->token != PARSER_TOKEN_CONSTANT && node->token != PARSER_TOKEN_VARIABLE) { printError(node->str_begin, node->str_end, "Unexpected %s", PARSER_TOKEN_STRINGS[node->token]); goto RETURN_ERROR; } ParserNodeVariableMetadata *node_metadata = node->metadata; AstTreeVariable *variable = a404m_malloc(sizeof(*variable)); variable->name_begin = node_metadata->name->str_begin; variable->name_end = node_metadata->name->str_end; variable->isConst = node->token == PARSER_TOKEN_CONSTANT; if (!pushVariable(NULL, &root->variables, variable)) { astTreeVariableDelete(variable); goto RETURN_ERROR; } } AstTreeVariables *variables = &root->variables; constexpr size_t variables_size = 1; AstTreeHelper helper = { .variables = &variables, .variables_size = variables_size, .variable = NULL, .globalDeps = a404m_malloc(variables->size * sizeof(*helper.globalDeps)), }; for (size_t i = 0; i < variables->size; ++i) { helper.globalDeps[i].size = 0; helper.globalDeps[i].data = a404m_malloc(helper.globalDeps->size * sizeof(*helper.globalDeps)); } for (size_t i = 0; i < nodes->size; ++i) { helper.variable = root->variables.data[i]; ParserNode *node = (ParserNodeSingleChildMetadata *)nodes->data[i]->metadata; ParserNodeVariableMetadata *node_metadata = node->metadata; if (node->token != PARSER_TOKEN_CONSTANT && node->token != PARSER_TOKEN_VARIABLE) { printError(node->str_begin, node->str_end, "Only variables are allowed here"); goto RETURN_ERROR; } if (node_metadata->value == NULL) { printError(node->str_begin, node->str_end, "Variables must be initialized"); goto RETURN_ERROR; } switch (node_metadata->value->token) { case PARSER_TOKEN_VALUE_BOOL: case PARSER_TOKEN_VALUE_INT: case PARSER_TOKEN_FUNCTION_DEFINITION: case PARSER_TOKEN_FUNCTION_CALL: case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_OPERATOR_ASSIGN: case PARSER_TOKEN_OPERATOR_PLUS: case PARSER_TOKEN_OPERATOR_MINUS: case PARSER_TOKEN_OPERATOR_SUM: case PARSER_TOKEN_OPERATOR_SUB: case PARSER_TOKEN_OPERATOR_MULTIPLY: case PARSER_TOKEN_OPERATOR_DIVIDE: case PARSER_TOKEN_OPERATOR_MODULO: case PARSER_TOKEN_OPERATOR_EQUAL: case PARSER_TOKEN_OPERATOR_NOT_EQUAL: case PARSER_TOKEN_OPERATOR_GREATER: case PARSER_TOKEN_OPERATOR_SMALLER: case PARSER_TOKEN_OPERATOR_GREATER_OR_EQUAL: case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL: case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_KEYWORD_IF: case PARSER_TOKEN_KEYWORD_WHILE: case PARSER_TOKEN_TYPE_TYPE: case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_TYPE_VOID: case PARSER_TOKEN_TYPE_I8: case PARSER_TOKEN_TYPE_U8: case PARSER_TOKEN_TYPE_I16: case PARSER_TOKEN_TYPE_U16: case PARSER_TOKEN_TYPE_I32: case PARSER_TOKEN_TYPE_U32: case PARSER_TOKEN_TYPE_I64: case PARSER_TOKEN_TYPE_U64: case PARSER_TOKEN_TYPE_BOOL: goto AFTER_SWITCH; case PARSER_TOKEN_ROOT: case PARSER_TOKEN_KEYWORD_PRINT_U64: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_EOL: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_COMMA: printError(node->str_begin, node->str_end, "Should not be here %s", PARSER_TOKEN_STRINGS[node->token]); goto RETURN_ERROR; case PARSER_TOKEN_NONE: } printError(node_metadata->value->str_begin, node_metadata->value->str_end, "Bad token %d", node_metadata->value->token); goto RETURN_ERROR; AFTER_SWITCH: AstTree *value = astTreeParse(node_metadata->value, &helper); if (value == NULL) { goto RETURN_ERROR; } AstTree *type; if (node_metadata->type != NULL) { type = astTreeParse(node_metadata->type, &helper); if (type == NULL) { goto RETURN_ERROR; } } else { type = NULL; } root->variables.data[i]->type = type; root->variables.data[i]->value = value; } helper.variable = NULL; if (!setAllTypesRoot(root, &helper)) { goto RETURN_ERROR; } for (size_t i = 0; i < variables->size; ++i) { free(helper.globalDeps[i].data); } free(helper.globalDeps); return root; RETURN_ERROR: free(root->variables.data); free(root); return NULL; } bool pushVariable(AstTreeHelper *helper, AstTreeVariables *variables, AstTreeVariable *variable) { (void)helper; for (size_t j = 0; j < variables->size; ++j) { char *var_begin = variables->data[j]->name_begin; char *var_end = variables->data[j]->name_end; if (variable->name_end - variable->name_begin == var_end - var_begin && strncmp(var_begin, variable->name_begin, variable->name_end - variable->name_begin) == 0) { printError(variable->name_begin, variable->name_end, "Variable exists"); return false; } } size_t variables_size = a404m_malloc_usable_size(variables->data) / sizeof(*variables->data); if (variables_size == variables->size) { variables_size += variables_size / 2 + 1; variables->data = a404m_realloc(variables->data, variables_size * sizeof(*variables->data)); } variables->data[variables->size] = variable; variables->size += 1; return true; } AstTreeVariable *getVariable(AstTreeHelper *helper, char *name_begin, char *name_end) { for (size_t i = helper->variables_size - 1; i != (size_t)-1ULL; --i) { AstTreeVariables vars = *helper->variables[i]; for (size_t j = 0; j < vars.size; ++j) { char *var_begin = vars.data[j]->name_begin; char *var_end = vars.data[j]->name_end; AstTreeVariable *variable = vars.data[j]; if (name_end - name_begin == var_end - var_begin && strncmp(var_begin, name_begin, name_end - name_begin) == 0) { if (i == 0 && helper->variable != NULL) { for (size_t i = 0; i < helper->variables[0]->size; ++i) { if (helper->variables[0]->data[i] == helper->variable) { size_t globalDeps_size = a404m_malloc_usable_size(helper->globalDeps[i].data) / sizeof(*helper->globalDeps[i].data); if (globalDeps_size == helper->globalDeps[i].size) { globalDeps_size += globalDeps_size / 2 + 1; helper->globalDeps[i].data = a404m_realloc( helper->globalDeps[i].data, globalDeps_size * sizeof(*helper->globalDeps[i].data)); } helper->globalDeps[i].data[helper->globalDeps[i].size] = variable; helper->globalDeps[i].size += 1; } } } return variable; } } } return NULL; } AstTree *astTreeParse(ParserNode *parserNode, AstTreeHelper *helper) { switch (parserNode->token) { case PARSER_TOKEN_FUNCTION_DEFINITION: return astTreeParseFunction(parserNode, helper); case PARSER_TOKEN_TYPE_TYPE: return &AST_TREE_TYPE_TYPE; case PARSER_TOKEN_TYPE_FUNCTION: return astTreeParseTypeFunction(parserNode, helper); case PARSER_TOKEN_TYPE_VOID: return &AST_TREE_VOID_TYPE; case PARSER_TOKEN_TYPE_I8: return &AST_TREE_I8_TYPE; case PARSER_TOKEN_TYPE_U8: return &AST_TREE_U8_TYPE; case PARSER_TOKEN_TYPE_I16: return &AST_TREE_I16_TYPE; case PARSER_TOKEN_TYPE_U16: return &AST_TREE_U16_TYPE; case PARSER_TOKEN_TYPE_I32: return &AST_TREE_I32_TYPE; case PARSER_TOKEN_TYPE_U32: return &AST_TREE_U32_TYPE; case PARSER_TOKEN_TYPE_I64: return &AST_TREE_I64_TYPE; case PARSER_TOKEN_TYPE_U64: return &AST_TREE_U64_TYPE; case PARSER_TOKEN_TYPE_F16: return &AST_TREE_F16_TYPE; case PARSER_TOKEN_TYPE_F32: return &AST_TREE_F32_TYPE; case PARSER_TOKEN_TYPE_F64: return &AST_TREE_F64_TYPE; case PARSER_TOKEN_TYPE_F128: return &AST_TREE_F128_TYPE; case PARSER_TOKEN_TYPE_BOOL: return &AST_TREE_BOOL_TYPE; case PARSER_TOKEN_FUNCTION_CALL: return astTreeParseFunctionCall(parserNode, helper); case PARSER_TOKEN_IDENTIFIER: return astTreeParseIdentifier(parserNode, helper); case PARSER_TOKEN_VALUE_INT: return newAstTree( AST_TREE_TOKEN_VALUE_INT, (void *)(AstTreeInt)(ParserNodeIntMetadata)parserNode->metadata, NULL, parserNode->str_begin, parserNode->str_end); case PARSER_TOKEN_VALUE_FLOAT: return astTreeParseFloat(parserNode); case PARSER_TOKEN_VALUE_BOOL: return newAstTree( AST_TREE_TOKEN_VALUE_BOOL, (void *)(AstTreeBool)(ParserNodeBoolMetadata)parserNode->metadata, &AST_TREE_BOOL_TYPE, parserNode->str_begin, parserNode->str_end); case PARSER_TOKEN_KEYWORD_PRINT_U64: return astTreeParsePrintU64(parserNode, helper); case PARSER_TOKEN_KEYWORD_RETURN: return astTreeParseReturn(parserNode, helper); case PARSER_TOKEN_OPERATOR_ASSIGN: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_ASSIGN); case PARSER_TOKEN_OPERATOR_SUM: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_SUM); case PARSER_TOKEN_OPERATOR_SUB: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_SUB); case PARSER_TOKEN_OPERATOR_MULTIPLY: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_MULTIPLY); case PARSER_TOKEN_OPERATOR_DIVIDE: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_DIVIDE); case PARSER_TOKEN_OPERATOR_MODULO: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_MODULO); case PARSER_TOKEN_OPERATOR_EQUAL: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_EQUAL); case PARSER_TOKEN_OPERATOR_NOT_EQUAL: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_NOT_EQUAL); case PARSER_TOKEN_OPERATOR_GREATER: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_GREATER); case PARSER_TOKEN_OPERATOR_SMALLER: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_SMALLER); case PARSER_TOKEN_OPERATOR_GREATER_OR_EQUAL: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL); case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL: return astTreeParseBinaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL); case PARSER_TOKEN_OPERATOR_PLUS: return astTreeParseUnaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_PLUS); case PARSER_TOKEN_OPERATOR_MINUS: return astTreeParseUnaryOperator(parserNode, helper, AST_TREE_TOKEN_OPERATOR_MINUS); case PARSER_TOKEN_VARIABLE: return astTreeParseVariable(parserNode, helper); case PARSER_TOKEN_KEYWORD_IF: return astTreeParseIf(parserNode, helper); case PARSER_TOKEN_KEYWORD_WHILE: return astTreeParseWhile(parserNode, helper); case PARSER_TOKEN_SYMBOL_EOL: return astTreeParse((ParserNodeSingleChildMetadata *)parserNode->metadata, helper); case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: return astTreeParseCurlyBracket(parserNode, helper); case PARSER_TOKEN_SYMBOL_PARENTHESIS: return astTreeParseParenthesis(parserNode, helper); case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_NONE: case PARSER_TOKEN_ROOT: } printError(parserNode->str_begin, parserNode->str_end, "Bad token %d", parserNode->token); return NULL; } AstTree *astTreeParseFunction(ParserNode *parserNode, AstTreeHelper *p_helper) { ParserNodeFunctionDefnitionMetadata *node_metadata = parserNode->metadata; ParserNodeArray *node_arguments = node_metadata->arguments->metadata; ParserNodeArray *body = node_metadata->body->metadata; size_t expressions_size = 0; AstTreeScope scope = { .expressions = a404m_malloc(expressions_size * sizeof(*scope.expressions)), .expressions_size = 0, .variables.data = a404m_malloc(0), .variables.size = 0, }; AstTreeFunction *function = a404m_malloc(sizeof(*function)); function->arguments.data = a404m_malloc(0); function->arguments.size = 0; size_t variables_size = p_helper->variables_size + 2; AstTreeVariables *variables[variables_size]; for (size_t i = 0; i < p_helper->variables_size; ++i) { variables[i] = p_helper->variables[i]; } variables[variables_size - 2] = &function->arguments; variables[variables_size - 1] = &scope.variables; AstTreeHelper helper = { .variables = variables, .variables_size = variables_size, .variable = p_helper->variable, .globalDeps = p_helper->globalDeps, }; if ((function->returnType = astTreeParse(node_metadata->returnType, &helper)) == NULL) { goto RETURN_ERROR; } for (size_t i = 0; i < node_arguments->size; ++i) { ParserNode *arg = node_arguments->data[i]; if (arg->token == PARSER_TOKEN_SYMBOL_COMMA) { arg = (ParserNodeSingleChildMetadata *)arg->metadata; } ParserNodeVariableMetadata *arg_metadata = arg->metadata; if (arg_metadata->value != NULL) { printError(arg->str_begin, arg->str_end, "arguments can't have default values (for now)"); goto RETURN_ERROR; } AstTree *type = astTreeParse(arg_metadata->type, &helper); if (type == NULL) { goto RETURN_ERROR; } AstTreeVariable *argument = a404m_malloc(sizeof(*argument)); argument->value = NULL; argument->type = type; argument->name_begin = arg_metadata->name->str_begin; argument->name_end = arg_metadata->name->str_end; argument->isConst = false; // all arguments are not constants if (!pushVariable(&helper, &function->arguments, argument)) { astTreeVariableDelete(argument); goto RETURN_ERROR; } } for (size_t i = 0; i < body->size; ++i) { ParserNode *node = body->data[i]; switch (node->token) { case PARSER_TOKEN_SYMBOL_EOL: node = (ParserNodeSingleChildMetadata *)node->metadata; goto OK_NODE; case PARSER_TOKEN_KEYWORD_IF: case PARSER_TOKEN_KEYWORD_WHILE: goto OK_NODE; case PARSER_TOKEN_ROOT: case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_VALUE_INT: case PARSER_TOKEN_VALUE_BOOL: case PARSER_TOKEN_TYPE_TYPE: case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_TYPE_VOID: case PARSER_TOKEN_TYPE_I8: case PARSER_TOKEN_TYPE_U8: case PARSER_TOKEN_TYPE_I16: case PARSER_TOKEN_TYPE_U16: case PARSER_TOKEN_TYPE_I32: case PARSER_TOKEN_TYPE_U32: case PARSER_TOKEN_TYPE_I64: case PARSER_TOKEN_TYPE_U64: case PARSER_TOKEN_TYPE_BOOL: case PARSER_TOKEN_KEYWORD_PRINT_U64: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_OPERATOR_ASSIGN: case PARSER_TOKEN_OPERATOR_PLUS: case PARSER_TOKEN_OPERATOR_MINUS: case PARSER_TOKEN_OPERATOR_SUM: case PARSER_TOKEN_OPERATOR_SUB: case PARSER_TOKEN_OPERATOR_MULTIPLY: case PARSER_TOKEN_OPERATOR_DIVIDE: case PARSER_TOKEN_OPERATOR_MODULO: case PARSER_TOKEN_OPERATOR_EQUAL: case PARSER_TOKEN_OPERATOR_NOT_EQUAL: case PARSER_TOKEN_OPERATOR_GREATER: case PARSER_TOKEN_OPERATOR_SMALLER: case PARSER_TOKEN_OPERATOR_GREATER_OR_EQUAL: case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL: case PARSER_TOKEN_FUNCTION_DEFINITION: case PARSER_TOKEN_FUNCTION_CALL: printError(node->str_begin, node->str_end, "Unexpected %s", PARSER_TOKEN_STRINGS[node->token]); goto RETURN_ERROR; case PARSER_TOKEN_NONE: } UNREACHABLE; OK_NODE: if (node->token == PARSER_TOKEN_CONSTANT) { if (!astTreeParseConstant(node, &helper)) { goto RETURN_ERROR; } } else { AstTree *tree = astTreeParse(node, &helper); if (tree == NULL) { goto RETURN_ERROR; } 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; } } scope.expressions = a404m_realloc( scope.expressions, scope.expressions_size * sizeof(*scope.expressions)); function->scope = scope; AstTree *result = newAstTree(AST_TREE_TOKEN_FUNCTION, function, NULL, parserNode->str_begin, parserNode->str_end); return result; RETURN_ERROR: free(function); free(scope.expressions); return NULL; } AstTree *astTreeParseTypeFunction(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeTypeFunctionMetadata *metadata = parserNode->metadata; ParserNodeArray *node_arguments = metadata->arguments->metadata; AstTreeTypeFunction *typeFunction = a404m_malloc(sizeof(*typeFunction)); size_t arguments_size = 0; typeFunction->arguments = a404m_malloc(arguments_size * sizeof(*typeFunction->arguments)); typeFunction->arguments_size = 0; for (size_t i = 0; i < node_arguments->size; ++i) { ParserNode *argument = node_arguments->data[i]; if (argument->token == PARSER_TOKEN_SYMBOL_COMMA) { argument = (ParserNodeSingleChildMetadata *)argument->metadata; } ParserNodeVariableMetadata *arg_metadata = argument->metadata; if (arg_metadata->value != NULL) { printError(argument->str_begin, argument->str_end, "arguments can't have default values (for now)"); goto RETURN_ERROR; } AstTree *type = astTreeParse(arg_metadata->type, helper); if (type == NULL) { goto RETURN_ERROR; } if (typeFunction->arguments_size == arguments_size) { arguments_size += arguments_size / 2 + 1; typeFunction->arguments = a404m_realloc(typeFunction->arguments, arguments_size * sizeof(*typeFunction->arguments)); } typeFunction->arguments[typeFunction->arguments_size] = type; typeFunction->arguments_size += 1; } if ((typeFunction->returnType = astTreeParse(metadata->returnType, helper)) == NULL) { goto RETURN_ERROR; } return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, typeFunction, &AST_TREE_TYPE_TYPE, parserNode->str_begin, parserNode->str_end); RETURN_ERROR: return NULL; } AstTree *astTreeParseFunctionCall(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeFunctionCall *node_metadata = parserNode->metadata; AstTree *function = astTreeParse(node_metadata->function, helper); if (function == NULL) { return NULL; } if (function->token != AST_TREE_TOKEN_VARIABLE) { printError(function->str_begin, function->str_end, "Not yet supported"); return NULL; } AstTreeFunctionCall *metadata = a404m_malloc(sizeof(*metadata)); metadata->function = function; metadata->parameters = a404m_malloc(sizeof(*metadata->parameters) * node_metadata->params->size); metadata->parameters_size = node_metadata->params->size; for (size_t i = 0; i < metadata->parameters_size; ++i) { ParserNode *param = node_metadata->params->data[i]; if (param->token == PARSER_TOKEN_SYMBOL_COMMA) { param = (ParserNodeSingleChildMetadata *)param->metadata; } metadata->parameters[i] = astTreeParse(param, helper); } return newAstTree(AST_TREE_TOKEN_FUNCTION_CALL, metadata, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseIdentifier(ParserNode *parserNode, AstTreeHelper *helper) { AstTreeVariable *var = getVariable(helper, parserNode->str_begin, parserNode->str_end); if (var == NULL) { printError(parserNode->str_begin, parserNode->str_end, "Variable not found"); return NULL; } return newAstTree(AST_TREE_TOKEN_VARIABLE, var, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseFloat(ParserNode *parserNode) { AstTreeFloat *metadata = a404m_malloc(sizeof(*metadata)); ParserNodeFloatMetadata *node_metadata = parserNode->metadata; *metadata = *node_metadata; return newAstTree(AST_TREE_TOKEN_VALUE_FLOAT, metadata, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParsePrintU64(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeSingleChildMetadata *node_metadata = parserNode->metadata; AstTree *operand = astTreeParse(node_metadata, helper); if (operand == NULL) { return NULL; } return newAstTree(AST_TREE_TOKEN_KEYWORD_PRINT_U64, (AstTreeSingleChild *)operand, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseReturn(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeReturnMetadata *node_metadata = parserNode->metadata; AstTree *value; if (node_metadata->value == NULL) { value = NULL; } else { value = astTreeParse(node_metadata->value, helper); if (value == NULL) { return NULL; } } AstTreeReturn *metadata = a404m_malloc(sizeof(*metadata)); metadata->value = value; return newAstTree(AST_TREE_TOKEN_KEYWORD_RETURN, metadata, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseBinaryOperator(ParserNode *parserNode, AstTreeHelper *helper, AstTreeToken token) { ParserNodeInfixMetadata *node_metadata = parserNode->metadata; AstTree *left = astTreeParse(node_metadata->left, helper); if (left == NULL) { return NULL; } AstTree *right = astTreeParse(node_metadata->right, helper); if (right == NULL) { return NULL; } AstTreeInfix *metadata = a404m_malloc(sizeof(*metadata)); metadata->left = *left; metadata->right = *right; free(left); free(right); return newAstTree(token, metadata, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseUnaryOperator(ParserNode *parserNode, AstTreeHelper *helper, AstTreeToken token) { ParserNodeSingleChildMetadata *node_metadata = parserNode->metadata; AstTreeSingleChild *metadata = astTreeParse(node_metadata, helper); if (metadata == NULL) { return NULL; } return newAstTree(token, metadata, NULL, parserNode->str_begin, parserNode->str_end); } bool astTreeParseConstant(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeVariableMetadata *node_metadata = parserNode->metadata; if (node_metadata->value == NULL || node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) { printError(parserNode->str_begin, parserNode->str_end, "Not supported"); return NULL; } AstTree *value = astTreeParse(node_metadata->value, helper); if (value == NULL) { goto RETURN_ERROR; } AstTree *type; if (node_metadata->type == NULL) { type = NULL; } else { type = astTreeParse(node_metadata->type, helper); if (type == NULL) { goto RETURN_ERROR; } } AstTreeVariable *variable = a404m_malloc(sizeof(*variable)); variable->type = type; variable->value = value; variable->name_begin = node_metadata->name->str_begin; variable->name_end = node_metadata->name->str_end; variable->isConst = true; if (!pushVariable(helper, helper->variables[helper->variables_size - 1], variable)) { astTreeVariableDelete(variable); goto RETURN_ERROR; } return true; RETURN_ERROR: return false; } AstTree *astTreeParseVariable(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeVariableMetadata *node_metadata = parserNode->metadata; if (node_metadata->value == NULL || node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) { printError(parserNode->str_begin, parserNode->str_end, "Not supported"); return NULL; } AstTree *value = astTreeParse(node_metadata->value, helper); if (value == NULL) { goto RETURN_ERROR; } AstTree *type; if (node_metadata->type == NULL) { type = NULL; } else { type = astTreeParse(node_metadata->type, helper); if (type == NULL) { goto RETURN_ERROR; } } AstTreeVariable *variable = a404m_malloc(sizeof(*variable)); variable->type = type; variable->value = value; variable->name_begin = node_metadata->name->str_begin; variable->name_end = node_metadata->name->str_end; variable->isConst = false; if (!pushVariable(helper, helper->variables[helper->variables_size - 1], variable)) { astTreeVariableDelete(variable); goto RETURN_ERROR; } return newAstTree(AST_TREE_TOKEN_VARIABLE_DEFINE, variable, NULL, parserNode->str_begin, parserNode->str_end); RETURN_ERROR: return NULL; } AstTree *astTreeParseIf(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeIfMetadata *node_metadata = parserNode->metadata; AstTree *condition = astTreeParse(node_metadata->condition, helper); if (condition == NULL) { return NULL; } AstTree *ifBody = astTreeParse(node_metadata->ifBody, helper); if (ifBody == NULL) { return NULL; } AstTree *elseBody; if (node_metadata->elseBody != NULL) { elseBody = astTreeParse(node_metadata->elseBody, helper); if (elseBody == NULL) { return NULL; } } else { elseBody = NULL; } AstTreeIf *metadata = a404m_malloc(sizeof(*metadata)); metadata->condition = condition; metadata->ifBody = ifBody; metadata->elseBody = elseBody; return newAstTree(AST_TREE_TOKEN_KEYWORD_IF, metadata, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseWhile(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeWhileMetadata *node_metadata = parserNode->metadata; AstTree *condition = astTreeParse(node_metadata->condition, helper); if (condition == NULL) { return NULL; } AstTree *body = astTreeParse(node_metadata->body, helper); if (body == NULL) { return NULL; } AstTreeWhile *metadata = a404m_malloc(sizeof(*metadata)); metadata->condition = condition; metadata->body = body; return newAstTree(AST_TREE_TOKEN_KEYWORD_WHILE, metadata, NULL, parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseCurlyBracket(ParserNode *parserNode, AstTreeHelper *p_helper) { ParserNodeArray *body = parserNode->metadata; size_t expressions_size = 0; AstTreeScope *scope = a404m_malloc(sizeof(*scope)); scope->variables.data = a404m_malloc(0); scope->variables.size = 0; scope->expressions = a404m_malloc(0); scope->expressions_size = 0; size_t variables_size = p_helper->variables_size + 1; AstTreeVariables *variables[variables_size]; for (size_t i = 0; i < p_helper->variables_size; ++i) { variables[i] = p_helper->variables[i]; } variables[variables_size - 1] = &scope->variables; AstTreeHelper helper = { .variables = variables, .variables_size = variables_size, .variable = p_helper->variable, .globalDeps = p_helper->globalDeps, }; for (size_t i = 0; i < body->size; ++i) { ParserNode *node = body->data[i]; switch (node->token) { case PARSER_TOKEN_SYMBOL_EOL: node = (ParserNodeSingleChildMetadata *)node->metadata; goto OK_NODE; case PARSER_TOKEN_KEYWORD_IF: goto OK_NODE; case PARSER_TOKEN_ROOT: case PARSER_TOKEN_IDENTIFIER: case PARSER_TOKEN_VALUE_INT: case PARSER_TOKEN_VALUE_BOOL: case PARSER_TOKEN_TYPE_TYPE: case PARSER_TOKEN_TYPE_FUNCTION: case PARSER_TOKEN_TYPE_VOID: case PARSER_TOKEN_TYPE_I8: case PARSER_TOKEN_TYPE_U8: case PARSER_TOKEN_TYPE_I16: case PARSER_TOKEN_TYPE_U16: case PARSER_TOKEN_TYPE_I32: case PARSER_TOKEN_TYPE_U32: case PARSER_TOKEN_TYPE_I64: case PARSER_TOKEN_TYPE_U64: case PARSER_TOKEN_TYPE_BOOL: case PARSER_TOKEN_KEYWORD_PRINT_U64: case PARSER_TOKEN_KEYWORD_RETURN: case PARSER_TOKEN_CONSTANT: case PARSER_TOKEN_VARIABLE: case PARSER_TOKEN_SYMBOL_CURLY_BRACKET: case PARSER_TOKEN_SYMBOL_PARENTHESIS: case PARSER_TOKEN_SYMBOL_COMMA: case PARSER_TOKEN_OPERATOR_ASSIGN: case PARSER_TOKEN_OPERATOR_PLUS: case PARSER_TOKEN_OPERATOR_MINUS: case PARSER_TOKEN_OPERATOR_SUM: case PARSER_TOKEN_OPERATOR_SUB: case PARSER_TOKEN_OPERATOR_MULTIPLY: case PARSER_TOKEN_OPERATOR_DIVIDE: case PARSER_TOKEN_OPERATOR_MODULO: case PARSER_TOKEN_OPERATOR_EQUAL: case PARSER_TOKEN_OPERATOR_NOT_EQUAL: case PARSER_TOKEN_OPERATOR_GREATER: case PARSER_TOKEN_OPERATOR_SMALLER: case PARSER_TOKEN_OPERATOR_GREATER_OR_EQUAL: case PARSER_TOKEN_OPERATOR_SMALLER_OR_EQUAL: case PARSER_TOKEN_FUNCTION_DEFINITION: case PARSER_TOKEN_FUNCTION_CALL: printError(node->str_begin, node->str_end, "Unexpected %s", PARSER_TOKEN_STRINGS[node->token]); goto RETURN_ERROR; case PARSER_TOKEN_NONE: } UNREACHABLE; OK_NODE: if (node->token == PARSER_TOKEN_CONSTANT) { if (!astTreeParseConstant(node, &helper)) { goto RETURN_ERROR; } } else { AstTree *tree = astTreeParse(node, &helper); if (tree == NULL) { goto RETURN_ERROR; } 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; } } scope->expressions = a404m_realloc(scope->expressions, scope->expressions_size * sizeof(*scope->expressions)); return newAstTree(AST_TREE_TOKEN_SCOPE, scope, NULL, parserNode->str_begin, parserNode->str_end); RETURN_ERROR: for (size_t i = 0; i < scope->expressions_size; ++i) { astTreeDelete(scope->expressions[i]); } free(scope->variables.data); free(scope->expressions); return NULL; } AstTree *astTreeParseParenthesis(ParserNode *parserNode, AstTreeHelper *helper) { ParserNodeArray *metadata = parserNode->metadata; if (metadata->size != 1) { printError(parserNode->str_begin, parserNode->str_end, "Bad parenthesis"); return NULL; } else { return astTreeParse(metadata->data[0], helper); } } AstTreeFunction *getFunction(AstTree *value) { switch (value->token) { case AST_TREE_TOKEN_FUNCTION: return value->metadata; case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *metadata = value->metadata; if (metadata->value->token == AST_TREE_TOKEN_FUNCTION) { return metadata->value->metadata; } else { return NULL; } } case AST_TREE_TOKEN_FUNCTION_CALL: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_IF: 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_BOOL: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_BOOL: 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: case AST_TREE_TOKEN_SCOPE: return NULL; case AST_TREE_TOKEN_NONE: } UNREACHABLE; } bool isConst(AstTree *tree, AstTreeHelper *helper) { 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_BOOL: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_BOOL: return true; case AST_TREE_TOKEN_KEYWORD_IF: { AstTreeIf *metadata = tree->metadata; return isConst(metadata->condition, helper) && isConst(metadata->ifBody, helper) && (metadata->elseBody == NULL || isConst(metadata->elseBody, helper)); } case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = tree->metadata; for (size_t i = 0; i < metadata->parameters_size; ++i) { if (!isConst(metadata->parameters[i], helper)) { return false; } } return isConst(metadata->function, helper); } case AST_TREE_TOKEN_FUNCTION: { return true; } 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: case AST_TREE_TOKEN_SCOPE: return false; case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *metadata = tree->metadata; return metadata->isConst; } case AST_TREE_TOKEN_NONE: } UNREACHABLE; } 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_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_BOOL: return &AST_TREE_TYPE_TYPE; 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, &AST_TREE_TYPE_TYPE, value->str_begin, value->str_end); } case AST_TREE_TOKEN_VALUE_VOID: return &AST_TREE_VOID_TYPE; case AST_TREE_TOKEN_VALUE_INT: return &AST_TREE_U64_TYPE; case AST_TREE_TOKEN_VALUE_BOOL: return &AST_TREE_BOOL_TYPE; case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *variable = value->metadata; return copyAstTree(variable->type); } case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: { AstTreeSingleChild *metadata = value->metadata; return copyAstTree(metadata->type); } case AST_TREE_TOKEN_OPERATOR_ASSIGN: 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: { AstTreeInfix *metadata = value->metadata; return copyAstTree(metadata->left.type); } 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 &AST_TREE_BOOL_TYPE; } case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_NONE: } UNREACHABLE; } bool typeIsEqual(const AstTree *type0, const AstTree *type1) { switch (type0->token) { 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_VALUE_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_FLOAT: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_OPERATOR_ASSIGN: 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_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: case AST_TREE_TOKEN_SCOPE: return false; case AST_TREE_TOKEN_TYPE_TYPE: 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_BOOL: case AST_TREE_TOKEN_TYPE_F16: case AST_TREE_TOKEN_TYPE_F32: case AST_TREE_TOKEN_TYPE_F64: case AST_TREE_TOKEN_TYPE_F128: return type1->token == type0->token; case AST_TREE_TOKEN_TYPE_FUNCTION: if (type1->token != AST_TREE_TOKEN_TYPE_FUNCTION) { return false; } AstTreeTypeFunction *type0_metadata = type0->metadata; AstTreeTypeFunction *type1_metadata = type1->metadata; if (!typeIsEqual(type0_metadata->returnType->type, type1_metadata->returnType->type)) { return false; } if (type0_metadata->arguments_size != type1_metadata->arguments_size) { return false; } return true; case AST_TREE_TOKEN_FUNCTION_CALL: printError(type0->str_begin, type0->str_end, "Not implemented yet"); exit(1); case AST_TREE_TOKEN_VARIABLE: return type1->token == AST_TREE_TOKEN_VARIABLE && type0->metadata == type1->metadata; case AST_TREE_TOKEN_NONE: break; } UNREACHABLE; } AstTree *getValue(AstTree *tree, AstTreeSetTypesHelper helper) { if (!isConst(tree, helper.treeHelper)) { printLog("Can't get value at compile time because it is not const"); return NULL; } switch (tree->token) { case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_TYPE: 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_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_FLOAT: case AST_TREE_TOKEN_VALUE_BOOL: return copyAstTree(tree); case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *metadata = tree->metadata; return getValue(metadata->value, helper); } case AST_TREE_TOKEN_FUNCTION_CALL: { AstTree *value = runExpression(tree, helper.pages); if (value == NULL) { printError(tree->str_begin, tree->str_end, "Unknown error"); } return value; } 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: { AstTree *value = calcAstTreeValue(tree, helper.pages); if (value == NULL) { printError(tree->str_begin, tree->str_end, "Unknown error"); } return value; } case AST_TREE_TOKEN_FUNCTION: { return tree; } 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_VARIABLE_DEFINE: case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_NONE: } UNREACHABLE; } bool isCircularDependencies(AstTreeHelper *helper, AstTreeVariable *variable, AstTree *tree) { 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: 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_VOID: case AST_TREE_TOKEN_VALUE_INT: case AST_TREE_TOKEN_VALUE_FLOAT: case AST_TREE_TOKEN_VALUE_BOOL: return false; case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: { AstTreeSingleChild *metadata = tree->metadata; return isCircularDependencies(helper, variable, metadata); } case AST_TREE_TOKEN_OPERATOR_ASSIGN: 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: { AstTreeInfix *metadata = tree->metadata; return isCircularDependencies(helper, variable, &metadata->left) || isCircularDependencies(helper, variable, &metadata->right); } case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = tree->metadata; for (size_t i = 0; i < metadata->parameters_size; ++i) { if (isCircularDependencies(helper, variable, metadata->parameters[i])) { return true; } } return isCircularDependencies(helper, variable, metadata->function); } case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *metadata = tree->metadata; for (size_t index = 0; index < helper->variables[0]->size; ++index) { if (helper->variables[0]->data[index] == metadata) { for (size_t i = 0; i < helper->globalDeps[index].size; ++i) { if (helper->globalDeps[index].data[i] == variable) { return true; } } break; } } return false; } case AST_TREE_TOKEN_FUNCTION: { return false; } case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_KEYWORD_IF: case AST_TREE_TOKEN_KEYWORD_WHILE: case AST_TREE_TOKEN_NONE: } UNREACHABLE; } bool setAllTypesRoot(AstTreeRoot *root, AstTreeHelper *helper) { for (size_t i = 0; i < root->variables.size; ++i) { AstTreeVariable *variable = root->variables.data[i]; if (isCircularDependencies(helper, variable, variable->value)) { printError(variable->name_begin, variable->name_end, "Circular dependecies"); return false; } } RunnerVariablePages pages = initRootPages(); AstTreeSetTypesHelper setTypesHelper = { .lookingType = NULL, .treeHelper = helper, .pages = &pages, }; for (size_t i = 0; i < root->variables.size; ++i) { AstTreeVariable *variable = root->variables.data[i]; if (!setTypesAstVariable(variable, setTypesHelper)) { destroyRootPages(pages); return false; } } destroyRootPages(pages); return true; } bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function) { if (tree->type != NULL) { return true; } switch (tree->token) { case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_TYPE_BOOL: 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_VALUE_VOID: case AST_TREE_TOKEN_VALUE_BOOL: return true; case AST_TREE_TOKEN_VALUE_INT: return setTypesValueInt(tree, helper); case AST_TREE_TOKEN_VALUE_FLOAT: return setTypesValueFloat(tree, helper); case AST_TREE_TOKEN_FUNCTION: return setTypesFunction(tree, helper); case AST_TREE_TOKEN_KEYWORD_PRINT_U64: return setTypesPrintU64(tree, helper); case AST_TREE_TOKEN_KEYWORD_RETURN: return setTypesReturn(tree, helper, function); case AST_TREE_TOKEN_TYPE_FUNCTION: return setTypesTypeFunction(tree, helper); case AST_TREE_TOKEN_FUNCTION_CALL: return setTypesFunctionCall(tree, helper); case AST_TREE_TOKEN_VARIABLE: return setTypesVariable(tree, helper); case AST_TREE_TOKEN_OPERATOR_ASSIGN: return setTypesOperatorAssign(tree, helper); case AST_TREE_TOKEN_OPERATOR_PLUS: case AST_TREE_TOKEN_OPERATOR_MINUS: return setTypesOperatorUnary(tree, helper); 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: return setTypesOperatorInfix(tree, helper); 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 setTypesOperatorInfixWithRet(tree, &AST_TREE_BOOL_TYPE, helper); case AST_TREE_TOKEN_VARIABLE_DEFINE: return setTypesVariableDefine(tree, helper); case AST_TREE_TOKEN_KEYWORD_IF: return setTypesIf(tree, helper, function); case AST_TREE_TOKEN_KEYWORD_WHILE: return setTypesWhile(tree, helper, function); case AST_TREE_TOKEN_SCOPE: return setTypesScope(tree, helper, function); case AST_TREE_TOKEN_NONE: break; } UNREACHABLE; } bool setTypesValueInt(AstTree *tree, AstTreeSetTypesHelper helper) { if (helper.lookingType == NULL || helper.lookingType == &AST_TREE_I64_TYPE) { tree->type = &AST_TREE_I64_TYPE; } else if (helper.lookingType == &AST_TREE_U64_TYPE) { tree->type = &AST_TREE_U64_TYPE; } else if (helper.lookingType == &AST_TREE_I32_TYPE) { AstTreeInt value = (AstTreeInt)tree->metadata; i32 newValue = value; tree->metadata = (void *)(u64)newValue; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_I32_TYPE; } else if (helper.lookingType == &AST_TREE_U32_TYPE) { AstTreeInt value = (AstTreeInt)tree->metadata; u32 newValue = value; tree->metadata = (void *)(u64)newValue; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_U32_TYPE; } else if (helper.lookingType == &AST_TREE_I16_TYPE) { AstTreeInt value = (AstTreeInt)tree->metadata; i16 newValue = value; tree->metadata = (void *)(u64)newValue; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_I16_TYPE; } else if (helper.lookingType == &AST_TREE_U16_TYPE) { AstTreeInt value = (AstTreeInt)tree->metadata; u16 newValue = value; tree->metadata = (void *)(u64)newValue; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_U16_TYPE; } else if (helper.lookingType == &AST_TREE_I8_TYPE) { AstTreeInt value = (AstTreeInt)tree->metadata; i8 newValue = value; tree->metadata = (void *)(u64)newValue; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_I8_TYPE; } else if (helper.lookingType == &AST_TREE_U8_TYPE) { AstTreeInt value = (AstTreeInt)tree->metadata; u8 newValue = value; tree->metadata = (void *)(u64)newValue; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_U8_TYPE; } else if (helper.lookingType == &AST_TREE_F16_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeInt value = (AstTreeInt)tree->metadata; f16 newValue = value; tree->metadata = a404m_malloc(sizeof(f128)); *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F16_TYPE; } else if (helper.lookingType == &AST_TREE_F32_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeInt value = (AstTreeInt)tree->metadata; f32 newValue = value; tree->metadata = a404m_malloc(sizeof(f128)); *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F32_TYPE; } else if (helper.lookingType == &AST_TREE_F64_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeInt value = (AstTreeInt)tree->metadata; f64 newValue = value; tree->metadata = a404m_malloc(sizeof(f128)); *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F64_TYPE; } else if (helper.lookingType == &AST_TREE_F128_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeInt value = (AstTreeInt)tree->metadata; f128 newValue = value; tree->metadata = a404m_malloc(sizeof(f128)); *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F128_TYPE; } else { UNREACHABLE; } return true; } bool setTypesValueFloat(AstTree *tree, AstTreeSetTypesHelper helper) { if (helper.lookingType == &AST_TREE_F16_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeFloat value = *(AstTreeFloat *)tree->metadata; f16 newValue = value; *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F16_TYPE; } else if (helper.lookingType == &AST_TREE_F32_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeFloat value = *(AstTreeFloat *)tree->metadata; f32 newValue = value; *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F32_TYPE; } else if (helper.lookingType == &AST_TREE_F64_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeFloat value = *(AstTreeFloat *)tree->metadata; f64 newValue = value; *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F64_TYPE; } else if (helper.lookingType == &AST_TREE_F128_TYPE) { tree->token = AST_TREE_TOKEN_VALUE_FLOAT; AstTreeFloat value = *(AstTreeFloat *)tree->metadata; f128 newValue = value; *(AstTreeFloat *)tree->metadata = value; if (value - newValue != 0) { printWarning(tree->str_begin, tree->str_end, "Value is overflowing"); } tree->type = &AST_TREE_F128_TYPE; } else { UNREACHABLE; } return true; } bool setTypesFunction(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeFunction *metadata = tree->metadata; for (size_t i = 0; i < metadata->arguments.size; ++i) { AstTreeVariable *variable = metadata->arguments.data[i]; if (!setTypesAstVariable(variable, helper)) { return false; } } if (!setAllTypes(metadata->returnType, helper, NULL)) { return false; } tree->type = makeTypeOf(tree); for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { if (!setAllTypes(metadata->scope.expressions[i], helper, metadata)) { return false; } } for (size_t i = 0; i < metadata->scope.variables.size; ++i) { if (!setTypesAstVariable(metadata->scope.variables.data[i], helper)) { return false; } } return true; } bool setTypesPrintU64(AstTree *tree, AstTreeSetTypesHelper _helper) { AstTreeSingleChild *metadata = tree->metadata; AstTreeSetTypesHelper helper = { .lookingType = &AST_TREE_U64_TYPE, .treeHelper = _helper.treeHelper, .pages = _helper.pages, }; if (!setAllTypes(metadata, helper, NULL)) { return false; } else if (!typeIsEqual(metadata->type, &AST_TREE_U64_TYPE)) { printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } else { tree->type = &AST_TREE_VOID_TYPE; return true; } } bool setTypesReturn(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function) { if (function == NULL) { printError(tree->str_begin, tree->str_end, "Return can't be here"); } AstTreeReturn *metadata = tree->metadata; if (metadata->value != NULL) { if (!setAllTypes(metadata->value, helper, NULL)) { return false; } else if (!typeIsEqual(metadata->value->type, function->returnType)) { printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } } tree->type = &AST_TREE_VOID_TYPE; return true; } bool setTypesTypeFunction(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeTypeFunction *metadata = tree->metadata; for (size_t i = 0; i < metadata->arguments_size; ++i) { printError(tree->str_begin, tree->str_end, "Not yet supported"); return false; } if (!setAllTypes(metadata->returnType, helper, NULL)) { return false; } else if (!typeIsEqual(metadata->returnType->type, &AST_TREE_TYPE_TYPE)) { printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } tree->type = &AST_TREE_TYPE_TYPE; return true; } bool setTypesFunctionCall(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeFunctionCall *metadata = tree->metadata; for (size_t i = 0; i < metadata->parameters_size; ++i) { if (!setAllTypes(metadata->parameters[i], helper, NULL)) { return false; } } if (metadata->function->token != AST_TREE_TOKEN_VARIABLE) { printError(tree->str_begin, tree->str_end, "Not yet supported"); return false; } else if (!setAllTypes(metadata->function, helper, NULL)) { return false; } AstTreeFunction *function = getFunction(metadata->function); if (function == NULL || function->arguments.size != metadata->parameters_size) { printError(tree->str_begin, tree->str_end, "Arguments doesn't match %ld != %ld", function->arguments.size, metadata->parameters_size); return NULL; } tree->type = copyAstTree(function->returnType); return true; } bool setTypesVariable(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeVariable *metadata = tree->metadata; if (setTypesAstVariable(metadata, helper)) { tree->type = copyAstTree(metadata->type); return true; } else { return false; } } bool setTypesOperatorAssign(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeInfix *infix = tree->metadata; if (!setTypesAstInfix(infix, helper)) { return false; } else if (!typeIsEqual(infix->left.type, infix->right.type)) { printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } else if (isConst(&infix->left, helper.treeHelper)) { printError(tree->str_begin, tree->str_end, "Constants can't be assigned"); return false; } else { tree->type = copyAstTree(infix->left.type); return true; } } bool setTypesOperatorInfix(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeInfix *infix = tree->metadata; if (!setTypesAstInfix(infix, helper)) { return false; } else if (!typeIsEqual(infix->left.type, infix->right.type)) { printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } else { tree->type = copyAstTree(infix->left.type); return true; } } bool setTypesOperatorInfixWithRet(AstTree *tree, AstTree *retType, AstTreeSetTypesHelper helper) { AstTreeInfix *infix = tree->metadata; if (!setTypesAstInfix(infix, helper)) { return false; } else if (!typeIsEqual(infix->left.type, infix->right.type)) { printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } else { tree->type = retType; return true; } } bool setTypesOperatorUnary(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeSingleChild *operand = tree->metadata; if (!setAllTypes(operand, helper, NULL)) { return false; } else { tree->type = copyAstTree(operand->type); return true; } } bool setTypesVariableDefine(AstTree *tree, AstTreeSetTypesHelper helper) { AstTreeVariable *metadata = tree->metadata; tree->type = &AST_TREE_VOID_TYPE; return setTypesAstVariable(metadata, helper); } bool setTypesAstVariable(AstTreeVariable *variable, AstTreeSetTypesHelper _helper) { AstTreeSetTypesHelper helper = { .lookingType = &AST_TREE_TYPE_TYPE, .treeHelper = _helper.treeHelper, .pages = _helper.pages, }; if (variable->type != NULL && !setAllTypes(variable->type, helper, NULL)) { return false; } if (variable->type != NULL) { AstTree *type = variable->type; variable->type = getValue(type, helper); if (variable->type == NULL) { return false; } if (type != variable->type) { astTreeDelete(type); } } helper.lookingType = variable->type; if (variable->value != NULL && !setAllTypes(variable->value, helper, NULL)) { return false; } if (variable->type == NULL) { variable->type = copyAstTree(variable->value->type); } if (variable->type == NULL) { return false; } else if (variable->value != NULL && !typeIsEqual(variable->value->type, variable->type)) { printError(variable->name_begin, variable->name_end, "Type mismatch %s", AST_TREE_TOKEN_STRINGS[variable->value->token]); return false; } if (variable->value != NULL && variable->isConst) { if (!isConst(variable->value, helper.treeHelper)) { printError(variable->value->str_begin, variable->value->str_end, "Can't initialize constant with non constant value"); return false; } AstTree *value = variable->value; variable->value = getValue(value, helper); if (variable->value != value) { astTreeDelete(value); } if (variable->value == NULL) { return false; } } return true; } bool setTypesIf(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function) { AstTreeIf *metadata = tree->metadata; if (!setAllTypes(metadata->condition, helper, function) || !setAllTypes(metadata->ifBody, helper, function) || (metadata->elseBody != NULL && !setAllTypes(metadata->elseBody, helper, function))) { return false; } if (!typeIsEqual(metadata->condition->type, &AST_TREE_BOOL_TYPE)) { printError(metadata->condition->str_begin, metadata->condition->str_end, "If condition must be boolean"); return false; } if (metadata->elseBody != NULL && typeIsEqual(metadata->ifBody, metadata->elseBody)) { tree->type = copyAstTree(metadata->ifBody); } else { tree->type = &AST_TREE_VOID_TYPE; } return true; } bool setTypesWhile(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function) { AstTreeWhile *metadata = tree->metadata; if (!setAllTypes(metadata->condition, helper, function) || !setAllTypes(metadata->body, helper, function)) { return false; } if (!typeIsEqual(metadata->condition->type, &AST_TREE_BOOL_TYPE)) { printError(metadata->condition->str_begin, metadata->condition->str_end, "If condition must be boolean"); return false; } tree->type = &AST_TREE_VOID_TYPE; return true; } bool setTypesScope(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunction *function) { AstTreeScope *metadata = tree->metadata; tree->type = &AST_TREE_VOID_TYPE; for (size_t i = 0; i < metadata->expressions_size; ++i) { if (!setAllTypes(metadata->expressions[i], helper, function)) { return false; } } for (size_t i = 0; i < metadata->variables.size; ++i) { if (!setTypesAstVariable(metadata->variables.data[i], helper)) { return false; } } return true; } bool setTypesAstInfix(AstTreeInfix *infix, AstTreeSetTypesHelper helper) { if (!setAllTypes(&infix->left, helper, NULL)) { return false; } AstTreeSetTypesHelper newHelper = { .lookingType = infix->left.type, .treeHelper = helper.treeHelper, .pages = helper.pages, }; return setAllTypes(&infix->right, newHelper, NULL); } size_t astTreeTypeSize(AstTree tree) { switch (tree.token) { case AST_TREE_TOKEN_TYPE_I8: case AST_TREE_TOKEN_TYPE_U8: return 1; case AST_TREE_TOKEN_TYPE_I16: case AST_TREE_TOKEN_TYPE_U16: return 2; case AST_TREE_TOKEN_TYPE_I32: case AST_TREE_TOKEN_TYPE_U32: return 4; case AST_TREE_TOKEN_TYPE_I64: case AST_TREE_TOKEN_TYPE_U64: return 8; case AST_TREE_TOKEN_TYPE_BOOL: return 1; case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_TYPE_TYPE: case AST_TREE_TOKEN_TYPE_FUNCTION: case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_FUNCTION_CALL: case AST_TREE_TOKEN_VARIABLE: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_INT: 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_KEYWORD_IF: case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_NONE: } UNREACHABLE; }