From 7494c89a4e1baa08a2720817b06676b34eebb284 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Wed, 1 Oct 2025 14:01:51 -0400 Subject: Fixes for indexing into lists with optional item types --- src/compile/indexing.c | 16 ++++++++++++++-- src/typecheck.c | 6 ++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/compile/indexing.c b/src/compile/indexing.c index af5056d7..13062641 100644 --- a/src/compile/indexing.c +++ b/src/compile/indexing.c @@ -43,8 +43,20 @@ Text_t compile_indexing(env_t *env, ast_t *ast, bool checked) { : Texts("(Int64_t)(", compile(env, indexing->index), ")")); if (checked) { int64_t start = (int64_t)(ast->start - ast->file->text), end = (int64_t)(ast->end - ast->file->text); - return Texts("List_get_checked(", list, ", ", index_code, ", ", compile_type(item_type), ", ", start, ", ", - end, ")"); + Text_t code = Texts("List_get_checked(", list, ", ", index_code, ", ", compile_type(item_type), ", ", start, + ", ", end, ")"); + if (item_type->tag == OptionalType) { + int64_t line = get_line_number(ast->file, ast->start); + return Texts("({ ", compile_declaration(item_type, Text("opt")), " = ", code, "; ", "if unlikely (", + check_none(item_type, Text("opt")), ")\n", "#line ", line, "\n", "fail_source(", + quoted_str(ast->file->filename), ", ", start, ", ", end, ", ", + "\"This was expected to be a value, but it's `none`\\n\");\n", + optional_into_nonnone(item_type, Text("opt")), "; })"); + } + return code; + } else if (item_type->tag == OptionalType) { + return Texts("List_get(", list, ", ", index_code, ", ", compile_type(item_type), ", value, value,", + compile_none(item_type), ")"); } else { return Texts("List_get(", list, ", ", index_code, ", ", compile_type(item_type), ", value, ", promote_to_optional(item_type, Text("value")), ", ", compile_none(item_type), ")"); diff --git a/src/typecheck.c b/src/typecheck.c index 3c820fa9..eff894be 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -934,8 +934,10 @@ type_t *get_type(env_t *env, ast_t *ast) { if (value_t->tag == ListType) { if (!indexing->index) return indexed_t; type_t *index_t = get_type(env, indexing->index); - if (index_t->tag == IntType || index_t->tag == BigIntType || index_t->tag == ByteType) - return Type(OptionalType, Match(value_t, ListType)->item_type); + if (index_t->tag == IntType || index_t->tag == BigIntType || index_t->tag == ByteType) { + type_t *item_type = Match(value_t, ListType)->item_type; + return item_type->tag == OptionalType ? item_type : Type(OptionalType, item_type); + } code_err(indexing->index, "I only know how to index lists using integers, not ", type_to_text(index_t)); } else if (value_t->tag == TableType) { DeclareMatch(table_type, value_t, TableType); -- cgit v1.2.3