diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/ast-tree.c | 266 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 8 | ||||
-rw-r--r-- | src/compiler/code-generator.c | 14 | ||||
-rw-r--r-- | src/runner/runner.c | 187 | ||||
-rw-r--r-- | src/runner/runner.h | 25 |
5 files changed, 375 insertions, 125 deletions
diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 0eea23d..ea5da0b 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -32,7 +32,7 @@ AstTree AST_TREE_BOOL_TYPE = { }; AstTree AST_TREE_VOID_VALUE = { - .token = AST_TREE_TOKEN_NONE, + .token = AST_TREE_TOKEN_VALUE_VOID, .metadata = NULL, .type = &AST_TREE_VOID_TYPE, }; @@ -54,6 +54,7 @@ const char *AST_TREE_TOKEN_STRINGS[] = { "AST_TREE_TOKEN_VARIABLE_DEFINE", "AST_TREE_TOKEN_VALUE_U64", "AST_TREE_TOKEN_VALUE_BOOL", + "AST_TREE_TOKEN_VALUE_VOID", "AST_TREE_TOKEN_OPERATOR_ASSIGN", "AST_TREE_TOKEN_OPERATOR_SUM", @@ -95,7 +96,7 @@ void astTreePrint(const AstTree *tree, int indent) { printf(" "); printf("expressions=[\n"); for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { - astTreePrint(&metadata->scope.expressions[i], indent + 1); + astTreePrint(metadata->scope.expressions[i], indent + 1); printf(",\n"); } for (int i = 0; i < indent; ++i) @@ -107,6 +108,7 @@ void astTreePrint(const AstTree *tree, int indent) { case AST_TREE_TOKEN_TYPE_VOID: 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_KEYWORD_PRINT_U64: { @@ -203,8 +205,7 @@ void astTreePrint(const AstTree *tree, int indent) { case AST_TREE_TOKEN_NONE: } - printLog("Bad token '%d'", tree->token); - exit(1); + UNREACHABLE; RETURN_SUCCESS: printf("}"); @@ -227,7 +228,7 @@ void astTreeDestroy(AstTree tree) { case AST_TREE_TOKEN_FUNCTION: { AstTreeFunction *metadata = tree.metadata; for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { - astTreeDestroy(metadata->scope.expressions[i]); + astTreeDelete(metadata->scope.expressions[i]); } for (size_t i = 0; i < metadata->scope.variables.size; ++i) { astTreeVariableDelete(metadata->scope.variables.data[i]); @@ -246,6 +247,7 @@ void astTreeDestroy(AstTree tree) { case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_VARIABLE_DEFINE: @@ -297,8 +299,7 @@ void astTreeDestroy(AstTree tree) { return; case AST_TREE_TOKEN_NONE: } - printLog("Bad token '%d'", tree.token); - exit(1); + UNREACHABLE; } void astTreeVariableDestroy(AstTreeVariable variable) { @@ -332,11 +333,14 @@ void astTreeRootDelete(AstTreeRoot *root) { free(root); } -AstTree *newAstTree(AstTreeToken token, void *metadata, AstTree *type) { +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; } @@ -346,12 +350,16 @@ AstTree *copyAstTree(AstTree *tree) { case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_VOID: return tree; case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: - return newAstTree(tree->token, tree->metadata, tree->type); + return newAstTree(tree->token, tree->metadata, tree->type, tree->str_begin, + tree->str_end); case AST_TREE_TOKEN_VARIABLE: - return newAstTree(tree->token, tree->metadata, copyAstTree(tree->type)); + 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)); @@ -362,19 +370,105 @@ AstTree *copyAstTree(AstTree *tree) { 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); + 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_FUNCTION: - case AST_TREE_TOKEN_KEYWORD_PRINT_U64: - case AST_TREE_TOKEN_KEYWORD_RETURN: - case AST_TREE_TOKEN_FUNCTION_CALL: - case AST_TREE_TOKEN_VARIABLE_DEFINE: + case AST_TREE_TOKEN_OPERATOR_SUM: { + 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_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_NONE: } - printLog("Bad token '%d'", tree->token); - exit(1); + printLog("Bad token %ld", tree->token); + *(int *)(NULL) = 2; + 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) { @@ -393,13 +487,15 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { for (size_t i = 0; i < nodes->size; ++i) { ParserNode *eol = nodes->data[i]; if (eol->token != PARSER_TOKEN_SYMBOL_EOL) { - printLog("Unexpected %s", PARSER_TOKEN_STRINGS[eol->token]); + printError(eol->str_begin, eol->str_end, "Unexpected %s", + PARSER_TOKEN_STRINGS[eol->token]); goto RETURN_ERROR; } ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata; if (node->token != PARSER_TOKEN_CONSTANT && node->token != PARSER_TOKEN_VARIABLE) { - printLog("Unexpected %s", PARSER_TOKEN_STRINGS[node->token]); + printError(node->str_begin, node->str_end, "Unexpected %s", + PARSER_TOKEN_STRINGS[node->token]); goto RETURN_ERROR; } ParserNodeVariableMetadata *node_metadata = node->metadata; @@ -425,12 +521,14 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { if (node->token != PARSER_TOKEN_CONSTANT && node->token != PARSER_TOKEN_VARIABLE) { - printLog("Only variables are allowed here"); + printError(node->str_begin, node->str_end, + "Only variables are allowed here"); goto RETURN_ERROR; } if (node_metadata->value == NULL) { - printLog("Variables must be initialized"); + printError(node->str_begin, node->str_end, + "Variables must be initialized"); goto RETURN_ERROR; } @@ -457,11 +555,12 @@ AstTreeRoot *makeAstTree(ParserNode *parsedRoot) { case PARSER_TOKEN_FUNCTION_CALL: case PARSER_TOKEN_OPERATOR_ASSIGN: case PARSER_TOKEN_OPERATOR_SUM: - printLog("Should not be here"); + printError(node->str_begin, node->str_end, "Should not be here"); goto RETURN_ERROR; case PARSER_TOKEN_NONE: } - printLog("Bad token %d", node_metadata->value->token); + printError(node_metadata->value->str_begin, node_metadata->value->str_end, + "Bad token %d", node_metadata->value->token); goto RETURN_ERROR; AFTER_SWITCH: @@ -506,7 +605,7 @@ bool pushVariable(AstTreeVariables *variables, AstTreeVariable *variable) { if (variable->name_end - variable->name_begin == var_end - var_begin && strncmp(var_begin, variable->name_begin, variable->name_end - variable->name_begin) == 0) { - printLog("Variable exists"); + printError(variable->name_begin, variable->name_end, "Variable exists"); return false; } } @@ -565,12 +664,12 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables, return newAstTree( AST_TREE_TOKEN_VALUE_U64, (void *)(AstTreeU64)(ParserNodeU64Metadata)parserNode->metadata, - &AST_TREE_U64_TYPE); + &AST_TREE_U64_TYPE, parserNode->str_begin, parserNode->str_end); case PARSER_TOKEN_VALUE_BOOL: return newAstTree( AST_TREE_TOKEN_VALUE_BOOL, (void *)(AstTreeBool)(ParserNodeBoolMetadata)parserNode->metadata, - &AST_TREE_BOOL_TYPE); + &AST_TREE_BOOL_TYPE, parserNode->str_begin, parserNode->str_end); case PARSER_TOKEN_KEYWORD_PRINT_U64: return astTreeParsePrintU64(parserNode, variables, variables_size); case PARSER_TOKEN_KEYWORD_RETURN: @@ -589,7 +688,8 @@ AstTree *astTreeParse(ParserNode *parserNode, AstTreeVariables **variables, case PARSER_TOKEN_NONE: case PARSER_TOKEN_ROOT: } - printLog("Bad token %d", parserNode->token); + printError(parserNode->str_begin, parserNode->str_end, "Bad token %d", + parserNode->token); return NULL; } @@ -635,7 +735,8 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, ParserNodeVariableMetadata *arg_metadata = arg->metadata; if (arg_metadata->value != NULL) { - printLog("arguments can't have default values (for now)"); + printError(arg->str_begin, arg->str_end, + "arguments can't have default values (for now)"); goto RETURN_ERROR; } @@ -660,7 +761,8 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, for (size_t i = 0; i < body->size; ++i) { ParserNode *eol = body->data[i]; if (eol->token != PARSER_TOKEN_SYMBOL_EOL) { - printLog("Unexpected %s", PARSER_TOKEN_STRINGS[eol->token]); + printError(eol->str_begin, eol->str_end, "Unexpected %s", + PARSER_TOKEN_STRINGS[eol->token]); goto RETURN_ERROR; } ParserNode *node = (ParserNodeSingleChildMetadata *)eol->metadata; @@ -681,10 +783,8 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, scope.expressions = a404m_realloc( scope.expressions, expressions_size * sizeof(*scope.expressions)); } - scope.expressions[scope.expressions_size] = *tree; + scope.expressions[scope.expressions_size] = tree; scope.expressions_size += 1; - - free(tree); } } @@ -693,7 +793,8 @@ AstTree *astTreeParseFunction(ParserNode *parserNode, function->scope = scope; - AstTree *result = newAstTree(AST_TREE_TOKEN_FUNCTION, function, NULL); + AstTree *result = newAstTree(AST_TREE_TOKEN_FUNCTION, function, NULL, + parserNode->str_begin, parserNode->str_end); return result; @@ -725,7 +826,8 @@ AstTree *astTreeParseTypeFunction(ParserNode *parserNode, ParserNodeVariableMetadata *arg_metadata = argument->metadata; if (arg_metadata->value != NULL) { - printLog("arguments can't have default values (for now)"); + printError(argument->str_begin, argument->str_end, + "arguments can't have default values (for now)"); goto RETURN_ERROR; } @@ -751,7 +853,8 @@ AstTree *astTreeParseTypeFunction(ParserNode *parserNode, } return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, typeFunction, - &AST_TREE_TYPE_TYPE); + &AST_TREE_TYPE_TYPE, parserNode->str_begin, + parserNode->str_end); RETURN_ERROR: return NULL; @@ -767,7 +870,7 @@ AstTree *astTreeParseFunctionCall(ParserNode *parserNode, return NULL; } if (function->token != AST_TREE_TOKEN_VARIABLE) { - printLog("Not yet supported"); + printError(function->str_begin, function->str_end, "Not yet supported"); return NULL; } @@ -786,7 +889,8 @@ AstTree *astTreeParseFunctionCall(ParserNode *parserNode, metadata->parameters[i] = astTreeParse(param, variables, variables_size); } - return newAstTree(AST_TREE_TOKEN_FUNCTION_CALL, metadata, NULL); + return newAstTree(AST_TREE_TOKEN_FUNCTION_CALL, metadata, NULL, + parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseIdentifier(ParserNode *parserNode, @@ -795,10 +899,12 @@ AstTree *astTreeParseIdentifier(ParserNode *parserNode, AstTreeVariable *var = getVariable( variables, variables_size, parserNode->str_begin, parserNode->str_end); if (var == NULL) { - printLog("Variable not found"); + printError(parserNode->str_begin, parserNode->str_end, + "Variable not found"); return NULL; } - return newAstTree(AST_TREE_TOKEN_VARIABLE, var, NULL); + return newAstTree(AST_TREE_TOKEN_VARIABLE, var, NULL, parserNode->str_begin, + parserNode->str_end); } AstTree *astTreeParsePrintU64(ParserNode *parserNode, @@ -812,7 +918,8 @@ AstTree *astTreeParsePrintU64(ParserNode *parserNode, } return newAstTree(AST_TREE_TOKEN_KEYWORD_PRINT_U64, - (AstTreeSingleChild *)operand, NULL); + (AstTreeSingleChild *)operand, NULL, parserNode->str_begin, + parserNode->str_end); } AstTree *astTreeParseReturn(ParserNode *parserNode, @@ -833,7 +940,8 @@ AstTree *astTreeParseReturn(ParserNode *parserNode, AstTreeReturn *metadata = a404m_malloc(sizeof(*metadata)); metadata->value = value; - return newAstTree(AST_TREE_TOKEN_KEYWORD_RETURN, metadata, NULL); + return newAstTree(AST_TREE_TOKEN_KEYWORD_RETURN, metadata, NULL, + parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseAssign(ParserNode *parserNode, @@ -859,7 +967,8 @@ AstTree *astTreeParseAssign(ParserNode *parserNode, free(left); free(right); - return newAstTree(AST_TREE_TOKEN_OPERATOR_ASSIGN, metadata, NULL); + return newAstTree(AST_TREE_TOKEN_OPERATOR_ASSIGN, metadata, NULL, + parserNode->str_begin, parserNode->str_end); } AstTree *astTreeParseSum(ParserNode *parserNode, AstTreeVariables **variables, @@ -884,7 +993,8 @@ AstTree *astTreeParseSum(ParserNode *parserNode, AstTreeVariables **variables, free(left); free(right); - return newAstTree(AST_TREE_TOKEN_OPERATOR_SUM, metadata, NULL); + return newAstTree(AST_TREE_TOKEN_OPERATOR_SUM, metadata, NULL, + parserNode->str_begin, parserNode->str_end); } bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables, @@ -893,7 +1003,7 @@ bool astTreeParseConstant(ParserNode *parserNode, AstTreeVariables **variables, if (node_metadata->value == NULL || node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) { - printLog("Not supported"); + printError(parserNode->str_begin, parserNode->str_end, "Not supported"); return NULL; } @@ -937,7 +1047,7 @@ AstTree *astTreeParseVariable(ParserNode *parserNode, if (node_metadata->value == NULL || node_metadata->name->token != PARSER_TOKEN_IDENTIFIER) { - printLog("Not supported"); + printError(parserNode->str_begin, parserNode->str_end, "Not supported"); return NULL; } @@ -969,7 +1079,8 @@ AstTree *astTreeParseVariable(ParserNode *parserNode, goto RETURN_ERROR; } - return newAstTree(AST_TREE_TOKEN_VARIABLE_DEFINE, variable, NULL); + return newAstTree(AST_TREE_TOKEN_VARIABLE_DEFINE, variable, NULL, + parserNode->str_begin, parserNode->str_end); RETURN_ERROR: return NULL; } @@ -998,6 +1109,7 @@ AstTreeFunction *getFunction(AstTree *value) { case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_VARIABLE_DEFINE: @@ -1006,8 +1118,7 @@ AstTreeFunction *getFunction(AstTree *value) { return NULL; case AST_TREE_TOKEN_NONE: } - printLog("Bad token '%d'", value->token); - exit(1); + UNREACHABLE; } bool isConst(AstTree *value) { @@ -1018,6 +1129,7 @@ bool isConst(AstTree *value) { case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: return true; @@ -1034,8 +1146,7 @@ bool isConst(AstTree *value) { } case AST_TREE_TOKEN_NONE: } - printLog("Bad token '%d'", value->token); - exit(1); + UNREACHABLE; } AstTree *makeTypeOf(AstTree *value) { @@ -1066,8 +1177,10 @@ AstTree *makeTypeOf(AstTree *value) { } return newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, - &AST_TREE_TYPE_TYPE); + &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_U64: return &AST_TREE_U64_TYPE; case AST_TREE_TOKEN_VALUE_BOOL: @@ -1086,8 +1199,7 @@ AstTree *makeTypeOf(AstTree *value) { case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_NONE: } - printLog("Bad token '%d'", value->token); - exit(1); + UNREACHABLE; } bool typeIsEqual(const AstTree *type0, const AstTree *type1) { @@ -1095,6 +1207,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: case AST_TREE_TOKEN_KEYWORD_RETURN: + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_VARIABLE_DEFINE: @@ -1126,7 +1239,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) { } return true; case AST_TREE_TOKEN_FUNCTION_CALL: - printLog("Not implemented yet"); + printError(type0->str_begin, type0->str_end, "Not implemented yet"); exit(1); case AST_TREE_TOKEN_VARIABLE: return type1->token == AST_TREE_TOKEN_VARIABLE && @@ -1134,8 +1247,7 @@ bool typeIsEqual(const AstTree *type0, const AstTree *type1) { case AST_TREE_TOKEN_NONE: break; } - printLog("Bad token '%d'", type0->token); - exit(1); + UNREACHABLE; } bool setAllTypesRoot(AstTreeRoot *root) { @@ -1158,6 +1270,7 @@ bool setAllTypes(AstTree *tree, AstTreeFunction *function) { case AST_TREE_TOKEN_TYPE_VOID: case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_TYPE_BOOL: + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: return true; @@ -1181,8 +1294,7 @@ bool setAllTypes(AstTree *tree, AstTreeFunction *function) { return setTypesVariableDefine(tree); case AST_TREE_TOKEN_NONE: } - printLog("Bad token '%d'", tree->token); - exit(1); + UNREACHABLE; } bool setTypesFunction(AstTree *tree) { @@ -1202,8 +1314,7 @@ bool setTypesFunction(AstTree *tree) { tree->type = makeTypeOf(tree); for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { - AstTree *expression = &metadata->scope.expressions[i]; - if (!setAllTypes(expression, metadata)) { + if (!setAllTypes(metadata->scope.expressions[i], metadata)) { return false; } } @@ -1222,7 +1333,7 @@ bool setTypesPrintU64(AstTree *tree) { if (!setAllTypes(metadata, NULL)) { return false; } else if (!typeIsEqual(metadata->type, &AST_TREE_U64_TYPE)) { - printLog("Type mismatch"); + printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } else { tree->type = &AST_TREE_VOID_TYPE; @@ -1236,7 +1347,7 @@ bool setTypesReturn(AstTree *tree, AstTreeFunction *function) { if (!setAllTypes(metadata->value, NULL)) { return false; } else if (!typeIsEqual(metadata->value->type, function->returnType)) { - printLog("Type mismatch"); + printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } } @@ -1248,14 +1359,14 @@ bool setTypesTypeFunction(AstTree *tree) { AstTreeTypeFunction *metadata = tree->metadata; for (size_t i = 0; i < metadata->arguments_size; ++i) { - printLog("Not yet supported"); + printError(tree->str_begin, tree->str_end, "Not yet supported"); return false; } if (!setAllTypes(metadata->returnType, NULL)) { return false; } else if (!typeIsEqual(metadata->returnType->type, &AST_TREE_TYPE_TYPE)) { - printLog("Type mismatch"); + printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } @@ -1273,7 +1384,7 @@ bool setTypesFunctionCall(AstTree *tree) { } if (metadata->function->token != AST_TREE_TOKEN_VARIABLE) { - printLog("Not yet supported"); + printError(tree->str_begin, tree->str_end, "Not yet supported"); return false; } else if (!setAllTypes(metadata->function, NULL)) { return false; @@ -1282,8 +1393,9 @@ bool setTypesFunctionCall(AstTree *tree) { AstTreeFunction *function = getFunction(metadata->function); if (function == NULL || function->arguments.size != metadata->parameters_size) { - printLog("Arguments doesn't match %ld != %ld", 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; } @@ -1306,10 +1418,10 @@ bool setTypesOperatorAssign(AstTree *tree) { if (!setTypesAstInfix(infix)) { return false; } else if (!typeIsEqual(infix->left.type, infix->right.type)) { - printLog("Type mismatch"); + printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } else if (isConst(&infix->left)) { - printLog("Constants can't be assigned"); + printError(tree->str_begin, tree->str_end, "Constants can't be assigned"); return false; } else { tree->type = copyAstTree(infix->left.type); @@ -1322,7 +1434,7 @@ bool setTypesOperatorSum(AstTree *tree) { if (!setTypesAstInfix(infix)) { return false; } else if (!typeIsEqual(infix->left.type, infix->right.type)) { - printLog("Type mismatch"); + printError(tree->str_begin, tree->str_end, "Type mismatch"); return false; } else { tree->type = copyAstTree(infix->left.type); @@ -1349,7 +1461,7 @@ bool setTypesAstVariable(AstTreeVariable *variable) { return false; } else if (variable->value != NULL && !typeIsEqual(variable->value->type, variable->type)) { - printLog("Type mismatch"); + printError(variable->name_begin, variable->name_end, "Type mismatch"); return false; } @@ -1382,6 +1494,7 @@ bool astTreeClean(AstTree *tree) { case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_TYPE_BOOL: case AST_TREE_TOKEN_FUNCTION_CALL: + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_VARIABLE_DEFINE: @@ -1390,8 +1503,7 @@ bool astTreeClean(AstTree *tree) { return true; case AST_TREE_TOKEN_NONE: } - printLog("Bad token '%d'", tree->token); - exit(1); + UNREACHABLE; } bool astTreeCleanFunction(AstTree *tree) { @@ -1409,8 +1521,7 @@ bool astTreeCleanFunction(AstTree *tree) { } for (size_t i = 0; i < metadata->scope.expressions_size; ++i) { - AstTree *expression = &metadata->scope.expressions[i]; - if (!astTreeClean(expression)) { + if (!astTreeClean(metadata->scope.expressions[i])) { return false; } } @@ -1470,6 +1581,7 @@ size_t astTreeTypeSize(AstTree tree) { 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_U64: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_OPERATOR_ASSIGN: diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index 83b77ef..d67560f 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -19,6 +19,7 @@ typedef enum AstTreeToken { AST_TREE_TOKEN_FUNCTION_CALL, AST_TREE_TOKEN_VARIABLE, AST_TREE_TOKEN_VARIABLE_DEFINE, + AST_TREE_TOKEN_VALUE_VOID, AST_TREE_TOKEN_VALUE_U64, AST_TREE_TOKEN_VALUE_BOOL, @@ -34,6 +35,8 @@ typedef struct AstTree { AstTreeToken token; void *metadata; struct AstTree *type; + char *str_begin; + char *str_end; } AstTree; extern AstTree AST_TREE_TYPE_TYPE; @@ -60,7 +63,7 @@ typedef struct AstTreeRoot { typedef struct AstTreeScope { AstTreeVariables variables; - AstTree *expressions; + AstTree **expressions; size_t expressions_size; } AstTreeScope; @@ -106,8 +109,9 @@ void astTreeVariableDelete(AstTreeVariable *variable); void astTreeDelete(AstTree *tree); void astTreeRootDelete(AstTreeRoot *root); -AstTree *newAstTree(AstTreeToken token, void *metadata, AstTree *type); +AstTree *newAstTree(AstTreeToken token, void *metadata, AstTree *type,char *str_begin,char *str_end); AstTree *copyAstTree(AstTree *tree); +AstTreeVariables copyAstTreeVariables(AstTreeVariables variables); AstTreeRoot *makeAstTree(ParserNode *parsedRoot); diff --git a/src/compiler/code-generator.c b/src/compiler/code-generator.c index ab7583e..d4ea1b9 100644 --- a/src/compiler/code-generator.c +++ b/src/compiler/code-generator.c @@ -255,10 +255,10 @@ bool codeGeneratorAstTreeFunction(char *name_begin, char *name_end, newCodeGeneratorFunctionBegin(name_begin, name_end))); for (size_t i = 0; i < scope.expressions_size; ++i) { - AstTree tree = scope.expressions[i]; - switch (tree.token) { + AstTree *tree = scope.expressions[i]; + switch (tree->token) { case AST_TREE_TOKEN_FUNCTION_CALL: { - AstTreeFunctionCall *metadata = tree.metadata; + AstTreeFunctionCall *metadata = tree->metadata; AstTree *function = metadata->function; if (metadata->parameters_size != 0) { printLog("Not implemented"); @@ -278,7 +278,7 @@ bool codeGeneratorAstTreeFunction(char *name_begin, char *name_end, } goto OK; case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { - AstTreeSingleChild *metadata = tree.metadata; + AstTreeSingleChild *metadata = tree->metadata; if (metadata->token == AST_TREE_TOKEN_VALUE_U64) { CodeGeneratorOperand *value = newCodeGeneratorOperand( (void *)(uint64_t)(AstTreeU64)metadata->metadata, false); @@ -313,7 +313,7 @@ bool codeGeneratorAstTreeFunction(char *name_begin, char *name_end, } goto OK; case AST_TREE_TOKEN_OPERATOR_ASSIGN: { - AstTreeInfix *infix = tree.metadata; + AstTreeInfix *infix = tree->metadata; if (infix->left.token != AST_TREE_TOKEN_VARIABLE) { printLog("Not implemented yet"); @@ -337,7 +337,7 @@ bool codeGeneratorAstTreeFunction(char *name_begin, char *name_end, } goto OK; case AST_TREE_TOKEN_OPERATOR_SUM: { - AstTreeInfix *infix = tree.metadata; + AstTreeInfix *infix = tree->metadata; if (infix->left.token != AST_TREE_TOKEN_VARIABLE) { printLog("Not implemented yet"); @@ -370,7 +370,7 @@ bool codeGeneratorAstTreeFunction(char *name_begin, char *name_end, case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_NONE: } - printLog("Bad token %d", tree.token); + printLog("Bad token %d", tree->token); return false; OK: } diff --git a/src/runner/runner.c b/src/runner/runner.c index dde5307..30f90f4 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -1,77 +1,189 @@ #include "runner.h" #include "compiler/ast-tree.h" #include "utils/log.h" +#include "utils/memory.h" #include <stdio.h> #include <stdlib.h> #include <string.h> +void runnerVariablePush(RunnerVariables *variables, AstTreeVariable *variable) { + 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] = + a404m_malloc(sizeof(*variables->data[variables->size])); + variables->data[variables->size]->variable = variable; + variables->data[variables->size]->value = NULL; + variables->size += 1; +} + +void runnerVariableSetValue(RunnerVariablePages *pages, + AstTreeVariable *variable, AstTree *value) { + if (variable->isConst) { + printError(variable->name_begin, variable->name_end, + "Can't assign to const"); + exit(1); + } + for (size_t i = 0; i < pages->size; ++i) { + RunnerVariables *variables = pages->data[i]; + for (size_t i = 0; i < variables->size; ++i) { + RunnerVariable *var = variables->data[i]; + if (var->variable == variable) { + if (var->value != NULL) { + astTreeDelete(var->value); + } + var->value = value; + return; + } + } + } + + UNREACHABLE; +} + +AstTree *runnerVariableGetValue(RunnerVariablePages *pages, + AstTreeVariable *variable) { + if (variable->isConst) { + return variable->value; + } + for (size_t i = 0; i < pages->size; ++i) { + RunnerVariables *variables = pages->data[i]; + for (size_t i = 0; i < variables->size; ++i) { + RunnerVariable *var = variables->data[i]; + if (var->variable == variable) { + if (var->value != NULL) { + return var->value; + } else { + return var->variable->value; + } + } + } + } + + UNREACHABLE; +} + bool runAstTree(AstTreeRoot *root) { constexpr char MAIN_STR[] = "main"; constexpr size_t MAIN_STR_SIZE = (sizeof(MAIN_STR) / sizeof(*MAIN_STR)) - sizeof(*MAIN_STR); + + RunnerVariablePages pages = { + .data = a404m_malloc(sizeof(*pages.data)), + .size = 1, + }; + + pages.data[pages.size - 1] = + a404m_malloc(sizeof(*pages.data[pages.size - 1])); + pages.data[pages.size - 1]->data = a404m_malloc(0); + pages.data[pages.size - 1]->size = 0; + for (size_t i = 0; i < root->variables.size; ++i) { AstTreeVariable *variable = root->variables.data[i]; + if (variable->isConst) { + runnerVariablePush(pages.data[pages.size - 1], variable); + } + } + + for (size_t i = 0; i < root->variables.size; ++i) { + AstTreeVariable *variable = root->variables.data[i]; + AstTree *variable_value = runnerVariableGetValue(&pages, variable); size_t name_size = variable->name_end - variable->name_begin; if (name_size == MAIN_STR_SIZE && strncmp(variable->name_begin, MAIN_STR, MAIN_STR_SIZE) == 0 && - variable->value->token == AST_TREE_TOKEN_FUNCTION) { + variable_value->token == AST_TREE_TOKEN_FUNCTION) { - AstTree *main = variable->value; - AstTreeFunction *mainFunction = main->metadata; - return runAstTreeFunction(mainFunction, NULL, 0) == &AST_TREE_VOID_VALUE; + AstTree *main = variable_value; + return runAstTreeFunction(main, NULL, 0, &pages) == &AST_TREE_VOID_VALUE; } } printLog("main function is not found"); return false; } -AstTree *runAstTreeFunction(AstTreeFunction *function, AstTree **arguments, - size_t arguments_size) { +AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments, + size_t arguments_size, + RunnerVariablePages *_pages) { + AstTreeFunction *function = tree->metadata; + + RunnerVariablePages pages = { + .data = a404m_malloc((_pages->size + 1) * sizeof(*pages.data)), + .size = _pages->size + 1, + }; + + for (size_t i = 0; i < _pages->size; ++i) { + pages.data[i] = _pages->data[i]; + } + + pages.data[pages.size - 1] = + a404m_malloc(sizeof(*pages.data[pages.size - 1])); + pages.data[pages.size - 1]->data = a404m_malloc(0); + pages.data[pages.size - 1]->size = 0; + for (size_t i = 0; i < arguments_size; ++i) { - function->arguments.data[i]->value = calcAstTreeValue(arguments[i]); + AstTreeVariable *variable = function->arguments.data[i]; + AstTree *value = calcAstTreeValue(arguments[i], &pages); + runnerVariablePush(pages.data[pages.size - 1], variable); + runnerVariableSetValue(&pages, variable, value); } + + for (size_t i = arguments_size; i < function->arguments.size; ++i) { + AstTreeVariable *variable = function->arguments.data[i]; + runnerVariablePush(pages.data[pages.size - 1], variable); + } + + for (size_t i = 0; i < function->scope.variables.size; ++i) { + AstTreeVariable *variable = function->scope.variables.data[i]; + runnerVariablePush(pages.data[pages.size - 1], variable); + } + + AstTree *ret = &AST_TREE_VOID_VALUE; + for (size_t i = 0; i < function->scope.expressions_size; ++i) { - AstTree expr = function->scope.expressions[i]; - switch (expr.token) { + AstTree *expr = function->scope.expressions[i]; + switch (expr->token) { case AST_TREE_TOKEN_KEYWORD_PRINT_U64: { - AstTreeSingleChild *metadata = expr.metadata; - AstTree *tree = calcAstTreeValue(metadata); + AstTreeSingleChild *metadata = expr->metadata; + AstTree *tree = calcAstTreeValue(metadata, &pages); printf("%ld", (AstTreeU64)tree->metadata); astTreeDelete(tree); } continue; case AST_TREE_TOKEN_FUNCTION_CALL: { - AstTree *ret = calcAstTreeValue(&expr); + AstTree *ret = calcAstTreeValue(expr, &pages); if (ret != &AST_TREE_VOID_VALUE) { astTreeDelete(ret); } } continue; case AST_TREE_TOKEN_OPERATOR_ASSIGN: { - AstTreeInfix *metadata = expr.metadata; + AstTreeInfix *metadata = expr->metadata; if (metadata->left.token == AST_TREE_TOKEN_VARIABLE) { AstTreeVariable *left = metadata->left.metadata; - astTreeDelete(left->value); - left->value = calcAstTreeValue(&metadata->right); + runnerVariableSetValue(&pages, left, + calcAstTreeValue(&metadata->right, &pages)); } else { UNREACHABLE; } } continue; case AST_TREE_TOKEN_KEYWORD_RETURN: { - AstTreeReturn *metadata = expr.metadata; + AstTreeReturn *metadata = expr->metadata; if (metadata->value != NULL) { - return calcAstTreeValue(metadata->value); + ret = calcAstTreeValue(metadata->value, &pages); } else { - return &AST_TREE_VOID_VALUE; + ret = &AST_TREE_VOID_VALUE; } + goto RETURN; } continue; case AST_TREE_TOKEN_VARIABLE_DEFINE: { - AstTreeVariable *variable = expr.metadata; - AstTree *value = calcAstTreeValue(variable->value); - astTreeDelete(variable->value); - variable->value = value; + AstTreeVariable *variable = expr->metadata; + runnerVariableSetValue(&pages, variable, variable->value); } continue; case AST_TREE_TOKEN_OPERATOR_SUM: @@ -82,43 +194,44 @@ AstTree *runAstTreeFunction(AstTreeFunction *function, AstTree **arguments, case AST_TREE_TOKEN_TYPE_U64: case AST_TREE_TOKEN_TYPE_BOOL: case AST_TREE_TOKEN_VARIABLE: + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: case AST_TREE_TOKEN_NONE: } - printLog("%d", expr.token); + printLog("Bad token %d", expr->token); UNREACHABLE; } - return &AST_TREE_VOID_VALUE; +RETURN: + return ret; } -AstTree *calcAstTreeValue(AstTree *tree) { +AstTree *calcAstTreeValue(AstTree *tree, RunnerVariablePages *pages) { switch (tree->token) { - case AST_TREE_TOKEN_VALUE_U64: { - return deepCopyAstTree(tree); - } - case AST_TREE_TOKEN_VALUE_BOOL: { + case AST_TREE_TOKEN_VALUE_VOID: + case AST_TREE_TOKEN_VALUE_U64: + case AST_TREE_TOKEN_VALUE_BOOL: return deepCopyAstTree(tree); - } case AST_TREE_TOKEN_VARIABLE: { AstTreeVariable *variable = tree->metadata; - return calcAstTreeValue(variable->value); + return calcAstTreeValue(runnerVariableGetValue(pages, variable), pages); } case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = tree->metadata; if (metadata->function->token == AST_TREE_TOKEN_VARIABLE) { AstTreeVariable *variable = metadata->function->metadata; - return runAstTreeFunction(variable->value->metadata, metadata->parameters, - metadata->parameters_size); + return runAstTreeFunction(runnerVariableGetValue(pages, variable), + metadata->parameters, metadata->parameters_size, + pages); } else { UNREACHABLE; } } case AST_TREE_TOKEN_OPERATOR_SUM: { AstTreeInfix *metadata = tree->metadata; - AstTree *left = calcAstTreeValue(&metadata->left); - AstTree *right = calcAstTreeValue(&metadata->right); + AstTree *left = calcAstTreeValue(&metadata->left, pages); + AstTree *right = calcAstTreeValue(&metadata->right, pages); if (left->type == &AST_TREE_U64_TYPE && right->type == &AST_TREE_U64_TYPE) { if (left->token == AST_TREE_TOKEN_VALUE_U64 && @@ -149,9 +262,11 @@ AstTree *calcAstTreeValue(AstTree *tree) { AstTree *deepCopyAstTree(AstTree *tree) { switch (tree->token) { + case AST_TREE_TOKEN_VALUE_VOID: case AST_TREE_TOKEN_VALUE_U64: case AST_TREE_TOKEN_VALUE_BOOL: - return newAstTree(tree->token, tree->metadata, copyAstTree(tree->type)); + return newAstTree(tree->token, tree->metadata, copyAstTree(tree->type), + NULL, NULL); case AST_TREE_TOKEN_VARIABLE: case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_KEYWORD_PRINT_U64: diff --git a/src/runner/runner.h b/src/runner/runner.h index 71c720b..ac36e84 100644 --- a/src/runner/runner.h +++ b/src/runner/runner.h @@ -3,10 +3,29 @@ #include "compiler/ast-tree.h" #include <stdint.h> +typedef struct RunnerVariable { + AstTreeVariable *variable; + AstTree *value; +} RunnerVariable; + +typedef struct RunnerVariables { + RunnerVariable **data; + size_t size; +} RunnerVariables; + +typedef struct RunnerVariablePages { + RunnerVariables **data; + size_t size; +} RunnerVariablePages; + +void runnerVariablePush(RunnerVariables *variables,AstTreeVariable *variable); +void runnerVariableSetValue(RunnerVariablePages *pages,AstTreeVariable *variable,AstTree *value); +AstTree* runnerVariableGetValue(RunnerVariablePages *pages,AstTreeVariable *variable); + bool runAstTree(AstTreeRoot *root); -AstTree *runAstTreeFunction(AstTreeFunction *function, AstTree **arguments, - size_t arguments_size); +AstTree *runAstTreeFunction(AstTree *tree, AstTree **arguments, + size_t arguments_size,RunnerVariablePages *pages); -AstTree *calcAstTreeValue(AstTree *tree); +AstTree *calcAstTreeValue(AstTree *tree,RunnerVariablePages *pages); AstTree *deepCopyAstTree(AstTree *tree); |