From 398d2cab6988e20c59e7037ff7ef551540339abb Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sun, 5 Oct 2025 17:52:33 -0400 Subject: Fix a bunch of issues with optional types --- src/compile/headers.c | 2 ++ src/compile/integers.c | 8 +++++--- src/compile/statements.c | 10 +++++++++- src/compile/structs.c | 8 +++++--- src/compile/types.c | 4 ++-- src/stdlib/functiontype.c | 2 +- src/stdlib/paths.c | 3 ++- src/stdlib/structs.c | 3 +-- src/stdlib/structs.h | 3 --- src/stdlib/types.h | 11 ----------- src/typecheck.c | 5 ++++- src/types.c | 8 +++----- 12 files changed, 34 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/compile/headers.c b/src/compile/headers.c index bc0156ad..f132b312 100644 --- a/src/compile/headers.c +++ b/src/compile/headers.c @@ -106,6 +106,8 @@ static void _make_typedefs(compile_typedef_info_t *info, ast_t *ast) { DeclareMatch(def, ast, LangDef); *info->header = Texts(*info->header, "typedef Text_t ", namespace_name(info->env, info->env->namespace, Texts(def->name, "$$type")), ";\n"); + *info->header = Texts(*info->header, "typedef Text_t ", "Optional", + namespace_name(info->env, info->env->namespace, Texts(def->name, "$$type")), ";\n"); } } diff --git a/src/compile/integers.c b/src/compile/integers.c index 41c2b78a..78d48b70 100644 --- a/src/compile/integers.c +++ b/src/compile/integers.c @@ -22,11 +22,13 @@ Text_t compile_int_to_type(env_t *env, ast_t *ast, type_t *target) { return code; } - if (target->tag == BigIntType) return compile(env, ast); + if (non_optional(target)->tag == BigIntType) return compile(env, ast); - if (target->tag == OptionalType && Match(target, OptionalType)->type) + if (target->tag == OptionalType && Match(target, OptionalType)->type) { return Texts("((", compile_type(target), - "){.value=", compile_int_to_type(env, ast, Match(target, OptionalType)->type), "})"); + "){.value=", compile_int_to_type(env, ast, Match(target, OptionalType)->type), + ", .has_value=true})"); + } const char *literal = Match(ast, Int)->str; OptionalInt_t int_val = Int$from_str(literal); diff --git a/src/compile/statements.c b/src/compile/statements.c index a9ec4327..0cd85b5d 100644 --- a/src/compile/statements.c +++ b/src/compile/statements.c @@ -117,7 +117,15 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) { code = Texts(code, compile_statement(deferred->defer_env, deferred->block)); } - type_t *ret_type = get_function_return_type(env, env->fn); + type_t *ret_type; + if (env->fn->tag == Lambda) { + if (Match(env->fn, Lambda)->ret_type != NULL) + ret_type = parse_type_ast(env, Match(env->fn, Lambda)->ret_type); + else ret_type = ret ? get_type(env, ret) : Type(VoidType); + } else { + ret_type = get_function_return_type(env, env->fn); + } + if (ret) { if (ret_type->tag == VoidType || ret_type->tag == AbortType) code_err(ast, "This function is not supposed to return any values, " diff --git a/src/compile/structs.c b/src/compile/structs.c index 2e7217f6..3f443c44 100644 --- a/src/compile/structs.c +++ b/src/compile/structs.c @@ -70,12 +70,14 @@ Text_t compile_struct_header(env_t *env, ast_t *ast) { Text_t struct_code = def->external ? EMPTY_TEXT : Texts(type_code, " {\n", fields, "};\n"); type_t *t = Table$str_get(*env->types, def->name); - Text_t unpadded_size = def->opaque ? Texts("sizeof(", type_code, ")") : Texts((int64_t)unpadded_struct_size(t)); Text_t typeinfo_code = Texts("extern const TypeInfo_t ", typeinfo_name, ";\n"); Text_t optional_code = EMPTY_TEXT; if (!def->opaque) { - optional_code = Texts("DEFINE_OPTIONAL_TYPE(", compile_type(t), ", ", unpadded_size, ", ", - namespace_name(env, env->namespace, Texts("$Optional", def->name, "$$type")), ");\n"); + optional_code = Texts("typedef struct {\n", compile_type(t), + " value;\n" + "Bool_t has_value;\n" + "} ", + namespace_name(env, env->namespace, Texts("$Optional", def->name, "$$type")), ";\n"); } return Texts(struct_code, optional_code, typeinfo_code); } diff --git a/src/compile/types.c b/src/compile/types.c index 58a0260b..2b345b41 100644 --- a/src/compile/types.c +++ b/src/compile/types.c @@ -135,8 +135,8 @@ Text_t compile_type_info(type_t *t) { } case OptionalType: { type_t *non_optional = Match(t, OptionalType)->type; - return Texts("Optional$info(sizeof(", compile_type(non_optional), "), __alignof__(", compile_type(non_optional), - "), ", compile_type_info(non_optional), ")"); + return Texts("Optional$info(", (int64_t)type_size(t), ", ", (int64_t)type_align(t), ", ", + compile_type_info(non_optional), ")"); } case TypeInfoType: return Texts("Type$info(", quoted_text(type_to_text(Match(t, TypeInfoType)->type)), ")"); case MemoryType: return Text("&Memory$info"); diff --git a/src/stdlib/functiontype.c b/src/stdlib/functiontype.c index 3270e0ca..6fc0d6bf 100644 --- a/src/stdlib/functiontype.c +++ b/src/stdlib/functiontype.c @@ -19,5 +19,5 @@ Text_t Func$as_text(const void *fn, bool colorize, const TypeInfo_t *type) { public PUREFUNC bool Func$is_none(const void *obj, const TypeInfo_t *info) { (void)info; - return *(void **)obj == NULL; + return ((Closure_t *)obj)->fn == NULL; } diff --git a/src/stdlib/paths.c b/src/stdlib/paths.c index d630ad7d..74526f7d 100644 --- a/src/stdlib/paths.c +++ b/src/stdlib/paths.c @@ -690,10 +690,11 @@ OptionalClosure_t Path$by_line(Path_t path) { // be closed by GC finalizers. GC_gcollect(); f = fopen(path_str, "r"); - if (f == NULL) return NONE_CLOSURE; } } + if (f == NULL) return NONE_CLOSURE; + FILE **wrapper = GC_MALLOC(sizeof(FILE *)); *wrapper = f; GC_register_finalizer(wrapper, (void *)_line_reader_cleanup, NULL, NULL, NULL); diff --git a/src/stdlib/structs.c b/src/stdlib/structs.c index b08d7967..885b903c 100644 --- a/src/stdlib/structs.c +++ b/src/stdlib/structs.c @@ -160,9 +160,8 @@ PUREFUNC public Text_t Struct$as_text(const void *obj, bool colorize, const Type return Text$concat(text, Text(")")); } -PUREFUNC public bool Struct$is_none(const void *obj, const TypeInfo_t *type) { return *(bool *)(obj + type->size); } - public + void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type) { ptrdiff_t byte_offset = 0; ptrdiff_t bit_offset = 0; diff --git a/src/stdlib/structs.h b/src/stdlib/structs.h index 368a670a..a582e9fb 100644 --- a/src/stdlib/structs.h +++ b/src/stdlib/structs.h @@ -13,7 +13,6 @@ PUREFUNC int32_t Struct$compare(const void *x, const void *y, const TypeInfo_t * PUREFUNC bool Struct$equal(const void *x, const void *y, const TypeInfo_t *type); PUREFUNC bool PackedData$equal(const void *x, const void *y, const TypeInfo_t *type); PUREFUNC Text_t Struct$as_text(const void *obj, bool colorize, const TypeInfo_t *type); -PUREFUNC bool Struct$is_none(const void *obj, const TypeInfo_t *type); void Struct$serialize(const void *obj, FILE *out, Table_t *pointers, const TypeInfo_t *type); void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo_t *type); @@ -23,7 +22,6 @@ void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo .compare = Struct$compare, \ .equal = Struct$equal, \ .as_text = Struct$as_text, \ - .is_none = Struct$is_none, \ .serialize = Struct$serialize, \ .deserialize = Struct$deserialize, \ } @@ -34,7 +32,6 @@ void Struct$deserialize(FILE *in, void *outval, List_t *pointers, const TypeInfo .compare = Struct$compare, \ .equal = PackedData$equal, \ .as_text = Struct$as_text, \ - .is_none = Struct$is_none, \ .serialize = Struct$serialize, \ .deserialize = Struct$deserialize, \ } diff --git a/src/stdlib/types.h b/src/stdlib/types.h index 85567815..bd2474fa 100644 --- a/src/stdlib/types.h +++ b/src/stdlib/types.h @@ -102,14 +102,3 @@ Text_t Type$as_text(const void *typeinfo, bool colorize, const TypeInfo_t *type) .tag = TypeInfoInfo, \ .TypeInfoInfo.type_str = typestr, \ .metamethods = {.serialize = cannot_serialize, .deserialize = cannot_deserialize, .as_text = Type$as_text}}) - -#define DEFINE_OPTIONAL_TYPE(t, unpadded_size, name) \ - typedef struct { \ - union { \ - t value; \ - struct { \ - char _padding[unpadded_size]; \ - Bool_t has_value; \ - }; \ - }; \ - } name diff --git a/src/typecheck.c b/src/typecheck.c index b21fa40f..906236c3 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -1067,7 +1067,10 @@ type_t *get_type(env_t *env, ast_t *ast) { } case Return: { ast_t *val = Match(ast, Return)->value; - if (env->fn) env = with_enum_scope(env, get_function_return_type(env, env->fn)); + if (env->fn && (env->fn->tag != Lambda || Match(env->fn, Lambda)->ret_type != NULL)) { + type_t *ret_type = get_function_return_type(env, env->fn); + env = with_enum_scope(env, ret_type); + } return Type(ReturnType, .ret = (val ? get_type(env, val) : Type(VoidType))); } case Stop: diff --git a/src/types.c b/src/types.c index 900588f5..bf986c80 100644 --- a/src/types.c +++ b/src/types.c @@ -476,11 +476,9 @@ PUREFUNC size_t type_size(type_t *t) { default: errx(1, "Invalid integer bit size"); } case StructType: { - size_t size = unpadded_struct_size(nonnull); - size += sizeof(bool); // is_null flag - size_t align = type_align(nonnull); - if (align > 0 && (size % align) > 0) size = (size + align) - (size % align); - return size; + arg_t *fields = new (arg_t, .name = "value", .type = nonnull, + .next = new (arg_t, .name = "has_value", .type = Type(BoolType))); + return type_size(Type(StructType, .fields = fields)); } default: return type_size(nonnull); } -- cgit v1.2.3