added: more semantic errors checks

This commit is contained in:
Sven Vogel 2024-06-09 21:34:45 +02:00
parent f243bb6bfe
commit d4ce3387b9
4 changed files with 543 additions and 547 deletions

View File

@ -181,9 +181,11 @@ static void build_target(ModuleFileStack *unit, const TargetConfig *target) {
print_ast_to_file(ast, target); print_ast_to_file(ast, target);
Module* module = create_set(ast); Module* module = create_set(ast);
if (module != NULL) {
run_backend_codegen(module, target); run_backend_codegen(module, target);
} }
} }
}
AST_delete_node(ast); AST_delete_node(ast);

View File

@ -10,6 +10,7 @@
#include <llvm/llvm-ir/func.h> #include <llvm/llvm-ir/func.h>
#include <llvm/llvm-ir/types.h> #include <llvm/llvm-ir/types.h>
#include <assert.h> #include <assert.h>
#include <mem/cache.h>
BackendError impl_assign_stmt( BackendError impl_assign_stmt(
LLVMBackendCompileUnit *unit, LLVMBackendCompileUnit *unit,
@ -146,12 +147,13 @@ gboolean is_parameter_out(Parameter *param) {
BackendError impl_func_call(LLVMBackendCompileUnit *unit, BackendError impl_func_call(LLVMBackendCompileUnit *unit,
LLVMBuilderRef builder, LLVMLocalScope *scope, LLVMBuilderRef builder, LLVMLocalScope *scope,
const FunctionCall *call) { const FunctionCall *call) {
DEBUG("implementing function call...");
BackendError err = SUCCESS; BackendError err = SUCCESS;
GArray *arguments = g_array_new(FALSE, FALSE, sizeof(LLVMValueRef)); LLVMValueRef* arguments = mem_alloc(MemoryNamespaceLlvm, sizeof(LLVMValueRef) * call->expressions->len);
for (size_t i = 0; i < call->expressions->len; i++) { for (size_t i = 0; i < call->expressions->len; i++) {
Expression *arg = ((Expression *) call->expressions->data) + i; Expression *arg = g_array_index(call->expressions, Expression*, i);
LLVMValueRef llvm_arg = NULL; LLVMValueRef llvm_arg = NULL;
err = impl_expr(unit, scope, builder, arg, &llvm_arg); err = impl_expr(unit, scope, builder, arg, &llvm_arg);
@ -159,25 +161,30 @@ BackendError impl_func_call(LLVMBackendCompileUnit *unit,
break; break;
} }
Parameter *parameter = g_array_index(call->function->impl.declaration.parameter, Parameter*, i); GArray* param_list;
if (call->function->kind == FunctionDeclarationKind) {
param_list = call->function->impl.definition.parameter;
} else {
param_list = call->function->impl.declaration.parameter;
}
if (is_parameter_out(parameter)) { Parameter parameter = g_array_index(param_list, Parameter, i);
if (is_parameter_out(&parameter)) {
LLVMValueRef zero = LLVMConstInt(LLVMInt32TypeInContext(unit->context), 0, 0); LLVMValueRef zero = LLVMConstInt(LLVMInt32TypeInContext(unit->context), 0, 0);
llvm_arg = LLVMBuildGEP2(builder, LLVMTypeOf(llvm_arg), llvm_arg, &zero, 1, ""); llvm_arg = LLVMBuildGEP2(builder, LLVMTypeOf(llvm_arg), llvm_arg, &zero, 1, "");
} }
g_array_append_vals(arguments, &llvm_arg, 1); arguments[i] = llvm_arg;
} }
if (err.kind == Success) { if (err.kind == Success) {
LLVMValueRef llvm_func = LLVMGetNamedFunction(unit->module, ""); LLVMValueRef llvm_func = LLVMGetNamedFunction(unit->module, call->function->name);
LLVMTypeRef llvm_func_type = LLVMTypeOf(llvm_func); LLVMTypeRef llvm_func_type = LLVMTypeOf(llvm_func);
LLVMBuildCall2(builder, llvm_func_type, llvm_func, (LLVMValueRef *) arguments->data, arguments->len, LLVMBuildCall2(builder, llvm_func_type, llvm_func, arguments, call->expressions->len,
"stmt.call"); "stmt.call");
} }
g_array_free(arguments, FALSE);
return err; return err;
} }

View File

@ -200,7 +200,6 @@ BackendError get_type_impl(LLVMBackendCompileUnit* unit, LLVMGlobalScope* scope,
break; break;
default: default:
PANIC("invalid type kind: %ld", gemstone_type->kind); PANIC("invalid type kind: %ld", gemstone_type->kind);
break;
} }
return err; return err;

View File

@ -1,7 +1,4 @@
#include <io/files.h> #include <io/files.h>
#include <yacc/parser.tab.h>
#include <complex.h>
#include <stdio.h>
#include <ast/ast.h> #include <ast/ast.h>
#include <set/types.h> #include <set/types.h>
#include <stdlib.h> #include <stdlib.h>
@ -9,7 +6,6 @@
#include <sys/log.h> #include <sys/log.h>
#include <glib.h> #include <glib.h>
#include <assert.h> #include <assert.h>
#include <math.h>
#include <set/set.h> #include <set/set.h>
#include <mem/cache.h> #include <mem/cache.h>
@ -219,6 +215,8 @@ int set_impl_composite_type(AST_NODE_PTR ast_type, CompositeType *composite) {
composite->scale = composite->scale * nested_type->impl.composite.scale; composite->scale = composite->scale * nested_type->impl.composite.scale;
if (composite->scale > 8 || composite->scale < 0.25) { if (composite->scale > 8 || composite->scale < 0.25) {
print_diagnostic(current_file, &typeKind->location, Error, "Invalid type scale of composite type: %lf",
composite->scale);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -274,8 +272,9 @@ int set_get_type_impl(AST_NODE_PTR currentNode, Type **type) {
if (g_hash_table_contains(declaredBoxes, typekind) == TRUE) { if (g_hash_table_contains(declaredBoxes, typekind) == TRUE) {
*type = g_hash_table_lookup(declaredBoxes, typekind); *type = g_hash_table_lookup(declaredBoxes, typekind);
if(currentNode->child_count > 1) {
if (currentNode->child_count > 1) {
print_diagnostic(current_file, &currentNode->location, Error, "Box type cannot modified");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
return SEMANTIC_OK; return SEMANTIC_OK;
@ -299,6 +298,9 @@ int set_get_type_impl(AST_NODE_PTR currentNode, Type **type) {
*type = new_type; *type = new_type;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
print_diagnostic(current_file, &currentNode->children[currentNode->child_count - 1]->location, Error,
"Expected either primitive or composite type");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -330,14 +332,11 @@ int createRef(AST_NODE_PTR currentNode, Type** reftype) {
assert(currentNode->child_count == 1); assert(currentNode->child_count == 1);
assert(AST_get_node(currentNode, 0)->kind == AST_Type); assert(AST_get_node(currentNode, 0)->kind == AST_Type);
Type *type = malloc(sizeof(Type)); Type *type = malloc(sizeof(Type));
Type *referenceType = malloc(sizeof(Type)); Type *referenceType = malloc(sizeof(Type));
referenceType->kind = TypeKindReference; referenceType->kind = TypeKindReference;
referenceType->nodePtr = currentNode; referenceType->nodePtr = currentNode;
int signal = set_get_type_impl(currentNode->children[0], &type); int signal = set_get_type_impl(currentNode->children[0], &type);
if (signal) { if (signal) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
@ -436,6 +435,9 @@ int createDef(AST_NODE_PTR currentNode, GArray **variables) {
case AST_Type: case AST_Type:
DEBUG("fill Type"); DEBUG("fill Type");
status = set_get_type_impl(declaration->children[i], &decl.type); status = set_get_type_impl(declaration->children[i], &decl.type);
if (status == SEMANTIC_ERROR) {
return SEMANTIC_ERROR;
}
break; break;
case AST_IdentList: case AST_IdentList:
break; break;
@ -501,7 +503,8 @@ int getVariableFromScope(const char *name, Variable **variable) {
DEBUG("Found var"); DEBUG("Found var");
return SEMANTIC_OK; return SEMANTIC_OK;
} else if (found > 1) { } else if (found > 1) {
WARN("Variable %s is a parameter and a declared variable. Returning parameter", name); print_diagnostic(current_file, &(*variable)->nodePtr->location, Warning,
"Parameter shadows variable of same name: %s", name);
return SEMANTIC_OK; return SEMANTIC_OK;
} }
DEBUG("nothing found"); DEBUG("nothing found");
@ -511,7 +514,7 @@ int getVariableFromScope(const char *name, Variable **variable) {
int addVarToScope(Variable *variable) { int addVarToScope(Variable *variable) {
Variable *tmp = NULL; Variable *tmp = NULL;
if (getVariableFromScope(variable->name, &tmp) == SEMANTIC_OK) { if (getVariableFromScope(variable->name, &tmp) == SEMANTIC_OK) {
INFO("this var already exist: ", variable->name); print_diagnostic(current_file, &variable->nodePtr->location, Error, "Variable already exist: ", variable->name);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
GHashTable *currentScope = g_array_index(Scope, GHashTable*, Scope->len - 1); GHashTable *currentScope = g_array_index(Scope, GHashTable*, Scope->len - 1);
@ -525,11 +528,11 @@ int fillTablesWithVars(GHashTable *variableTable, const GArray* variables) {
for (size_t i = 0; i < variables->len; i++) { for (size_t i = 0; i < variables->len; i++) {
Variable *var = g_array_index(variables, Variable *, i); Variable *var = g_array_index(variables, Variable *, i);
// this variable is discarded, only need status code // this variable is discarded, only need status code
if (g_hash_table_contains(variableTable, (gpointer) var->name)) { if (g_hash_table_contains(variableTable, (gpointer) var->name)) {
print_diagnostic(current_file, &var->nodePtr->location, Error, "Variable already exists");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -540,6 +543,7 @@ int fillTablesWithVars(GHashTable *variableTable, const GArray* variables) {
} }
[[nodiscard("type must be freed")]] [[nodiscard("type must be freed")]]
TypeValue createTypeValue(AST_NODE_PTR currentNode) { TypeValue createTypeValue(AST_NODE_PTR currentNode) {
DEBUG("create TypeValue"); DEBUG("create TypeValue");
TypeValue value; TypeValue value;
@ -552,11 +556,9 @@ TypeValue createTypeValue(AST_NODE_PTR currentNode){
case AST_Int: case AST_Int:
type->impl.primitive = Int; type->impl.primitive = Int;
break; break;
case AST_Float: case AST_Float:
type->impl.primitive = Float; type->impl.primitive = Float;
break; 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;
@ -593,7 +595,8 @@ Type* createTypeFromOperands(Type* LeftOperandType, Type* RightOperandType, AST_
resultImpl.nodePtr = currentNode; resultImpl.nodePtr = currentNode;
resultImpl.sign = MAX(LeftOperandType->impl.composite.sign, RightOperandType->impl.composite.sign); resultImpl.sign = MAX(LeftOperandType->impl.composite.sign, RightOperandType->impl.composite.sign);
resultImpl.scale = MAX(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale); resultImpl.scale = MAX(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale);
resultImpl.primitive = MAX(LeftOperandType->impl.composite.primitive , RightOperandType->impl.composite.primitive); resultImpl.primitive = MAX(LeftOperandType->impl.composite.primitive,
RightOperandType->impl.composite.primitive);
result->impl.composite = resultImpl; result->impl.composite = resultImpl;
@ -620,6 +623,7 @@ Type* createTypeFromOperands(Type* LeftOperandType, Type* RightOperandType, AST_
result->impl.composite.nodePtr = currentNode; result->impl.composite.nodePtr = currentNode;
} else { } else {
mem_free(result); mem_free(result);
print_diagnostic(current_file, &currentNode->location, Error, "Incompatible types in expression");
return NULL; return NULL;
} }
DEBUG("Succsessfully created type"); DEBUG("Succsessfully created type");
@ -641,6 +645,8 @@ int createTypeCastFromExpression(Expression * expression, Type * resultType, Exp
if (expression->result->kind != TypeKindComposite if (expression->result->kind != TypeKindComposite
&& expression->result->kind != TypeKindPrimitive) { && expression->result->kind != TypeKindPrimitive) {
print_diagnostic(current_file, &expression->nodePtr->location, Error,
"Expected either primitive or composite type");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
*result = expr; *result = expr;
@ -711,7 +717,6 @@ int createArithOperation(Expression* ParentExpression, AST_NODE_PTR currentNode,
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) {
Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i);
if (!compareTypes(operand->result, ParentExpression->result)) { if (!compareTypes(operand->result, ParentExpression->result)) {
@ -724,8 +729,6 @@ int createArithOperation(Expression* ParentExpression, AST_NODE_PTR currentNode,
} }
} }
return SEMANTIC_OK; return SEMANTIC_OK;
} }
@ -734,12 +737,15 @@ int createRelationalOperation(Expression* ParentExpression, AST_NODE_PTR current
ParentExpression->impl.operation.kind = Relational; ParentExpression->impl.operation.kind = Relational;
ParentExpression->impl.operation.nodePtr = currentNode; ParentExpression->impl.operation.nodePtr = currentNode;
ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *)); ParentExpression->impl.operation.operands = g_array_new(FALSE, FALSE, sizeof(Expression *));
// fill Operands // fill Operands
for (size_t i = 0; i < currentNode->child_count; i++) { for (size_t i = 0; i < currentNode->child_count; i++) {
Expression *expression = createExpression(currentNode->children[i]); Expression *expression = createExpression(currentNode->children[i]);
if (NULL == expression) { if (NULL == expression) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
g_array_append_val(ParentExpression->impl.operation.operands, expression); g_array_append_val(ParentExpression->impl.operation.operands, expression);
} }
@ -767,10 +773,14 @@ int createRelationalOperation(Expression* ParentExpression, AST_NODE_PTR current
ParentExpression->result = result; ParentExpression->result = result;
for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) {
Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i);
if (!compareTypes(operand->result, ParentExpression->result)) { if (!compareTypes(operand->result, ParentExpression->result)) {
Expression *expr; Expression *expr;
int status = createTypeCastFromExpression(operand, ParentExpression->result, &expr); int status = createTypeCastFromExpression(operand, ParentExpression->result, &expr);
if (status == SEMANTIC_ERROR) { if (status == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -807,7 +817,7 @@ int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode)
ParentExpression->impl.operation.impl.boolean = BooleanXor; ParentExpression->impl.operation.impl.boolean = BooleanXor;
break; break;
default: default:
PANIC("Current node is not an boolean operater"); PANIC("Current node is not an boolean operator");
break; break;
} }
@ -886,13 +896,15 @@ int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNod
result->nodePtr = currentNode; result->nodePtr = currentNode;
if (Operand->kind == TypeKindBox || Operand->kind == TypeKindReference) { if (Operand->kind == TypeKindBox || Operand->kind == TypeKindReference) {
print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); print_diagnostic(current_file, &Operand->nodePtr->location, Error,
"Operand must be a variant of primitive type int");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
if (Operand->kind == TypeKindPrimitive) { if (Operand->kind == TypeKindPrimitive) {
if (Operand->impl.primitive == Float) { if (Operand->impl.primitive == Float) {
print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); print_diagnostic(current_file, &Operand->nodePtr->location, Error,
"Operand must be a variant of primitive type int");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
result->kind = Operand->kind; result->kind = Operand->kind;
@ -900,7 +912,8 @@ int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNod
} else if (Operand->kind == TypeKindComposite) { } else if (Operand->kind == TypeKindComposite) {
if (Operand->impl.composite.primitive == Float) { if (Operand->impl.composite.primitive == Float) {
print_diagnostic(current_file, &Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); print_diagnostic(current_file, &Operand->nodePtr->location, Error,
"Operand must be a variant of primitive type int");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
result->kind = Operand->kind; result->kind = Operand->kind;
@ -1179,7 +1192,8 @@ int createBoxAccess(Expression* ParentExpression,AST_NODE_PTR currentNode) {
int status = getVariableFromScope(boxname, &boxVariable); int status = getVariableFromScope(boxname, &boxVariable);
if (status == SEMANTIC_ERROR) { if (status == SEMANTIC_ERROR) {
print_diagnostic(current_file, &currentNode->children[0]->location, Error, "Variable of name `%s` does not exist"); print_diagnostic(current_file, &currentNode->children[0]->location, Error,
"Variable of name `%s` does not exist");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
Type *boxType; Type *boxType;
@ -1287,20 +1301,24 @@ int createDeref(Expression* ParentExpression, AST_NODE_PTR currentNode) {
Type *indexType = deref.index->result; Type *indexType = deref.index->result;
//indexType can only be a composite or a primitive //indexType can only be a composite or a primitive
if (indexType->kind != TypeKindComposite && indexType->kind != TypeKindPrimitive) { if (indexType->kind != TypeKindComposite && indexType->kind != TypeKindPrimitive) {
print_diagnostic(current_file, &AST_get_node(currentNode, 1)->location, Error,
"Index must a primitive int or composite variation");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
//indexType can only be int //indexType can only be int
if (indexType->kind == TypeKindPrimitive) { if (indexType->kind == TypeKindPrimitive) {
if (indexType->impl.primitive != Int) { if (indexType->impl.primitive != Int) {
print_diagnostic(current_file, &AST_get_node(currentNode, 1)->location, Error,
"Index must a primitive int or composite variation");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
if (indexType->kind == TypeKindComposite) { if (indexType->kind == TypeKindComposite) {
if (indexType->impl.composite.primitive != Int) { if (indexType->impl.composite.primitive != Int) {
print_diagnostic(current_file, &AST_get_node(currentNode, 1)->location, Error,
"Index must a primitive int or composite variation");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
@ -1309,12 +1327,14 @@ int createDeref(Expression* ParentExpression, AST_NODE_PTR currentNode) {
//variable has to be made //variable has to be made
if (deref.index == NULL) { if (deref.index == NULL) {
print_diagnostic(current_file, &AST_get_node(currentNode, 1)->location, Error, "Invalid index");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
//variable can only be a reference //variable can only be a reference
if (deref.variable->result->kind != TypeKindReference) { if (deref.variable->result->kind != TypeKindReference) {
print_diagnostic(current_file, &AST_get_node(currentNode, 0)->location, Error,
"Only references can be dereferenced");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -1332,7 +1352,6 @@ int createAddressOf(Expression* ParentExpression, AST_NODE_PTR currentNode) {
address_of.variable = createExpression(AST_get_node(currentNode, 0)); address_of.variable = createExpression(AST_get_node(currentNode, 0));
if (address_of.variable == NULL) { if (address_of.variable == NULL) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -1458,14 +1477,12 @@ Expression *createExpression(AST_NODE_PTR currentNode){
case AST_Dereference: case AST_Dereference:
expression->kind = ExpressionKindDereference; expression->kind = ExpressionKindDereference;
if (createDeref(expression, currentNode)) { if (createDeref(expression, currentNode)) {
return NULL; return NULL;
} }
break; break;
case AST_AddressOf: case AST_AddressOf:
expression->kind = ExpressionKindAddressOf; expression->kind = ExpressionKindAddressOf;
if (createAddressOf(expression, currentNode)) { if (createAddressOf(expression, currentNode)) {
return NULL; return NULL;
} }
break; break;
@ -1479,7 +1496,6 @@ Expression *createExpression(AST_NODE_PTR currentNode){
return expression; return expression;
} }
bool compareTypes(Type *leftType, Type *rightType) { bool compareTypes(Type *leftType, Type *rightType) {
if (leftType->kind != rightType->kind) { if (leftType->kind != rightType->kind) {
return FALSE; return FALSE;
@ -1544,16 +1560,16 @@ bool compareTypes(Type * leftType, Type * rightType) {
varType = assign.variable->impl.definiton.declaration.type; varType = assign.variable->impl.definiton.declaration.type;
} }
bool result = compareTypes(varType, assign.value->result); bool result = compareTypes(varType, assign.value->result);
if (result == FALSE) { if (result == FALSE) {
print_diagnostic(current_file, &currentNode->location, Error, "Assignment expression has incompatible type");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
ParentStatement->impl.assignment = assign; ParentStatement->impl.assignment = assign;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int createStatement(Block *block, AST_NODE_PTR currentNode); int createStatement(Block *block, AST_NODE_PTR currentNode);
int fillBlock(Block *block, AST_NODE_PTR currentNode) { int fillBlock(Block *block, AST_NODE_PTR currentNode) {
@ -1563,7 +1579,6 @@ int fillBlock(Block * block,AST_NODE_PTR currentNode){
GHashTable *lowerScope = g_hash_table_new(g_str_hash, g_str_equal); GHashTable *lowerScope = g_hash_table_new(g_str_hash, g_str_equal);
g_array_append_val(Scope, lowerScope); g_array_append_val(Scope, lowerScope);
for (size_t i = 0; i < currentNode->child_count; i++) { for (size_t i = 0; i < currentNode->child_count; i++) {
int signal = createStatement(block, AST_get_node(currentNode, i)); int signal = createStatement(block, AST_get_node(currentNode, i));
if (signal) { if (signal) {
@ -1600,8 +1615,6 @@ int createWhile(Statement * ParentStatement, AST_NODE_PTR currentNode){
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int createIf(Branch *Parentbranch, AST_NODE_PTR currentNode) { int createIf(Branch *Parentbranch, AST_NODE_PTR currentNode) {
If ifbranch; If ifbranch;
ifbranch.nodePtr = currentNode; ifbranch.nodePtr = currentNode;
@ -1611,11 +1624,12 @@ int createIf(Branch* Parentbranch, AST_NODE_PTR currentNode){
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
ifbranch.conditon = expression; ifbranch.conditon = expression;
int status = fillBlock(&ifbranch.block, currentNode->children[1]);
int status = fillBlock(&ifbranch.block, currentNode->children[1]);
if (status) { if (status) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
Parentbranch->ifBranch = ifbranch; Parentbranch->ifBranch = ifbranch;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
@ -1699,13 +1713,12 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
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; 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);
if (result == SEMANTIC_ERROR) { if (result == SEMANTIC_ERROR) {
print_diagnostic(current_file, &currentNode->location, Error, "Unknown function: `%s`", nameNode);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
@ -1721,6 +1734,7 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
int result = getFunction(name, &fun); int result = getFunction(name, &fun);
if (result) { if (result) {
print_diagnostic(current_file, &currentNode->location, Error, "Unknown function: `%s`", nameNode);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
@ -1741,6 +1755,8 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
} }
if (count != paramCount) { if (count != paramCount) {
print_diagnostic(current_file, &currentNode->location, Error, "Expected %d arguments instead of %d", paramCount,
count);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -1759,13 +1775,11 @@ int createfuncall(Statement *parentStatement, AST_NODE_PTR currentNode) {
} }
funcall.expressions = expressions; funcall.expressions = expressions;
parentStatement->kind = StatementKindFunctionCall;
parentStatement->impl.call = funcall; parentStatement->impl.call = funcall;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int createStatement(Block *Parentblock, AST_NODE_PTR currentNode) { int createStatement(Block *Parentblock, AST_NODE_PTR currentNode) {
DEBUG("create Statement"); DEBUG("create Statement");
@ -1777,13 +1791,12 @@ int createStatement(Block * Parentblock , AST_NODE_PTR currentNode){
if (status) { if (status) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
for(size_t i = 0; i < variable->len ; i++){
for (size_t i = 0; i < variable->len; i++) {
Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement));
statement->nodePtr = currentNode; statement->nodePtr = currentNode;
statement->kind = StatementKindDeclaration; statement->kind = StatementKindDeclaration;
statement->impl.variable = g_array_index(variable, Variable *, i); statement->impl.variable = g_array_index(variable, Variable *, i);
g_array_append_val(Parentblock->statemnts, statement); g_array_append_val(Parentblock->statemnts, statement);
} }
@ -1793,11 +1806,10 @@ int createStatement(Block * Parentblock , AST_NODE_PTR currentNode){
case AST_Def: { case AST_Def: {
GArray *variable = g_array_new(FALSE, FALSE, sizeof(Variable *)); GArray *variable = g_array_new(FALSE, FALSE, sizeof(Variable *));
int status = createDef(currentNode, &variable); if (createDef(currentNode, &variable)) {
if(status){
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
for (size_t i = 0; i < variable->len; i++) { for (size_t i = 0; i < variable->len; i++) {
Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement));
@ -1848,6 +1860,7 @@ int createStatement(Block * Parentblock , AST_NODE_PTR currentNode){
if (result == SEMANTIC_ERROR) { if (result == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
g_array_append_val(Parentblock->statemnts, statement);
break; break;
default: default:
PANIC("Node is not a statement"); PANIC("Node is not a statement");
@ -1857,7 +1870,6 @@ int createStatement(Block * Parentblock , AST_NODE_PTR currentNode){
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) { int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) {
assert(currentNode->kind == AST_Parameter); assert(currentNode->kind == AST_Parameter);
DEBUG("start param"); DEBUG("start param");
@ -1884,8 +1896,7 @@ int createParam(GArray * Paramlist ,AST_NODE_PTR currentNode){
PANIC("IO_Qualifier has not the right amount of children"); PANIC("IO_Qualifier has not the right amount of children");
} }
int signal = set_get_type_impl(paramdecl->children[0], &(decl.type)); if (set_get_type_impl(paramdecl->children[0], &(decl.type))) {
if(signal){
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
Parameter param; Parameter param;
@ -1907,8 +1918,8 @@ int createParam(GArray * Paramlist ,AST_NODE_PTR currentNode){
paramvar->impl.declaration.qualifier = Local; paramvar->impl.declaration.qualifier = Local;
paramvar->impl.declaration.type = param.impl.declaration.type; paramvar->impl.declaration.type = param.impl.declaration.type;
if (g_hash_table_contains(functionParameter, param.name)) { if (g_hash_table_contains(functionParameter, param.name)) {
print_diagnostic(current_file, &param.nodePtr->location, Error, "Names of function parameters must be unique");
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
g_hash_table_insert(functionParameter, (gpointer) param.name, paramvar); g_hash_table_insert(functionParameter, (gpointer) param.name, paramvar);
@ -1917,15 +1928,12 @@ int createParam(GArray * Paramlist ,AST_NODE_PTR currentNode){
return SEMANTIC_OK; return SEMANTIC_OK;
} }
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 = currentNode->children[0]; AST_NODE_PTR nameNode = currentNode->children[0];
AST_NODE_PTR paramlistlist = currentNode->children[1]; AST_NODE_PTR paramlistlist = currentNode->children[1];
AST_NODE_PTR statementlist = currentNode->children[2]; AST_NODE_PTR statementlist = currentNode->children[2];
FunctionDefinition fundef; FunctionDefinition fundef;
fundef.nodePtr = currentNode; fundef.nodePtr = currentNode;
@ -1942,17 +1950,15 @@ int createFunDef(Function * Parentfunction ,AST_NODE_PTR currentNode){
for (size_t j = 0; j < paramlist->child_count; j++) { for (size_t j = 0; j < paramlist->child_count; j++) {
DEBUG("param child count: %i", AST_get_node(paramlist, j)->child_count); DEBUG("param child count: %i", AST_get_node(paramlist, j)->child_count);
int signal = createParam(fundef.parameter ,AST_get_node(paramlist, j));
//all params per list
if (signal){ if (createParam(fundef.parameter, AST_get_node(paramlist, j))) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
DEBUG("End of Paramlist"); DEBUG("End of Paramlist");
} }
int signal = fillBlock(fundef.body, statementlist);
if(signal){ if (fillBlock(fundef.body, statementlist)) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -1961,8 +1967,6 @@ int createFunDef(Function * Parentfunction ,AST_NODE_PTR currentNode){
Parentfunction->impl.definition = fundef; Parentfunction->impl.definition = fundef;
Parentfunction->name = fundef.name; Parentfunction->name = fundef.name;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
bool compareParameter(GArray *leftParameter, GArray *rightParameter) { bool compareParameter(GArray *leftParameter, GArray *rightParameter) {
@ -1998,22 +2002,25 @@ bool compareParameter(GArray *leftParameter,GArray *rightParameter) {
int addFunction(const char *name, Function *function) { int addFunction(const char *name, Function *function) {
if (function->kind == FunctionDefinitionKind) { if (function->kind == FunctionDefinitionKind) {
if (g_hash_table_contains(definedFunctions, name)) { if (g_hash_table_contains(definedFunctions, name)) {
print_diagnostic(current_file, &function->nodePtr->location, Error, "Multiple definition of function: `%s`", function->name);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
g_hash_table_insert(declaredFunctions, (gpointer) name, function); g_hash_table_insert(declaredFunctions, (gpointer) name, function);
} else if (function->kind == FunctionDeclarationKind) { } else if (function->kind == FunctionDeclarationKind) {
if (g_hash_table_contains(declaredFunctions, name)) { if (g_hash_table_contains(declaredFunctions, name)) {
Function *declaredFunction = g_hash_table_lookup(declaredFunctions, name); Function *declaredFunction = g_hash_table_lookup(declaredFunctions, name);
bool result = compareParameter(declaredFunction->impl.declaration.parameter, function->impl.declaration.parameter); bool result = compareParameter(declaredFunction->impl.declaration.parameter,
function->impl.declaration.parameter);
// a function can have multiple declartations but all have to be identical
if (result == FALSE) { if (result == FALSE) {
print_diagnostic(current_file, &function->nodePtr->location, Error, "Divergent declaration of function: `%s`", function->name);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
//a function can have multiple declartations but all have to be identical
} }
g_hash_table_insert(declaredFunctions, (gpointer) name, function); g_hash_table_insert(declaredFunctions, (gpointer) name, function);
} }
return SEMANTIC_OK;
return SEMANTIC_OK;
} }
int getFunction(const char *name, Function **function) { int getFunction(const char *name, Function **function) {
@ -2035,15 +2042,12 @@ int createFunDecl(Function * Parentfunction ,AST_NODE_PTR currentNode){
AST_NODE_PTR nameNode = currentNode->children[0]; AST_NODE_PTR nameNode = currentNode->children[0];
AST_NODE_PTR paramlistlist = currentNode->children[1]; AST_NODE_PTR paramlistlist = currentNode->children[1];
FunctionDeclaration fundecl; FunctionDeclaration fundecl;
fundecl.nodePtr = currentNode; fundecl.nodePtr = currentNode;
fundecl.name = nameNode->value; fundecl.name = nameNode->value;
fundecl.parameter = mem_alloc(MemoryNamespaceSet, sizeof(GArray)); fundecl.parameter = mem_alloc(MemoryNamespaceSet, sizeof(GArray));
for (size_t i = 0; i < paramlistlist->child_count; i++) { for (size_t i = 0; i < paramlistlist->child_count; i++) {
//all parameter lists //all parameter lists
@ -2051,9 +2055,7 @@ int createFunDecl(Function * Parentfunction ,AST_NODE_PTR currentNode){
for (size_t j = 0; j < paramlistlist->child_count; j++) { for (size_t j = 0; j < paramlistlist->child_count; j++) {
int signal = createParam(fundecl.parameter ,paramlist->children[i]); if (createParam(fundecl.parameter, paramlist->children[i])) {
//all params per list
if (signal){
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} }
@ -2066,19 +2068,17 @@ int createFunDecl(Function * Parentfunction ,AST_NODE_PTR currentNode){
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int createFunction(Function *function, AST_NODE_PTR currentNode) {
int createFunction(Function ** function, AST_NODE_PTR currentNode){
assert(currentNode->kind == AST_Fun); assert(currentNode->kind == AST_Fun);
Function * fun = mem_alloc(MemoryNamespaceSet,sizeof(Function));
functionParameter = g_hash_table_new(g_str_hash, g_str_equal); functionParameter = g_hash_table_new(g_str_hash, g_str_equal);
if (currentNode->child_count == 2) { if (currentNode->child_count == 2) {
int signal = createFunDecl(fun, currentNode); int signal = createFunDecl(function, currentNode);
if (signal) { if (signal) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
} else if (currentNode->child_count == 3) { } else if (currentNode->child_count == 3) {
int signal = createFunDef(fun, currentNode); int signal = createFunDef(function, currentNode);
if (signal) { if (signal) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -2086,21 +2086,17 @@ int createFunction(Function ** function, AST_NODE_PTR currentNode){
PANIC("function should have 2 or 3 children"); PANIC("function should have 2 or 3 children");
} }
g_hash_table_destroy(functionParameter); g_hash_table_destroy(functionParameter);
functionParameter = NULL;
int result = addFunction(fun->name,fun); int result = addFunction(function->name, function);
if (result == SEMANTIC_ERROR) { if (result == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
*function = fun;
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int createDeclMember(BoxType *ParentBox, AST_NODE_PTR currentNode) { int createDeclMember(BoxType *ParentBox, AST_NODE_PTR currentNode) {
Type *declType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); Type *declType = mem_alloc(MemoryNamespaceSet, sizeof(Type));
@ -2159,7 +2155,7 @@ int createDefMember(BoxType *ParentBox, AST_NODE_PTR currentNode){
int createBoxFunction(const char *boxName, Type *ParentBoxType, AST_NODE_PTR currentNode) { int createBoxFunction(const char *boxName, Type *ParentBoxType, AST_NODE_PTR currentNode) {
Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function)); Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function));
int result = createFunction(&function,currentNode); int result = createFunction(function, currentNode);
if (result == SEMANTIC_ERROR) { if (result == SEMANTIC_ERROR) {
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
@ -2195,7 +2191,6 @@ int createBox(GHashTable *boxes, AST_NODE_PTR currentNode){
boxType->nodePtr = currentNode; boxType->nodePtr = currentNode;
boxType->impl.box = box; boxType->impl.box = box;
for (size_t i = 0; boxMemberList->child_count; i++) { for (size_t i = 0; boxMemberList->child_count; i++) {
switch (boxMemberList->children[i]->kind) { switch (boxMemberList->children[i]->kind) {
case AST_Decl: case AST_Decl:
@ -2224,10 +2219,7 @@ int createBox(GHashTable *boxes, AST_NODE_PTR currentNode){
} }
g_hash_table_insert(boxes, (gpointer) boxName, box); g_hash_table_insert(boxes, (gpointer) boxName, box);
return SEMANTIC_OK; return SEMANTIC_OK;
} }
int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode) { int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode) {
@ -2235,7 +2227,6 @@ int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode){
AST_NODE_PTR typeNode = currentNode->children[0]; AST_NODE_PTR typeNode = currentNode->children[0];
AST_NODE_PTR nameNode = currentNode->children[1]; AST_NODE_PTR nameNode = currentNode->children[1];
Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type));
int status = set_get_type_impl(typeNode, &type); int status = set_get_type_impl(typeNode, &type);
if (status) { if (status) {
@ -2248,10 +2239,15 @@ int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode){
def->type = type; def->type = type;
if (g_hash_table_contains(types, (gpointer) def->name)) { if (g_hash_table_contains(types, (gpointer) def->name)) {
print_diagnostic(current_file, &currentNode->location, Error, "Multiple definition of type: `%s`",
nameNode->value);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
g_hash_table_insert(types, (gpointer) def->name, def); g_hash_table_insert(types, (gpointer) def->name, def);
if (g_hash_table_contains(declaredComposites, (gpointer) def->name)) { if (g_hash_table_contains(declaredComposites, (gpointer) def->name)) {
print_diagnostic(current_file, &currentNode->location, Error, "Multiple definition of type: `%s`",
nameNode->value);
return SEMANTIC_ERROR; return SEMANTIC_ERROR;
} }
g_hash_table_insert(declaredComposites, (gpointer) def->name, def->type); g_hash_table_insert(declaredComposites, (gpointer) def->name, def->type);
@ -2270,7 +2266,6 @@ Module *create_set(AST_NODE_PTR currentNode){
//create scope //create scope
Scope = g_array_new(FALSE, FALSE, sizeof(GHashTable *)); Scope = g_array_new(FALSE, FALSE, sizeof(GHashTable *));
//building current scope for module //building current scope for module
GHashTable *globalscope = g_hash_table_new(g_str_hash, g_str_equal); GHashTable *globalscope = g_hash_table_new(g_str_hash, g_str_equal);
globalscope = g_hash_table_new(g_str_hash, g_str_equal); globalscope = g_hash_table_new(g_str_hash, g_str_equal);
@ -2292,24 +2287,16 @@ Module *create_set(AST_NODE_PTR currentNode){
DEBUG("created Module struct"); DEBUG("created Module struct");
for (size_t i = 0; i < currentNode->child_count; i++) { for (size_t i = 0; i < currentNode->child_count; i++) {
DEBUG("created Child with type: %i", currentNode->children[i]->kind); DEBUG("created Child with type: %i", currentNode->children[i]->kind);
switch (currentNode->children[i]->kind) { switch (currentNode->children[i]->kind) {
case AST_Decl: { case AST_Decl: {
GArray *vars; GArray *vars = NULL;
int status = createDecl(currentNode->children[i], &vars); int status = createDecl(currentNode->children[i], &vars);
if (status) { if (status) {
return NULL; return NULL;
} }
if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) { if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) {
// TODO: this diagnostic will highlight entire declaration of
// of variables even if just one of the declared variables
// is duplicate. Consider moving this diagnostic to
// `fillTablesWithVars` for more precise messaging.
print_diagnostic(current_file, &currentNode->children[i]->location, Error,
"Variable already declared");
INFO("var already exists"); INFO("var already exists");
break; break;
} }
@ -2322,6 +2309,10 @@ Module *create_set(AST_NODE_PTR currentNode){
if (status) { if (status) {
return NULL; return NULL;
} }
if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) {
INFO("var already exists");
break;
}
DEBUG("created Definition successfully"); DEBUG("created Definition successfully");
break; break;
} }
@ -2330,27 +2321,27 @@ Module *create_set(AST_NODE_PTR currentNode){
if (status) { if (status) {
return NULL; return NULL;
} }
DEBUG("created Box successfully"); DEBUG("created Box successfully");
break; break;
} }
case AST_Fun: { case AST_Fun: {
DEBUG("start function"); DEBUG("start function");
Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function)); Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function));
int status = createFunction(&function,currentNode->children[i]);
if(status == SEMANTIC_ERROR) { if (createFunction(function, currentNode->children[i]) == SEMANTIC_ERROR) {
return NULL; return NULL;
} }
if (g_hash_table_contains(functions, function->name)) { if (g_hash_table_contains(functions, function->name)) {
print_diagnostic(current_file, &function->impl.definition.nodePtr->location, Error,
"Multiple definition of function: `%s`", function->name);
return NULL; return NULL;
} }
g_hash_table_insert(functions, (gpointer) function->name, function); g_hash_table_insert(functions, (gpointer) function->name, function);
if (status){
return NULL;
}
DEBUG("created function successfully"); DEBUG("created function successfully");
break; break;
} }
case AST_Typedef: { case AST_Typedef: {
int status = createTypeDef(types, currentNode->children[i]); int status = createTypeDef(types, currentNode->children[i]);
@ -2367,12 +2358,9 @@ Module *create_set(AST_NODE_PTR currentNode){
default: default:
INFO("Provided source file could not be parsed because of semantic error."); INFO("Provided source file could not be parsed because of semantic error.");
break; break;
}
}
}
}
DEBUG("created set successfully"); DEBUG("created set successfully");
return rootModule; return rootModule;
} }