Prepare for struct refactoring.

This commit is contained in:
Christoffer Lerno
2020-05-30 20:58:09 +02:00
parent 1b69423f45
commit c9ab05bfec
15 changed files with 149 additions and 51 deletions

View File

@@ -974,6 +974,46 @@ func void testMethodFunctions()
printf("%d %d %d\n", x.x.x, x.x.y, x.x.z);
}
enum TestEnumSize : ushort
{
BLURB
}
enum TestEnumSizeDefault
{
BLURB
}
struct TestStructSize
{
char x;
long y;
}
struct TestStructInt
{
int a;
int b;
int c;
}
union TestUnionSize
{
short a;
int b;
char[5] c;
}
func void testTypeValues()
{
TestUnionSize.a.sizeof;
printf("Enum size: %d = 2\n", TestEnumSize.sizeof);
printf("Enum size: %d = 4\n", TestEnumSizeDefault.sizeof);
printf("Struct size: %d = 12\n", TestStructInt.sizeof);
printf("Struct size: %d = 16\n", TestStructSize.sizeof);
printf("Union size: %d = 5\n", TestUnionSize.sizeof);
printf("Error size: %d = 4\n", Err.sizeof);
}
func int main(int x)
{
printf("Helo!\n");
@@ -990,6 +1030,7 @@ func int main(int x)
testExprBlock();
testFuncPointer();
testMethodFunctions();
testTypeValues();
int efd = 9;
uint fefoek = 1;
printf("Helo: %d\n", efd + cast(fefoek, int));

View File

@@ -335,6 +335,10 @@ void fprint_type_recursive(FILE *file, Type *type, int indent)
case TYPE_ERROR:
DUMPF("(error %s)", type->name);
return;
case TYPE_MEMBER:
DUMPF("(member %s", type->name);
DUMPTYPE(type->decl->parent_struct->type);
DUMPEND();
case TYPE_TYPEDEF:
DUMPF("(typedef %s", type->name);
DUMPTYPE(type->canonical);

View File

@@ -189,7 +189,7 @@ struct _Type
void *backend_debug_type;
union
{
// Error, Struct, Union, Typedef
// Error, Struct, Union, Typedef, Member
Decl *decl;
// int, float, bool
TypeBuiltin builtin;
@@ -415,7 +415,7 @@ typedef struct _Decl
union
{
Decl* parent_struct;
Decl** method_functions;
Decl** methods;
};
union
{
@@ -471,7 +471,7 @@ typedef struct
union
{
Token name;
Decl *method;
Decl *decl;
};
} ExprTypeAccess;
@@ -949,7 +949,7 @@ typedef struct _Context
Decl **error_types;
Decl **types;
Decl **functions;
Decl **method_functions;
Decl **methods;
Decl **vars;
Decl **ct_ifs;
Ast **defers;
@@ -1021,6 +1021,13 @@ typedef struct
Type **type;
} Compiler;
typedef enum
{
MODULE_SYMBOL_SEARCH_EXTERNAL,
MODULE_SYMBOL_SEARCH_PARENT,
MODULE_SYMBOL_SEARCH_THIS
} ModuleSymbolSearch;
extern Compiler compiler;
extern Ast *poisoned_ast;
extern Decl *poisoned_decl;
@@ -1041,7 +1048,8 @@ extern Type *type_typeid, *type_error_union, *type_error_base;
extern const char *attribute_list[NUMBER_OF_ATTRIBUTES];
extern const char *main_kw;
extern const char *kw_main;
extern const char *kw_sizeof;
#define AST_NEW_TOKEN(_kind, _token) new_ast(_kind, _token.span)
#define AST_NEW(_kind, _loc) new_ast(_kind, _loc)
@@ -1202,12 +1210,6 @@ void lexer_init_with_file(Lexer *lexer, File *file);
File* lexer_current_file(Lexer *lexer);
typedef enum
{
MODULE_SYMBOL_SEARCH_EXTERNAL,
MODULE_SYMBOL_SEARCH_PARENT,
MODULE_SYMBOL_SEARCH_THIS
} ModuleSymbolSearch;
Decl *module_find_symbol(Module *module, const char *symbol, ModuleSymbolSearch search);
@@ -1306,7 +1308,7 @@ static inline bool type_is_signed(Type *type) { return type->type_kind >= TYPE_I
static inline bool type_is_unsigned(Type *type) { return type->type_kind >= TYPE_U8 && type->type_kind <= TYPE_U64; }
static inline bool type_ok(Type *type) { return !type || type->type_kind != TYPE_POISONED; }
static inline bool type_info_ok(TypeInfo *type_info) { return !type_info || type_info->kind != TYPE_INFO_POISON; }
bool type_may_have_method_functions(Type *type);
bool type_may_have_method(Type *type);
static inline Type *type_reduced(Type *type)
{

View File

@@ -96,7 +96,7 @@ void context_register_global_decl(Context *context, Decl *decl)
case DECL_FUNC:
if (decl->func.type_parent)
{
vec_add(context->method_functions, decl);
vec_add(context->methods, decl);
// TODO set name
return;
}

View File

@@ -507,6 +507,7 @@ typedef enum
TYPE_VARARRAY,
TYPE_SUBARRAY,
TYPE_TYPEID,
TYPE_MEMBER,
TYPE_LAST = TYPE_TYPEID
} TypeKind;

View File

@@ -358,9 +358,9 @@ void llvm_codegen(Context *context)
{
gencontext_emit_extern_decl(&gen_context, context->external_symbol_list[i]);
}
VECEACH(context->method_functions, i)
VECEACH(context->methods, i)
{
gencontext_emit_function_decl(&gen_context, context->method_functions[i]);
gencontext_emit_function_decl(&gen_context, context->methods[i]);
}
VECEACH(context->functions, i)
{
@@ -383,9 +383,9 @@ void llvm_codegen(Context *context)
Decl *decl = context->functions[i];
if (decl->func.body) gencontext_emit_function_body(&gen_context, decl);
}
VECEACH(context->method_functions, i)
VECEACH(context->methods, i)
{
Decl *decl = context->method_functions[i];
Decl *decl = context->methods[i];
if (decl->func.body) gencontext_emit_function_body(&gen_context, decl);
}

View File

@@ -108,6 +108,7 @@ LLVMMetadataRef gencontext_get_debug_type(GenContext *context, Type *type)
case TYPE_IXX:
case TYPE_FXX:
case TYPE_TYPEID:
case TYPE_MEMBER:
UNREACHABLE
case TYPE_BOOL:
return gencontext_simple_debug_type(context, type, DW_ATE_boolean);

View File

@@ -165,7 +165,9 @@ LLVMTypeRef llvm_get_type(LLVMContextRef context, Type *type)
DEBUG_LOG("Generating type %s", type->name);
switch (type->type_kind)
{
case TYPE_MEMBER:
case TYPE_POISONED:
UNREACHABLE
case TYPE_TYPEID:
return type->backend_type = LLVMIntTypeInContext(context, type->builtin.bitsize);
case TYPE_ERROR:

View File

@@ -1528,7 +1528,7 @@ static inline Decl *parse_func_definition(Context *context, Visibility visibilit
func->func.type_parent = type;
advance_and_verify(context, TOKEN_TYPE_IDENT);
TRY_CONSUME_OR(TOKEN_DOT, "Expected '.' after the type in a method function.", poisoned_decl);
TRY_CONSUME_OR(TOKEN_DOT, "Expected '.' after the type in a method declaration.", poisoned_decl);
}
EXPECT_IDENT_FOR_OR("function name", poisoned_decl);

View File

@@ -796,6 +796,7 @@ CastKind cast_to_bool_kind(Type *type)
case TYPE_ERROR:
case TYPE_ENUM:
case TYPE_FUNC:
case TYPE_MEMBER:
case TYPE_ARRAY:
case TYPE_VARARRAY:
case TYPE_SUBARRAY:
@@ -835,6 +836,7 @@ bool cast(Expr *expr, Type *to_type, CastType cast_type)
case TYPE_POISONED:
case TYPE_VOID:
case TYPE_TYPEID:
case TYPE_MEMBER:
break;
case TYPE_BOOL:
// Bool may convert into integers and floats but only explicitly.

View File

@@ -410,30 +410,30 @@ static inline bool sema_analyse_enum(Context *context, Decl *decl)
static inline bool sema_analyse_method_function(Context *context, Decl *decl)
static inline bool sema_analyse_method(Context *context, Decl *decl)
{
TypeInfo *parent_type = decl->func.type_parent;
if (!sema_resolve_type_info(context, parent_type)) return false;
if (!type_may_have_method_functions(parent_type->type))
if (!type_may_have_method(parent_type->type))
{
SEMA_ERROR(decl,
"Method functions can not be associated with '%s'",
"Methods can not be associated with '%s'",
type_to_error_string(decl->func.type_parent->type));
return false;
}
Decl *parent = parent_type->type->decl;
VECEACH(parent->method_functions, i)
VECEACH(parent->methods, i)
{
Decl *function = parent->method_functions[i];
Decl *function = parent->methods[i];
if (function->name == decl->name)
{
SEMA_ERROR(decl, "Duplicate name '%s' for method function.", function->name);
SEMA_ERROR(decl, "Duplicate name '%s' for method.", function->name);
SEMA_PREV(function, "Previous definition here.");
return false;
}
}
DEBUG_LOG("Method function '%s.%s' analysed.", parent->name, decl->name);
vec_add(parent->method_functions, decl);
DEBUG_LOG("Method '%s.%s' analysed.", parent->name, decl->name);
vec_add(parent->methods, decl);
return true;
}
@@ -563,7 +563,7 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
if (!func_type) return decl_poison(decl);
if (decl->func.type_parent)
{
if (!sema_analyse_method_function(context, decl)) return decl_poison(decl);
if (!sema_analyse_method(context, decl)) return decl_poison(decl);
}
VECEACH(decl->attributes, i)
{
@@ -608,7 +608,7 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
return decl_poison(decl);
}
}
if (decl->name == main_kw)
if (decl->name == kw_main)
{
if (decl->visibility == VISIBLE_LOCAL)
{

View File

@@ -480,7 +480,7 @@ static inline bool sema_expr_analyse_call(Context *context, Type *to, Expr *expr
switch (func_expr->expr_kind)
{
case EXPR_TYPE_ACCESS:
decl = func_expr->type_access.method;
decl = func_expr->type_access.decl;
break;
case EXPR_IDENTIFIER:
decl = func_expr->identifier_expr.decl;
@@ -641,12 +641,12 @@ static inline bool sema_expr_analyse_subscript(Context *context, Type *to, Expr
return sema_expr_analyse_subscript_after_parent_resolution(context, NULL, expr);
}
static inline bool sema_expr_analyse_method_function(Context *context, Expr *expr, Decl *decl, bool is_pointer)
static inline bool sema_expr_analyse_method(Context *context, Expr *expr, Decl *decl, bool is_pointer)
{
const char *name = expr->access_expr.sub_element.string;
VECEACH(decl->method_functions, i)
VECEACH(decl->methods, i)
{
Decl *function = decl->method_functions[i];
Decl *function = decl->methods[i];
if (function->name == name)
{
expr->access_expr.ref = function;
@@ -657,11 +657,11 @@ static inline bool sema_expr_analyse_method_function(Context *context, Expr *exp
if (decl_is_struct_type(decl))
{
SEMA_ERROR(expr, "There is no element nor method function '%s.%s'.", decl->name, name);
SEMA_ERROR(expr, "There is no element nor method '%s.%s'.", decl->name, name);
}
else
{
SEMA_ERROR(expr, "Cannot find method function '%s.%s'", decl->name, name);
SEMA_ERROR(expr, "Cannot find method '%s.%s'", decl->name, name);
}
return false;
}
@@ -706,7 +706,7 @@ static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
{
type = type->pointer;
}
if (!type_may_have_method_functions(type))
if (!type_may_have_method(type))
{
SEMA_ERROR(expr, "Cannot access '%s' on '%s'", expr->access_expr.sub_element.string, type_to_error_string(parent_type));
return false;
@@ -716,7 +716,7 @@ static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
{
case DECL_ENUM:
case DECL_ERROR:
return sema_expr_analyse_method_function(context, expr, decl, is_pointer);
return sema_expr_analyse_method(context, expr, decl, is_pointer);
case DECL_STRUCT:
case DECL_UNION:
break;
@@ -726,7 +726,7 @@ static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
Decl *member = strukt_recursive_search_member(decl, expr->access_expr.sub_element.string);
if (!member)
{
return sema_expr_analyse_method_function(context, expr, decl, is_pointer);
return sema_expr_analyse_method(context, expr, decl, is_pointer);
return false;
}
if (is_pointer)
@@ -743,6 +743,13 @@ static inline bool sema_expr_analyse_access(Context *context, Expr *expr)
return true;
}
static inline void expr_rewrite_to_int_const(Expr *expr_to_rewrite, Type *type, uint64_t value)
{
expr_to_rewrite->expr_kind = EXPR_CONST;
expr_const_set_int(&expr_to_rewrite->const_expr, value, type->canonical->type_kind);
expr_to_rewrite->type = type;
expr_to_rewrite->resolve_status = true;
}
static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Expr *expr)
{
@@ -757,9 +764,9 @@ static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Exp
expr->resolve_status = RESOLVE_DONE;
return true;
}
if (!type_may_have_method_functions(canonical))
if (!type_may_have_method(canonical))
{
SEMA_ERROR(expr, "'%s' does not have method functions.", type_to_error_string(type_info->type));
SEMA_ERROR(expr, "'%s' does not have methods.", type_to_error_string(type_info->type));
return false;
}
Decl *decl = canonical->decl;
@@ -777,6 +784,11 @@ static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Exp
}
return true;
}
if (expr->type_access.name.start == kw_sizeof)
{
expr_rewrite_to_int_const(expr, type_usize, type_size(decl->enums.type_info->type));
return true;
}
break;
case DECL_ERROR:
if (expr->type_access.name.type == TOKEN_CONST_IDENT)
@@ -788,24 +800,46 @@ static inline bool sema_expr_analyse_type_access(Context *context, Type *to, Exp
}
return true;
}
if (expr->type_access.name.start == kw_sizeof)
{
expr_rewrite_to_int_const(expr, type_usize, type_size(type_error_base->canonical));
return true;
}
break;
case DECL_UNION:
case DECL_STRUCT:
if (expr->type_access.name.start == kw_sizeof)
{
expr_rewrite_to_int_const(expr, type_usize, type_size(decl->type));
return true;
}
break;
default:
UNREACHABLE
}
VECEACH(type_info->type->decl->method_functions, i)
VECEACH(decl->methods, i)
{
Decl *function = type_info->type->decl->method_functions[i];
Decl *function = decl->methods[i];
if (expr->type_access.name.string == function->name)
{
expr->type_access.method = function;
expr->type = function->func.function_signature.rtype->type;
expr->type_access.decl = function;
expr->type = function->type;
return true;
}
}
SEMA_ERROR(expr, "No function '%s.%s' found.", type_to_error_string(type_info->type), expr->type_access.name.string);
VECEACH(decl->strukt.members, i)
{
Decl *member = decl->strukt.members[i];
if (expr->type_access.name.string == member->name)
{
expr->type_access.decl = member;
expr->type = member->type;
return true;
}
}
SEMA_ERROR(expr, "No function or member '%s.%s' found.", type_to_error_string(type_info->type), expr->type_access.name.string);
return false;
}
@@ -2018,6 +2052,7 @@ static bool sema_expr_analyse_comp(Context *context, Expr *expr, Expr *left, Exp
case TYPE_VARARRAY:
case TYPE_SUBARRAY:
case TYPE_TYPEID:
case TYPE_MEMBER:
// Only != and == allowed.
goto ERR;
case ALL_INTS:
@@ -2259,6 +2294,7 @@ static bool sema_expr_analyse_not(Context *context, Type *to, Expr *expr, Expr *
case TYPE_ENUM:
case TYPE_ERROR:
case TYPE_TYPEID:
case TYPE_MEMBER:
SEMA_ERROR(expr, "Cannot use 'not' on %s", type_to_error_string(inner->type));
return false;
}

View File

@@ -114,9 +114,9 @@ void sema_analysis_pass_decls(Context *context)
{
sema_analyse_decl(context, context->error_types[i]);
}
VECEACH(context->method_functions, i)
VECEACH(context->methods, i)
{
sema_analyse_decl(context, context->method_functions[i]);
sema_analyse_decl(context, context->methods[i]);
}
VECEACH(context->vars, i)
{
@@ -126,9 +126,9 @@ void sema_analysis_pass_decls(Context *context)
{
sema_analyse_decl(context, context->functions[i]);
}
VECEACH(context->method_functions, i)
VECEACH(context->methods, i)
{
analyse_func_body(context, context->method_functions[i]);
analyse_func_body(context, context->methods[i]);
}
VECEACH(context->functions, i)
{

View File

@@ -36,7 +36,8 @@ static SymTab symtab;
const char *attribute_list[NUMBER_OF_ATTRIBUTES];
const char *main_kw;
const char *kw_main;
const char *kw_sizeof;
void symtab_init(uint32_t capacity)
{
@@ -70,7 +71,8 @@ void symtab_init(uint32_t capacity)
// Init some constant idents
TokenType type = TOKEN_IDENT;
#define KW_DEF(x) symtab_add(x, sizeof(x) - 1, fnv1a(x, sizeof(x) - 1), &type)
main_kw = KW_DEF("main");
kw_main = KW_DEF("main");
kw_sizeof = KW_DEF("sizeof");
attribute_list[ATTRIBUTE_INLINE] = KW_DEF("inline");
attribute_list[ATTRIBUTE_NOINLINE] = KW_DEF("noinline");
attribute_list[ATTRIBUTE_STDCALL] = KW_DEF("stdcall");

View File

@@ -133,6 +133,8 @@ const char *type_to_error_string(Type *type)
}
asprintf(&buffer, "%s*", type_to_error_string(type->pointer));
return buffer;
case TYPE_MEMBER:
return "member";
case TYPE_STRING:
return "string";
case TYPE_ARRAY:
@@ -236,6 +238,8 @@ size_t type_size(Type *canonical)
case ALL_INTS:
case ALL_FLOATS:
return canonical->builtin.bytesize;
case TYPE_MEMBER:
return type_size(canonical->decl->var.type_info->type);
case TYPE_FUNC:
case TYPE_POINTER:
case TYPE_VARARRAY:
@@ -272,6 +276,8 @@ unsigned int type_abi_alignment(Type *canonical)
case ALL_FLOATS:
case TYPE_ERROR_UNION:
return canonical->builtin.abi_alignment;
case TYPE_MEMBER:
return type_abi_alignment(canonical->decl->var.type_info->type);
case TYPE_FUNC:
case TYPE_POINTER:
case TYPE_VARARRAY:
@@ -552,7 +558,7 @@ bool type_is_subtype(Type *type, Type *possible_subtype)
}
bool type_may_have_method_functions(Type *type)
bool type_may_have_method(Type *type)
{
// An alias is not ok.
switch (type->type_kind)
@@ -737,6 +743,7 @@ Type *type_find_max_type(Type *type, Type *other)
case TYPE_ERROR:
if (other->type_kind == TYPE_ERROR) return type_error_union;
return NULL;
case TYPE_MEMBER:
case TYPE_FUNC:
case TYPE_UNION:
case TYPE_ERROR_UNION: