aboutsummaryrefslogtreecommitdiff
path: root/src/compile/indexing.c
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2025-08-24 18:21:39 -0400
committerBruce Hill <bruce@bruce-hill.com>2025-08-24 18:21:39 -0400
commit74e8aa30901dba029f3e39d187337a09740db4e0 (patch)
treeb17b37dec809aa9c054ab7d82bfe4a52fe5c4fab /src/compile/indexing.c
parent7e5e03f191c4379bf7e34cccfa044ec928189eed (diff)
Move indexing into its own file
Diffstat (limited to 'src/compile/indexing.c')
-rw-r--r--src/compile/indexing.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/compile/indexing.c b/src/compile/indexing.c
new file mode 100644
index 00000000..7245e9cf
--- /dev/null
+++ b/src/compile/indexing.c
@@ -0,0 +1,78 @@
+// This file defines how to compile indexing like `list[i]` or `ptr[]`
+
+#include "../ast.h"
+#include "../config.h"
+#include "../environment.h"
+#include "../stdlib/text.h"
+#include "../stdlib/util.h"
+#include "../typecheck.h"
+#include "expressions.h"
+#include "integers.h"
+#include "optionals.h"
+#include "pointers.h"
+#include "promotions.h"
+#include "types.h"
+
+public
+Text_t compile_indexing(env_t *env, ast_t *ast) {
+ DeclareMatch(indexing, ast, Index);
+ type_t *indexed_type = get_type(env, indexing->indexed);
+ if (!indexing->index) {
+ if (indexed_type->tag != PointerType)
+ code_err(ast, "Only pointers can use the '[]' operator to "
+ "dereference "
+ "the entire value.");
+ DeclareMatch(ptr, indexed_type, PointerType);
+ if (ptr->pointed->tag == ListType) {
+ return Texts("*({ List_t *list = ", compile(env, indexing->indexed), "; LIST_INCREF(*list); list; })");
+ } else if (ptr->pointed->tag == TableType || ptr->pointed->tag == SetType) {
+ return Texts("*({ Table_t *t = ", compile(env, indexing->indexed), "; TABLE_INCREF(*t); t; })");
+ } else {
+ return Texts("*(", compile(env, indexing->indexed), ")");
+ }
+ }
+
+ type_t *container_t = value_type(indexed_type);
+ type_t *index_t = get_type(env, indexing->index);
+ if (container_t->tag == ListType) {
+ if (index_t->tag != IntType && index_t->tag != BigIntType && index_t->tag != ByteType)
+ code_err(indexing->index, "Lists can only be indexed by integers, not ", type_to_str(index_t));
+ type_t *item_type = Match(container_t, ListType)->item_type;
+ Text_t list = compile_to_pointer_depth(env, indexing->indexed, 0, false);
+ file_t *f = indexing->index->file;
+ Text_t index_code =
+ indexing->index->tag == Int
+ ? compile_int_to_type(env, indexing->index, Type(IntType, .bits = TYPE_IBITS64))
+ : (index_t->tag == BigIntType ? Texts("Int64$from_int(", compile(env, indexing->index), ", no)")
+ : Texts("(Int64_t)(", compile(env, indexing->index), ")"));
+ if (indexing->unchecked)
+ return Texts("List_get_unchecked(", compile_type(item_type), ", ", list, ", ", index_code, ")");
+ else
+ return Texts("List_get(", compile_type(item_type), ", ", list, ", ", index_code, ", ",
+ String((int64_t)(indexing->index->start - f->text)), ", ",
+ String((int64_t)(indexing->index->end - f->text)), ")");
+ } else if (container_t->tag == TableType) {
+ DeclareMatch(table_type, container_t, TableType);
+ if (indexing->unchecked) code_err(ast, "Table indexes cannot be unchecked");
+ if (table_type->default_value) {
+ return Texts("Table$get_or_default(", compile_to_pointer_depth(env, indexing->indexed, 0, false), ", ",
+ compile_type(table_type->key_type), ", ", compile_type(table_type->value_type), ", ",
+ compile(env, indexing->index), ", ",
+ compile_to_type(env, table_type->default_value, table_type->value_type), ", ",
+ compile_type_info(container_t), ")");
+ } else {
+ return Texts("Table$get_optional(", compile_to_pointer_depth(env, indexing->indexed, 0, false), ", ",
+ compile_type(table_type->key_type), ", ", compile_type(table_type->value_type), ", ",
+ compile(env, indexing->index),
+ ", "
+ "_, ",
+ promote_to_optional(table_type->value_type, Text("(*_)")), ", ",
+ compile_none(table_type->value_type), ", ", compile_type_info(container_t), ")");
+ }
+ } else if (container_t->tag == TextType) {
+ return Texts("Text$cluster(", compile_to_pointer_depth(env, indexing->indexed, 0, false), ", ",
+ compile_to_type(env, indexing->index, Type(BigIntType)), ")");
+ } else {
+ code_err(ast, "Indexing is not supported for type: ", type_to_str(container_t));
+ }
+}