#include #include #include #include #include #include #include #include #include static GHashTable *declaredComposites = NULL;//pointer to composites with names static GHashTable *declaredBoxes = NULL;//pointer to type static GHashTable *functionParameter = NULL; static GHashTable *definedFunctions = NULL; static GHashTable *declaredFunctions = NULL; static GArray *Scope = NULL;//list of hashtables. last Hashtable is current depth of program. hashtable key: ident, value: Variable* to var int createTypeCastFromExpression(Expression *expression, Type *resultType, Expression **result); bool compareTypes(Type *leftType, Type *rightType); char *type_to_string(Type *type); const Type ShortShortUnsingedIntType = { .kind = TypeKindComposite, .impl = { .composite = { .sign = Unsigned, .scale = 0.25, .primitive = Int } }, .nodePtr = NULL, }; const Type StringLiteralType = { .kind = TypeKindReference, .impl = { .reference = (ReferenceType) &ShortShortUnsingedIntType, }, .nodePtr = NULL, }; /** * @brief Convert a string into a sign typ * @return 0 on success, 1 otherwise */ int sign_from_string(const char *string, Sign *sign) { assert(string != NULL); assert(sign != NULL); if (strcmp(string, "unsigned") == 0) { *sign = Unsigned; return SEMANTIC_OK; } if (strcmp(string, "signed") == 0) { *sign = Signed; return SEMANTIC_OK; } return SEMANTIC_ERROR; } /** * @brief Convert a string into a primitive type * @return 0 on success, 1 otherwise */ int primitive_from_string(const char *string, PrimitiveType *primitive) { assert(string != NULL); assert(primitive != NULL); DEBUG("find primitive in string"); if (strcmp(string, "int") == 0) { *primitive = Int; return SEMANTIC_OK; } if (strcmp(string, "float") == 0) { *primitive = Float; return SEMANTIC_OK; } return SEMANTIC_ERROR; } int scale_factor_from(const char *string, double *factor) { assert(string != NULL); assert(factor != NULL); if (strcmp(string, "half") == 0 || strcmp(string, "short") == 0) { *factor = 0.5; return SEMANTIC_OK; } if (strcmp(string, "double") == 0 || strcmp(string, "long") == 0) { *factor = 2.0; return SEMANTIC_OK; } return SEMANTIC_ERROR; } int check_scale_factor(AST_NODE_PTR node, Scale scale) { assert(node != NULL); if (8 < scale) { print_diagnostic(&node->location, Error, "Composite scale overflow"); return SEMANTIC_ERROR; } if (0.25 > scale) { print_diagnostic(&node->location, Error, "Composite scale underflow"); return SEMANTIC_ERROR; } return SEMANTIC_OK; } int merge_scale_list(AST_NODE_PTR scale_list, Scale *scale) { assert(scale_list != NULL); assert(scale != NULL); for (size_t i = 0; i < scale_list->children->len; i++) { double scale_in_list = 1.0; int scale_invalid = scale_factor_from(AST_get_node(scale_list, i)->value, &scale_in_list); if (scale_invalid == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } *scale *= scale_in_list; } return SEMANTIC_OK; } /** * @brief Get an already declared type from its name */ int get_type_decl(const char *name, Type **type) { assert(name != NULL); assert(type != NULL); if (g_hash_table_contains(declaredComposites, name) == TRUE) { *type = (Type *) g_hash_table_lookup(declaredComposites, name); return SEMANTIC_OK; } return SEMANTIC_ERROR; } int set_impl_composite_type(AST_NODE_PTR ast_type, CompositeType *composite) { assert(ast_type != NULL); assert(composite != NULL); DEBUG("Type is a Composite"); int status = SEMANTIC_OK; int scaleNodeOffset = 0; composite->sign = Signed; // check if we have a sign if (AST_Sign == AST_get_node(ast_type, 0)->kind) { status = sign_from_string(AST_get_node(ast_type, 0)->value, &composite->sign); if (status == SEMANTIC_ERROR) { ERROR("invalid sign: %s", AST_get_node(ast_type, 0)->value); return SEMANTIC_ERROR; } scaleNodeOffset++; } composite->scale = 1.0; // check if we have a list of scale factors if (AST_get_node(ast_type, scaleNodeOffset)->kind == AST_List) { status = merge_scale_list(AST_get_node(ast_type, scaleNodeOffset), &composite->scale); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } } AST_NODE_PTR typeKind = AST_get_last_node(ast_type); status = primitive_from_string(typeKind->value, &composite->primitive); // type kind is not primitve, must be a predefined composite if (status == SEMANTIC_ERROR) { // not a primitive try to resolve the type by name (must be a composite) Type *nested_type = NULL; status = get_type_decl(typeKind->value, &nested_type); if (status == SEMANTIC_ERROR) { print_diagnostic(&typeKind->location, Error, "Unknown composite type in declaration"); return SEMANTIC_ERROR; } if (nested_type->kind == TypeKindComposite) { // valid composite type composite->primitive = nested_type->impl.composite.primitive; // no sign was set, use sign of type if (scaleNodeOffset == 0) { composite->sign = nested_type->impl.composite.sign; } composite->scale = composite->scale * nested_type->impl.composite.scale; if (composite->scale > 8 || composite->scale < 0.25) { print_diagnostic(&typeKind->location, Error, "Invalid type scale of composite type: %lf", composite->scale); return SEMANTIC_ERROR; } } else { print_diagnostic(&typeKind->location, Error, "Type must be either composite or primitive"); return SEMANTIC_ERROR; } } return check_scale_factor(ast_type, composite->scale); } int set_get_type_impl(AST_NODE_PTR currentNode, Type **type); int set_impl_reference_type(AST_NODE_PTR currentNode, Type **type) { DEBUG("implementing reference type"); ReferenceType reference; int status = set_get_type_impl(AST_get_node(currentNode, 0), &reference); *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); (*type)->kind = TypeKindReference; (*type)->impl.reference = reference; return status; } /** * @brief Converts the given AST node to a gemstone type implementation. * @param currentNode AST node of type kind type * @param type pointer output for the type * @return the gemstone type implementation */ int set_get_type_impl(AST_NODE_PTR currentNode, Type **type) { assert(currentNode != NULL); assert(currentNode->kind == AST_Type || currentNode->kind == AST_Reference); assert(currentNode->children->len > 0); DEBUG("start Type"); int status; if (currentNode->kind == AST_Reference) { return set_impl_reference_type(currentNode, type); } const char *typekind = AST_get_node(currentNode, currentNode->children->len - 1)->value; //find type in composites if (g_hash_table_contains(declaredComposites, typekind) == TRUE) { *type = g_hash_table_lookup(declaredComposites, typekind); return SEMANTIC_OK; } if (g_hash_table_contains(declaredBoxes, typekind) == TRUE) { *type = g_hash_table_lookup(declaredBoxes, typekind); if (currentNode->children->len > 1) { print_diagnostic(¤tNode->location, Error, "Box type cannot modified"); return SEMANTIC_ERROR; } return SEMANTIC_OK; } // type is not yet declared, make a new one Type *new_type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); new_type->nodePtr = currentNode; // only one child means either composite or primitive // try to implement primitive first // if not successfull continue building a composite if (currentNode->children->len == 1) { // type is a primitive new_type->kind = TypeKindPrimitive; status = primitive_from_string(typekind, &new_type->impl.primitive); // if err continue at composite construction if (status == SEMANTIC_OK) { *type = new_type; return SEMANTIC_OK; } print_diagnostic(&AST_get_last_node(currentNode)->location, Error, "Expected either primitive or composite type: `%s`", AST_get_last_node(currentNode)->value); return SEMANTIC_ERROR; } new_type->kind = TypeKindComposite; new_type->impl.composite.nodePtr = currentNode; status = set_impl_composite_type(currentNode, &new_type->impl.composite); *type = new_type; return status; } StorageQualifier Qualifier_from_string(const char *str) { assert(str != NULL); if (strcmp(str, "local") == 0) return Local; if (strcmp(str, "static") == 0) return Static; if (strcmp(str, "global") == 0) return Global; PANIC("Provided string is not a storagequalifier: %s", str); } int addVarToScope(Variable *variable); int createRef(AST_NODE_PTR currentNode, Type **reftype) { assert(currentNode != NULL); assert(currentNode->children->len == 1); Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); Type *referenceType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); referenceType->kind = TypeKindReference; referenceType->nodePtr = currentNode; AST_NODE_PTR ast_type = AST_get_node(currentNode, 0); int signal = set_get_type_impl(ast_type, &type); if (signal) { return SEMANTIC_ERROR; } referenceType->impl.reference = type; *reftype = referenceType; return SEMANTIC_OK; } int createDecl(AST_NODE_PTR currentNode, GArray **variables) { DEBUG("create declaration"); AST_NODE_PTR ident_list = AST_get_last_node(currentNode); *variables = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *)); VariableDeclaration decl; decl.nodePtr = currentNode; decl.qualifier = Static; int status = SEMANTIC_OK; DEBUG("Child Count: %i", currentNode->children->len); for (size_t i = 0; i < currentNode->children->len; i++) { switch (AST_get_node(currentNode, i)->kind) { case AST_Storage: DEBUG("fill Qualifier"); decl.qualifier = Qualifier_from_string(AST_get_node(currentNode, i)->value); break; case AST_Type: DEBUG("fill Type"); status = set_get_type_impl(AST_get_node(currentNode, i), &decl.type); break; case AST_IdentList: break; case AST_Reference: status = createRef(AST_get_node(currentNode, i), &decl.type); break; default: PANIC("invalid node type: %ld", AST_get_node(currentNode, i)->kind); break; } } for (size_t i = 0; i < ident_list->children->len; i++) { Variable *variable = mem_alloc(MemoryNamespaceSet, sizeof(Variable)); variable->kind = VariableKindDeclaration; variable->nodePtr = currentNode; variable->name = AST_get_node(ident_list, i)->value; variable->impl.declaration = decl; g_array_append_val(*variables, variable); int signal = addVarToScope(variable); if (signal) { return SEMANTIC_ERROR; } } return status; } Expression *createExpression(AST_NODE_PTR currentNode); int createDef(AST_NODE_PTR currentNode, GArray **variables) { assert(variables != NULL); assert(currentNode != NULL); assert(currentNode->kind == AST_Def); DEBUG("create definition"); AST_NODE_PTR declaration = AST_get_node(currentNode, 0); AST_NODE_PTR expression = AST_get_node(currentNode, 1); AST_NODE_PTR ident_list = AST_get_last_node(declaration); *variables = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *)); VariableDeclaration decl; VariableDefiniton def; def.nodePtr = currentNode; decl.qualifier = Static; decl.nodePtr = AST_get_node(currentNode, 0); int status = SEMANTIC_OK; DEBUG("Child Count: %i", declaration->children->len); for (size_t i = 0; i < declaration->children->len; i++) { AST_NODE_PTR child = AST_get_node(declaration, i); switch (child->kind) { case AST_Storage: DEBUG("fill Qualifier"); decl.qualifier = Qualifier_from_string(child->value); break; case AST_Reference: case AST_Type: DEBUG("fill Type"); status = set_get_type_impl(child, &decl.type); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } break; case AST_IdentList: break; default: PANIC("invalid node type: %ld", child->kind); break; } } def.declaration = decl; Expression *name = createExpression(expression); if (name == NULL) { status = SEMANTIC_OK; } if (!compareTypes(def.declaration.type, name->result)) { char *expected_type = type_to_string(def.declaration.type); char *gotten_type = type_to_string(name->result); print_diagnostic(&name->nodePtr->location, Warning, "expected `%s` got `%s`", expected_type, gotten_type); def.initializer = mem_alloc(MemoryNamespaceSet, sizeof(Expression)); if (createTypeCastFromExpression(name, def.declaration.type, &def.initializer) == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } } else { def.initializer = name; } for (size_t i = 0; i < ident_list->children->len; i++) { Variable *variable = mem_alloc(MemoryNamespaceSet, sizeof(Variable)); variable->kind = VariableKindDefinition; variable->nodePtr = currentNode; variable->name = AST_get_node(ident_list, i)->value; variable->impl.definiton = def; g_array_append_val(*variables, variable); if (addVarToScope(variable) == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } } return status; } char *type_to_string(Type *type) { char *string = NULL; switch (type->kind) { case TypeKindPrimitive: if (type->impl.primitive == Int) { string = mem_strdup(MemoryNamespaceSet, "int"); } else if (type->impl.primitive == Float){ string = mem_strdup(MemoryNamespaceSet, "float"); } else if (type->impl.primitive == Char){ string = mem_strdup(MemoryNamespaceSet, "codepoint"); } break; case TypeKindComposite: { if (type->impl.composite.primitive == Int) { string = mem_strdup(MemoryNamespaceSet, "int"); } else { string = mem_strdup(MemoryNamespaceSet, "float"); } if (type->impl.composite.scale < 1.0) { for (int i = 0; i < (int) (type->impl.composite.scale * 4); i++) { char *concat = g_strconcat("half ", string, NULL); string = mem_strdup(MemoryNamespaceSet, concat); g_free(concat); } } else if (type->impl.composite.scale > 1.0) { for (int i = 0; i < (int) type->impl.composite.scale; i++) { char *concat = g_strconcat("long ", string, NULL); string = mem_strdup(MemoryNamespaceSet, concat); g_free(concat); } } if (type->impl.composite.sign == Unsigned) { char *concat = g_strconcat("unsigned ", string, NULL); string = mem_strdup(MemoryNamespaceSet, concat); g_free(concat); } break; } case TypeKindReference: { char *type_string = type_to_string(type->impl.reference); char *concat = g_strconcat("ref ", type_string, NULL); mem_free(type_string); string = mem_strdup(MemoryNamespaceSet, concat); g_free(concat); break; } case TypeKindBox: string = mem_strdup(MemoryNamespaceSet, "box"); break; } return string; } int getParameter(const char *name, Parameter **parameter) { // loop through all variable scope and find a variable if (functionParameter != NULL) { if (g_hash_table_contains(functionParameter, name)) { *parameter = g_hash_table_lookup(functionParameter, name); return SEMANTIC_OK; } } return SEMANTIC_ERROR; } int getVariableFromScope(const char *name, Variable **variable) { assert(name != NULL); assert(variable != NULL); assert(Scope != NULL); DEBUG("getting var from scope"); int found = 0; for (size_t i = 0; i < Scope->len; i++) { GHashTable *variable_table = g_array_index(Scope, GHashTable*, i); if (g_hash_table_contains(variable_table, name)) { if (found == 0) { *variable = g_hash_table_lookup(variable_table, name); } found += 1; } } if (found == 1) { DEBUG("Var: %s", (*variable)->name); DEBUG("Var Typekind: %d", (*variable)->kind); DEBUG("Found var"); return SEMANTIC_OK; } else if (found > 1) { print_diagnostic(&(*variable)->nodePtr->location, Warning, "Parameter shadows variable of same name: %s", name); return SEMANTIC_OK; } DEBUG("nothing found"); return SEMANTIC_ERROR; } int addVarToScope(Variable *variable) { Variable *tmp = NULL; if (getVariableFromScope(variable->name, &tmp) == SEMANTIC_OK) { print_diagnostic(&variable->nodePtr->location, Error, "Variable already exist: ", variable->name); return SEMANTIC_ERROR; } GHashTable *currentScope = g_array_index(Scope, GHashTable*, Scope->len - 1); g_hash_table_insert(currentScope, (gpointer) variable->name, variable); return SEMANTIC_OK; } int fillTablesWithVars(GHashTable *variableTable, const GArray *variables) { DEBUG("filling vars in scope and table"); for (size_t i = 0; i < variables->len; i++) { Variable *var = g_array_index(variables, Variable *, i); // this variable is discarded, only need status code if (g_hash_table_contains(variableTable, (gpointer) var->name)) { print_diagnostic(&var->nodePtr->location, Error, "Variable already exists"); return SEMANTIC_ERROR; } g_hash_table_insert(variableTable, (gpointer) var->name, var); } return SEMANTIC_OK; } [[nodiscard("type must be freed")]] TypeValue createTypeValue(AST_NODE_PTR currentNode) { DEBUG("create TypeValue"); TypeValue value; Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); value.type = type; type->kind = TypeKindPrimitive; type->nodePtr = currentNode; switch (currentNode->kind) { case AST_Int: type->impl.primitive = Int; break; case AST_Float: type->impl.primitive = Float; break; case AST_Char: // validate we have a single UTF-8 codepoint if (g_utf8_strlen(currentNode->value, 4) != 1) { print_diagnostic(¤tNode->location, Error, "Character must be UTF-8 codepoint"); } type->impl.primitive = Char; break; default: PANIC("Node is not an expression but from kind: %i", currentNode->kind); break; } value.nodePtr = currentNode; value.value = currentNode->value; return value; } #define CLONE(x) mem_clone(MemoryNamespaceSet, (void*)&(x), sizeof(x)) TypeValue createString(AST_NODE_PTR currentNode) { DEBUG("create String"); TypeValue value; Type *type = CLONE(StringLiteralType); value.type = type; value.nodePtr = currentNode; value.value = currentNode->value; return value; } Type *createTypeFromOperands(Type *LeftOperandType, Type *RightOperandType, AST_NODE_PTR currentNode) { DEBUG("create type from operands"); Type *result = mem_alloc(MemoryNamespaceSet, sizeof(Type)); result->nodePtr = currentNode; DEBUG("LeftOperandType->kind: %i", LeftOperandType->kind); DEBUG("RightOperandType->kind: %i", RightOperandType->kind); if (LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindComposite) { result->kind = TypeKindComposite; CompositeType resultImpl; resultImpl.nodePtr = currentNode; resultImpl.sign = MAX(LeftOperandType->impl.composite.sign, RightOperandType->impl.composite.sign); resultImpl.scale = MAX(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale); resultImpl.primitive = MAX(LeftOperandType->impl.composite.primitive, RightOperandType->impl.composite.primitive); result->impl.composite = resultImpl; } else if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive) { DEBUG("both operands are primitive"); result->kind = TypeKindPrimitive; result->impl.primitive = MAX(LeftOperandType->impl.primitive, RightOperandType->impl.primitive); } else if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite) { result->kind = TypeKindComposite; result->impl.composite.sign = Signed; result->impl.composite.scale = MAX(1.0, RightOperandType->impl.composite.scale); result->impl.composite.primitive = MAX(Int, RightOperandType->impl.composite.primitive); result->impl.composite.nodePtr = currentNode; } else if (LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive) { result->kind = TypeKindComposite; result->impl.composite.sign = Signed; result->impl.composite.scale = MAX(1.0, LeftOperandType->impl.composite.scale); result->impl.composite.primitive = MAX(Int, LeftOperandType->impl.composite.primitive); result->impl.composite.nodePtr = currentNode; } else { mem_free(result); print_diagnostic(¤tNode->location, Error, "Incompatible types in expression"); return NULL; } DEBUG("Succsessfully created type"); return result; } int createTypeCastFromExpression(Expression *expression, Type *resultType, Expression **result) { Expression *expr = mem_alloc(MemoryNamespaceSet, sizeof(Expression)); expr->result = resultType; expr->nodePtr = expression->nodePtr; expr->kind = ExpressionKindTypeCast; TypeCast typeCast; typeCast.nodePtr = expression->nodePtr; typeCast.targetType = resultType; typeCast.operand = expression; expr->impl.typecast = typeCast; if (expression->result->kind != TypeKindComposite && expression->result->kind != TypeKindPrimitive) { print_diagnostic(&expression->nodePtr->location, Error, "Expected either primitive or composite type"); return SEMANTIC_ERROR; } *result = expr; return SEMANTIC_OK; } int createArithOperation(Expression *ParentExpression, AST_NODE_PTR currentNode, size_t expectedChildCount) { DEBUG("create arithmetic operation"); ParentExpression->impl.operation.kind = Arithmetic; ParentExpression->impl.operation.nodePtr = currentNode; ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); assert(expectedChildCount == currentNode->children->len); for (size_t i = 0; i < currentNode->children->len; i++) { Expression *expression = createExpression(AST_get_node(currentNode, i)); if (NULL == expression) { return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands, expression); } DEBUG("created all Expressions"); switch (currentNode->kind) { case AST_Add: ParentExpression->impl.operation.impl.arithmetic = Add; break; case AST_Sub: ParentExpression->impl.operation.impl.arithmetic = Sub; break; case AST_Mul: ParentExpression->impl.operation.impl.arithmetic = Mul; break; case AST_Div: ParentExpression->impl.operation.impl.arithmetic = Div; break; case AST_Negate: ParentExpression->impl.operation.impl.arithmetic = Negate; break; default: PANIC("Current node is not an arithmetic operater"); break; } if (ParentExpression->impl.operation.impl.arithmetic == Negate) { Type *result = g_array_index(ParentExpression->impl.operation.operands, Expression *, 0)->result; result->nodePtr = currentNode; if (result->kind == TypeKindReference || result->kind == TypeKindBox) { print_diagnostic(¤tNode->location, Error, "Invalid type for arithmetic operation"); return SEMANTIC_ERROR; } else if (result->kind == TypeKindComposite) { result->impl.composite.sign = Signed; } ParentExpression->result = result; } else { Type *LeftOperandType = g_array_index(ParentExpression->impl.operation.operands, Expression *, 0)->result; Type *RightOperandType = g_array_index(ParentExpression->impl.operation.operands, Expression *, 1)->result; ParentExpression->result = createTypeFromOperands(LeftOperandType, RightOperandType, currentNode); } if (ParentExpression->result == NULL) { return SEMANTIC_ERROR; } for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); if (!compareTypes(operand->result, ParentExpression->result)) { Expression *result; int status = createTypeCastFromExpression(operand, ParentExpression->result, &result); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } g_array_index(ParentExpression->impl.operation.operands, Expression*, i) = result; } } return SEMANTIC_OK; } int createRelationalOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { // fill kind and Nodeptr ParentExpression->impl.operation.kind = Relational; ParentExpression->impl.operation.nodePtr = currentNode; ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); // fill Operands for (size_t i = 0; i < currentNode->children->len; i++) { Expression *expression = createExpression(AST_get_node(currentNode, i)); if (NULL == expression) { return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands, expression); } // fill impl switch (currentNode->kind) { case AST_Eq: ParentExpression->impl.operation.impl.relational = Equal; break; case AST_Less: ParentExpression->impl.operation.impl.relational = Less; break; case AST_Greater: ParentExpression->impl.operation.impl.relational = Greater; break; default: PANIC("Current node is not an relational operater"); break; } Type *result = mem_alloc(MemoryNamespaceSet, sizeof(Type)); result->impl.primitive = Int; result->kind = TypeKindPrimitive; result->nodePtr = currentNode; ParentExpression->result = result; for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); if (!compareTypes(operand->result, ParentExpression->result)) { Expression *expr; int status = createTypeCastFromExpression(operand, ParentExpression->result, &expr); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } g_array_index(ParentExpression->impl.operation.operands, Expression*, i) = expr; } } return 0; } int createBoolOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { // fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); // fill Operands for (size_t i = 0; i < currentNode->children->len; i++) { Expression *expression = createExpression(AST_get_node(currentNode, i)); if (NULL == expression) { return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands, expression); } switch (currentNode->kind) { case AST_BoolAnd: ParentExpression->impl.operation.impl.boolean = BooleanAnd; break; case AST_BoolOr: ParentExpression->impl.operation.impl.boolean = BooleanOr; break; case AST_BoolXor: ParentExpression->impl.operation.impl.boolean = BooleanXor; break; default: PANIC("Current node is not an boolean operator"); break; } Expression *lhs = g_array_index(ParentExpression->impl.operation.operands, Expression*, 0); Expression *rhs = g_array_index(ParentExpression->impl.operation.operands, Expression*, 1); Type *LeftOperandType = lhs->result; Type *RightOperandType = rhs->result; // should not be a box or a reference if (LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite) { print_diagnostic(&lhs->nodePtr->location, Error, "invalid type for boolean operation"); return SEMANTIC_ERROR; } if (RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite) { print_diagnostic(&rhs->nodePtr->location, Error, "invalid type for boolean operation"); return SEMANTIC_ERROR; } // should not be a float if (LeftOperandType->kind == TypeKindComposite) { if (LeftOperandType->impl.composite.primitive == Float) { print_diagnostic(&lhs->nodePtr->location, Error, "operand must not be a float"); return SEMANTIC_ERROR; } } else if (LeftOperandType->kind == TypeKindPrimitive) { if (LeftOperandType->impl.primitive == Float) { print_diagnostic(&lhs->nodePtr->location, Error, "operand must not be a float"); return SEMANTIC_ERROR; } } else if (RightOperandType->kind == TypeKindComposite) { if (RightOperandType->impl.composite.primitive == Float) { print_diagnostic(&rhs->nodePtr->location, Error, "operand must not be a float"); return SEMANTIC_ERROR; } } else if (RightOperandType->kind == TypeKindPrimitive) { if (RightOperandType->impl.primitive == Float) { print_diagnostic(&rhs->nodePtr->location, Error, "operand must not be a float"); return SEMANTIC_ERROR; } } ParentExpression->result = createTypeFromOperands(LeftOperandType, RightOperandType, currentNode); for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); if (!compareTypes(operand->result, ParentExpression->result)) { Expression *expr; int status = createTypeCastFromExpression(operand, ParentExpression->result, &expr); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } g_array_index(ParentExpression->impl.operation.operands, Expression*, i) = expr; } } return SEMANTIC_OK; } int createBoolNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { //fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); //fill Operand Expression *expression = createExpression(AST_get_node(currentNode, 0)); if (NULL == expression) { return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands, expression); ParentExpression->impl.operation.impl.boolean = BooleanNot; Type *Operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, 0)->result; Type *result = mem_alloc(MemoryNamespaceSet, sizeof(Type)); result->nodePtr = currentNode; if (Operand->kind == TypeKindBox || Operand->kind == TypeKindReference) { print_diagnostic(&Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); return SEMANTIC_ERROR; } if (Operand->kind == TypeKindPrimitive) { if (Operand->impl.primitive == Float) { print_diagnostic(&Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); return SEMANTIC_ERROR; } result->kind = Operand->kind; result->impl = Operand->impl; } else if (Operand->kind == TypeKindComposite) { if (Operand->impl.composite.primitive == Float) { print_diagnostic(&Operand->nodePtr->location, Error, "Operand must be a variant of primitive type int"); return SEMANTIC_ERROR; } result->kind = Operand->kind; result->impl = Operand->impl; } ParentExpression->result = result; for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); if (!compareTypes(operand->result, ParentExpression->result)) { Expression *expr; int status = createTypeCastFromExpression(operand, ParentExpression->result, &expr); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } g_array_index(ParentExpression->impl.operation.operands, Expression*, i) = expr; } } return SEMANTIC_OK; } bool isScaleEqual(double leftScale, double rightScale) { int leftIntScale = (int) (leftScale * BASE_BYTES); int rightIntScale = (int) (rightScale * BASE_BYTES); return leftIntScale == rightIntScale; } int createBitOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { // fill kind and Nodeptr ParentExpression->impl.operation.kind = Boolean; ParentExpression->impl.operation.nodePtr = currentNode; ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); // fill Operands for (size_t i = 0; i < currentNode->children->len; i++) { Expression *expression = createExpression(AST_get_node(currentNode, i)); if (NULL == expression) { return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands, expression); } switch (currentNode->kind) { case AST_BitAnd: ParentExpression->impl.operation.impl.bitwise = BitwiseAnd; break; case AST_BitOr: ParentExpression->impl.operation.impl.bitwise = BitwiseOr; break; case AST_BitXor: ParentExpression->impl.operation.impl.bitwise = BitwiseXor; break; default: PANIC("Current node is not an bitwise operater"); break; } Type *result = mem_alloc(MemoryNamespaceSet, sizeof(Type)); result->nodePtr = currentNode; Expression *lhs = g_array_index(ParentExpression->impl.operation.operands, Expression*, 0); Expression *rhs = g_array_index(ParentExpression->impl.operation.operands, Expression*, 1); Type *LeftOperandType = lhs->result; Type *RightOperandType = rhs->result; //should not be a box or a reference if (LeftOperandType->kind != TypeKindPrimitive && LeftOperandType->kind != TypeKindComposite) { print_diagnostic(&lhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } if (RightOperandType->kind != TypeKindPrimitive && RightOperandType->kind != TypeKindComposite) { print_diagnostic(&rhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindPrimitive) { if (LeftOperandType->impl.primitive == Float) { print_diagnostic(&lhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } if (RightOperandType->impl.primitive == Float) { print_diagnostic(&rhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } result->kind = TypeKindPrimitive; result->impl.primitive = Int; } else if (LeftOperandType->kind == TypeKindPrimitive && RightOperandType->kind == TypeKindComposite) { if (LeftOperandType->impl.primitive == Float) { print_diagnostic(&lhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } if (RightOperandType->impl.composite.primitive == Float) { print_diagnostic(&rhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } result->kind = TypeKindPrimitive; result->impl.primitive = Int; } else if (LeftOperandType->kind == TypeKindComposite && RightOperandType->kind == TypeKindPrimitive) { if (LeftOperandType->impl.composite.primitive == Float) { print_diagnostic(&lhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } if (RightOperandType->impl.primitive == Float) { print_diagnostic(&rhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } result->kind = TypeKindPrimitive; result->impl.primitive = Int; } else { if (RightOperandType->impl.composite.primitive == Float) { print_diagnostic(&rhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } if (LeftOperandType->impl.composite.primitive == Float) { print_diagnostic(&lhs->nodePtr->location, Error, "Must be a type variant of int"); return SEMANTIC_ERROR; } if (!isScaleEqual(LeftOperandType->impl.composite.scale, RightOperandType->impl.composite.scale)) { print_diagnostic(¤tNode->location, Error, "Operands must be of equal size"); return SEMANTIC_ERROR; } result->kind = TypeKindComposite; result->impl.composite.nodePtr = currentNode; result->impl.composite.scale = LeftOperandType->impl.composite.scale; result->impl.composite.sign = MAX(LeftOperandType->impl.composite.sign, RightOperandType->impl.composite.sign); } ParentExpression->result = result; for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); if (!compareTypes(operand->result, ParentExpression->result)) { Expression *expr; int status = createTypeCastFromExpression(operand, ParentExpression->result, &expr); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } g_array_index(ParentExpression->impl.operation.operands, Expression*, i) = expr; } } return 0; } int createBitNotOperation(Expression *ParentExpression, AST_NODE_PTR currentNode) { //fill kind and Nodeptr ParentExpression->impl.operation.kind = Bitwise; ParentExpression->impl.operation.nodePtr = currentNode; ParentExpression->impl.operation.operands = mem_new_g_array(MemoryNamespaceSet, sizeof(Expression *)); //fill Operand Expression *expression = createExpression(AST_get_node(currentNode, 0)); if (NULL == expression) { return SEMANTIC_ERROR; } g_array_append_val(ParentExpression->impl.operation.operands, expression); ParentExpression->impl.operation.impl.bitwise = BitwiseNot; Type *Operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, 0)->result; Type *result = mem_alloc(MemoryNamespaceSet, sizeof(Type)); result->nodePtr = currentNode; if (Operand->kind == TypeKindPrimitive) { if (Operand->impl.primitive == Float) { print_diagnostic(&Operand->nodePtr->location, Error, "Operand type must be a variant of int"); return SEMANTIC_ERROR; } result->kind = TypeKindPrimitive; result->impl.primitive = Int; } else if (Operand->kind == TypeKindComposite) { if (Operand->impl.composite.primitive == Float) { print_diagnostic(&Operand->nodePtr->location, Error, "Operand type must be a variant of int"); return SEMANTIC_ERROR; } result->kind = TypeKindComposite; result->impl.composite.nodePtr = currentNode; result->impl.composite.primitive = Int; result->impl.composite.sign = Operand->impl.composite.sign; result->impl.composite.scale = Operand->impl.composite.scale; } ParentExpression->result = result; for (size_t i = 0; i < ParentExpression->impl.operation.operands->len; i++) { Expression *operand = g_array_index(ParentExpression->impl.operation.operands, Expression*, i); if (!compareTypes(operand->result, ParentExpression->result)) { Expression *expr; int status = createTypeCastFromExpression(operand, ParentExpression->result, &expr); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } g_array_index(ParentExpression->impl.operation.operands, Expression*, i) = expr; } } return SEMANTIC_OK; } /** * @brief Return a copy of all BoxMembers specified by their name in names from a boxes type * Will run recursively in case the first name refers to a subbox * @param currentBoxType * @param names * @return */ GArray *getBoxMember(Type *currentBoxType, GArray *names) { GArray *members = mem_new_g_array(MemoryNamespaceSet, sizeof(BoxMember)); // list of members of the type GHashTable *memberList = currentBoxType->impl.box->member; // name of member to extract const char *currentName = g_array_index(names, const char *, 0); // look for member of this name if (g_hash_table_contains(memberList, currentName)) { // get member and store in array BoxMember *currentMember = g_hash_table_lookup(memberList, currentName); g_array_append_val(members, currentMember); // last name in list, return g_array_remove_index(names, 0); if (names->len == 0) { return members; } // other names may refer to members of child boxes if (currentMember->type->kind == TypeKindBox) { GArray *otherMember = getBoxMember(currentMember->type, names); if (NULL == otherMember) { return NULL; } g_array_append_vals(members, (BoxMember *) otherMember->data, otherMember->len); return members; } } return NULL; } int createBoxAccess(Expression *ParentExpression, AST_NODE_PTR currentNode) { const char *boxname = AST_get_node(currentNode, 0)->value; Variable *boxVariable = NULL; int status = getVariableFromScope(boxname, &boxVariable); if (status == SEMANTIC_ERROR) { print_diagnostic(&AST_get_node(currentNode, 0)->location, Error, "Variable of name `%s` does not exist"); return SEMANTIC_ERROR; } Type *boxType; if (boxVariable->kind == VariableKindDeclaration) { boxType = boxVariable->impl.declaration.type; } else if (boxVariable->kind == VariableKindDefinition) { boxType = boxVariable->impl.definiton.declaration.type; } else { return SEMANTIC_ERROR; } if (boxType->kind != TypeKindBox) { return SEMANTIC_ERROR; } // filling boxAccess variable ParentExpression->impl.variable->kind = VariableKindBoxMember; ParentExpression->impl.variable->nodePtr = currentNode; ParentExpression->impl.variable->name = NULL; ParentExpression->impl.variable->impl.member.nodePtr = currentNode; //filling boxacces.variable ParentExpression->impl.variable->impl.member.variable = boxVariable; //first one is the box itself GArray *names = mem_alloc(MemoryNamespaceSet, sizeof(GArray)); if (currentNode->kind == AST_IdentList) { for (size_t i = 1; i < currentNode->children->len; i++) { g_array_append_val(names, AST_get_node(currentNode, i)->value); } } else if (currentNode->kind == AST_List) { for (size_t i = 1; i < AST_get_node(currentNode, 1)->children->len; i++) { g_array_append_val(names, AST_get_node(AST_get_node(currentNode, 1), i)->value); } } else { PANIC("current Node is not an Access"); } GArray *boxMember = getBoxMember(boxType, names); ParentExpression->impl.variable->impl.member.member = boxMember; ParentExpression->result = g_array_index(boxMember, BoxMember, boxMember->len).type; return SEMANTIC_OK; } int createTypeCast(Expression *ParentExpression, AST_NODE_PTR currentNode) { DEBUG("create type cast"); ParentExpression->impl.typecast.nodePtr = currentNode; ParentExpression->impl.typecast.operand = createExpression(AST_get_node(currentNode, 0)); if (ParentExpression->impl.typecast.operand == NULL) { return SEMANTIC_ERROR; } if (ParentExpression->impl.typecast.operand->result->kind != TypeKindComposite && ParentExpression->impl.typecast.operand->result->kind != TypeKindPrimitive && ParentExpression->impl.typecast.operand->result->kind != TypeKindReference) { print_diagnostic(¤tNode->location, Error, "cannot cast type: `%s`", type_to_string(ParentExpression->impl.typecast.operand->result)); return SEMANTIC_ERROR; } Type *target = mem_alloc(MemoryNamespaceSet, sizeof(Type)); int status = set_get_type_impl(AST_get_node(currentNode, 1), &target); if (status) { return SEMANTIC_ERROR; } ParentExpression->impl.typecast.targetType = target; ParentExpression->result = target; return SEMANTIC_OK; } int createTransmute(Expression *ParentExpression, AST_NODE_PTR currentNode) { ParentExpression->impl.transmute.nodePtr = currentNode; ParentExpression->impl.transmute.operand = createExpression(AST_get_node(currentNode, 0)); if (ParentExpression->impl.transmute.operand == NULL) { return SEMANTIC_ERROR; } Type *target = mem_alloc(MemoryNamespaceSet, sizeof(Type)); int status = set_get_type_impl(AST_get_node(currentNode, 1), &target); if (status) { print_diagnostic(&AST_get_node(currentNode, 1)->location, Error, "Unknown type"); return SEMANTIC_ERROR; } ParentExpression->impl.typecast.targetType = target; ParentExpression->result = target; return SEMANTIC_OK; } int createDeref(Expression *ParentExpression, AST_NODE_PTR currentNode) { assert(currentNode->children->len == 2); Dereference deref; deref.nodePtr = currentNode; AST_NODE_PTR expression_node = AST_get_node(currentNode, 1); deref.index = createExpression(expression_node); //index has to be made if (deref.index == NULL) { return SEMANTIC_ERROR; } Type *indexType = deref.index->result; //indexType can only be a composite or a primitive if (indexType->kind != TypeKindComposite && indexType->kind != TypeKindPrimitive) { print_diagnostic(&expression_node->location, Error, "Index must a primitive int or composite variation"); return SEMANTIC_ERROR; } //indexType can only be int if (indexType->kind == TypeKindPrimitive) { if (indexType->impl.primitive != Int) { print_diagnostic(&AST_get_node(currentNode, 1)->location, Error, "Index must a primitive int or composite variation"); return SEMANTIC_ERROR; } } if (indexType->kind == TypeKindComposite) { if (indexType->impl.composite.primitive != Int) { print_diagnostic(&AST_get_node(currentNode, 1)->location, Error, "Index must a primitive int or composite variation"); return SEMANTIC_ERROR; } } deref.variable = createExpression(AST_get_node(currentNode, 0)); //variable has to be made if (deref.index == NULL) { print_diagnostic(&AST_get_node(currentNode, 0)->location, Error, "Invalid index"); return SEMANTIC_ERROR; } //variable can only be a reference if (deref.variable->result->kind != TypeKindReference) { print_diagnostic(&AST_get_node(currentNode, 0)->location, Error, "Only references can be dereferenced"); return SEMANTIC_ERROR; } ParentExpression->impl.dereference = deref; ParentExpression->result = deref.variable->result->impl.reference; return SEMANTIC_OK; } int createAddressOf(Expression *ParentExpression, AST_NODE_PTR currentNode) { assert(currentNode != NULL); assert(currentNode->children->len == 1); AddressOf address_of; address_of.node_ptr = currentNode; address_of.variable = createExpression(AST_get_node(currentNode, 0)); if (address_of.variable == NULL) { return SEMANTIC_ERROR; } Type *resultType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); resultType->nodePtr = currentNode; resultType->kind = TypeKindReference; resultType->impl.reference = address_of.variable->result; ParentExpression->impl.addressOf = address_of; ParentExpression->result = resultType; return SEMANTIC_OK; } IO_Qualifier getParameterQualifier(Parameter *parameter) { if (parameter->kind == ParameterDeclarationKind) { return parameter->impl.declaration.qualifier; } else { return parameter->impl.definiton.declaration.qualifier; } } int createfuncall(FunctionCall* funcall, AST_NODE_PTR currentNode); Expression *createExpression(AST_NODE_PTR currentNode) { DEBUG("create Expression"); Expression *expression = mem_alloc(MemoryNamespaceSet, sizeof(Expression)); expression->nodePtr = currentNode; switch (currentNode->kind) { case AST_Int: case AST_Float: case AST_Char: expression->kind = ExpressionKindConstant; expression->impl.constant = createTypeValue(currentNode); expression->result = expression->impl.constant.type; break; case AST_String: expression->kind = ExpressionKindConstant; expression->impl.constant = createString(currentNode); expression->result = expression->impl.constant.type; break; case AST_Ident: DEBUG("find var"); expression->kind = ExpressionKindVariable; int status = getVariableFromScope(currentNode->value, &expression->impl.variable); if (status == SEMANTIC_ERROR) { expression->kind = ExpressionKindParameter; status = getParameter(currentNode->value, &expression->impl.parameter); if (status == SEMANTIC_ERROR) { DEBUG("Identifier is not in current scope"); print_diagnostic(¤tNode->location, Error, "Unknown identifier: `%s`", currentNode->value); return NULL; } if (getParameterQualifier(expression->impl.parameter) == Out) { print_diagnostic(¤tNode->location, Error, "Parameter is write-only: `%s`", currentNode->value); return NULL; } if (expression->impl.parameter->kind == ParameterDeclarationKind) { expression->result = expression->impl.parameter->impl.declaration.type; } else { expression->result = expression->impl.parameter->impl.definiton.declaration.type; } } else { if (expression->impl.variable->kind == VariableKindDeclaration) { expression->result = expression->impl.variable->impl.declaration.type; } else { expression->result = expression->impl.variable->impl.definiton.declaration.type; } } break; case AST_Add: case AST_Sub: case AST_Mul: case AST_Div: expression->kind = ExpressionKindOperation; if (createArithOperation(expression, currentNode, 2)) { return NULL; } break; case AST_Negate: expression->kind = ExpressionKindOperation; if (createArithOperation(expression, currentNode, 1)) { return NULL; } break; case AST_Eq: case AST_Less: case AST_Greater: expression->kind = ExpressionKindOperation; if (createRelationalOperation(expression, currentNode)) { return NULL; } break; case AST_BoolAnd: case AST_BoolOr: case AST_BoolXor: expression->kind = ExpressionKindOperation; if (createBoolOperation(expression, currentNode)) { return NULL; } break; case AST_BoolNot: expression->kind = ExpressionKindOperation; if (createBoolNotOperation(expression, currentNode)) { return NULL; } break; case AST_BitAnd: case AST_BitOr: case AST_BitXor: expression->kind = ExpressionKindOperation; if (createBitOperation(expression, currentNode)) { return NULL; } break; case AST_BitNot: expression->kind = ExpressionKindOperation; if (createBitNotOperation(expression, currentNode)) { return NULL; } break; case AST_IdentList: case AST_List: expression->kind = ExpressionKindVariable; if (createBoxAccess(expression, currentNode)) { return NULL; } break; case AST_Typecast: expression->kind = ExpressionKindTypeCast; if (createTypeCast(expression, currentNode)) { return NULL; } break; case AST_Transmute: expression->kind = ExpressionKindTransmute; if (createTransmute(expression, currentNode)) { return NULL; } break; case AST_Dereference: expression->kind = ExpressionKindDereference; if (createDeref(expression, currentNode)) { return NULL; } break; case AST_AddressOf: expression->kind = ExpressionKindAddressOf; if (createAddressOf(expression, 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; } DEBUG("expression result typekind: %d", expression->result->kind); DEBUG("successfully created Expression"); return expression; } bool compareTypes(Type *leftType, Type *rightType) { if (leftType->kind == TypeKindPrimitive && rightType->kind == TypeKindPrimitive) { return leftType->impl.primitive == rightType->impl.primitive; } if (leftType->kind == TypeKindComposite) { if (rightType->kind == TypeKindPrimitive) { CompositeType leftComposite = leftType->impl.composite; if (leftComposite.scale == 1 && leftComposite.sign == Signed) { return leftComposite.primitive == rightType->impl.primitive; } return FALSE; } else if (rightType->kind == TypeKindComposite) { // Compare composites CompositeType leftComposite = leftType->impl.composite; CompositeType rightComposite = rightType->impl.composite; if (leftComposite.primitive != rightComposite.primitive) { return FALSE; } if (leftComposite.sign != rightComposite.sign) { return FALSE; } if (leftComposite.scale != rightComposite.scale) { return FALSE; } return TRUE; } return FALSE; } if (leftType->kind == TypeKindBox && rightType->kind == TypeKindBox) { if (leftType->impl.box != rightType->impl.box) { return FALSE; } return TRUE; } if (leftType->kind == TypeKindReference && rightType->kind == TypeKindReference) { bool result = compareTypes(leftType->impl.reference, rightType->impl.reference); return result; } return FALSE; } Type *getVariableType(Variable *variable) { if (variable->kind == VariableKindDeclaration) { return variable->impl.declaration.type; } else { return variable->impl.definiton.declaration.type; } } Type *getParameterType(Parameter *parameter) { if (parameter->kind == ParameterDeclarationKind) { return parameter->impl.declaration.type; } else { return parameter->impl.definiton.declaration.type; } } int createStorageExpr(StorageExpr *expr, AST_NODE_PTR node) { switch (node->kind) { case AST_Ident: expr->kind = StorageExprKindVariable; int status = getVariableFromScope(node->value, &expr->impl.variable); if (status == SEMANTIC_ERROR) { expr->kind = StorageExprKindParameter; status = getParameter(node->value, &expr->impl.parameter); if (status == SEMANTIC_ERROR) { print_diagnostic(&node->location, Error, "Unknown token: `%s`", node->value); return SEMANTIC_ERROR; } else { expr->target_type = getParameterType(expr->impl.parameter); } } else { expr->target_type = getVariableType(expr->impl.variable); } break; case AST_Dereference: expr->kind = StorageExprKindDereference; AST_NODE_PTR array_node = AST_get_node(node, 0); AST_NODE_PTR index_node = AST_get_node(node, 1); expr->impl.dereference.index = createExpression(index_node); expr->impl.dereference.array = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr)); if (createStorageExpr(expr->impl.dereference.array, array_node) == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } if (expr->impl.dereference.array->target_type->kind == TypeKindReference) { expr->target_type = expr->impl.dereference.array->target_type->impl.reference; } else { print_diagnostic(&array_node->location, Error, "Cannot dereference non reference type: %s", type_to_string(expr->impl.dereference.array->target_type)); return SEMANTIC_ERROR; }; break; default: print_message(Error, "Unimplemented"); return SEMANTIC_ERROR; break; } return SEMANTIC_OK; } int createAssign(Statement *ParentStatement, AST_NODE_PTR currentNode) { DEBUG("create Assign"); Assignment assign; assign.nodePtr = currentNode; assign.destination = mem_alloc(MemoryNamespaceSet, sizeof(StorageExpr)); AST_NODE_PTR strg_expr = AST_get_node(currentNode, 0); int status = createStorageExpr(assign.destination, strg_expr); if (status == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } if (strg_expr->kind == AST_Parameter) { if (getParameterQualifier(assign.destination->impl.parameter) == In) { print_diagnostic(¤tNode->location, Error, "Parameter is read-only: `%s`", assign.destination->impl.parameter->name); return SEMANTIC_ERROR; } } assign.value = createExpression(AST_get_node(currentNode, 1)); if (assign.value == NULL) { return SEMANTIC_ERROR; } if (!compareTypes(assign.destination->target_type, assign.value->result)) { print_diagnostic(&assign.value->nodePtr->location, Error, "assignment requires `%s` but got `%s`", type_to_string(assign.destination->target_type), type_to_string(assign.value->result)); return SEMANTIC_ERROR; } ParentStatement->impl.assignment = assign; return SEMANTIC_OK; } int createStatement(Block *block, AST_NODE_PTR currentNode); int fillBlock(Block *block, AST_NODE_PTR currentNode) { DEBUG("start filling Block"); block->nodePtr = currentNode; block->statemnts = mem_new_g_array(MemoryNamespaceSet, sizeof(Statement *)); GHashTable *lowerScope = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); g_array_append_val(Scope, lowerScope); for (size_t i = 0; i < currentNode->children->len; i++) { AST_NODE_PTR stmt_node = AST_get_node(currentNode, i); int signal = createStatement(block, stmt_node); if (signal) { return SEMANTIC_ERROR; } } mem_free(lowerScope); g_array_remove_index(Scope, Scope->len - 1); DEBUG("created Block successfully"); return SEMANTIC_OK; } int createWhile(Statement *ParentStatement, AST_NODE_PTR currentNode) { assert(ParentStatement != NULL); assert(currentNode != NULL); assert(currentNode->kind == AST_While); While whileStruct; whileStruct.nodePtr = currentNode; whileStruct.conditon = createExpression(AST_get_node(currentNode, 0)); if (NULL == whileStruct.conditon) { return SEMANTIC_ERROR; } AST_NODE_PTR statementList = AST_get_node(currentNode, 1); int signal = fillBlock(&whileStruct.block, statementList); if (signal) { return SEMANTIC_ERROR; } ParentStatement->impl.whileLoop = whileStruct; return SEMANTIC_OK; } int createIf(Branch *Parentbranch, AST_NODE_PTR currentNode) { If ifbranch; ifbranch.nodePtr = currentNode; Expression *expression = createExpression(AST_get_node(currentNode, 0)); if (NULL == expression) { return SEMANTIC_ERROR; } ifbranch.conditon = expression; int status = fillBlock(&ifbranch.block, AST_get_node(currentNode, 1)); if (status) { return SEMANTIC_ERROR; } Parentbranch->ifBranch = ifbranch; return SEMANTIC_OK; } int createElse(Branch *Parentbranch, AST_NODE_PTR currentNode) { Else elseBranch; elseBranch.nodePtr = currentNode; int status = fillBlock(&elseBranch.block, AST_get_node(currentNode, 0)); if (status) { return SEMANTIC_ERROR; } Parentbranch->elseBranch = elseBranch; return SEMANTIC_OK; } int createElseIf(Branch *Parentbranch, AST_NODE_PTR currentNode) { ElseIf elseIfBranch; elseIfBranch.nodePtr = currentNode; if (Parentbranch->elseIfBranches == NULL) { Parentbranch->elseIfBranches = mem_new_g_array(MemoryNamespaceSet, sizeof(ElseIf)); } Expression *expression = createExpression(AST_get_node(currentNode, 0)); if (NULL == expression) { return SEMANTIC_ERROR; } elseIfBranch.conditon = expression; int status = fillBlock(&elseIfBranch.block, AST_get_node(currentNode, 1)); if (status) { return SEMANTIC_ERROR; } g_array_append_val(Parentbranch->elseIfBranches, elseIfBranch); return SEMANTIC_OK; } int createBranch(Statement *ParentStatement, AST_NODE_PTR currentNode) { Branch branch; branch.nodePtr = currentNode; branch.elseBranch.block.statemnts = NULL; branch.elseIfBranches = NULL; for (size_t i = 0; i < currentNode->children->len; i++) { switch (AST_get_node(currentNode, i)->kind) { case AST_If: if (createIf(&branch, AST_get_node(currentNode, i))) { return SEMANTIC_ERROR; } break; case AST_IfElse: if (createElseIf(&branch, AST_get_node(currentNode, i))) { return SEMANTIC_ERROR; } break; case AST_Else: if (createElse(&branch, AST_get_node(currentNode, i))) { return SEMANTIC_ERROR; } break; default: PANIC("current node is not part of a Branch"); break; } } ParentStatement->impl.branch = branch; return SEMANTIC_OK; } int getFunction(const char *name, Function **function); Parameter get_param_from_func(Function* func, size_t index) { if (func->kind == FunctionDeclarationKind) { return g_array_index(func->impl.declaration.parameter, Parameter, index); } else { return g_array_index(func->impl.definition.parameter, Parameter, index); } } 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); Function *fun = NULL; if (nameNode->kind == AST_Ident) { int result = getFunction(nameNode->value, &fun); if (result == SEMANTIC_ERROR) { print_diagnostic(¤tNode->location, Error, "Unknown function: `%s`", nameNode->value); return SEMANTIC_ERROR; } } if (nameNode->kind == AST_IdentList) { assert(nameNode->children->len > 1); //idents.boxname.funname() //only boxname and funname are needed, because the combination is unique const char *boxName = AST_get_node(nameNode, (nameNode->children->len - 2))->value; const char *funName = AST_get_node(nameNode, (nameNode->children->len - 1))->value; const char *name = g_strjoin("", boxName, ".", funName, NULL); int result = getFunction(name, &fun); if (result) { print_diagnostic(¤tNode->location, Error, "Unknown function: `%s`", nameNode); return SEMANTIC_ERROR; } } funcall->function = fun; funcall->nodePtr = currentNode; size_t paramCount = 0; if (fun->kind == FunctionDeclarationKind) { paramCount = fun->impl.declaration.parameter->len; } else if (fun->kind == FunctionDefinitionKind) { paramCount = fun->impl.definition.parameter->len; } size_t count = 0; for (size_t i = 0; i < argsListNode->children->len; i++) { count += AST_get_node(argsListNode, i)->children->len; } if (count != paramCount) { print_diagnostic(¤tNode->location, Error, "Expected %d arguments instead of %d", paramCount, count); return SEMANTIC_ERROR; } GArray *expressions = mem_new_g_array(MemoryNamespaceSet, (sizeof(Expression *))); //exprlists for (size_t i = 0; i < argsListNode->children->len; i++) { AST_NODE_PTR currentExprList = AST_get_node(argsListNode, i); for (int j = ((int) currentExprList->children->len) - 1; j >= 0; j--) { AST_NODE_PTR expr_node = AST_get_node(currentExprList, j); Expression *expr = createExpression(expr_node); if (expr == NULL) { return SEMANTIC_ERROR; } Parameter param = get_param_from_func(fun, i + currentExprList->children->len - j - 1); if (!compareTypes(expr->result, param.impl.declaration.type)) { print_diagnostic(&expr_node->location, Error, "parameter and argument `%s` type mismatch, expected `%s` got `%s`", param.name, type_to_string(param.impl.declaration.type), type_to_string(expr->result)); return SEMANTIC_ERROR; } g_array_append_val(expressions, expr); } } funcall->expressions = expressions; return SEMANTIC_OK; } int createStatement(Block *Parentblock, AST_NODE_PTR currentNode) { DEBUG("create Statement"); switch (currentNode->kind) { case AST_Decl: { GArray *variable = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *)); int status = createDecl(currentNode, &variable); if (status) { return SEMANTIC_ERROR; } for (size_t i = 0; i < variable->len; i++) { Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); statement->nodePtr = currentNode; statement->kind = StatementKindDeclaration; statement->impl.variable = g_array_index(variable, Variable *, i); g_array_append_val(Parentblock->statemnts, statement); } } break; case AST_Def: { GArray *variable = mem_new_g_array(MemoryNamespaceSet, sizeof(Variable *)); if (createDef(currentNode, &variable)) { return SEMANTIC_ERROR; } for (size_t i = 0; i < variable->len; i++) { Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); statement->nodePtr = currentNode; statement->kind = StatementKindDefinition; statement->impl.variable = g_array_index(variable, Variable *, i); g_array_append_val(Parentblock->statemnts, statement); } } break; case AST_While: { Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); statement->nodePtr = currentNode; statement->kind = StatementKindWhile; if (createWhile(statement, currentNode)) { return SEMANTIC_ERROR; } g_array_append_val(Parentblock->statemnts, statement); } break; case AST_Stmt: { Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); statement->nodePtr = currentNode; statement->kind = StatementKindBranch; if (createBranch(statement, currentNode)) { return SEMANTIC_ERROR; } g_array_append_val(Parentblock->statemnts, statement); } break; case AST_Assign: { Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); statement->nodePtr = currentNode; statement->kind = StatementKindAssignment; if (createAssign(statement, currentNode)) { return SEMANTIC_ERROR; } g_array_append_val(Parentblock->statemnts, statement); } break; case AST_Call: { Statement *statement = mem_alloc(MemoryNamespaceSet, sizeof(Statement)); statement->nodePtr = currentNode; statement->kind = StatementKindFunctionCall; 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: %s", AST_node_to_string(currentNode)); break; } return SEMANTIC_OK; } int createParam(GArray *Paramlist, AST_NODE_PTR currentNode) { assert(currentNode->kind == AST_Parameter); DEBUG("start param"); DEBUG("current node child count: %i", currentNode->children->len); AST_NODE_PTR paramdecl = AST_get_node(currentNode, 1); AST_NODE_PTR ioQualifierList = AST_get_node(currentNode, 0); ParameterDeclaration decl; decl.nodePtr = paramdecl; DEBUG("iolistnode child count: %i", ioQualifierList->children->len); if (ioQualifierList->children->len == 2) { decl.qualifier = InOut; } else if (ioQualifierList->children->len == 1) { if (strcmp(AST_get_node(ioQualifierList, 0)->value, "in") == 0) { decl.qualifier = In; } else if (strcmp(AST_get_node(ioQualifierList, 0)->value, "out") == 0) { decl.qualifier = Out; } else { PANIC("IO_Qualifier is not in or out"); } } else { PANIC("IO_Qualifier has not the right amount of children"); } if (set_get_type_impl(AST_get_node(paramdecl, 0), &(decl.type))) { return SEMANTIC_ERROR; } Parameter *param = mem_alloc(MemoryNamespaceSet, sizeof(Parameter)); param->nodePtr = currentNode; param->kind = ParameterDeclarationKind; param->impl.declaration = decl; param->name = AST_get_node(paramdecl, 1)->value; DEBUG("param name: %s", param->name); g_array_append_val(Paramlist, *param); if (g_hash_table_contains(functionParameter, param->name)) { print_diagnostic(¶m->nodePtr->location, Error, "Names of function parameters must be unique: %s", param->name); return SEMANTIC_ERROR; } g_hash_table_insert(functionParameter, (gpointer) param->name, param); DEBUG("created param successfully"); return SEMANTIC_OK; } int createFunDef(Function *Parentfunction, AST_NODE_PTR currentNode) { DEBUG("start fundef"); 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); AST_NODE_PTR statementlist = AST_get_node(currentNode, 3); 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; 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++) { //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; } bool compareParameter(GArray *leftParameter, GArray *rightParameter) { if (leftParameter->len != rightParameter->len) { return FALSE; } for (size_t i = 0; i < leftParameter->len; i++) { Parameter currentLeftParam = g_array_index(leftParameter, Parameter, i); Parameter currentRightParam = g_array_index(leftParameter, Parameter, i); if (strcmp(currentLeftParam.name, currentRightParam.name) != 0) { return FALSE; } if (currentLeftParam.kind != currentRightParam.kind) { return FALSE; } if (currentLeftParam.kind == ParameterDeclarationKind) { ParameterDeclaration leftDecl = currentLeftParam.impl.declaration; ParameterDeclaration rightDecl = currentLeftParam.impl.declaration; if (leftDecl.qualifier != rightDecl.qualifier) { return FALSE; } if (compareTypes(leftDecl.type, rightDecl.type) == FALSE) { return FALSE; } } } return TRUE; } int addFunction(const char *name, Function *function) { if (function->kind == FunctionDefinitionKind) { if (g_hash_table_contains(definedFunctions, name)) { print_diagnostic(&function->nodePtr->location, Error, "Multiple definition of function: `%s`", function->name); return SEMANTIC_ERROR; } g_hash_table_insert(declaredFunctions, (gpointer) name, function); } else if (function->kind == FunctionDeclarationKind) { if (g_hash_table_contains(declaredFunctions, name)) { Function *declaredFunction = g_hash_table_lookup(declaredFunctions, name); 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) { print_diagnostic(&function->nodePtr->location, Error, "Divergent declaration of function: `%s`", function->name); return SEMANTIC_ERROR; } } g_hash_table_insert(declaredFunctions, (gpointer) name, function); } return SEMANTIC_OK; } int getFunction(const char *name, Function **function) { if (g_hash_table_contains(definedFunctions, name)) { Function *fun = g_hash_table_lookup(definedFunctions, name); *function = fun; return SEMANTIC_OK; } if (g_hash_table_contains(declaredFunctions, name)) { Function *fun = g_hash_table_lookup(declaredFunctions, name); *function = fun; return SEMANTIC_OK; } return SEMANTIC_ERROR; } 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); FunctionDeclaration fundecl; 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++) { //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 createFunction(Function *function, AST_NODE_PTR currentNode) { functionParameter = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); switch (currentNode->kind) { case AST_FunDecl: if (createFunDecl(function, currentNode)) { return SEMANTIC_ERROR; } break; case AST_FunDef: if (createFunDef(function, currentNode)) { return SEMANTIC_ERROR; } 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); functionParameter = NULL; int result = addFunction(function->name, function); if (result == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } return SEMANTIC_OK; } int createDeclMember(BoxType *ParentBox, AST_NODE_PTR currentNode) { Type *declType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); int status = set_get_type_impl(AST_get_node(currentNode, 0), &declType); if (status) { return SEMANTIC_ERROR; } AST_NODE_PTR nameList = AST_get_node(currentNode, 1); for (size_t i = 0; i < nameList->children->len; i++) { BoxMember *decl = mem_alloc(MemoryNamespaceSet, sizeof(BoxMember)); decl->name = AST_get_node(nameList, i)->value; decl->nodePtr = currentNode; decl->box = ParentBox; decl->initalizer = NULL; decl->type = declType; if (g_hash_table_contains(ParentBox->member, (gpointer) decl->name)) { return SEMANTIC_ERROR; } g_hash_table_insert(ParentBox->member, (gpointer) decl->name, decl); } return SEMANTIC_OK; } int createDefMember(BoxType *ParentBox, AST_NODE_PTR currentNode) { AST_NODE_PTR declNode = AST_get_node(currentNode, 0); AST_NODE_PTR expressionNode = AST_get_node(currentNode, 1); AST_NODE_PTR nameList = AST_get_node(declNode, 1); Type *declType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); int status = set_get_type_impl(AST_get_node(currentNode, 0), &declType); if (status) { return SEMANTIC_ERROR; } Expression *init = createExpression(expressionNode); if (init == NULL) { return SEMANTIC_ERROR; } for (size_t i = 0; i < nameList->children->len; i++) { BoxMember *def = mem_alloc(MemoryNamespaceSet, sizeof(BoxMember)); def->box = ParentBox; def->type = declType; def->initalizer = init; def->name = AST_get_node(nameList, i)->value; def->nodePtr = currentNode; if (g_hash_table_contains(ParentBox->member, (gpointer) def->name)) { return SEMANTIC_ERROR; } g_hash_table_insert(ParentBox->member, (gpointer) def->name, def); } return SEMANTIC_OK; } int createBoxFunction(const char *boxName, Type *ParentBoxType, AST_NODE_PTR currentNode) { Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function)); int result = createFunction(function, currentNode); if (result == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } function->name = g_strjoin("", boxName, ".", function->name, NULL); Parameter param; param.name = "self"; param.nodePtr = currentNode; param.kind = ParameterDeclarationKind; param.impl.declaration.qualifier = In; param.impl.declaration.nodePtr = currentNode; param.impl.declaration.type = ParentBoxType; if (function->kind == FunctionDeclarationKind) { g_array_prepend_val(function->impl.declaration.parameter, param); } else { g_array_append_val(function->impl.definition.parameter, param); } addFunction(function->name, function); return SEMANTIC_OK; } int createBox(GHashTable *boxes, AST_NODE_PTR currentNode) { BoxType *box = mem_alloc(MemoryNamespaceSet, sizeof(BoxType)); box->nodePtr = currentNode; const char *boxName = AST_get_node(currentNode, 0)->value; AST_NODE_PTR boxMemberList = AST_get_node(currentNode, 1); Type *boxType = mem_alloc(MemoryNamespaceSet, sizeof(Type)); boxType->nodePtr = currentNode; boxType->impl.box = box; for (size_t i = 0; boxMemberList->children->len; i++) { switch (AST_get_node(boxMemberList, i)->kind) { case AST_Decl: case AST_Def: if (createDeclMember(box, AST_get_node(boxMemberList, i))) { return SEMANTIC_ERROR; } break; case AST_FunDef: { int result = createBoxFunction(boxName, boxType, AST_get_node(boxMemberList, i)); if (result == SEMANTIC_ERROR) { return SEMANTIC_ERROR; } } default: break; } } if (g_hash_table_contains(boxes, (gpointer) boxName)) { return SEMANTIC_ERROR; } g_hash_table_insert(boxes, (gpointer) boxName, box); return SEMANTIC_OK; } int createTypeDef(GHashTable *types, AST_NODE_PTR currentNode) { DEBUG("create Type define"); AST_NODE_PTR typeNode = AST_get_node(currentNode, 0); AST_NODE_PTR nameNode = AST_get_node(currentNode, 1); Type *type = mem_alloc(MemoryNamespaceSet, sizeof(Type)); int status = set_get_type_impl(typeNode, &type); if (status) { return SEMANTIC_ERROR; } Typedefine *def = mem_alloc(MemoryNamespaceSet, sizeof(Typedefine)); def->name = nameNode->value; def->nodePtr = currentNode; def->type = type; if (g_hash_table_contains(types, (gpointer) def->name)) { print_diagnostic(¤tNode->location, Error, "Multiple definition of type: `%s`", nameNode->value); return SEMANTIC_ERROR; } g_hash_table_insert(types, (gpointer) def->name, def); if (g_hash_table_contains(declaredComposites, (gpointer) def->name)) { print_diagnostic(¤tNode->location, Error, "Multiple definition of type: `%s`", nameNode->value); return SEMANTIC_ERROR; } g_hash_table_insert(declaredComposites, (gpointer) def->name, def->type); return SEMANTIC_OK; } Module *create_set(AST_NODE_PTR currentNode) { DEBUG("create root Module"); //create tables for types declaredComposites = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); declaredBoxes = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); declaredFunctions = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); definedFunctions = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); //create scope Scope = mem_new_g_array(MemoryNamespaceSet, sizeof(GHashTable *)); //building current scope for module GHashTable *globalscope = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); globalscope = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); g_array_append_val(Scope, globalscope); Module *rootModule = mem_alloc(MemoryNamespaceSet, sizeof(Module)); GHashTable *boxes = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); GHashTable *types = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); GHashTable *functions = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); GHashTable *variables = mem_new_g_hash_table(MemoryNamespaceSet, g_str_hash, g_str_equal); GArray *imports = mem_new_g_array(MemoryNamespaceSet, sizeof(const char *)); GArray *includes = mem_new_g_array(MemoryNamespaceSet, sizeof(const char *)); rootModule->boxes = boxes; rootModule->types = types; rootModule->functions = functions; rootModule->variables = variables; rootModule->imports = imports; rootModule->includes = includes; DEBUG("created Module struct"); for (size_t i = 0; i < currentNode->children->len; i++) { DEBUG("created Child with type: %i", AST_get_node(currentNode, i)->kind); switch (AST_get_node(currentNode, i)->kind) { case AST_Decl: { GArray *vars = NULL; int status = createDecl(AST_get_node(currentNode, i), &vars); if (status) { return NULL; } if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) { INFO("var already exists"); break; } DEBUG("filled successfull the module and scope with vars"); break; } case AST_Def: { GArray *vars; int status = createDef(AST_get_node(currentNode, i), &vars); if (status) { return NULL; } if (fillTablesWithVars(variables, vars) == SEMANTIC_ERROR) { INFO("var already exists"); break; } DEBUG("created Definition successfully"); break; } case AST_Box: { int status = createBox(boxes, AST_get_node(currentNode, i)); if (status) { return NULL; } DEBUG("created Box successfully"); break; } case AST_FunDef: case AST_FunDecl: case AST_ProcDef: case AST_ProcDecl: { DEBUG("start function"); Function *function = mem_alloc(MemoryNamespaceSet, sizeof(Function)); if (createFunction(function, AST_get_node(currentNode, i)) == SEMANTIC_ERROR) { return NULL; } if (g_hash_table_contains(functions, function->name)) { print_diagnostic(&function->impl.definition.nodePtr->location, Error, "Multiple definition of function: `%s`", function->name); return NULL; } g_hash_table_insert(functions, (gpointer) function->name, function); DEBUG("created function successfully"); break; } case AST_Typedef: { int status = createTypeDef(types, AST_get_node(currentNode, i)); if (status) { return NULL; } DEBUG("created Typedef successfully"); break; } case AST_Import: DEBUG("create Import"); g_array_append_val(imports, AST_get_node(currentNode, i)->value); break; case AST_Include: DEBUG("create Include"); g_array_append_val(includes, AST_get_node(currentNode, i)->value); break; default: INFO("Provided source file could not be parsed because of semantic error."); break; } } DEBUG("created set successfully"); return rootModule; }