aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA404M <ahmadmahmoudiprogrammer@gmail.com>2025-05-30 14:56:47 +0330
committerA404M <ahmadmahmoudiprogrammer@gmail.com>2025-05-30 14:56:47 +0330
commitc8e1a4ed4885c25ffa3893afe967867852769452 (patch)
treeefde4f6d329c30fb58dd59e02e247e565c4fe75b
parent31637af96ec7555b81e742114ff41d80f37e3e6b (diff)
better operator overload
-rw-r--r--code/main.felan29
-rw-r--r--src/compiler/ast-tree.c635
-rw-r--r--src/compiler/ast-tree.h13
-rw-r--r--src/runner/runner.c36
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;