diff options
author | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-05-30 14:56:47 +0330 |
---|---|---|
committer | A404M <ahmadmahmoudiprogrammer@gmail.com> | 2025-05-30 14:56:47 +0330 |
commit | c8e1a4ed4885c25ffa3893afe967867852769452 (patch) | |
tree | efde4f6d329c30fb58dd59e02e247e565c4fe75b | |
parent | 31637af96ec7555b81e742114ff41d80f37e3e6b (diff) |
better operator overload
-rw-r--r-- | code/main.felan | 29 | ||||
-rw-r--r-- | src/compiler/ast-tree.c | 635 | ||||
-rw-r--r-- | src/compiler/ast-tree.h | 13 | ||||
-rw-r--r-- | src/runner/runner.c | 36 |
4 files changed, 459 insertions, 254 deletions
diff --git a/code/main.felan b/code/main.felan index d629a26..98aa762 100644 --- a/code/main.felan +++ b/code/main.felan @@ -1,16 +1,6 @@ -@import("lib/operator.felan"); +@import("basic.felan"); -/* -print :: (value:anytype) -> void { - if comptime @type_of(value) == u8 { - @putc(value); - }else{ - @putc('h'); - } -}; -*/ - -print :: (value:*anytype)->void{ +print :: (value:**anytype)->void{ if comptime @type_of(value.*) == u8 { @putc(value.*); }else{ @@ -18,11 +8,16 @@ print :: (value:*anytype)->void{ } }; +__sum__ :: (left:*anytype,right:i64) -> (@type_of(left)) { + return @add(left,right); +}; + main :: ()->void{ - a := 'a'; - b := 123; - print(&a); - print(&b); - // print(123); + arr :[10]i64= undefined; + arr[0] = 2; + arr[1] = 3; + p := &arr[0]; + p += 1; + print(p.*); }; diff --git a/src/compiler/ast-tree.c b/src/compiler/ast-tree.c index 57abc0d..6e5c5ae 100644 --- a/src/compiler/ast-tree.c +++ b/src/compiler/ast-tree.c @@ -790,6 +790,15 @@ void astTreeFunctionDestroy(AstTreeFunction function) { free(function.arguments.data); } +void astTreeDeleteFunctionCall(AstTreeFunctionCall *functionCall) { + astTreeDelete(functionCall->function); + for (size_t i = 0; i < functionCall->parameters_size; ++i) { + astTreeDelete(functionCall->parameters[i].value); + } + free(functionCall->parameters); + free(functionCall); +} + void astTreeDestroy(AstTree tree) { if (tree.type != NULL) { astTreeDelete(tree.type); @@ -949,12 +958,7 @@ void astTreeDestroy(AstTree tree) { 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].value); - } - free(metadata->parameters); - free(metadata); + astTreeDeleteFunctionCall(metadata); } return; case AST_TREE_TOKEN_VARIABLE: { @@ -983,6 +987,11 @@ void astTreeDestroy(AstTree tree) { AstTreeInfix *metadata = tree.metadata; astTreeDelete(metadata->left); astTreeDelete(metadata->right); + if (metadata->functionCall != NULL) { + astTreeDelete(metadata->functionCall->function); + free(metadata->functionCall->parameters); + free(metadata->functionCall); + } free(metadata); } return; @@ -1392,8 +1401,31 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], new_metadata->right = copyAstTreeBack(metadata->right, oldVariables, newVariables, variables_size, safetyCheck); - new_metadata->function = copyAstTreeBackFindVariable( - metadata->function, oldVariables, newVariables, variables_size); + if (metadata->functionCall == NULL) { + new_metadata->functionCall = NULL; + } else { + new_metadata->functionCall = + a404m_malloc(sizeof(*new_metadata->functionCall)); + new_metadata->functionCall->function = + copyAstTreeBack(metadata->functionCall->function, oldVariables, + newVariables, variables_size, safetyCheck); + new_metadata->functionCall->parameters_size = + metadata->functionCall->parameters_size; + new_metadata->functionCall->parameters = + a404m_malloc(new_metadata->functionCall->parameters_size * + sizeof(*new_metadata->functionCall->parameters)); + + new_metadata->functionCall->parameters[0] = (AstTreeFunctionCallParam){ + .value = new_metadata->left, + .nameBegin = NULL, + .nameEnd = NULL, + }; + new_metadata->functionCall->parameters[1] = (AstTreeFunctionCallParam){ + .value = new_metadata->right, + .nameBegin = NULL, + .nameEnd = NULL, + }; + } return newAstTree(tree->token, new_metadata, copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size, safetyCheck), @@ -1497,22 +1529,8 @@ AstTree *copyAstTreeBack(AstTree *tree, AstTreeVariables oldVariables[], } case AST_TREE_TOKEN_FUNCTION_CALL: { AstTreeFunctionCall *metadata = tree->metadata; - AstTreeFunctionCall *new_metadata = a404m_malloc(sizeof(*new_metadata)); - - new_metadata->function = - copyAstTreeBack(metadata->function, oldVariables, newVariables, - variables_size, safetyCheck); - - 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].nameBegin = metadata->parameters[i].nameBegin; - new_metadata->parameters[i].nameEnd = metadata->parameters[i].nameEnd; - new_metadata->parameters[i].value = - copyAstTreeBack(metadata->parameters[i].value, oldVariables, - newVariables, variables_size, safetyCheck); - } + AstTreeFunctionCall *new_metadata = copyAstTreeFunctionCall( + metadata, oldVariables, newVariables, variables_size, safetyCheck); return newAstTree(tree->token, new_metadata, copyAstTreeBack(tree->type, oldVariables, newVariables, variables_size, safetyCheck), @@ -1811,6 +1829,30 @@ AstTreeFunction *copyAstTreeFunction(AstTreeFunction *metadata, return new_metadata; } +AstTreeFunctionCall *copyAstTreeFunctionCall(AstTreeFunctionCall *metadata, + AstTreeVariables oldVariables[], + AstTreeVariables newVariables[], + size_t variables_size, + bool safetyCheck) { + AstTreeFunctionCall *new_metadata = a404m_malloc(sizeof(*new_metadata)); + new_metadata->function = + copyAstTreeBack(metadata->function, oldVariables, newVariables, + variables_size, safetyCheck); + + 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].nameBegin = metadata->parameters[i].nameBegin; + new_metadata->parameters[i].nameEnd = metadata->parameters[i].nameEnd; + new_metadata->parameters[i].value = + copyAstTreeBack(metadata->parameters[i].value, oldVariables, + newVariables, variables_size, safetyCheck); + } + + return new_metadata; +} + AstTreeRoots makeAstTree(const char *filePath #ifdef PRINT_STATISTICS , @@ -3028,7 +3070,7 @@ AstTree *astTreeParseBinaryOperator(const ParserNode *parserNode, metadata->left = left; metadata->right = right; - metadata->function = NULL; + metadata->functionCall = NULL; return newAstTree(token, metadata, NULL, parserNode->str_begin, parserNode->str_end); @@ -3080,7 +3122,7 @@ AstTree *astTreeParseOperateAssignOperator(const ParserNode *parserNode, metadata->left = left; metadata->right = right; - metadata->function = NULL; + metadata->functionCall = NULL; AstTreeInfix *assignMetadata = a404m_malloc(sizeof(*assignMetadata)); @@ -3090,7 +3132,7 @@ AstTree *astTreeParseOperateAssignOperator(const ParserNode *parserNode, assignMetadata->left = assignLeft; assignMetadata->right = assignRight; - assignMetadata->function = NULL; + assignMetadata->functionCall = NULL; return newAstTree(AST_TREE_TOKEN_OPERATOR_ASSIGN, assignMetadata, NULL, parserNode->str_begin, parserNode->str_end); @@ -3653,6 +3695,8 @@ bool hasAnyTypeInside(AstTree *type) { AstTreeBracket *metadata = type->metadata; return hasAnyTypeInside(metadata->operand); } + case AST_TREE_TOKEN_VARIABLE: + return false; case AST_TREE_TOKEN_FUNCTION: case AST_TREE_TOKEN_KEYWORD_RETURN: case AST_TREE_TOKEN_KEYWORD_BREAK: @@ -3662,7 +3706,6 @@ bool hasAnyTypeInside(AstTree *type) { case AST_TREE_TOKEN_KEYWORD_COMPTIME: case AST_TREE_TOKEN_KEYWORD_STRUCT: case AST_TREE_TOKEN_FUNCTION_CALL: - case AST_TREE_TOKEN_VARIABLE: case AST_TREE_TOKEN_VARIABLE_DEFINE: case AST_TREE_TOKEN_VALUE_SHAPE_SHIFTER: case AST_TREE_TOKEN_VALUE_C_LIBRARY: @@ -3699,6 +3742,7 @@ bool hasAnyTypeInside(AstTree *type) { case AST_TREE_TOKEN_SCOPE: case AST_TREE_TOKEN_NONE: } + printLog("Bad token %s", AST_TREE_TOKEN_STRINGS[type->token]); UNREACHABLE; } @@ -3844,7 +3888,7 @@ bool isConst(AstTree *tree) { case AST_TREE_TOKEN_OPERATOR_SHIFT_LEFT: case AST_TREE_TOKEN_OPERATOR_SHIFT_RIGHT: { AstTreeInfix *metadata = tree->metadata; - return metadata->function->isConst && isConst(metadata->function->value) && + return isConst(metadata->functionCall->function) && isConst(metadata->left) && isConst(metadata->right); } case AST_TREE_TOKEN_VARIABLE: { @@ -3998,7 +4042,8 @@ AstTree *makeTypeOf(AstTree *value) { case AST_TREE_TOKEN_OPERATOR_GREATER_OR_EQUAL: case AST_TREE_TOKEN_OPERATOR_SMALLER_OR_EQUAL: { AstTreeInfix *metadata = value->metadata; - AstTreeTypeFunction *function = metadata->function->type->metadata; + AstTreeTypeFunction *function = + metadata->functionCall->function->type->metadata; return copyAstTree(function->returnType); } case AST_TREE_TOKEN_OPERATOR_ACCESS: { @@ -5183,6 +5228,7 @@ bool setAllTypes(AstTree *tree, AstTreeSetTypesHelper helper, return setTypesBuiltinUnary(tree, helper, functionCall); case AST_TREE_TOKEN_BUILTIN_ADD: case AST_TREE_TOKEN_BUILTIN_SUB: + return setTypesBuiltinBinaryAlsoPointer(tree, helper, functionCall); case AST_TREE_TOKEN_BUILTIN_MUL: case AST_TREE_TOKEN_BUILTIN_DIV: case AST_TREE_TOKEN_BUILTIN_MOD: @@ -5700,193 +5746,13 @@ bool setTypesFunctionCall(AstTree *tree, AstTreeSetTypesHelper _helper) { tree->type = copyAstTree(function->returnType); } else if (metadata->function->type->token == AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER) { - if (!isConst(metadata->function)) { - printError(metadata->function->str_begin, metadata->function->str_end, - "Shape Shifters must be constant"); - return false; - } else if (metadata->function->token != AST_TREE_TOKEN_VARIABLE) { - printError(metadata->function->str_begin, metadata->function->str_end, - "Shape Shifters must be constant variable but got %s", - AST_TREE_TOKEN_STRINGS[metadata->function->token]); + AstTree *function = getShapeShifterElement(metadata, helper); + if (function == NULL) { return false; } - AstTreeVariable *variable = metadata->function->metadata; - AstTreeShapeShifter *shapeShifter = variable->value->metadata; - - AstTreeFunction *newFunction = - copyAstTreeFunction(shapeShifter->function, NULL, NULL, 0, true); - - AstTreeFunctionCallParam initedArguments[newFunction->arguments.size]; - size_t initedArguments_size = newFunction->arguments.size; - - for (size_t i = 0; i < initedArguments_size; ++i) { - initedArguments[i].value = NULL; - } - - for (size_t i = 0; i < metadata->parameters_size; ++i) { - AstTreeFunctionCallParam param = metadata->parameters[i]; - if (param.nameBegin != param.nameEnd) { - const size_t param_name_size = param.nameEnd - param.nameBegin; - for (size_t j = 0; j < newFunction->arguments.size; ++j) { - AstTreeVariable *arg = newFunction->arguments.data[j]; - if ((size_t)(arg->name_end - arg->name_begin) == param_name_size && - strnEquals(arg->name_begin, param.nameBegin, param_name_size)) { - if (arg->isConst) { - arg->value = getValue(param.value, true); - } - if (hasAnyTypeInside(arg->type)) { - astTreeDelete(arg->type); - arg->type = copyAstTree(param.value->type); - } - initedArguments[j] = param; - goto END_OF_NAMED_FOR1; - } - } - printError(param.value->str_begin, param.value->str_end, - "Argument not found"); - return false; - } - END_OF_NAMED_FOR1: - } - - for (size_t i = 0; i < metadata->parameters_size; ++i) { - AstTreeFunctionCallParam param = metadata->parameters[i]; - if (param.nameBegin == param.nameEnd) { - for (size_t j = 0; j < newFunction->arguments.size; ++j) { - AstTreeVariable *arg = newFunction->arguments.data[j]; - if (initedArguments[j].value == NULL) { - if (arg->isConst) { - arg->value = getValue(param.value, true); - } - if (hasAnyTypeInside(arg->type)) { - astTreeDelete(arg->type); - arg->type = copyAstTree(param.value->type); - } - initedArguments[j] = param; - goto END_OF_UNNAMED_FOR1; - } - } - printError(param.value->str_begin, param.value->str_end, - "Too many arguments"); - return false; - } - END_OF_UNNAMED_FOR1: - } - - for (size_t i = 0; i < newFunction->arguments.size; ++i) { - AstTreeVariable *arg = newFunction->arguments.data[i]; - if (initedArguments[i].value == NULL) { - printError(arg->name_begin, arg->name_end, - "Argument is not initialized"); - return false; - } - } - - for (size_t i = 0; i < initedArguments_size; ++i) { - metadata->parameters[i] = initedArguments[i]; - } - - bool found = false; - size_t element_index; - - for (size_t i = 0; i < shapeShifter->generateds.size; ++i) { - AstTreeFunctionCall *call = shapeShifter->generateds.calls[i]; - if (metadata->parameters_size != call->parameters_size) - continue; - - for (size_t i = 0; i < metadata->parameters_size; ++i) { - AstTreeFunctionCallParam p0 = metadata->parameters[i]; - AstTreeFunctionCallParam p1 = call->parameters[i]; - if (!typeIsEqual(p0.value->type, p1.value->type)) { - goto SEARCH_LOOP_CONTINUE; - } - if (shapeShifter->function->arguments.data[i]->isConst) { - AstTree *v0 = getValue(p0.value, true); - AstTree *v1 = getValue(p1.value, true); - - bool res = isEqual(v0, v1); - - astTreeDelete(v0); - astTreeDelete(v1); - - if (!res) { - goto SEARCH_LOOP_CONTINUE; - } - } - } - element_index = i; - astTreeFunctionDestroy(*newFunction); - free(newFunction); - found = true; - break; - SEARCH_LOOP_CONTINUE: - } - - if (!found) { - AstTreeVariable - *variables[helper.variables.size + newFunction->arguments.size]; - - for (size_t i = 0; i < helper.variables.size; ++i) { - variables[i] = helper.variables.data[i]; - } - - for (size_t i = 0; i < newFunction->arguments.size; ++i) { - variables[helper.variables.size + i] = newFunction->arguments.data[i]; - } - - AstTreeSetTypesHelper newHelper = { - .root = helper.root, - .variables.data = variables, - .variables.size = helper.variables.size, - .lookingType = NULL, - .dependencies = helper.dependencies, - .loops = helper.loops, - .loops_size = helper.loops_size, - }; - - for (size_t i = 0; i < newFunction->arguments.size; ++i) { - AstTreeVariable *var = newFunction->arguments.data[i]; - if (!setTypesAstVariable(var, newHelper)) { - return false; - } - newHelper.variables.size += 1; - } - - if (!setTypesAstFunction(newFunction, helper)) { - return false; - } - - size_t generateds_size = - a404m_malloc_usable_size(shapeShifter->generateds.functions) / - sizeof(*shapeShifter->generateds.functions); - if (generateds_size == shapeShifter->generateds.size) { - generateds_size += generateds_size / 2 + 1; - shapeShifter->generateds.functions = a404m_realloc( - shapeShifter->generateds.functions, - generateds_size * sizeof(*shapeShifter->generateds.functions)); - shapeShifter->generateds.calls = a404m_realloc( - shapeShifter->generateds.calls, - generateds_size * sizeof(*shapeShifter->generateds.calls)); - } - shapeShifter->generateds.functions[shapeShifter->generateds.size] = - newFunction; - shapeShifter->generateds.calls[shapeShifter->generateds.size] = metadata; - - element_index = shapeShifter->generateds.size; - shapeShifter->generateds.size += 1; - } - - AstTreeShapeShifterElement *element = a404m_malloc(sizeof(*element)); - element->shapeShifter = metadata->function; - element->index = element_index; - metadata->function = - newAstTree(AST_TREE_TOKEN_SHAPE_SHIFTER_ELEMENT, element, NULL, - metadata->function->str_begin, metadata->function->str_end); - metadata->function->type = makeTypeOf(metadata->function); - - AstTreeTypeFunction *function = metadata->function->type->metadata; - - tree->type = copyAstTree(function->returnType); + metadata->function = function; + AstTreeTypeFunction *functionType = function->type->metadata; + tree->type = copyAstTree(functionType->returnType); } else if (metadata->function->type->token == AST_TREE_TOKEN_TYPE_C_FUNCTION) { AstTreeCFunctionType *cFunction = metadata->function->type->metadata; @@ -6018,36 +5884,54 @@ bool setTypesOperatorInfix(AstTree *tree, AstTreeSetTypesHelper _helper, return false; } - AstTreeFunctionCallParam parameters[] = { - (AstTreeFunctionCallParam){ - .nameBegin = NULL, - .nameEnd = NULL, - .value = metadata->left, - }, - (AstTreeFunctionCallParam){ - .nameBegin = NULL, - .nameEnd = NULL, - .value = metadata->right, - }, - }; - - AstTreeFunctionCall functionCall = { + AstTreeFunctionCall *functionCall = a404m_malloc(sizeof(*functionCall)); + *functionCall = (AstTreeFunctionCall){ .function = NULL, - .parameters = parameters, + .parameters = a404m_malloc(2 * sizeof(*functionCall->parameters)), .parameters_size = 2, }; + functionCall->parameters[0] = (AstTreeFunctionCallParam){ + .nameBegin = NULL, + .nameEnd = NULL, + .value = metadata->left, + }; + functionCall->parameters[1] = (AstTreeFunctionCallParam){ + .nameBegin = NULL, + .nameEnd = NULL, + .value = metadata->right, + }; + + metadata->functionCall = functionCall; AstTreeVariable *variable = - setTypesFindVariable(str, str + str_size, helper, &functionCall); + setTypesFindVariable(str, str + str_size, helper, functionCall); if (variable == NULL) { printError(tree->str_begin, tree->str_end, "Can't find operator"); return false; + } else if (!variable->isConst) { + printError(tree->str_begin, tree->str_end, + "Overloaded operator must be constant"); + return false; } - metadata->function = variable; - AstTreeTypeFunction *function = metadata->function->type->metadata; + functionCall->function = newAstTree(AST_TREE_TOKEN_VARIABLE, variable, + copyAstTree(variable->type), NULL, NULL); + if (functionCall->function->type->token == AST_TREE_TOKEN_TYPE_FUNCTION) { + AstTreeTypeFunction *function = functionCall->function->type->metadata; + tree->type = copyAstTree(function->returnType); + } else if (functionCall->function->type->token == + AST_TREE_TOKEN_TYPE_SHAPE_SHIFTER) { + AstTree *function = getShapeShifterElement(functionCall, helper); + if (function == NULL) { + return NULL; + } + functionCall->function = function; + AstTreeTypeFunction *functionType = functionCall->function->type->metadata; + tree->type = copyAstTree(functionType->returnType); + } else { + UNREACHABLE; + } - tree->type = copyAstTree(function->returnType); return true; } @@ -7034,6 +6918,96 @@ AFTER_SWITCH: return true; } +bool setTypesBuiltinBinaryAlsoPointer(AstTree *tree, + AstTreeSetTypesHelper helper, + AstTreeFunctionCall *functionCall) { + (void)helper; + if (functionCall->parameters_size != 2) { + printError(tree->str_begin, tree->str_end, "Too many or too few arguments"); + return false; + } + AstTree *left = NULL; + AstTree *right = NULL; + + static char LEFT_STR[] = "left"; + static const size_t LEFT_STR_SIZE = + sizeof(LEFT_STR) / sizeof(*LEFT_STR) - sizeof(*LEFT_STR); + static char RIGHT_STR[] = "right"; + static const size_t RIGHT_STR_SIZE = + sizeof(RIGHT_STR) / sizeof(*RIGHT_STR) - sizeof(*RIGHT_STR); + + for (size_t i = 0; i < functionCall->parameters_size; ++i) { + AstTreeFunctionCallParam param = functionCall->parameters[i]; + const size_t param_name_size = param.nameEnd - param.nameBegin; + + if (param_name_size == 0) { + if (left == NULL) { + left = param.value; + } else if (right == NULL) { + right = param.value; + } else { + printError(param.value->str_begin, param.value->str_end, + "Bad paramter"); + return false; + } + } else if (param_name_size == LEFT_STR_SIZE && + strnEquals(param.nameBegin, LEFT_STR, LEFT_STR_SIZE) && + left == NULL) { + left = param.value; + } else if (param_name_size == RIGHT_STR_SIZE && + strnEquals(param.nameBegin, RIGHT_STR, RIGHT_STR_SIZE) && + right == NULL) { + right = param.value; + } else { + printError(param.value->str_begin, param.value->str_end, "Bad paramter"); + return false; + } + } + + if (left == NULL || right == NULL) { + return false; + } else if (left->type->token != AST_TREE_TOKEN_OPERATOR_POINTER && + !typeIsEqual(left->type, right->type)) { + printError(tree->str_begin, tree->str_end, "Type mismatch"); + return false; + } else if (left->type->token == AST_TREE_TOKEN_OPERATOR_POINTER && + !typeIsEqual(right->type, &AST_TREE_I64_TYPE) && + !typeIsEqual(right->type, &AST_TREE_U64_TYPE)) { + printError(tree->str_begin, tree->str_end, + "Pointer can only have right hand as u64 or i64"); + return false; + } + + AstTreeTypeFunction *type_metadata = a404m_malloc(sizeof(*type_metadata)); + type_metadata->arguments_size = 2; + type_metadata->arguments = a404m_malloc(type_metadata->arguments_size * + sizeof(*type_metadata->arguments)); + + type_metadata->returnType = copyAstTree(left->type); + + type_metadata->arguments[0] = (AstTreeTypeFunctionArgument){ + .type = copyAstTree(left->type), + .name_begin = LEFT_STR, + .name_end = LEFT_STR + LEFT_STR_SIZE, + .str_begin = NULL, + .str_end = NULL, + .isComptime = false, + }; + + type_metadata->arguments[1] = (AstTreeTypeFunctionArgument){ + .type = copyAstTree(right->type), + .name_begin = RIGHT_STR, + .name_end = RIGHT_STR + RIGHT_STR_SIZE, + .str_begin = NULL, + .str_end = NULL, + .isComptime = false, + }; + + tree->type = newAstTree(AST_TREE_TOKEN_TYPE_FUNCTION, type_metadata, + &AST_TREE_TYPE_TYPE, NULL, NULL); + return true; +} + bool setTypesBuiltinBinary(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunctionCall *functionCall) { (void)helper; @@ -7103,7 +7077,7 @@ bool setTypesBuiltinBinary(AstTree *tree, AstTreeSetTypesHelper helper, }; type_metadata->arguments[1] = (AstTreeTypeFunctionArgument){ - .type = copyAstTree(left->type), + .type = copyAstTree(right->type), .name_begin = RIGHT_STR, .name_end = RIGHT_STR + RIGHT_STR_SIZE, .str_begin = NULL, @@ -7581,6 +7555,10 @@ bool setTypesAstFunction(AstTreeFunction *metadata, return false; } + if (isConst(metadata->returnType)) { + metadata->returnType = getValue(metadata->returnType, false); + } + for (size_t i = 0; i < helper.dependencies.size; ++i) { deps[deps_size] = helper.dependencies.data[i]; deps_size += 1; @@ -7923,6 +7901,193 @@ AstTreeVariable *setTypesFindVariable(const char *name_begin, return variable; } +AstTree *getShapeShifterElement(AstTreeFunctionCall *metadata, + AstTreeSetTypesHelper helper) { + if (!isConst(metadata->function)) { + printError(metadata->function->str_begin, metadata->function->str_end, + "Shape Shifters must be constant"); + return NULL; + } else if (metadata->function->token != AST_TREE_TOKEN_VARIABLE) { + printError(metadata->function->str_begin, metadata->function->str_end, + "Shape Shifters must be constant variable but got %s", + AST_TREE_TOKEN_STRINGS[metadata->function->token]); + return NULL; + } + AstTreeVariable *variable = metadata->function->metadata; + AstTreeShapeShifter *shapeShifter = variable->value->metadata; + + AstTreeFunction *newFunction = + copyAstTreeFunction(shapeShifter->function, NULL, NULL, 0, true); + + AstTreeFunctionCallParam initedArguments[newFunction->arguments.size]; + size_t initedArguments_size = newFunction->arguments.size; + + for (size_t i = 0; i < initedArguments_size; ++i) { + initedArguments[i].value = NULL; + } + + for (size_t i = 0; i < metadata->parameters_size; ++i) { + AstTreeFunctionCallParam param = metadata->parameters[i]; + if (param.nameBegin != param.nameEnd) { + const size_t param_name_size = param.nameEnd - param.nameBegin; + for (size_t j = 0; j < newFunction->arguments.size; ++j) { + AstTreeVariable *arg = newFunction->arguments.data[j]; + if ((size_t)(arg->name_end - arg->name_begin) == param_name_size && + strnEquals(arg->name_begin, param.nameBegin, param_name_size)) { + if (arg->isConst) { + arg->value = getValue(param.value, true); + } + if (hasAnyTypeInside(arg->type)) { + astTreeDelete(arg->type); + arg->type = copyAstTree(param.value->type); + } + initedArguments[j] = param; + goto END_OF_NAMED_FOR1; + } + } + printError(param.value->str_begin, param.value->str_end, + "Argument not found"); + return NULL; + } + END_OF_NAMED_FOR1: + } + + for (size_t i = 0; i < metadata->parameters_size; ++i) { + AstTreeFunctionCallParam param = metadata->parameters[i]; + if (param.nameBegin == param.nameEnd) { + for (size_t j = 0; j < newFunction->arguments.size; ++j) { + AstTreeVariable *arg = newFunction->arguments.data[j]; + if (initedArguments[j].value == NULL) { + if (arg->isConst) { + arg->value = getValue(param.value, true); + } + if (hasAnyTypeInside(arg->type)) { + astTreeDelete(arg->type); + arg->type = copyAstTree(param.value->type); + } + initedArguments[j] = param; + goto END_OF_UNNAMED_FOR1; + } + } + printError(param.value->str_begin, param.value->str_end, + "Too many arguments"); + return NULL; + } + END_OF_UNNAMED_FOR1: + } + + for (size_t i = 0; i < newFunction->arguments.size; ++i) { + AstTreeVariable *arg = newFunction->arguments.data[i]; + if (initedArguments[i].value == NULL) { + printError(arg->name_begin, arg->name_end, "Argument is not initialized"); + return NULL; + } + } + + for (size_t i = 0; i < initedArguments_size; ++i) { + metadata->parameters[i] = initedArguments[i]; + } + + bool found = false; + size_t element_index; + + for (size_t i = 0; i < shapeShifter->generateds.size; ++i) { + AstTreeFunctionCall *call = shapeShifter->generateds.calls[i]; + if (metadata->parameters_size != call->parameters_size) + continue; + + for (size_t i = 0; i < metadata->parameters_size; ++i) { + AstTreeFunctionCallParam p0 = metadata->parameters[i]; + AstTreeFunctionCallParam p1 = call->parameters[i]; + if (!typeIsEqual(p0.value->type, p1.value->type)) { + goto SEARCH_LOOP_CONTINUE; + } + if (shapeShifter->function->arguments.data[i]->isConst) { + AstTree *v0 = getValue(p0.value, true); + AstTree *v1 = getValue(p1.value, true); + + bool res = isEqual(v0, v1); + + astTreeDelete(v0); + astTreeDelete(v1); + + if (!res) { + goto SEARCH_LOOP_CONTINUE; + } + } + } + element_index = i; + astTreeFunctionDestroy(*newFunction); + free(newFunction); + found = true; + break; + SEARCH_LOOP_CONTINUE: + } + + if (!found) { + AstTreeVariable + *variables[helper.variables.size + newFunction->arguments.size]; + + for (size_t i = 0; i < helper.variables.size; ++i) { + variables[i] = helper.variables.data[i]; + } + + for (size_t i = 0; i < newFunction->arguments.size; ++i) { + variables[helper.variables.size + i] = newFunction->arguments.data[i]; + } + + AstTreeSetTypesHelper newHelper = { + .root = helper.root, + .variables.data = variables, + .variables.size = helper.variables.size, + .lookingType = NULL, + .dependencies = helper.dependencies, + .loops = helper.loops, + .loops_size = helper.loops_size, + }; + + for (size_t i = 0; i < newFunction->arguments.size; ++i) { + AstTreeVariable *var = newFunction->arguments.data[i]; + if (!setTypesAstVariable(var, newHelper)) { + return NULL; + } + newHelper.variables.size += 1; + } + + if (!setTypesAstFunction(newFunction, helper)) { + return NULL; + } + + size_t generateds_size = + a404m_malloc_usable_size(shapeShifter->generateds.functions) / + sizeof(*shapeShifter->generateds.functions); + if (generateds_size == shapeShifter->generateds.size) { + generateds_size += generateds_size / 2 + 1; + shapeShifter->generateds.functions = a404m_realloc( + shapeShifter->generateds.functions, + generateds_size * sizeof(*shapeShifter->generateds.functions)); + shapeShifter->generateds.calls = a404m_realloc( + shapeShifter->generateds.calls, + generateds_size * sizeof(*shapeShifter->generateds.calls)); + } + shapeShifter->generateds.functions[shapeShifter->generateds.size] = + newFunction; + shapeShifter->generateds.calls[shapeShifter->generateds.size] = metadata; + + element_index = shapeShifter->generateds.size; + shapeShifter->generateds.size += 1; + } + + AstTreeShapeShifterElement *element = a404m_malloc(sizeof(*element)); + element->shapeShifter = metadata->function; + element->index = element_index; + metadata->function = + newAstTree(AST_TREE_TOKEN_SHAPE_SHIFTER_ELEMENT, element, NULL, + metadata->function->str_begin, metadata->function->str_end); + metadata->function->type = makeTypeOf(metadata->function); + return metadata->function; +} + char *u8ArrayToCString(AstTree *tree) { if (tree->token == AST_TREE_TOKEN_RAW_VALUE || tree->token == AST_TREE_TOKEN_RAW_VALUE_NOT_OWNED) { diff --git a/src/compiler/ast-tree.h b/src/compiler/ast-tree.h index abe38c2..8e3b9e7 100644 --- a/src/compiler/ast-tree.h +++ b/src/compiler/ast-tree.h @@ -257,7 +257,7 @@ typedef struct AstTreeUnary { typedef struct AstTreeInfix { AstTree *left; AstTree *right; - AstTreeVariable *function; + AstTreeFunctionCall *functionCall; } AstTreeInfix; typedef struct AstTreeReturn { @@ -353,6 +353,7 @@ void astTreeRootPrint(const AstTreeRoot *root); #endif void astTreeFunctionDestroy(AstTreeFunction function); +void astTreeDeleteFunctionCall(AstTreeFunctionCall *functionCall); void astTreeDestroy(AstTree tree); void astTreeVariableDestroy(AstTreeVariable variable); void astTreeVariableDelete(AstTreeVariable *variable); @@ -380,6 +381,11 @@ AstTreeFunction *copyAstTreeFunction(AstTreeFunction *function, AstTreeVariables oldVariables[], AstTreeVariables newVariables[], size_t variables_size, bool safetyCheck); +AstTreeFunctionCall *copyAstTreeFunctionCall(AstTreeFunctionCall *functionCall, + AstTreeVariables oldVariables[], + AstTreeVariables newVariables[], + size_t variables_size, + bool safetyCheck); AstTreeRoots makeAstTree(const char *filePath #ifdef PRINT_STATISTICS @@ -504,6 +510,9 @@ bool setTypesBuiltinHeapAlloc(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunctionCall *functionCall); bool setTypesBuiltinUnary(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunctionCall *functionCall); +bool setTypesBuiltinBinaryAlsoPointer(AstTree *tree, + AstTreeSetTypesHelper helper, + AstTreeFunctionCall *functionCall); bool setTypesBuiltinBinary(AstTree *tree, AstTreeSetTypesHelper helper, AstTreeFunctionCall *functionCall); bool setTypesBuiltinBinaryWithRet(AstTree *tree, AstTreeSetTypesHelper helper, @@ -528,6 +537,8 @@ AstTreeVariable *setTypesFindVariable(const char *name_begin, const char *name_end, AstTreeSetTypesHelper helper, AstTreeFunctionCall *functionCall); +AstTree *getShapeShifterElement(AstTreeFunctionCall *metadata, + AstTreeSetTypesHelper helper); char *u8ArrayToCString(AstTree *tree); diff --git a/src/runner/runner.c b/src/runner/runner.c index 04f26b6..b238da2 100644 --- a/src/runner/runner.c +++ b/src/runner/runner.c @@ -334,6 +334,23 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_TYPE_F128: *(f128 *)ret = *(f128 *)left->metadata + *(f128 *)right->metadata; break; + case AST_TREE_TOKEN_OPERATOR_POINTER: + if (typeIsEqual(right->type, &AST_TREE_I64_TYPE)) { + *(u8 **)ret = + *(u8 **)left->metadata + + *(i64 *)right->metadata * + getSizeOfType((AstTreeSingleChild *)left->type->metadata); + break; + } else if (typeIsEqual(right->type, &AST_TREE_U64_TYPE)) { + *(u8 **)ret = + *(u8 **)left->metadata + + *(u64 *)right->metadata * + getSizeOfType((AstTreeSingleChild *)left->type->metadata); + break; + } else { + printLog("%s", AST_TREE_TOKEN_STRINGS[right->type->token]); + UNREACHABLE; + } default: UNREACHABLE; } @@ -384,6 +401,23 @@ AstTree *runAstTreeBuiltin(AstTree *tree, AstTreeScope *scope, case AST_TREE_TOKEN_TYPE_F128: *(f128 *)ret = *(f128 *)left->metadata - *(f128 *)right->metadata; break; + case AST_TREE_TOKEN_OPERATOR_POINTER: + if (typeIsEqual(right->type, &AST_TREE_I64_TYPE)) { + *(u8 **)ret = + *(u8 **)left->metadata - + *(i64 *)right->metadata * + getSizeOfType((AstTreeSingleChild *)left->type->metadata); + break; + } else if (typeIsEqual(right->type, &AST_TREE_U64_TYPE)) { + *(u8 **)ret = + *(u8 **)left->metadata - + *(u64 *)right->metadata * + getSizeOfType((AstTreeSingleChild *)left->type->metadata); + break; + } else { + printLog("%s", AST_TREE_TOKEN_STRINGS[right->type->token]); + UNREACHABLE; + } default: UNREACHABLE; } @@ -1535,7 +1569,7 @@ AstTree *runExpression(AstTree *expr, AstTreeScope *scope, bool *shouldRet, case AST_TREE_TOKEN_OPERATOR_SHIFT_RIGHT: { AstTreeInfix *metadata = expr->metadata; AstTree *function = - runExpression(metadata->function->value, scope, shouldRet, false, + runExpression(metadata->functionCall->function, scope, shouldRet, false, isComptime, breakCount, shouldContinue, false); if (discontinue(*shouldRet, *breakCount)) { return function; |