diff --git a/src/llvm/function/function.c b/src/llvm/function/function.c index 73daecc..08a3e45 100644 --- a/src/llvm/function/function.c +++ b/src/llvm/function/function.c @@ -1,5 +1,6 @@ #include "ast/ast.h" +#include "llvm/types/scope.h" #include #include #include @@ -55,7 +56,7 @@ static enum IO_Qualifier_t io_qualifier_from_ast_list(const AST_NODE_PTR node) { return qualifier; } -GemstoneParam param_from_ast(const AST_NODE_PTR node) { +GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node) { GemstoneParam param; // node is expected to be a parameter @@ -68,7 +69,7 @@ GemstoneParam param_from_ast(const AST_NODE_PTR node) { AST_NODE_PTR param_decl = AST_get_node(node, 1); AST_NODE_PTR param_type = AST_get_node(param_decl, 0); - param.typename = get_type_from_ast(param_type); + param.typename = get_type_from_ast(scope, param_type); param.name = AST_get_node(param_decl, 1)->value; return param; diff --git a/src/llvm/function/function.h b/src/llvm/function/function.h index 54df9a4..da74126 100644 --- a/src/llvm/function/function.h +++ b/src/llvm/function/function.h @@ -15,7 +15,7 @@ enum IO_Qualifier_t { typedef struct GemstoneParam_t { const char* name; enum IO_Qualifier_t qualifier; - GemstoneType typename; + GemstoneTypeRef typename; } GemstoneParam; typedef struct GemstoneFun_t { @@ -29,7 +29,7 @@ typedef struct GemstoneFun_t { * @param node the node starting a function parameter * @return GemstoneParam */ -GemstoneParam param_from_ast(const AST_NODE_PTR node); +GemstoneParam param_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); /** * @brief Convert an AST node into a function @@ -37,6 +37,6 @@ GemstoneParam param_from_ast(const AST_NODE_PTR node); * @param node the node starting a function * @return GemstoneFun */ -GemstoneFun fun_from_ast(const AST_NODE_PTR node); +GemstoneFun fun_from_ast(const TypeScopeRef scope, const AST_NODE_PTR node); #endif // LLVM_FUNCTION_H_ diff --git a/src/llvm/types/composite-types.h b/src/llvm/types/composite-types.h new file mode 100644 index 0000000..49f04c2 --- /dev/null +++ b/src/llvm/types/composite-types.h @@ -0,0 +1,35 @@ + +#ifndef LLVM_TYPES_COMPOSITE_TYPES_H_ +#define LLVM_TYPES_COMPOSITE_TYPES_H_ + +#define BITS_PER_BYTE 8 + +enum Sign_t { + Signed = 1, + Unsigned = -1 +}; + +enum Scale_t { + ATOM = 1, + HALF = 2, + SINGLE = 4, + DOUBLE = 8, + QUAD = 16, + OCTO = 32 +}; + +enum Primitive_t { + Int, + Float +}; + +typedef struct CompositeType_t { + enum Sign_t sign; + enum Scale_t scale; + enum Primitive_t prim; +} Composite; + +typedef struct CompositeType_t* CompositeRef; + + +#endif // LLVM_TYPES_COMPOSITE_TYPES_H_ \ No newline at end of file diff --git a/src/llvm/types/composite.c b/src/llvm/types/composite.c index 416087b..f58d2c3 100644 --- a/src/llvm/types/composite.c +++ b/src/llvm/types/composite.c @@ -1,4 +1,7 @@ +#include "llvm/types/composite-types.h" +#include "llvm/types/scope.h" +#include "llvm/types/structs.h" #include #include @@ -46,8 +49,8 @@ double get_scale_factor(const char* keyword) { PANIC("invalid scale factor: %s", keyword); } -enum Scale_t collapse_scale_list(const AST_NODE_PTR list) { - double sum = 1.0; +enum Scale_t collapse_scale_list(const AST_NODE_PTR list, double base) { + double sum = base; for (size_t i = 0; i < list->child_count; i++) { AST_NODE_PTR scale = AST_get_node(list, i); @@ -84,27 +87,49 @@ static enum Primitive_t resolve_primitive(const char* typename) { return Int; } -struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type) { +struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type) { size_t count = type->child_count; struct CompositeType_t composite; - composite.name = NULL; composite.prim = Int; composite.scale = SINGLE; composite.sign = Signed; if (count == 1) { - // only other type given - composite.prim = resolve_primitive(AST_get_node(type, 0)->value); + const char* typename = AST_get_node(type, 0)->value; + GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); + + if (known_type == NULL) { + // only other type given + composite.prim = resolve_primitive(typename); + } else if (known_type->type->kind == TypeComposite) { + return known_type->type->specs.composite; + } else { + PANIC("not a composite"); + } } else if (count == 2) { // either scale and type // or sign and type AST_NODE_PTR first_child = AST_get_node(type, 0); + const char* typename = AST_get_node(type, 1)->value; + GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); + + if (known_type == NULL) { + // only other type given + composite.prim = resolve_primitive(typename); + } else if (known_type->type->kind == TypeComposite) { + composite.prim = known_type->type->specs.composite.prim; + composite.scale = known_type->type->specs.composite.scale; + composite.sign = known_type->type->specs.composite.sign; + } else { + PANIC("not a composite"); + } + switch (first_child->kind) { case AST_List: - composite.scale = collapse_scale_list(first_child); + composite.scale = collapse_scale_list(first_child, (double) composite.scale); break; case AST_Sign: composite.sign = string_to_sign(first_child->value); @@ -113,12 +138,24 @@ struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type) { PANIC("unexpected node kind: %s", AST_node_to_string(first_child)); } - composite.prim = resolve_primitive(AST_get_node(type, 1)->value); - } else if (count == 3) { + const char* typename = AST_get_node(type, 3)->value; + GemstoneTypedefRef known_type = type_scope_get_type_from_name(scope, typename); + + if (known_type == NULL) { + // only other type given + composite.prim = resolve_primitive(typename); + } else if (known_type->type->kind == TypeComposite) { + composite.prim = known_type->type->specs.composite.prim; + composite.scale = known_type->type->specs.composite.scale; + composite.sign = known_type->type->specs.composite.sign; + } else { + PANIC("not a composite"); + } + // sign, scale and type composite.sign = string_to_sign(AST_get_node(type, 0)->value); - composite.scale = collapse_scale_list(AST_get_node(type, 0)); + composite.scale = collapse_scale_list(AST_get_node(type, 1), (double) composite.scale); composite.prim = resolve_primitive(AST_get_node(type, 2)->value); } diff --git a/src/llvm/types/composite.h b/src/llvm/types/composite.h index a8df186..5289c6d 100644 --- a/src/llvm/types/composite.h +++ b/src/llvm/types/composite.h @@ -6,48 +6,13 @@ #include #include #include - -#define BITS_PER_BYTE 8 - -enum Sign_t { - Signed, - Unsigned -}; - -enum Scale_t { - ATOM = 1, - HALF = 2, - SINGLE = 4, - DOUBLE = 8, - QUAD = 16, - OCTO = 32 -}; - -enum Primitive_t { - Int, - Float -}; - -typedef struct CompositeType_t { - const char* name; - enum Sign_t sign; - enum Scale_t scale; - enum Primitive_t prim; -} Composite; - -typedef struct TypeScope_t { - // vector of composite data types - Composite* composites; - size_t composite_len; - size_t composite_cap; -} TypeScope; - -typedef struct CompositeType_t* CompositeRef; +#include +#include #define INVALID_COMPOSITE NULL LLVMTypeRef llvm_type_from_composite(LLVMContextRef context, const CompositeRef composite); -struct CompositeType_t ast_type_to_composite(AST_NODE_PTR type); +struct CompositeType_t ast_type_to_composite(const TypeScopeRef scope, AST_NODE_PTR type); #endif // LLVM_TYPE_H_ diff --git a/src/llvm/types/scope.c b/src/llvm/types/scope.c new file mode 100644 index 0000000..659a99f --- /dev/null +++ b/src/llvm/types/scope.c @@ -0,0 +1,75 @@ + +#include +#include +#include + +struct TypeScope_t { + GArray* types; + GArray* scopes; + TypeScopeRef parent; +}; + +TypeScopeRef type_scope_new() { + TypeScopeRef scope = malloc(sizeof(TypeScope)); + + // neither zero termination no initialisazion to zero needed + scope->scopes = g_array_new(FALSE, FALSE, sizeof(TypeScopeRef)); + scope->types = g_array_new(FALSE, FALSE, sizeof(GemstoneTypedefRef)); + scope->parent = NULL; + + return scope; +} + +void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type) { + g_array_append_val(scope->types, type); +} + +void type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope) { + g_array_append_val(scope->scopes, child_scope); + child_scope->parent = scope; +} + +GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t index) { + return ((GemstoneTypedefRef*) scope->types->data)[index]; +} + +size_t type_scope_types_len(TypeScopeRef scope) { + return scope->types->len; +} + +size_t type_scope_scopes_len(TypeScopeRef scope) { + return scope->scopes->len; +} + +GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* name) { + for (guint i = 0; i < scope->types->len; i++) { + GemstoneTypedefRef typeref = ((GemstoneTypedefRef*) scope->types->data)[i]; + + if (strcmp(typeref->name, name) == 0) { + return typeref; + } + } + + if (scope->parent == NULL) { + return NULL; + } + + return type_scope_get_type_from_name(scope->parent, name); +} + +void type_scope_delete(TypeScopeRef scope) { + + for (guint i = 0; i < scope->scopes->len; i++) { + TypeScopeRef scoperef = ((TypeScopeRef*) scope->scopes->data)[i]; + type_scope_delete(scoperef); + } + + for (guint i = 0; i < scope->types->len; i++) { + // TODO: free gemstone type + } + + g_array_free(scope->scopes, TRUE); + g_array_free(scope->types, TRUE); + + free(scope); +} diff --git a/src/llvm/types/scope.h b/src/llvm/types/scope.h new file mode 100644 index 0000000..3e79003 --- /dev/null +++ b/src/llvm/types/scope.h @@ -0,0 +1,83 @@ + +#ifndef LLVM_TYPE_SCOPE_H_ +#define LLVM_TYPE_SCOPE_H_ + +#include +#include + +typedef struct TypeScope_t TypeScope; + +typedef TypeScope* TypeScopeRef; + +/** + * @brief Allocate a new type scope + * + * @return TypeScopeRef + */ +[[nodiscard("heap allocation")]] +TypeScopeRef type_scope_new(); + +/** + * @brief Add a new type to this scope + * + * @param scope + * @param type + */ +[[gnu::nonnull(1)]] +void type_scope_append_type(TypeScopeRef scope, GemstoneTypedefRef type); + +/** + * @brief Add a new child scope to this scope + * + * @param scope + * @param child_scope + */ +[[gnu::nonnull(1), gnu::nonnull(2)]] +void type_scope_append_scope(TypeScopeRef scope, TypeScopeRef child_scope); + +/** + * @brief Get the type at the specified index in this scope level + * + * @param scope + * @param indx + */ +[[gnu::nonnull(1)]] +GemstoneTypedefRef type_scope_get_type(TypeScopeRef scope, size_t indx); + +/** + * @brief Get the number of types in this scope level + * + * @param scope + * @return size_t + */ +[[gnu::nonnull(1)]] +size_t type_scope_types_len(TypeScopeRef scope); + +/** + * @brief Get the number of child scopes + * + * @param scope + * @return size_t + */ +[[gnu::nonnull(1)]] +size_t type_scope_scopes_len(TypeScopeRef scope); + +/** + * @brief Return a type inside this scope which matches the given name. + * @attention Returns NULL if no type by this name is found. + * + * @param name + * @return GemstoneTypedefRef + */ +[[gnu::nonnull(1)]] +GemstoneTypedefRef type_scope_get_type_from_name(TypeScopeRef scope, const char* name); + +/** + * @brief Delete the scope. Deallocates all child scopes + * + * @param scope + */ +[[gnu::nonnull(1)]] +void type_scope_delete(TypeScopeRef scope); + +#endif // LLVM_TYPE_SCOPE_H_ diff --git a/src/llvm/types/structs.h b/src/llvm/types/structs.h new file mode 100644 index 0000000..cca447e --- /dev/null +++ b/src/llvm/types/structs.h @@ -0,0 +1,36 @@ + +#ifndef LLVM_TYPE_STRUCTS_H_ +#define LLVM_TYPE_STRUCTS_H_ + +#include + +enum GemstoneTypeKind_t { + TypeComposite, + TypeReference, + TypeBox +}; + +struct GemstoneType_t; + +typedef struct GemstoneRefType_t { + struct GemstoneType_t* type; +} GemstoneRefType; + +typedef struct GemstoneType_t { + enum GemstoneTypeKind_t kind; + union GemstoneTypeSpecs_t { + Composite composite; + GemstoneRefType reference; + } specs; +} GemstoneType; + +typedef GemstoneType* GemstoneTypeRef; + +typedef struct GemstoneTypedef_t { + const char* name; + GemstoneTypeRef type; +} GemstoneTypedef; + +typedef GemstoneTypedef* GemstoneTypedefRef; + +#endif // LLVM_TYPE_STRUCTS_H_ diff --git a/src/llvm/types/type.c b/src/llvm/types/type.c index 2b8911d..47f1ef9 100644 --- a/src/llvm/types/type.c +++ b/src/llvm/types/type.c @@ -1,23 +1,73 @@ +#include "llvm/types/structs.h" +#include #include #include #include +#include -GemstoneType get_type_from_ast(const AST_NODE_PTR type_node) { +GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type_node) { if (type_node->kind != AST_Type) { PANIC("Node must be of type AST_Type: %s", AST_node_to_string(type_node)); } - GemstoneType type; + GemstoneTypeRef type = malloc(sizeof(GemstoneType)); if (type_node->child_count > 1) { // must be composite - type.kind = TypeComposite; - type.specs.composite = ast_type_to_composite(type_node); + type->kind = TypeComposite; + type->specs.composite = ast_type_to_composite(scope, type_node); } else { // either custom type or box - // TODO: resolve concrete type from TypeScope + GemstoneTypedefRef resolved_type = type_scope_get_type_from_name(scope, AST_get_node(type_node, 0)->value); + + if (resolved_type == NULL) { + type->kind = TypeComposite; + type->specs.composite = ast_type_to_composite(scope, type_node); + } else { + free(type); + type = resolved_type->type; + } } return type; } + +GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name) { + GemstoneTypedefRef typedefref = malloc(sizeof(GemstoneTypedef)); + + typedefref->name = name; + typedefref->type = type; + + return typedefref; +} + +void delete_type(GemstoneTypeRef typeref) { + switch(typeref->kind) { + case TypeReference: + delete_type(typeref->specs.reference.type); + break; + case TypeComposite: + break; + case TypeBox: + PANIC("NOT IMPLEMENTED"); + break; + } + + free(typeref); +} + +void delete_typedefref(GemstoneTypedefRef ref) { + delete_type(ref->type); +} + +GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef) { + if (typdef->kind != AST_Typedef) { + PANIC("node must be of type AST_Typedef"); + } + + GemstoneTypeRef type = get_type_from_ast(scope, AST_get_node(typdef, 0)); + const char* name = AST_get_node(typdef, 1)->value; + + return new_typedefref(type, name); +} diff --git a/src/llvm/types/type.h b/src/llvm/types/type.h index d7e2617..c6a2b1b 100644 --- a/src/llvm/types/type.h +++ b/src/llvm/types/type.h @@ -4,33 +4,8 @@ #include #include - -enum GemstoneTypeKind_t { - TypeComposite, - TypeReference, - TypeBox -}; - -struct GemstoneType_t; - -typedef struct GemstoneRefType_t { - struct GemstoneType_t* type; -} GemstoneRefType; - -typedef struct GemstoneType_t { - enum GemstoneTypeKind_t kind; - union GemstoneTypeSpecs_t { - Composite composite; - GemstoneRefType reference; - } specs; -} GemstoneType; - -struct TypeScope_t; - -typedef struct TypeScope_t { - // TODO: array of child scopes - // TODO: array of types -} TypeScope; +#include +#include /** * @brief Convert a type declaration into a concrete type. @@ -38,6 +13,30 @@ typedef struct TypeScope_t { * @param type A type declaration (either identifier or composite) * @return GemstoneType */ -GemstoneType get_type_from_ast(const AST_NODE_PTR type); +GemstoneTypeRef get_type_from_ast(const TypeScopeRef scope, const AST_NODE_PTR type); + +/** + * @brief Convert the type definition AST into a typedef reference + * + * @param typdef + * @return GemstoneTypedefRef + */ +GemstoneTypedefRef get_type_def_from_ast(const TypeScopeRef scope, const AST_NODE_PTR typdef); + +/** + * @brief Create an new typedefine reference + * + * @param type + * @param name + * @return GemstoneTypedefRef + */ +GemstoneTypedefRef new_typedefref(GemstoneTypeRef type, const char* name); + +/** + * @brief Free the type definition reference and its underlying type + * + * @param ref + */ +void delete_typedefref(GemstoneTypedefRef ref); #endif // GEMSTONE_TYPE_H_