aboutsummaryrefslogtreecommitdiff
path: root/src/compile
diff options
context:
space:
mode:
Diffstat (limited to 'src/compile')
-rw-r--r--src/compile/assignments.c16
-rw-r--r--src/compile/expressions.c2
-rw-r--r--src/compile/indexing.c36
-rw-r--r--src/compile/indexing.h4
-rw-r--r--src/compile/optionals.c4
5 files changed, 38 insertions, 24 deletions
diff --git a/src/compile/assignments.c b/src/compile/assignments.c
index 3cb60fd5..6848e298 100644
--- a/src/compile/assignments.c
+++ b/src/compile/assignments.c
@@ -92,7 +92,8 @@ Text_t compile_assignment_statement(env_t *env, ast_t *ast) {
if (assign->targets && !assign->targets->next) {
type_t *lhs_t = get_type(env, assign->targets->ast);
if (assign->targets->ast->tag == Index && lhs_t->tag == OptionalType
- && value_type(get_type(env, Match(assign->targets->ast, Index)->indexed))->tag == TableType)
+ && (value_type(get_type(env, Match(assign->targets->ast, Index)->indexed))->tag == TableType
+ || value_type(get_type(env, Match(assign->targets->ast, Index)->indexed))->tag == ListType))
lhs_t = Match(lhs_t, OptionalType)->type;
if (has_stack_memory(lhs_t))
code_err(ast, "Stack references cannot be assigned to "
@@ -110,7 +111,8 @@ Text_t compile_assignment_statement(env_t *env, ast_t *ast) {
value = value->next, target = target->next) {
type_t *lhs_t = get_type(env, target->ast);
if (target->ast->tag == Index && lhs_t->tag == OptionalType
- && value_type(get_type(env, Match(target->ast, Index)->indexed))->tag == TableType)
+ && (value_type(get_type(env, Match(target->ast, Index)->indexed))->tag == TableType
+ || value_type(get_type(env, Match(target->ast, Index)->indexed))->tag == ListType))
lhs_t = Match(lhs_t, OptionalType)->type;
if (has_stack_memory(lhs_t))
code_err(ast, "Stack references cannot be assigned to "
@@ -166,13 +168,8 @@ Text_t compile_lvalue(env_t *env, ast_t *ast) {
? compile_int_to_type(env, index->index, Type(IntType, .bits = TYPE_IBITS64))
: (index_t->tag == BigIntType ? Texts("Int64$from_int(", compile(env, index->index), ", no)")
: Texts("(Int64_t)(", compile(env, index->index), ")"));
- if (index->unchecked) {
- return Texts("List_lvalue_unchecked(", compile_type(item_type), ", ", target_code, ", ", index_code,
- ")");
- } else {
- return Texts("List_lvalue(", compile_type(item_type), ", ", target_code, ", ", index_code, ", ",
- (int64_t)(ast->start - ast->file->text), ", ", (int64_t)(ast->end - ast->file->text), ")");
- }
+ return Texts("List_lvalue(", compile_type(item_type), ", ", target_code, ", ", index_code, ", ",
+ (int64_t)(ast->start - ast->file->text), ", ", (int64_t)(ast->end - ast->file->text), ")");
} else if (container_t->tag == TableType) {
DeclareMatch(table_type, container_t, TableType);
if (table_type->default_value) {
@@ -183,7 +180,6 @@ Text_t compile_lvalue(env_t *env, ast_t *ast) {
compile_to_type(env, table_type->default_value, table_type->value_type), ", ",
compile_type_info(container_t), ")");
}
- if (index->unchecked) code_err(ast, "Table indexes cannot be unchecked");
return Texts("*(", compile_type(Type(PointerType, table_type->value_type)), ")Table$reserve(",
compile_to_pointer_depth(env, index->indexed, 1, false), ", ",
compile_to_type(env, index->index, Type(PointerType, table_type->key_type, .is_stack = true)),
diff --git a/src/compile/expressions.c b/src/compile/expressions.c
index 544b7723..e888ce16 100644
--- a/src/compile/expressions.c
+++ b/src/compile/expressions.c
@@ -234,7 +234,7 @@ Text_t compile(env_t *env, ast_t *ast) {
case If: return compile_if_expression(env, ast);
case Reduction: return compile_reduction(env, ast);
case FieldAccess: return compile_field_access(env, ast);
- case Index: return compile_indexing(env, ast);
+ case Index: return compile_indexing(env, ast, false);
case InlineCCode: {
type_t *t = get_type(env, ast);
if (Match(ast, InlineCCode)->type_ast != NULL) return Texts("({", compile_statement(env, ast), "; })");
diff --git a/src/compile/indexing.c b/src/compile/indexing.c
index 1510e924..bb7bf6b9 100644
--- a/src/compile/indexing.c
+++ b/src/compile/indexing.c
@@ -1,5 +1,7 @@
// This file defines how to compile indexing like `list[i]` or `ptr[]`
+#include <stdbool.h>
+
#include "../ast.h"
#include "../config.h"
#include "../environment.h"
@@ -9,7 +11,7 @@
#include "compilation.h"
public
-Text_t compile_indexing(env_t *env, ast_t *ast) {
+Text_t compile_indexing(env_t *env, ast_t *ast, bool checked) {
DeclareMatch(indexing, ast, Index);
type_t *indexed_type = get_type(env, indexing->indexed);
if (!indexing->index) {
@@ -34,27 +36,33 @@ Text_t compile_indexing(env_t *env, ast_t *ast) {
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, ", ",
- (int64_t)(indexing->index->start - f->text), ", ", (int64_t)(indexing->index->end - f->text),
- ")");
+ 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, ")");
+ } else {
+ return Texts("List_get(", list, ", ", index_code, ", ", compile_type(item_type), ", value, ",
+ promote_to_optional(item_type, Text("value")), ", ", compile_none(item_type), ")");
+ }
} 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_to_type(env, indexing->index, table_type->key_type), ", ",
compile_to_type(env, table_type->default_value, table_type->value_type), ", ",
compile_type_info(container_t), ")");
+ } else if (checked) {
+ int64_t start = (int64_t)(ast->start - ast->file->text), end = (int64_t)(ast->end - ast->file->text);
+ return Texts("Table$get_checked(", 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), ", ", start, ", ", end, ", ", 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), ", ",
@@ -65,8 +73,14 @@ Text_t compile_indexing(env_t *env, ast_t *ast) {
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)), ")");
+ if (checked) {
+ int64_t start = (int64_t)(ast->start - ast->file->text), end = (int64_t)(ast->end - ast->file->text);
+ return Texts("Text$cluster_checked(", compile_to_pointer_depth(env, indexing->indexed, 0, false), ", ",
+ compile_to_type(env, indexing->index, Type(BigIntType)), ", ", start, ", ", end, ")");
+ } else {
+ 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));
}
diff --git a/src/compile/indexing.h b/src/compile/indexing.h
index bf30f98a..5b76692b 100644
--- a/src/compile/indexing.h
+++ b/src/compile/indexing.h
@@ -2,8 +2,10 @@
#pragma once
+#include <stdbool.h>
+
#include "../ast.h"
#include "../environment.h"
#include "../stdlib/datatypes.h"
-Text_t compile_indexing(env_t *env, ast_t *ast);
+Text_t compile_indexing(env_t *env, ast_t *ast, bool checked);
diff --git a/src/compile/optionals.c b/src/compile/optionals.c
index cd50b1bf..8340ecaa 100644
--- a/src/compile/optionals.c
+++ b/src/compile/optionals.c
@@ -8,6 +8,7 @@
#include "../typecheck.h"
#include "../types.h"
#include "compilation.h"
+#include "indexing.h"
Text_t optional_into_nonnone(type_t *t, Text_t value) {
if (t->tag == OptionalType) t = Match(t, OptionalType)->type;
@@ -122,6 +123,7 @@ Text_t compile_optional(env_t *env, ast_t *ast) {
public
Text_t compile_non_optional(env_t *env, ast_t *ast) {
ast_t *value = Match(ast, NonOptional)->value;
+ if (value->tag == Index && Match(value, Index)->index != NULL) return compile_indexing(env, value, true);
type_t *t = get_type(env, value);
Text_t value_code = compile(env, value);
int64_t line = get_line_number(ast->file, ast->start);
@@ -129,5 +131,5 @@ Text_t compile_non_optional(env_t *env, ast_t *ast) {
"({ ", compile_declaration(t, Text("opt")), " = ", value_code, "; ", "if unlikely (",
check_none(t, Text("opt")), ")\n", "#line ", line, "\n", "fail_source(", quoted_str(ast->file->filename), ", ",
(int64_t)(value->start - value->file->text), ", ", (int64_t)(value->end - value->file->text), ", ",
- "\"This was expected to be a value, but it's none\");\n", optional_into_nonnone(t, Text("opt")), "; })");
+ "\"This was expected to be a value, but it's `none`\\n\");\n", optional_into_nonnone(t, Text("opt")), "; })");
}