added function return type

This commit is contained in:
Sven Vogel 2024-08-04 16:20:23 +02:00
parent 53840881d7
commit b786b3e156
11 changed files with 412 additions and 144 deletions

View File

@ -67,7 +67,10 @@ void AST_init() {
lookup_table[AST_Typedef] = "typedef"; lookup_table[AST_Typedef] = "typedef";
lookup_table[AST_Box] = "box"; lookup_table[AST_Box] = "box";
lookup_table[AST_Fun] = "fun"; lookup_table[AST_FunDecl] = "fun";
lookup_table[AST_FunDef] = "fun";
lookup_table[AST_ProcDecl] = "fun";
lookup_table[AST_ProcDef] = "fun";
lookup_table[AST_Call] = "funcall"; lookup_table[AST_Call] = "funcall";
lookup_table[AST_Typecast] = "typecast"; lookup_table[AST_Typecast] = "typecast";

View File

@ -57,7 +57,10 @@ enum AST_SyntaxElement_t {
// Defintions // Defintions
AST_Typedef, AST_Typedef,
AST_Box, AST_Box,
AST_Fun, AST_FunDecl,
AST_FunDef,
AST_ProcDecl,
AST_ProcDef,
AST_Import, AST_Import,
// amount of variants // amount of variants
// in this enums // in this enums

View File

@ -524,6 +524,9 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
deref_depth, deref_depth,
llvm_result); llvm_result);
break; break;
case ExpressionKindFunctionCall:
err = impl_func_call(unit, builder, scope, expr->impl.call, llvm_result);
break;
default: default:
err = new_backend_impl_error(Implementation, NULL, "unknown expression"); err = new_backend_impl_error(Implementation, NULL, "unknown expression");
break; break;

View File

@ -10,6 +10,7 @@
#include <set/types.h> #include <set/types.h>
#include <sys/log.h> #include <sys/log.h>
#include <mem/cache.h> #include <mem/cache.h>
#include <llvm/llvm-ir/expr.h>
LLVMLocalScope* new_local_scope(LLVMLocalScope* parent) { LLVMLocalScope* new_local_scope(LLVMLocalScope* parent) {
LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope)); LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope));
@ -127,8 +128,19 @@ BackendError impl_func_type(LLVMBackendCompileUnit* unit,
DEBUG("implemented %ld parameter", llvm_params->len); DEBUG("implemented %ld parameter", llvm_params->len);
LLVMTypeRef llvm_return_type = LLVMVoidTypeInContext(unit->context);
if (func->kind == FunctionDeclarationKind) {
if (func->impl.declaration.return_value != NULL) {
err = get_type_impl(unit, scope, func->impl.declaration.return_value, &llvm_return_type);
}
} else {
if (func->impl.definition.return_value != NULL) {
err = get_type_impl(unit, scope, func->impl.definition.return_value, &llvm_return_type);
}
}
LLVMTypeRef llvm_fun_type = LLVMTypeRef llvm_fun_type =
LLVMFunctionType(LLVMVoidTypeInContext(unit->context), LLVMFunctionType(llvm_return_type,
(LLVMTypeRef*)llvm_params->data, llvm_params->len, 0); (LLVMTypeRef*)llvm_params->data, llvm_params->len, 0);
*llvm_fun = LLVMAddFunction(unit->module, func->name, llvm_fun_type); *llvm_fun = LLVMAddFunction(unit->module, func->name, llvm_fun_type);
@ -180,14 +192,39 @@ BackendError impl_func_def(LLVMBackendCompileUnit* unit,
LLVMPositionBuilderAtEnd(builder, entry); LLVMPositionBuilderAtEnd(builder, entry);
LLVMBuildBr(builder, llvm_start_body_block); LLVMBuildBr(builder, llvm_start_body_block);
LLVMValueRef terminator = LLVMGetBasicBlockTerminator(llvm_end_body_block);
if (terminator == NULL) {
// insert returning end block // insert returning end block
LLVMBasicBlockRef end_block = LLVMBasicBlockRef end_block =
LLVMAppendBasicBlockInContext(unit->context, llvm_func, "func.end"); LLVMAppendBasicBlockInContext(unit->context, llvm_func, "func.end");
LLVMPositionBuilderAtEnd(builder, end_block); LLVMPositionBuilderAtEnd(builder, end_block);
LLVMValueRef llvm_return = NULL;
if (func->kind == FunctionDeclarationKind) {
if (func->impl.declaration.return_value != NULL) {
err = get_type_default_value(unit, global_scope, func->impl.declaration.return_value, &llvm_return);
if (err.kind != Success) {
return err;
}
LLVMBuildRet(builder, llvm_return);
}else {
LLVMBuildRetVoid(builder); LLVMBuildRetVoid(builder);
}
} else {
if (func->impl.definition.return_value != NULL) {
err = get_type_default_value(unit, global_scope, func->impl.definition.return_value, &llvm_return);
if (err.kind != Success) {
return err;
}
LLVMBuildRet(builder, llvm_return);
} else {
LLVMBuildRetVoid(builder);
}
}
LLVMPositionBuilderAtEnd(builder, llvm_end_body_block); LLVMPositionBuilderAtEnd(builder, llvm_end_body_block);
LLVMBuildBr(builder, end_block); LLVMBuildBr(builder, end_block);
}
LLVMDisposeBuilder(builder); LLVMDisposeBuilder(builder);
} }
@ -247,3 +284,83 @@ BackendError impl_functions(LLVMBackendCompileUnit* unit,
return err; return err;
} }
gboolean is_parameter_out(Parameter *param) {
gboolean is_out = FALSE;
if (param->kind == ParameterDeclarationKind) {
is_out = param->impl.declaration.qualifier == Out || param->impl.declaration.qualifier == InOut;
} else {
is_out = param->impl.definiton.declaration.qualifier == Out ||
param->impl.definiton.declaration.qualifier == InOut;
}
return is_out;
}
BackendError impl_func_call(LLVMBackendCompileUnit *unit,
LLVMBuilderRef builder, LLVMLocalScope *scope,
const FunctionCall *call,
LLVMValueRef* return_value) {
DEBUG("implementing function call...");
BackendError err = SUCCESS;
LLVMValueRef* arguments = NULL;
// prevent memory allocation when number of bytes would be zero
// avoid going of assertion in memory cache
if (call->expressions->len > 0) {
arguments = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef) * call->expressions->len);
for (size_t i = 0; i < call->expressions->len; i++) {
Expression *arg = g_array_index(call->expressions, Expression*, i);
GArray* param_list;
if (call->function->kind == FunctionDeclarationKind) {
param_list = call->function->impl.definition.parameter;
} else {
param_list = call->function->impl.declaration.parameter;
}
Parameter param = g_array_index(param_list, Parameter, i);
LLVMValueRef llvm_arg = NULL;
err = impl_expr(unit, scope, builder, arg, is_parameter_out(&param), 0, &llvm_arg);
if (err.kind != Success) {
break;
}
if (is_parameter_out(&param)) {
if ((arg->kind == ExpressionKindParameter && !is_parameter_out(arg->impl.parameter)) || arg->kind != ExpressionKindParameter) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), 0, false);
LLVMTypeRef llvm_type = NULL;
get_type_impl(unit, scope->func_scope->global_scope, param.impl.declaration.type, &llvm_type);
llvm_arg = LLVMBuildGEP2(builder, llvm_type, llvm_arg, &index, 1, "");
}
}
arguments[i] = llvm_arg;
}
}
if (err.kind == Success) {
LLVMValueRef llvm_func = LLVMGetNamedFunction(unit->module, call->function->name);
if (llvm_func == NULL) {
return new_backend_impl_error(Implementation, NULL, "no declared function");
}
LLVMTypeRef llvm_func_type = g_hash_table_lookup(scope->func_scope->global_scope->functions, call->function->name);
LLVMValueRef value = LLVMBuildCall2(builder, llvm_func_type, llvm_func, arguments, call->expressions->len,
"");
if (NULL != return_value) {
*return_value = value;
}
}
return err;
}

View File

@ -40,4 +40,9 @@ BackendError impl_functions(LLVMBackendCompileUnit* unit,
LLVMGlobalScope* scope, LLVMGlobalScope* scope,
GHashTable* variables); GHashTable* variables);
BackendError impl_func_call(LLVMBackendCompileUnit *unit,
LLVMBuilderRef builder, LLVMLocalScope *scope,
const FunctionCall *call,
LLVMValueRef* return_value);
#endif // LLVM_BACKEND_FUNC_H_ #endif // LLVM_BACKEND_FUNC_H_

View File

@ -141,6 +141,8 @@ BackendError impl_basic_block(LLVMBackendCompileUnit *unit,
LLVMBasicBlockRef end_previous_block = *llvm_start_block; LLVMBasicBlockRef end_previous_block = *llvm_start_block;
bool terminated = false;
for (size_t i = 0; i < block->statemnts->len; i++) { for (size_t i = 0; i < block->statemnts->len; i++) {
DEBUG("building block statement %d of %d", i, block->statemnts->len); DEBUG("building block statement %d of %d", i, block->statemnts->len);
Statement* stmt = g_array_index(block->statemnts, Statement*, i); Statement* stmt = g_array_index(block->statemnts, Statement*, i);
@ -152,12 +154,20 @@ BackendError impl_basic_block(LLVMBackendCompileUnit *unit,
return err; return err;
} }
if (llvm_next_end_block != NULL) { terminated = LLVMGetBasicBlockTerminator(end_previous_block);
if (llvm_next_end_block != NULL && !terminated) {
LLVMPositionBuilderAtEnd(builder, end_previous_block); LLVMPositionBuilderAtEnd(builder, end_previous_block);
LLVMBuildBr(builder, llvm_next_start_block); LLVMBuildBr(builder, llvm_next_start_block);
LLVMPositionBuilderAtEnd(builder, llvm_next_end_block); LLVMPositionBuilderAtEnd(builder, llvm_next_end_block);
end_previous_block = llvm_next_end_block; end_previous_block = llvm_next_end_block;
} }
if (terminated) {
end_previous_block = LLVMAppendBasicBlockInContext(unit->context, scope->func_scope->llvm_func,
"ret.after");
LLVMPositionBuilderAtEnd(builder, end_previous_block);
}
} }
*llvm_end_block = end_previous_block; *llvm_end_block = end_previous_block;
@ -213,80 +223,6 @@ BackendError impl_while(LLVMBackendCompileUnit *unit,
return err; return err;
} }
gboolean is_parameter_out(Parameter *param) {
gboolean is_out = FALSE;
if (param->kind == ParameterDeclarationKind) {
is_out = param->impl.declaration.qualifier == Out || param->impl.declaration.qualifier == InOut;
} else {
is_out = param->impl.definiton.declaration.qualifier == Out ||
param->impl.definiton.declaration.qualifier == InOut;
}
return is_out;
}
BackendError impl_func_call(LLVMBackendCompileUnit *unit,
LLVMBuilderRef builder, LLVMLocalScope *scope,
const FunctionCall *call) {
DEBUG("implementing function call...");
BackendError err = SUCCESS;
LLVMValueRef* arguments = NULL;
// prevent memory allocation when number of bytes would be zero
// avoid going of assertion in memory cache
if (call->expressions->len > 0) {
arguments = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef) * call->expressions->len);
for (size_t i = 0; i < call->expressions->len; i++) {
Expression *arg = g_array_index(call->expressions, Expression*, i);
GArray* param_list;
if (call->function->kind == FunctionDeclarationKind) {
param_list = call->function->impl.definition.parameter;
} else {
param_list = call->function->impl.declaration.parameter;
}
Parameter param = g_array_index(param_list, Parameter, i);
LLVMValueRef llvm_arg = NULL;
err = impl_expr(unit, scope, builder, arg, is_parameter_out(&param), 0, &llvm_arg);
if (err.kind != Success) {
break;
}
if (is_parameter_out(&param)) {
if ((arg->kind == ExpressionKindParameter && !is_parameter_out(arg->impl.parameter)) || arg->kind != ExpressionKindParameter) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), 0, false);
LLVMTypeRef llvm_type = NULL;
get_type_impl(unit, scope->func_scope->global_scope, param.impl.declaration.type, &llvm_type);
llvm_arg = LLVMBuildGEP2(builder, llvm_type, llvm_arg, &index, 1, "");
}
}
arguments[i] = llvm_arg;
}
}
if (err.kind == Success) {
LLVMValueRef llvm_func = LLVMGetNamedFunction(unit->module, call->function->name);
if (llvm_func == NULL) {
return new_backend_impl_error(Implementation, NULL, "no declared function");
}
LLVMTypeRef llvm_func_type = g_hash_table_lookup(scope->func_scope->global_scope->functions, call->function->name);
LLVMBuildCall2(builder, llvm_func_type, llvm_func, arguments, call->expressions->len,
"");
}
return err;
}
BackendError BackendError
impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Expression *cond, impl_cond_block(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLVMLocalScope *scope, Expression *cond,
const Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *start_body_block, LLVMBasicBlockRef *end_body_block, const Block *block, LLVMBasicBlockRef *cond_block, LLVMBasicBlockRef *start_body_block, LLVMBasicBlockRef *end_body_block,
@ -432,6 +368,23 @@ BackendError impl_decl(LLVMBackendCompileUnit *unit,
return err; return err;
} }
BackendError impl_return(LLVMBackendCompileUnit *unit,
LLVMBuilderRef builder,
LLVMLocalScope *scope,
Return *returnStmt) {
BackendError err = SUCCESS;
LLVMValueRef expr = NULL;
err = impl_expr(unit, scope, builder, returnStmt->value, false, 0, &expr);
if (err.kind != Success) {
return err;
}
LLVMBuildRet(builder, expr);
return err;
}
BackendError impl_def(LLVMBackendCompileUnit *unit, BackendError impl_def(LLVMBackendCompileUnit *unit,
LLVMBuilderRef builder, LLVMBuilderRef builder,
LLVMLocalScope *scope, LLVMLocalScope *scope,
@ -502,7 +455,10 @@ BackendError impl_stmt(LLVMBackendCompileUnit *unit, LLVMBuilderRef builder, LLV
err = impl_while(unit, builder, scope, llvm_start_block, llvm_end_block, &stmt->impl.whileLoop); err = impl_while(unit, builder, scope, llvm_start_block, llvm_end_block, &stmt->impl.whileLoop);
break; break;
case StatementKindFunctionCall: case StatementKindFunctionCall:
err = impl_func_call(unit, builder, scope, &stmt->impl.call); err = impl_func_call(unit, builder, scope, &stmt->impl.call, NULL);
break;
case StatementKindReturn:
err = impl_return(unit, builder, scope, &stmt->impl.returnStmt);
break; break;
default: default:
err = new_backend_impl_error(Implementation, NULL, "Unexpected statement kind"); err = new_backend_impl_error(Implementation, NULL, "Unexpected statement kind");

View File

@ -1463,6 +1463,8 @@ IO_Qualifier getParameterQualifier(Parameter *parameter) {
} }
} }
int createfuncall(FunctionCall* funcall, AST_NODE_PTR currentNode);
Expression *createExpression(AST_NODE_PTR currentNode) { Expression *createExpression(AST_NODE_PTR currentNode) {
DEBUG("create Expression"); DEBUG("create Expression");
Expression *expression = mem_alloc(MemoryNamespaceSet, sizeof(Expression)); Expression *expression = mem_alloc(MemoryNamespaceSet, sizeof(Expression));
@ -1595,6 +1597,14 @@ Expression *createExpression(AST_NODE_PTR currentNode) {
return NULL; return NULL;
} }
break; break;
case AST_Call:
expression->kind = ExpressionKindFunctionCall;
expression->impl.call = mem_alloc(MemoryNamespaceSet, sizeof(FunctionCall));
if (createfuncall(expression->impl.call, currentNode) == SEMANTIC_ERROR) {
return NULL;
}
expression->result = SET_function_get_return_type(expression->impl.call->function);
break;
default: default:
PANIC("Node is not an expression but from kind: %i", currentNode->kind); PANIC("Node is not an expression but from kind: %i", currentNode->kind);
break; break;
@ -1901,14 +1911,13 @@ Parameter get_param_from_func(Function* func, size_t index) {
} }
} }
int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) { int createfuncall(FunctionCall* funcall, AST_NODE_PTR currentNode) {
assert(currentNode != NULL); assert(currentNode != NULL);
assert(currentNode->children->len == 2); assert(currentNode->children->len == 2);
AST_NODE_PTR argsListNode = AST_get_node(currentNode, 1); AST_NODE_PTR argsListNode = AST_get_node(currentNode, 1);
AST_NODE_PTR nameNode = AST_get_node(currentNode, 0); AST_NODE_PTR nameNode = AST_get_node(currentNode, 0);
FunctionCall funcall;
Function *fun = NULL; Function *fun = NULL;
if (nameNode->kind == AST_Ident) { if (nameNode->kind == AST_Ident) {
int result = getFunction(nameNode->value, &fun); int result = getFunction(nameNode->value, &fun);
@ -1934,8 +1943,8 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
} }
} }
funcall.function = fun; funcall->function = fun;
funcall.nodePtr = currentNode; funcall->nodePtr = currentNode;
size_t paramCount = 0; size_t paramCount = 0;
if (fun->kind == FunctionDeclarationKind) { if (fun->kind == FunctionDeclarationKind) {
@ -1980,10 +1989,7 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
g_array_append_val(expressions, expr); g_array_append_val(expressions, expr);
} }
} }
funcall.expressions = expressions; funcall->expressions = expressions;
parentStatement->kind = StatementKindFunctionCall;
parentStatement->impl.call = funcall;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
@ -2059,18 +2065,37 @@ int createStatement(Block *Parentblock, AST_NODE_PTR currentNode) {
g_array_append_val(Parentblock->statemnts, statement); g_array_append_val(Parentblock->statemnts, statement);
} }
break; break;
case AST_Call: case AST_Call: {
Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement));
statement->nodePtr = currentNode; statement->nodePtr = currentNode;
statement->kind = StatementKindFunctionCall; statement->kind = StatementKindFunctionCall;
int result = createfuncall(statement, currentNode); int result = createfuncall(&statement->impl.call, currentNode);
if (result == SEMANTIC_ERROR) { if (result == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
g_array_append_val(Parentblock->statemnts, statement); g_array_append_val(Parentblock->statemnts, statement);
break; break;
}
case AST_Return: {
Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement));
statement->nodePtr = currentNode;
statement->kind = StatementKindReturn;
AST_NODE_PTR expr_node = AST_get_node(currentNode, 0);
statement->impl.returnStmt.value = createExpression(expr_node);
statement->impl.returnStmt.nodePtr = currentNode;
if (statement->impl.returnStmt.value == NULL) {
return SEMANTIC_ERROR;
}
// TODO: compare result and function return type
g_array_append_val(Parentblock->statemnts, statement);
break;
}
default: default:
PANIC("Node is not a statement"); PANIC("Node is not a statement: %s", AST_node_to_string(currentNode));
break; break;
} }
@ -2129,8 +2154,9 @@ int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) {
int createFunDef(Function *Parentfunction, AST_NODE_PTR currentNode) { int createFunDef(Function *Parentfunction, AST_NODE_PTR currentNode) {
DEBUG("start fundef"); DEBUG("start fundef");
AST_NODE_PTR nameNode = AST_get_node(currentNode, 0); AST_NODE_PTR nameNode = AST_get_node(currentNode, 0);
AST_NODE_PTR paramlistlist = AST_get_node(currentNode, 1); AST_NODE_PTR return_value_node = AST_get_node(currentNode, 1);
AST_NODE_PTR statementlist = AST_get_node(currentNode, 2); AST_NODE_PTR paramlistlist = AST_get_node(currentNode, 2);
AST_NODE_PTR statementlist = AST_get_node(currentNode, 3);
FunctionDefinition fundef; FunctionDefinition fundef;
@ -2138,6 +2164,12 @@ int createFunDef(Function *Parentfunction, AST_NODE_PTR currentNode) {
fundef.name = nameNode->value; fundef.name = nameNode->value;
fundef.body = mem_alloc(MemoryNamespaceSet, sizeof(Block)); fundef.body = mem_alloc(MemoryNamespaceSet, sizeof(Block));
fundef.parameter = mem_new_g_array(MemoryNamespaceSet, sizeof(Parameter)); fundef.parameter = mem_new_g_array(MemoryNamespaceSet, sizeof(Parameter));
fundef.return_value = NULL;
if (set_get_type_impl(return_value_node, &fundef.return_value) == SEMANTIC_ERROR) {
print_diagnostic(&return_value_node->location, Error, "Unknown return value type");
return SEMANTIC_ERROR;
}
DEBUG("paramlistlist child count: %i", paramlistlist->children->len); DEBUG("paramlistlist child count: %i", paramlistlist->children->len);
for (size_t i = 0; i < paramlistlist->children->len; i++) { for (size_t i = 0; i < paramlistlist->children->len; i++) {
@ -2237,7 +2269,49 @@ int getFunction(const char *name, Function **function) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
int createFunDecl(Function *Parentfunction, AST_NODE_PTR currentNode) { int createProcDef(Function *Parentfunction, AST_NODE_PTR currentNode) {
DEBUG("start fundef");
AST_NODE_PTR nameNode = AST_get_node(currentNode, 0);
AST_NODE_PTR paramlistlist = AST_get_node(currentNode, 1);
AST_NODE_PTR statementlist = AST_get_node(currentNode, 2);
FunctionDefinition fundef;
fundef.nodePtr = currentNode;
fundef.name = nameNode->value;
fundef.body = mem_alloc(MemoryNamespaceSet, sizeof(Block));
fundef.parameter = mem_new_g_array(MemoryNamespaceSet, sizeof(Parameter));
fundef.return_value = NULL;
DEBUG("paramlistlist child count: %i", paramlistlist->children->len);
for (size_t i = 0; i < paramlistlist->children->len; i++) {
//all parameterlists
AST_NODE_PTR paramlist = AST_get_node(paramlistlist, i);
DEBUG("paramlist child count: %i", paramlist->children->len);
for (int j = ((int) paramlist->children->len) - 1; j >= 0; j--) {
DEBUG("param child count: %i", AST_get_node(paramlist, j)->children->len);
if (createParam(fundef.parameter, AST_get_node(paramlist, j))) {
return SEMANTIC_ERROR;
}
}
DEBUG("End of Paramlist");
}
if (fillBlock(fundef.body, statementlist)) {
return SEMANTIC_ERROR;
}
Parentfunction->nodePtr = currentNode;
Parentfunction->kind = FunctionDefinitionKind;
Parentfunction->impl.definition = fundef;
Parentfunction->name = fundef.name;
return SEMANTIC_OK;
}
int createProcDecl(Function *Parentfunction, AST_NODE_PTR currentNode) {
DEBUG("start fundecl"); DEBUG("start fundecl");
AST_NODE_PTR nameNode = AST_get_node(currentNode, 0); AST_NODE_PTR nameNode = AST_get_node(currentNode, 0);
AST_NODE_PTR paramlistlist = AST_get_node(currentNode, 1); AST_NODE_PTR paramlistlist = AST_get_node(currentNode, 1);
@ -2247,6 +2321,46 @@ int createFunDecl(Function *Parentfunction, AST_NODE_PTR currentNode) {
fundecl.nodePtr = currentNode; fundecl.nodePtr = currentNode;
fundecl.name = nameNode->value; fundecl.name = nameNode->value;
fundecl.parameter = mem_new_g_array(MemoryNamespaceSet, sizeof(Parameter)); fundecl.parameter = mem_new_g_array(MemoryNamespaceSet, sizeof(Parameter));
fundecl.return_value = NULL;
for (size_t i = 0; i < paramlistlist->children->len; i++) {
//all parameter lists
AST_NODE_PTR paramlist = AST_get_node(paramlistlist, i);
for (int j = ((int) paramlist->children->len) - 1; j >= 0; j--) {
AST_NODE_PTR param = AST_get_node(paramlist, j);
if (createParam(fundecl.parameter, param)) {
return SEMANTIC_ERROR;
}
}
}
Parentfunction->nodePtr = currentNode;
Parentfunction->kind = FunctionDeclarationKind;
Parentfunction->impl.declaration = fundecl;
Parentfunction->name = fundecl.name;
return SEMANTIC_OK;
}
int createFunDecl(Function *Parentfunction, AST_NODE_PTR currentNode) {
DEBUG("start fundecl");
AST_NODE_PTR nameNode = AST_get_node(currentNode, 0);
AST_NODE_PTR return_value_node = AST_get_node(currentNode, 1);
AST_NODE_PTR paramlistlist = AST_get_node(currentNode, 2);
FunctionDeclaration fundecl;
fundecl.nodePtr = currentNode;
fundecl.name = nameNode->value;
fundecl.parameter = mem_new_g_array(MemoryNamespaceSet, sizeof(Parameter));
fundecl.return_value = NULL;
if (set_get_type_impl(return_value_node, &fundecl.return_value) == SEMANTIC_ERROR) {
print_diagnostic(&return_value_node->location, Error, "Unknown return value type");
return SEMANTIC_ERROR;
}
for (size_t i = 0; i < paramlistlist->children->len; i++) { for (size_t i = 0; i < paramlistlist->children->len; i++) {
@ -2270,21 +2384,32 @@ int createFunDecl(Function *Parentfunction, AST_NODE_PTR currentNode) {
} }
int createFunction(Function *function, AST_NODE_PTR currentNode) { int createFunction(Function *function, AST_NODE_PTR currentNode) {
assert(currentNode->kind == AST_Fun);
functionParameter = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); functionParameter = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal);
if (currentNode->children->len == 2) { switch (currentNode->kind) {
int signal = createFunDecl(function, currentNode); case AST_FunDecl:
if (signal) { if (createFunDecl(function, currentNode)) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} else if (currentNode->children->len == 3) { break;
int signal = createFunDef(function, currentNode); case AST_FunDef:
if (signal) { if (createFunDef(function, currentNode)) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} else { break;
PANIC("function should have 2 or 3 children"); case AST_ProcDecl:
if (createProcDecl(function, currentNode)) {
return SEMANTIC_ERROR;
}
break;
case AST_ProcDef:
if (createProcDef(function, currentNode)) {
return SEMANTIC_ERROR;
}
break;
default:
ERROR("invalid AST node type: %s", AST_node_to_string(currentNode));
return SEMANTIC_ERROR;
} }
mem_free(functionParameter); mem_free(functionParameter);
@ -2400,7 +2525,7 @@ int createBox(GHashTable *boxes, AST_NODE_PTR currentNode) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
break; break;
case AST_Fun: { case AST_FunDef: {
int result = createBoxFunction(boxName, boxType, AST_get_node(boxMemberList, i)); int result = createBoxFunction(boxName, boxType, AST_get_node(boxMemberList, i));
if (result == SEMANTIC_ERROR) { if (result == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
@ -2523,7 +2648,10 @@ Module *create_set(AST_NODE_PTR currentNode) {
DEBUG("created Box successfully"); DEBUG("created Box successfully");
break; break;
} }
case AST_Fun: { case AST_FunDef:
case AST_FunDecl:
case AST_ProcDef:
case AST_ProcDecl: {
DEBUG("start function"); DEBUG("start function");
Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function)); Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function));

28
src/set/types.c Normal file
View File

@ -0,0 +1,28 @@
//
// Created by servostar on 8/4/24.
//
#include <assert.h>
#include <set/types.h>
#include <sys/log.h>
Type* SET_function_get_return_type(Function* function) {
assert(NULL != function);
const Type* return_type = NULL;
switch (function->kind) {
case FunctionDeclarationKind:
return_type = function->impl.declaration.return_value;
break;
case FunctionDefinitionKind:
return_type = function->impl.definition.return_value;
break;
default:
PANIC("invalid function kind: %d", function->kind);
}
if (NULL == return_type) {
ERROR("Function return type is nullptr");
}
}

View File

@ -213,6 +213,7 @@ typedef struct FunctionDefinition_t {
// hashtable of parameters // hashtable of parameters
// associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration)
GArray* parameter; // Parameter GArray* parameter; // Parameter
Type* return_value;
AST_NODE_PTR nodePtr; AST_NODE_PTR nodePtr;
// body of function // body of function
Block *body; Block *body;
@ -225,6 +226,7 @@ typedef struct FunctionDeclaration_t {
// associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration) // associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration)
GArray* parameter; // Parameter GArray* parameter; // Parameter
AST_NODE_PTR nodePtr; AST_NODE_PTR nodePtr;
Type* return_value;
const char* name; const char* name;
} FunctionDeclaration; } FunctionDeclaration;
@ -439,8 +441,11 @@ typedef enum ExpressionKind_t {
ExpressionKindParameter, ExpressionKindParameter,
ExpressionKindDereference, ExpressionKindDereference,
ExpressionKindAddressOf, ExpressionKindAddressOf,
ExpressionKindFunctionCall,
} ExpressionKind; } ExpressionKind;
typedef struct FunctionCall_t FunctionCall;
typedef struct Expression_t { typedef struct Expression_t {
ExpressionKind kind; ExpressionKind kind;
// type of resulting data // type of resulting data
@ -454,6 +459,7 @@ typedef struct Expression_t {
Parameter* parameter; Parameter* parameter;
Dereference dereference; Dereference dereference;
AddressOf addressOf; AddressOf addressOf;
FunctionCall* call;
} impl; } impl;
AST_NODE_PTR nodePtr; AST_NODE_PTR nodePtr;
} Expression; } Expression;
@ -554,6 +560,11 @@ typedef struct Assignment_t {
AST_NODE_PTR nodePtr; AST_NODE_PTR nodePtr;
} Assignment; } Assignment;
typedef struct Return_t {
Expression* value;
AST_NODE_PTR nodePtr;
} Return;
typedef enum StatementKind_t { typedef enum StatementKind_t {
StatementKindFunctionCall, StatementKindFunctionCall,
StatementKindFunctionBoxCall, StatementKindFunctionBoxCall,
@ -561,7 +572,8 @@ typedef enum StatementKind_t {
StatementKindBranch, StatementKindBranch,
StatementKindAssignment, StatementKindAssignment,
StatementKindDeclaration, StatementKindDeclaration,
StatementKindDefinition StatementKindDefinition,
StatementKindReturn
} StatementKind; } StatementKind;
typedef struct Statement_t { typedef struct Statement_t {
@ -573,6 +585,7 @@ typedef struct Statement_t {
Branch branch; Branch branch;
Assignment assignment; Assignment assignment;
Variable *variable; Variable *variable;
Return returnStmt;
} impl; } impl;
AST_NODE_PTR nodePtr; AST_NODE_PTR nodePtr;
} Statement; } Statement;
@ -591,6 +604,11 @@ typedef struct Module_t {
GArray* includes; GArray* includes;
} Module; } Module;
// .------------------------------------------------.
// | Utility |
// '------------------------------------------------'
Type* SET_function_get_return_type(Function* function);
// .------------------------------------------------. // .------------------------------------------------.
// | Cleanup Code | // | Cleanup Code |

View File

@ -58,6 +58,8 @@
%type <node_ptr> programbody %type <node_ptr> programbody
%type <node_ptr> fundef %type <node_ptr> fundef
%type <node_ptr> fundecl %type <node_ptr> fundecl
%type <node_ptr> procdecl
%type <node_ptr> procdef
%type <node_ptr> box %type <node_ptr> box
%type <node_ptr> typedef %type <node_ptr> typedef
%type <node_ptr> exprlist %type <node_ptr> exprlist
@ -72,7 +74,7 @@
%type <node_ptr> reinterpretcast %type <node_ptr> reinterpretcast
%type <node_ptr> program %type <node_ptr> program
%type <node_ptr> storage_expr %type <node_ptr> storage_expr
%type <node_ptr> return %type <node_ptr> returnstmt
%token KeyInt %token KeyInt
@ -151,6 +153,8 @@ programbody: moduleimport {$$ = $1;}
| moduleinclude {$$ = $1;} | moduleinclude {$$ = $1;}
| fundef{$$ = $1;} | fundef{$$ = $1;}
| fundecl{$$ = $1;} | fundecl{$$ = $1;}
| procdecl{$$ = $1;}
| procdef{$$ = $1;}
| box{$$ = $1;} | box{$$ = $1;}
| definition{$$ = $1;} | definition{$$ = $1;}
| decl{$$ = $1;} | decl{$$ = $1;}
@ -170,6 +174,7 @@ expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);}
| typecast{$$ = $1;} | typecast{$$ = $1;}
| reinterpretcast{$$ = $1;} | reinterpretcast{$$ = $1;}
| '(' expr ')' {$$=$2;} | '(' expr ')' {$$=$2;}
| funcall {$$=$1;}
| KeyRef Ident {AST_NODE_PTR addrof = AST_new_node(new_loc(), AST_AddressOf, NULL); | KeyRef Ident {AST_NODE_PTR addrof = AST_new_node(new_loc(), AST_AddressOf, NULL);
AST_push_node(addrof, AST_new_node(new_loc(), AST_Ident, $2)); AST_push_node(addrof, AST_new_node(new_loc(), AST_Ident, $2));
$$ = addrof;} $$ = addrof;}
@ -194,36 +199,40 @@ argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3);
$$ = list;}; $$ = list;};
// TODO: add ast node for definition and declaration procdef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_ProcDef, NULL);
fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2);
AST_push_node(fun, ident); AST_push_node(fun, ident);
AST_push_node(fun, $3); AST_push_node(fun, $3);
AST_push_node(fun, $5); AST_push_node(fun, $5);
$$ = fun; $$ = fun;
DEBUG("Function");} DEBUG("Function");}
| KeyFun Ident paramlist ':' type '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL);
procdecl: KeyFun Ident paramlist {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_ProcDecl, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2);
AST_push_node(fun, ident); AST_push_node(fun, ident);
AST_push_node(fun, $3); AST_push_node(fun, $3);
AST_push_node(fun, $5);
AST_push_node(fun, $7);
$$ = fun; $$ = fun;
DEBUG("Function");}; DEBUG("Function");};
fundecl: KeyFun Ident paramlist {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL); fundef: KeyFun type ':' Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_FunDef, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2); AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
AST_push_node(fun, ident); AST_push_node(fun, ident);
AST_push_node(fun, $3); AST_push_node(fun, $2);
AST_push_node(fun, $5);
AST_push_node(fun, $7);
$$ = fun; $$ = fun;
DEBUG("Function");} DEBUG("Function");}
| KeyFun Ident paramlist ':' type {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2); fundecl: KeyFun type ':' Ident paramlist {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_FunDecl, NULL);
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $4);
AST_push_node(fun, ident); AST_push_node(fun, ident);
AST_push_node(fun, $3); AST_push_node(fun, $2);
AST_push_node(fun, $5);
$$ = fun; $$ = fun;
DEBUG("Function");}; DEBUG("Function");};
paramlist: paramlist '(' params ')' {AST_push_node($1, $3); paramlist: paramlist '(' params ')' {AST_push_node($1, $3);
$$ = $1;} $$ = $1;}
| paramlist '(' ')'{$$ = $1;} | paramlist '(' ')'{$$ = $1;}
@ -365,12 +374,13 @@ statement: assign {$$ = $1;}
| definition {$$ = $1;} | definition {$$ = $1;}
| while {$$ = $1;} | while {$$ = $1;}
| branchfull {$$ = $1;} | branchfull {$$ = $1;}
| return {$$ = $1;} | returnstmt {$$ = $1;}
| funcall {$$ = $1;} | funcall {$$ = $1;}
| boxcall{$$ = $1;}; | boxcall{$$ = $1;};
return: KeyReturn expr { AST_NODE_PTR return_stmt = AST_new_node(new_loc(), AST_Return, NULL); returnstmt: KeyReturn expr { AST_NODE_PTR return_stmt = AST_new_node(new_loc(), AST_Return, NULL);
AST_push_node(return_stmt, $2); }; AST_push_node(return_stmt, $2);
$$ = return_stmt; };
branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_If, NULL); branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_If, NULL);
AST_push_node(branch, $2); AST_push_node(branch, $2);

View File

@ -1,7 +1,7 @@
import "std" import "std"
fun ulog10(in u32: num, out u32: log) fun u32:ulog10(in u32: num)
{ {
u32: base = 1 as u32 u32: base = 1 as u32
u32: count = 0 as u32 u32: count = 0 as u32
@ -16,13 +16,12 @@ fun ulog10(in u32: num, out u32: log)
count = 1 as u32 count = 1 as u32
} }
log = count ret count
} }
fun u32ToCstr(in u32: number)(out cstr: result, out u32: len) fun u32ToCstr(in u32: number)(out cstr: result, out u32: len)
{ {
u32: bytes = 0 as u32 u32: bytes = ulog10(number)
ulog10(number, bytes)
cstr: buf = 0 as cstr cstr: buf = 0 as cstr
heapAlloc(bytes)(buf as ref u8) heapAlloc(bytes)(buf as ref u8)
@ -92,10 +91,8 @@ fun test_matrix()
heapFree(matrix as ref u8) heapFree(matrix as ref u8)
} }
fun main(): u32 fun i32:main()
{ {
test_matrix() test_matrix()
exit_code = 0
ret 0 ret 0
} }