diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast.h | 1 | ||||
| -rw-r--r-- | src/compile/assignments.c | 18 | ||||
| -rw-r--r-- | src/compile/indexing.c | 10 | ||||
| -rw-r--r-- | src/modules.c | 6 | ||||
| -rw-r--r-- | src/parse/suffixes.c | 3 | ||||
| -rw-r--r-- | src/stdlib/lists.h | 47 | ||||
| -rw-r--r-- | src/typecheck.c | 2 |
7 files changed, 30 insertions, 57 deletions
@@ -429,7 +429,6 @@ struct ast_s { } LangDef; struct { ast_t *indexed, *index; - bool unchecked; } Index; struct { ast_t *fielded; diff --git a/src/compile/assignments.c b/src/compile/assignments.c index ab28b972..5fedad9a 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,14 +168,9 @@ 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, ", ", - String((int)(ast->start - ast->file->text)), ", ", - String((int)(ast->end - ast->file->text)), ")"); - } + return Texts("List_lvalue(", compile_type(item_type), ", ", target_code, ", ", index_code, ", ", + String((int)(ast->start - ast->file->text)), ", ", String((int)(ast->end - ast->file->text)), + ")"); } else if (container_t->tag == TableType) { DeclareMatch(table_type, container_t, TableType); if (table_type->default_value) { @@ -184,7 +181,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/indexing.c b/src/compile/indexing.c index e99feeb2..d2e98388 100644 --- a/src/compile/indexing.c +++ b/src/compile/indexing.c @@ -34,21 +34,15 @@ 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, ", ", - String((int64_t)(indexing->index->start - f->text)), ", ", - String((int64_t)(indexing->index->end - f->text)), ")"); + 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), ", ", diff --git a/src/modules.c b/src/modules.c index 40b3daf3..ff112c02 100644 --- a/src/modules.c +++ b/src/modules.c @@ -52,14 +52,14 @@ module_info_t get_module_info(ast_t *use) { module_info_t *info = new (module_info_t, .name = name); if (streq(name, "commands")) info->version = "v1.0"; else if (streq(name, "random")) info->version = "v1.0"; - else if (streq(name, "base64")) info->version = "v1.0"; + else if (streq(name, "base64")) info->version = "v1.1"; else if (streq(name, "core")) info->version = "v1.0"; else if (streq(name, "patterns")) info->version = "v1.1"; - else if (streq(name, "json")) info->version = "v1.0"; + else if (streq(name, "json")) info->version = "v1.1"; else if (streq(name, "pthreads")) info->version = "v1.0"; else if (streq(name, "shell")) info->version = "v1.0"; else if (streq(name, "time")) info->version = "v1.0"; - else if (streq(name, "uuid")) info->version = "v1.0"; + else if (streq(name, "uuid")) info->version = "v1.1"; else { read_modules_ini(Path$sibling(Path$from_str(use->file->filename), Text("modules.ini")), info); read_modules_ini(Path$with_extension(Path$from_str(use->file->filename), Text(":modules.ini"), false), info); diff --git a/src/parse/suffixes.c b/src/parse/suffixes.c index 7e748caf..4aa09cb8 100644 --- a/src/parse/suffixes.c +++ b/src/parse/suffixes.c @@ -47,9 +47,8 @@ ast_t *parse_index_suffix(parse_ctx_t *ctx, ast_t *lhs) { whitespace(&pos); ast_t *index = optional(ctx, &pos, parse_extended_expr); whitespace(&pos); - bool unchecked = match(&pos, ";") && (spaces(&pos), match_word(&pos, "unchecked") != 0); expect_closing(ctx, &pos, "]", "I wasn't able to parse the rest of this index"); - return NewAST(ctx->file, start, pos, Index, .indexed = lhs, .index = index, .unchecked = unchecked); + return NewAST(ctx->file, start, pos, Index, .indexed = lhs, .index = index); } ast_t *parse_comprehension_suffix(parse_ctx_t *ctx, ast_t *expr) { diff --git a/src/stdlib/lists.h b/src/stdlib/lists.h index 1ba46222..74314aa6 100644 --- a/src/stdlib/lists.h +++ b/src/stdlib/lists.h @@ -10,26 +10,19 @@ #include "util.h" // Convert negative indices to back-indexed without branching: index0 = index + (index < 0)*(len+1)) - 1 -#define List_get(item_type, arr_expr, index_expr, start, end) \ - *({ \ - const List_t list = arr_expr; \ +#define List_get(list_expr, index_expr, item_type, var, optional_expr, none_expr) \ + ({ \ + const List_t list = list_expr; \ int64_t index = index_expr; \ - int64_t off = index + (index < 0) * (list.length + 1) - 1; \ - if (unlikely(off < 0 || off >= list.length)) \ - fail_source(__SOURCE_FILE__, start, end, "Invalid list index: ", index, " (list has length ", \ - (int64_t)list.length, ")\n"); \ - (item_type *)(list.data + list.stride * off); \ + int64_t offset = index + (index < 0) * (list.length + 1) - 1; \ + unlikely(offset < 0 || offset >= list.length) ? none_expr : ({ \ + item_type var = *(item_type *)(list.data + list.stride * offset); \ + optional_expr; \ + }); \ }) -#define List_get_unchecked(type, x, i) \ +#define List_lvalue(item_type, list_expr, index_expr, start, end) \ *({ \ - const List_t list = x; \ - int64_t index = i; \ - int64_t off = index + (index < 0) * (list.length + 1) - 1; \ - (type *)(list.data + list.stride * off); \ - }) -#define List_lvalue(item_type, arr_expr, index_expr, start, end) \ - *({ \ - List_t *list = arr_expr; \ + List_t *list = list_expr; \ int64_t index = index_expr; \ int64_t off = index + (index < 0) * (list->length + 1) - 1; \ if (unlikely(off < 0 || off >= list->length)) \ @@ -38,15 +31,7 @@ if (list->data_refcount > 0) List$compact(list, sizeof(item_type)); \ (item_type *)(list->data + list->stride * off); \ }) -#define List_lvalue_unchecked(item_type, arr_expr, index_expr) \ - *({ \ - List_t *list = arr_expr; \ - int64_t index = index_expr; \ - int64_t off = index + (index < 0) * (list->length + 1) - 1; \ - if (list->data_refcount > 0) List$compact(list, sizeof(item_type)); \ - (item_type *)(list->data + list->stride * off); \ - }) -#define List_set(item_type, list, index, value, start, end) List_lvalue(item_type, arr_expr, index, start, end) = value +#define List_set(item_type, list, index, value, start, end) List_lvalue(item_type, list_expr, index, start, end) = value #define is_atomic(x) \ _Generic(x, \ bool: true, \ @@ -103,9 +88,9 @@ void List$remove_item(List_t *list, void *item, Int_t max_removals, const TypeIn #define List$remove_item_value(list, item_expr, max, type) \ List$remove_item(list, (__typeof(item_expr)[1]){item_expr}, max, type) -#define List$pop(arr_expr, index_expr, item_type, nonnone_var, nonnone_expr, none_expr) \ +#define List$pop(list_expr, index_expr, item_type, nonnone_var, nonnone_expr, none_expr) \ ({ \ - List_t *list = arr_expr; \ + List_t *list = list_expr; \ Int_t index = index_expr; \ int64_t index64 = Int64$from_int(index, false); \ int64_t off = index64 + (index64 < 0) * (list->length + 1) - 1; \ @@ -131,9 +116,9 @@ List_t List$shuffled(List_t list, OptionalClosure_t random_int64, int64_t padded void *List$random(List_t list, OptionalClosure_t random_int64); #define List$random_value(list, random_int64, t) \ ({ \ - List_t _arr = list; \ - if (_arr.length == 0) fail("Cannot get a random value from an empty list!"); \ - *(t *)List$random(_arr, random_int64); \ + List_t _list_expr = list; \ + if (_list_expr.length == 0) fail("Cannot get a random value from an empty list!"); \ + *(t *)List$random(_list_expr, random_int64); \ }) List_t List$sample(List_t list, Int_t n, List_t weights, Closure_t random_num, int64_t padded_item_size); Table_t List$counts(List_t list, const TypeInfo_t *type); diff --git a/src/typecheck.c b/src/typecheck.c index 50df9327..eba12a6e 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -890,7 +890,7 @@ type_t *get_type(env_t *env, ast_t *ast) { 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 Match(value_t, ListType)->item_type; + return Type(OptionalType, Match(value_t, ListType)->item_type); code_err(indexing->index, "I only know how to index lists using integers, not ", type_to_str(index_t)); } else if (value_t->tag == TableType) { DeclareMatch(table_type, value_t, TableType); |
