diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index 68ec4dbc3..ba74422d8 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -9,6 +9,11 @@ fault IteratorResult NO_MORE_ELEMENT } +fault SearchResult +{ + MISSING +} + fault VarCastResult { TYPE_MISMATCH @@ -92,7 +97,19 @@ macro bitcast(expr, $Type) @builtin var $size = (usize)($sizeof(expr)); $assert($size == $Type.sizeof, "Cannot bitcast between types of different size."); $Type x = void; - memcpy(&x, &expr, $size, false, $alignof($Type), $alignof(expr)); + mem::memcpy(&x, &expr, $size, false, $alignof($Type), $alignof(expr)); return x; } +/** + * @require $Type.kind == TypeKind.ENUM `Only enums may be used` + **/ +macro enum_by_name($Type, char[] enum_name) @builtin +{ + typeid x = $Type.typeid; + foreach (i, name : x.names) + { + if (str::compare(name, enum_name)) return ($Type)i; + } + return SearchResult.MISSING!; +} \ No newline at end of file diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 0a5570a73..064eee4db 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -51,8 +51,6 @@ macro void memset(void* dst, char val, usize bytes, bool $is_volatile = false, u } - - enum AllocationKind { ALLOC, diff --git a/lib/std/core/str.c3 b/lib/std/core/str.c3 index 0191986e6..3ee2e081b 100644 --- a/lib/std/core/str.c3 +++ b/lib/std/core/str.c3 @@ -48,6 +48,15 @@ fn ZString tcopy_zstring(char[] s) return (ZString)str; } +fn bool compare(char[] a, char[] b) +{ + if (a.len != b.len) return false; + foreach (i, c : a) + { + if (c != b[i]) return false; + } + return true; +} fault UnicodeResult { INVALID_UTF8, diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index b5c03aaec..099c74641 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -5576,7 +5576,8 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex return; case ACCESS_FAULTNAME: { - assert(inner->type->canonical->type_kind == TYPE_FAULTTYPE || inner->type->canonical->type_kind == TYPE_ANYERR); + Type *inner_type = type_no_fail(inner->type)->canonical; + assert(inner_type->type_kind == TYPE_FAULTTYPE || inner_type->type_kind == TYPE_ANYERR); llvm_value_rvalue(c, be_value); LLVMValueRef val = llvm_emit_alloca_aligned(c, type_chars, "faultname_zero"); BEValue zero; @@ -5606,12 +5607,13 @@ static inline void llvm_emit_builtin_access(GenContext *c, BEValue *be_value, Ex } case ACCESS_ENUMNAME: { - assert(inner->type->canonical->type_kind == TYPE_ENUM); + Type *inner_type = type_no_fail(inner->type)->canonical; + assert(inner_type->canonical->type_kind == TYPE_ENUM); llvm_value_rvalue(c, be_value); LLVMTypeRef subarray = llvm_get_type(c, type_chars); - LLVMTypeRef backend = LLVMTypeOf(inner->type->canonical->backend_typeid); - LLVMValueRef to_introspect = LLVMBuildIntToPtr(c->builder, inner->type->canonical->backend_typeid, + LLVMTypeRef backend = LLVMTypeOf(inner_type->backend_typeid); + LLVMValueRef to_introspect = LLVMBuildIntToPtr(c->builder, inner_type->backend_typeid, LLVMPointerType(c->introspect_type, 0), ""); LLVMValueRef ptr = LLVMBuildStructGEP2(c->builder, c->introspect_type, to_introspect, INTROSPECT_INDEX_ADDITIONAL, ""); LLVMValueRef ptr_to_first = llvm_emit_bitcast(c, ptr, type_get_ptr(type_chars)); diff --git a/src/compiler/sema_casts.c b/src/compiler/sema_casts.c index 300411355..e10abfa58 100644 --- a/src/compiler/sema_casts.c +++ b/src/compiler/sema_casts.c @@ -229,10 +229,19 @@ static bool int_literal_to_int(Expr *expr, Type *canonical, Type *type) /** * Convert from compile time int to any enum */ -bool lit_integer_to_enum(Expr *expr, Type *canonical, Type *type) +bool integer_to_enum(Expr *expr, Type *canonical, Type *type) { assert(canonical->type_kind == TYPE_ENUM); - unsigned max_enums = vec_size(canonical->decl->enums.values); + Decl *enum_decl = canonical->decl; + if (expr->expr_kind != EXPR_CONST) + { + REMINDER("Add check for runtime enum conversions"); + Type *underlying_type = enum_decl->enums.type_info->type->canonical; + if (!cast(expr, underlying_type)) return false; + expr->type = type; + return true; + } + unsigned max_enums = vec_size(enum_decl->enums.values); Int to_convert = expr->const_expr.ixx; if (int_is_neg(to_convert)) { @@ -245,7 +254,7 @@ bool lit_integer_to_enum(Expr *expr, Type *canonical, Type *type) SEMA_ERROR(expr, "This value exceeds the number of enums in %s.", canonical->decl->name); return false; } - Decl *decl = canonical->decl->enums.values[to_convert.i.low]; + Decl *decl = enum_decl->enums.values[to_convert.i.low]; expr->const_expr = (ExprConst) { .enum_val = decl, .const_kind = CONST_ENUM @@ -1288,7 +1297,7 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type) if (type_is_float(to)) return int_to_float(expr, CAST_SIFP, to, to_type); if (to == type_bool) return integer_to_bool(expr, to_type); if (to->type_kind == TYPE_POINTER) return int_to_pointer(expr, to_type); - if (to->type_kind == TYPE_ENUM) return lit_integer_to_enum(expr, to, to_type); + if (to->type_kind == TYPE_ENUM) return integer_to_enum(expr, to, to_type); break; case ALL_UNSIGNED_INTS: if (type_is_integer_unsigned(to)) return int_conversion(expr, CAST_UIUI, to, to_type); @@ -1296,7 +1305,7 @@ static bool cast_inner(Expr *expr, Type *from_type, Type *to, Type *to_type) if (type_is_float(to)) return int_to_float(expr, CAST_UIFP, to, to_type); if (to == type_bool) return integer_to_bool(expr, to_type); if (to->type_kind == TYPE_POINTER) return int_to_pointer(expr, to_type); - if (to->type_kind == TYPE_ENUM) return lit_integer_to_enum(expr, to, to_type); + if (to->type_kind == TYPE_ENUM) return integer_to_enum(expr, to, to_type); break; case ALL_FLOATS: if (type_is_integer(to)) return float_to_integer(expr, to, to_type); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 277224c97..1eff28309 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -65,7 +65,7 @@ void expr_rewrite_to_builtin_access(SemaContext *context, Expr *expr, Expr *pare expr->expr_kind = EXPR_BUILTIN_ACCESS; expr->builtin_access_expr.kind = kind; expr->builtin_access_expr.inner = exprid(parent); - expr->type = type; + expr->type = type_get_opt_fail(type, IS_FAILABLE(parent)); expr->resolve_status = RESOLVE_DONE; } @@ -3683,7 +3683,7 @@ CHECK_DEEPER: if (flat_type->type_kind == TYPE_TYPEID) { if (sema_expr_apply_typeid_property(context, expr, parent, kw)) return true; - SEMA_ERROR(identifier, "'%s' is not a valid proprty for typeid.", kw); + SEMA_ERROR(identifier, "'%s' is not a valid property for typeid.", kw); return false; } diff --git a/src/version.h b/src/version.h index 6a508efb7..c0954336a 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.2.24" \ No newline at end of file +#define COMPILER_VERSION "0.2.25" \ No newline at end of file