added function return type
This commit is contained in:
parent
53840881d7
commit
b786b3e156
|
@ -67,7 +67,10 @@ void AST_init() {
|
|||
|
||||
lookup_table[AST_Typedef] = "typedef";
|
||||
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_Typecast] = "typecast";
|
||||
|
|
|
@ -57,7 +57,10 @@ enum AST_SyntaxElement_t {
|
|||
// Defintions
|
||||
AST_Typedef,
|
||||
AST_Box,
|
||||
AST_Fun,
|
||||
AST_FunDecl,
|
||||
AST_FunDef,
|
||||
AST_ProcDecl,
|
||||
AST_ProcDef,
|
||||
AST_Import,
|
||||
// amount of variants
|
||||
// in this enums
|
||||
|
|
|
@ -524,6 +524,9 @@ BackendError impl_expr(LLVMBackendCompileUnit *unit, LLVMLocalScope *scope,
|
|||
deref_depth,
|
||||
llvm_result);
|
||||
break;
|
||||
case ExpressionKindFunctionCall:
|
||||
err = impl_func_call(unit, builder, scope, expr->impl.call, llvm_result);
|
||||
break;
|
||||
default:
|
||||
err = new_backend_impl_error(Implementation, NULL, "unknown expression");
|
||||
break;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <set/types.h>
|
||||
#include <sys/log.h>
|
||||
#include <mem/cache.h>
|
||||
#include <llvm/llvm-ir/expr.h>
|
||||
|
||||
LLVMLocalScope* new_local_scope(LLVMLocalScope* parent) {
|
||||
LLVMLocalScope* scope = malloc(sizeof(LLVMLocalScope));
|
||||
|
@ -127,8 +128,19 @@ BackendError impl_func_type(LLVMBackendCompileUnit* unit,
|
|||
|
||||
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 =
|
||||
LLVMFunctionType(LLVMVoidTypeInContext(unit->context),
|
||||
LLVMFunctionType(llvm_return_type,
|
||||
(LLVMTypeRef*)llvm_params->data, llvm_params->len, 0);
|
||||
|
||||
*llvm_fun = LLVMAddFunction(unit->module, func->name, llvm_fun_type);
|
||||
|
@ -180,14 +192,39 @@ BackendError impl_func_def(LLVMBackendCompileUnit* unit,
|
|||
LLVMPositionBuilderAtEnd(builder, entry);
|
||||
LLVMBuildBr(builder, llvm_start_body_block);
|
||||
|
||||
LLVMValueRef terminator = LLVMGetBasicBlockTerminator(llvm_end_body_block);
|
||||
if (terminator == NULL) {
|
||||
// insert returning end block
|
||||
LLVMBasicBlockRef end_block =
|
||||
LLVMAppendBasicBlockInContext(unit->context, llvm_func, "func.end");
|
||||
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);
|
||||
}
|
||||
} 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);
|
||||
LLVMBuildBr(builder, end_block);
|
||||
}
|
||||
|
||||
LLVMDisposeBuilder(builder);
|
||||
}
|
||||
|
@ -247,3 +284,83 @@ BackendError impl_functions(LLVMBackendCompileUnit* unit,
|
|||
|
||||
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(¶m), 0, &llvm_arg);
|
||||
|
||||
if (err.kind != Success) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_parameter_out(¶m)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,4 +40,9 @@ BackendError impl_functions(LLVMBackendCompileUnit* unit,
|
|||
LLVMGlobalScope* scope,
|
||||
GHashTable* variables);
|
||||
|
||||
BackendError impl_func_call(LLVMBackendCompileUnit *unit,
|
||||
LLVMBuilderRef builder, LLVMLocalScope *scope,
|
||||
const FunctionCall *call,
|
||||
LLVMValueRef* return_value);
|
||||
|
||||
#endif // LLVM_BACKEND_FUNC_H_
|
||||
|
|
|
@ -141,6 +141,8 @@ BackendError impl_basic_block(LLVMBackendCompileUnit *unit,
|
|||
|
||||
LLVMBasicBlockRef end_previous_block = *llvm_start_block;
|
||||
|
||||
bool terminated = false;
|
||||
|
||||
for (size_t i = 0; i < block->statemnts->len; i++) {
|
||||
DEBUG("building block statement %d of %d", i, block->statemnts->len);
|
||||
Statement* stmt = g_array_index(block->statemnts, Statement*, i);
|
||||
|
@ -152,12 +154,20 @@ BackendError impl_basic_block(LLVMBackendCompileUnit *unit,
|
|||
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);
|
||||
LLVMBuildBr(builder, llvm_next_start_block);
|
||||
|
||||
LLVMPositionBuilderAtEnd(builder, 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;
|
||||
|
@ -213,80 +223,6 @@ BackendError impl_while(LLVMBackendCompileUnit *unit,
|
|||
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(¶m), 0, &llvm_arg);
|
||||
|
||||
if (err.kind != Success) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_parameter_out(¶m)) {
|
||||
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
|
||||
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,
|
||||
|
@ -432,6 +368,23 @@ BackendError impl_decl(LLVMBackendCompileUnit *unit,
|
|||
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,
|
||||
LLVMBuilderRef builder,
|
||||
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);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
err = new_backend_impl_error(Implementation, NULL, "Unexpected statement kind");
|
||||
|
|
178
src/set/set.c
178
src/set/set.c
|
@ -1463,6 +1463,8 @@ IO_Qualifier getParameterQualifier(Parameter *parameter) {
|
|||
}
|
||||
}
|
||||
|
||||
int createfuncall(FunctionCall* funcall, AST_NODE_PTR currentNode);
|
||||
|
||||
Expression *createExpression(AST_NODE_PTR currentNode) {
|
||||
DEBUG("create Expression");
|
||||
Expression *expression = mem_alloc(MemoryNamespaceSet, sizeof(Expression));
|
||||
|
@ -1595,6 +1597,14 @@ Expression *createExpression(AST_NODE_PTR currentNode) {
|
|||
return NULL;
|
||||
}
|
||||
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:
|
||||
PANIC("Node is not an expression but from kind: %i", currentNode->kind);
|
||||
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->children->len == 2);
|
||||
|
||||
AST_NODE_PTR argsListNode = AST_get_node(currentNode, 1);
|
||||
AST_NODE_PTR nameNode = AST_get_node(currentNode, 0);
|
||||
|
||||
FunctionCall funcall;
|
||||
Function *fun = NULL;
|
||||
if (nameNode->kind == AST_Ident) {
|
||||
int result = getFunction(nameNode->value, &fun);
|
||||
|
@ -1934,8 +1943,8 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
|
|||
}
|
||||
}
|
||||
|
||||
funcall.function = fun;
|
||||
funcall.nodePtr = currentNode;
|
||||
funcall->function = fun;
|
||||
funcall->nodePtr = currentNode;
|
||||
|
||||
size_t paramCount = 0;
|
||||
if (fun->kind == FunctionDeclarationKind) {
|
||||
|
@ -1980,10 +1989,7 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
|
|||
g_array_append_val(expressions, expr);
|
||||
}
|
||||
}
|
||||
funcall.expressions = expressions;
|
||||
|
||||
parentStatement->kind = StatementKindFunctionCall;
|
||||
parentStatement->impl.call = funcall;
|
||||
funcall->expressions = expressions;
|
||||
return SEMANTIC_OK;
|
||||
}
|
||||
|
||||
|
@ -2059,18 +2065,37 @@ int createStatement(Block *Parentblock, AST_NODE_PTR currentNode) {
|
|||
g_array_append_val(Parentblock->statemnts, statement);
|
||||
}
|
||||
break;
|
||||
case AST_Call:
|
||||
case AST_Call: {
|
||||
Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement));
|
||||
statement->nodePtr = currentNode;
|
||||
statement->kind = StatementKindFunctionCall;
|
||||
int result = createfuncall(statement, currentNode);
|
||||
int result = createfuncall(&statement->impl.call, currentNode);
|
||||
if (result == SEMANTIC_ERROR) {
|
||||
return SEMANTIC_ERROR;
|
||||
}
|
||||
g_array_append_val(Parentblock->statemnts, statement);
|
||||
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:
|
||||
PANIC("Node is not a statement");
|
||||
PANIC("Node is not a statement: %s", AST_node_to_string(currentNode));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2129,8 +2154,9 @@ int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) {
|
|||
int createFunDef(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);
|
||||
AST_NODE_PTR return_value_node = AST_get_node(currentNode, 1);
|
||||
AST_NODE_PTR paramlistlist = AST_get_node(currentNode, 2);
|
||||
AST_NODE_PTR statementlist = AST_get_node(currentNode, 3);
|
||||
|
||||
FunctionDefinition fundef;
|
||||
|
||||
|
@ -2138,6 +2164,12 @@ int createFunDef(Function *Parentfunction, AST_NODE_PTR 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;
|
||||
|
||||
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);
|
||||
for (size_t i = 0; i < paramlistlist->children->len; i++) {
|
||||
|
@ -2237,7 +2269,49 @@ int getFunction(const char *name, Function **function) {
|
|||
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");
|
||||
AST_NODE_PTR nameNode = AST_get_node(currentNode, 0);
|
||||
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.name = nameNode->value;
|
||||
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++) {
|
||||
|
||||
|
@ -2270,21 +2384,32 @@ int createFunDecl(Function *Parentfunction, 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);
|
||||
|
||||
if (currentNode->children->len == 2) {
|
||||
int signal = createFunDecl(function, currentNode);
|
||||
if (signal) {
|
||||
switch (currentNode->kind) {
|
||||
case AST_FunDecl:
|
||||
if (createFunDecl(function, currentNode)) {
|
||||
return SEMANTIC_ERROR;
|
||||
}
|
||||
} else if (currentNode->children->len == 3) {
|
||||
int signal = createFunDef(function, currentNode);
|
||||
if (signal) {
|
||||
break;
|
||||
case AST_FunDef:
|
||||
if (createFunDef(function, currentNode)) {
|
||||
return SEMANTIC_ERROR;
|
||||
}
|
||||
} else {
|
||||
PANIC("function should have 2 or 3 children");
|
||||
break;
|
||||
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);
|
||||
|
@ -2400,7 +2525,7 @@ int createBox(GHashTable *boxes, AST_NODE_PTR currentNode) {
|
|||
return SEMANTIC_ERROR;
|
||||
}
|
||||
break;
|
||||
case AST_Fun: {
|
||||
case AST_FunDef: {
|
||||
int result = createBoxFunction(boxName, boxType, AST_get_node(boxMemberList, i));
|
||||
if (result == SEMANTIC_ERROR) {
|
||||
return SEMANTIC_ERROR;
|
||||
|
@ -2523,7 +2648,10 @@ Module *create_set(AST_NODE_PTR currentNode) {
|
|||
DEBUG("created Box successfully");
|
||||
break;
|
||||
}
|
||||
case AST_Fun: {
|
||||
case AST_FunDef:
|
||||
case AST_FunDecl:
|
||||
case AST_ProcDef:
|
||||
case AST_ProcDecl: {
|
||||
DEBUG("start function");
|
||||
Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function));
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -213,6 +213,7 @@ typedef struct FunctionDefinition_t {
|
|||
// hashtable of parameters
|
||||
// associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration)
|
||||
GArray* parameter; // Parameter
|
||||
Type* return_value;
|
||||
AST_NODE_PTR nodePtr;
|
||||
// body of function
|
||||
Block *body;
|
||||
|
@ -225,6 +226,7 @@ typedef struct FunctionDeclaration_t {
|
|||
// associates a parameters name (const char*) with its parameter declaration (ParameterDeclaration)
|
||||
GArray* parameter; // Parameter
|
||||
AST_NODE_PTR nodePtr;
|
||||
Type* return_value;
|
||||
const char* name;
|
||||
} FunctionDeclaration;
|
||||
|
||||
|
@ -439,8 +441,11 @@ typedef enum ExpressionKind_t {
|
|||
ExpressionKindParameter,
|
||||
ExpressionKindDereference,
|
||||
ExpressionKindAddressOf,
|
||||
ExpressionKindFunctionCall,
|
||||
} ExpressionKind;
|
||||
|
||||
typedef struct FunctionCall_t FunctionCall;
|
||||
|
||||
typedef struct Expression_t {
|
||||
ExpressionKind kind;
|
||||
// type of resulting data
|
||||
|
@ -454,6 +459,7 @@ typedef struct Expression_t {
|
|||
Parameter* parameter;
|
||||
Dereference dereference;
|
||||
AddressOf addressOf;
|
||||
FunctionCall* call;
|
||||
} impl;
|
||||
AST_NODE_PTR nodePtr;
|
||||
} Expression;
|
||||
|
@ -554,6 +560,11 @@ typedef struct Assignment_t {
|
|||
AST_NODE_PTR nodePtr;
|
||||
} Assignment;
|
||||
|
||||
typedef struct Return_t {
|
||||
Expression* value;
|
||||
AST_NODE_PTR nodePtr;
|
||||
} Return;
|
||||
|
||||
typedef enum StatementKind_t {
|
||||
StatementKindFunctionCall,
|
||||
StatementKindFunctionBoxCall,
|
||||
|
@ -561,7 +572,8 @@ typedef enum StatementKind_t {
|
|||
StatementKindBranch,
|
||||
StatementKindAssignment,
|
||||
StatementKindDeclaration,
|
||||
StatementKindDefinition
|
||||
StatementKindDefinition,
|
||||
StatementKindReturn
|
||||
} StatementKind;
|
||||
|
||||
typedef struct Statement_t {
|
||||
|
@ -573,6 +585,7 @@ typedef struct Statement_t {
|
|||
Branch branch;
|
||||
Assignment assignment;
|
||||
Variable *variable;
|
||||
Return returnStmt;
|
||||
} impl;
|
||||
AST_NODE_PTR nodePtr;
|
||||
} Statement;
|
||||
|
@ -591,6 +604,11 @@ typedef struct Module_t {
|
|||
GArray* includes;
|
||||
} Module;
|
||||
|
||||
// .------------------------------------------------.
|
||||
// | Utility |
|
||||
// '------------------------------------------------'
|
||||
|
||||
Type* SET_function_get_return_type(Function* function);
|
||||
|
||||
// .------------------------------------------------.
|
||||
// | Cleanup Code |
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
%type <node_ptr> programbody
|
||||
%type <node_ptr> fundef
|
||||
%type <node_ptr> fundecl
|
||||
%type <node_ptr> procdecl
|
||||
%type <node_ptr> procdef
|
||||
%type <node_ptr> box
|
||||
%type <node_ptr> typedef
|
||||
%type <node_ptr> exprlist
|
||||
|
@ -72,7 +74,7 @@
|
|||
%type <node_ptr> reinterpretcast
|
||||
%type <node_ptr> program
|
||||
%type <node_ptr> storage_expr
|
||||
%type <node_ptr> return
|
||||
%type <node_ptr> returnstmt
|
||||
|
||||
|
||||
%token KeyInt
|
||||
|
@ -151,6 +153,8 @@ programbody: moduleimport {$$ = $1;}
|
|||
| moduleinclude {$$ = $1;}
|
||||
| fundef{$$ = $1;}
|
||||
| fundecl{$$ = $1;}
|
||||
| procdecl{$$ = $1;}
|
||||
| procdef{$$ = $1;}
|
||||
| box{$$ = $1;}
|
||||
| definition{$$ = $1;}
|
||||
| decl{$$ = $1;}
|
||||
|
@ -170,6 +174,7 @@ expr: ValFloat {$$ = AST_new_node(new_loc(), AST_Float, $1);}
|
|||
| typecast{$$ = $1;}
|
||||
| reinterpretcast{$$ = $1;}
|
||||
| '(' expr ')' {$$=$2;}
|
||||
| funcall {$$=$1;}
|
||||
| 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));
|
||||
$$ = addrof;}
|
||||
|
@ -194,36 +199,40 @@ argumentlist: argumentlist '(' exprlist ')' {AST_push_node($1, $3);
|
|||
$$ = list;};
|
||||
|
||||
|
||||
// TODO: add ast node for definition and declaration
|
||||
fundef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL);
|
||||
procdef: KeyFun Ident paramlist '{' statementlist'}' {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_ProcDef, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2);
|
||||
AST_push_node(fun, ident);
|
||||
AST_push_node(fun, $3);
|
||||
AST_push_node(fun, $5);
|
||||
$$ = fun;
|
||||
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_push_node(fun, ident);
|
||||
AST_push_node(fun, $3);
|
||||
AST_push_node(fun, $5);
|
||||
AST_push_node(fun, $7);
|
||||
$$ = fun;
|
||||
DEBUG("Function");};
|
||||
|
||||
fundecl: KeyFun Ident paramlist {AST_NODE_PTR fun = AST_new_node(new_loc(), AST_Fun, NULL);
|
||||
AST_NODE_PTR ident = AST_new_node(new_loc(), AST_Ident, $2);
|
||||
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, $4);
|
||||
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;
|
||||
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, $3);
|
||||
AST_push_node(fun, $2);
|
||||
AST_push_node(fun, $5);
|
||||
$$ = fun;
|
||||
DEBUG("Function");};
|
||||
|
||||
|
||||
|
||||
paramlist: paramlist '(' params ')' {AST_push_node($1, $3);
|
||||
$$ = $1;}
|
||||
| paramlist '(' ')'{$$ = $1;}
|
||||
|
@ -365,12 +374,13 @@ statement: assign {$$ = $1;}
|
|||
| definition {$$ = $1;}
|
||||
| while {$$ = $1;}
|
||||
| branchfull {$$ = $1;}
|
||||
| return {$$ = $1;}
|
||||
| returnstmt {$$ = $1;}
|
||||
| funcall {$$ = $1;}
|
||||
| boxcall{$$ = $1;};
|
||||
|
||||
return: KeyReturn expr { AST_NODE_PTR return_stmt = AST_new_node(new_loc(), AST_Return, NULL);
|
||||
AST_push_node(return_stmt, $2); };
|
||||
returnstmt: KeyReturn expr { AST_NODE_PTR return_stmt = AST_new_node(new_loc(), AST_Return, NULL);
|
||||
AST_push_node(return_stmt, $2);
|
||||
$$ = return_stmt; };
|
||||
|
||||
branchif: KeyIf expr '{' statementlist '}' { AST_NODE_PTR branch = AST_new_node(new_loc(), AST_If, NULL);
|
||||
AST_push_node(branch, $2);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
import "std"
|
||||
|
||||
fun ulog10(in u32: num, out u32: log)
|
||||
fun u32:ulog10(in u32: num)
|
||||
{
|
||||
u32: base = 1 as u32
|
||||
u32: count = 0 as u32
|
||||
|
@ -16,13 +16,12 @@ fun ulog10(in u32: num, out u32: log)
|
|||
count = 1 as u32
|
||||
}
|
||||
|
||||
log = count
|
||||
ret count
|
||||
}
|
||||
|
||||
fun u32ToCstr(in u32: number)(out cstr: result, out u32: len)
|
||||
{
|
||||
u32: bytes = 0 as u32
|
||||
ulog10(number, bytes)
|
||||
u32: bytes = ulog10(number)
|
||||
|
||||
cstr: buf = 0 as cstr
|
||||
heapAlloc(bytes)(buf as ref u8)
|
||||
|
@ -92,10 +91,8 @@ fun test_matrix()
|
|||
heapFree(matrix as ref u8)
|
||||
}
|
||||
|
||||
fun main(): u32
|
||||
fun i32:main()
|
||||
{
|
||||
test_matrix()
|
||||
exit_code = 0
|
||||
|
||||
ret 0
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue