aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES.md3
-rw-r--r--docs/lists.md17
-rw-r--r--examples/colorful/CHANGES.md4
-rw-r--r--examples/colorful/colorful.tm6
-rw-r--r--examples/http-server/CHANGES.md4
-rw-r--r--examples/http-server/http-server.tm12
-rw-r--r--examples/ini/CHANGES.md4
-rw-r--r--examples/ini/ini.tm8
-rw-r--r--lib/base64/CHANGES.md4
-rw-r--r--lib/base64/base64.tm34
-rw-r--r--lib/json/CHANGES.md4
-rw-r--r--lib/json/json.tm2
-rw-r--r--lib/uuid/CHANGES.md4
-rw-r--r--lib/uuid/uuid.tm4
-rw-r--r--src/ast.h1
-rw-r--r--src/compile/assignments.c18
-rw-r--r--src/compile/indexing.c10
-rw-r--r--src/modules.c6
-rw-r--r--src/parse/suffixes.c3
-rw-r--r--src/stdlib/lists.h47
-rw-r--r--src/typecheck.c2
-rw-r--r--test/enums.tm4
-rw-r--r--test/iterators.tm3
23 files changed, 101 insertions, 103 deletions
diff --git a/CHANGES.md b/CHANGES.md
index 965a1aea..eca192c8 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,8 @@
# Version History
+## v1.0
+- List indexing now gives an optional value
+
## v0.3
- Added a versioning system based on `CHANGES.md` files and `modules.ini`
diff --git a/docs/lists.md b/docs/lists.md
index dfb64aad..d12a0b5b 100644
--- a/docs/lists.md
+++ b/docs/lists.md
@@ -62,24 +62,23 @@ last item, `-2` is the second-to-last, and so on.
```tomo
list := [10, 20, 30, 40]
>> list[1]
-= 10
+= 10?
>> list[2]
-= 20
+= 20?
+
+>> list[999]
+= none
>> list[-1]
-= 40
+= 40?
>> list[-2]
-= 30
+= 30?
```
If a list index of `0` or any value larger than the length of the list is
-used, it will trigger a runtime error that will print what the invalid list
-index was, the length of the list, and a stack trace. As a performance
-operation, if list bounds checking proves to be a performance hot spot, you
-can explicitly disable bounds checking by adding `list[i; unchecked]` to the
-list access.
+used, a `none` value will be returned.
## Iteration
diff --git a/examples/colorful/CHANGES.md b/examples/colorful/CHANGES.md
index 093cc077..985e98a7 100644
--- a/examples/colorful/CHANGES.md
+++ b/examples/colorful/CHANGES.md
@@ -1,5 +1,9 @@
# Version History
+## v1.3
+
+- Version bump for Tomo syntax changes.
+
## v1.2
- Version bump for patterns.
diff --git a/examples/colorful/colorful.tm b/examples/colorful/colorful.tm
index 5b01cfd5..fed873fd 100644
--- a/examples/colorful/colorful.tm
+++ b/examples/colorful/colorful.tm
@@ -45,7 +45,7 @@ func main(texts:[Text], files:[Path]=[], by_line=no)
func _for_terminal(c:Colorful, state:_TermState -> Text)
- return c.text.map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch) _add_ansi_sequences(m.captures[1], state))
+ return c.text.map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch) _add_ansi_sequences(m.captures[1]!, state))
enum _Color(Default, Bright(color:Int16), Color8Bit(color:Int16), Color24Bit(color:Int32))
func from_text(text:Text -> _Color?)
@@ -174,7 +174,7 @@ func _add_ansi_sequences(text:Text, prev_state:_TermState -> Text)
text.pattern_captures($Pat/{0+..}:{0+..}/) or
return "@("++_for_terminal(Colorful.from_text(text), prev_state)++")"
)
- attributes := parts[1].split_pattern($Pat/{0+space},{0+space}/)
+ attributes := parts[1]!.split_pattern($Pat/{0+space},{0+space}/)
new_state := prev_state
for attr in attributes
if attr.starts_with("fg=")
@@ -215,6 +215,6 @@ func _add_ansi_sequences(text:Text, prev_state:_TermState -> Text)
fail("Invalid attribute: '$attr'")
result := prev_state.apply(new_state)
- result ++= parts[2].map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch) _add_ansi_sequences(m.captures[1], new_state))
+ result ++= parts[2]!.map_pattern(recursive=no, $Pat/@(?)/, func(m:PatternMatch) _add_ansi_sequences(m.captures[1]!, new_state))
result ++= new_state.apply(prev_state)
return result
diff --git a/examples/http-server/CHANGES.md b/examples/http-server/CHANGES.md
index 42ae752c..636f9296 100644
--- a/examples/http-server/CHANGES.md
+++ b/examples/http-server/CHANGES.md
@@ -1,5 +1,9 @@
# Version History
+## v1.1
+
+Version bump for Tomo syntax changes.
+
## v1.0
Initial version
diff --git a/examples/http-server/http-server.tm b/examples/http-server/http-server.tm
index 8e8aff7e..cc99b521 100644
--- a/examples/http-server/http-server.tm
+++ b/examples/http-server/http-server.tm
@@ -74,12 +74,12 @@ func serve(port:Int32, handler:func(request:HTTPRequest -> HTTPResponse), num_th
struct HTTPRequest(method:Text, path:Text, version:Text, headers:[Text], body:Text)
func from_text(text:Text -> HTTPRequest?)
m := text.pattern_captures($Pat'{word} {..} HTTP/{..}{crlf}{..}') or return none
- method := m[1]
- path := m[2].replace_pattern($Pat'{2+ /}', '/')
- version := m[3]
- rest := m[-1].pattern_captures($Pat/{..}{2 crlf}{0+ ..}/) or return none
- headers := rest[1].split_pattern($Pat/{crlf}/)
- body := rest[-1]
+ method := m[1]!
+ path := m[2]!.replace_pattern($Pat'{2+ /}', '/')
+ version := m[3]!
+ rest := m[-1]!.pattern_captures($Pat/{..}{2 crlf}{0+ ..}/) or return none
+ headers := rest[1]!.split_pattern($Pat/{crlf}/)
+ body := rest[-1]!
return HTTPRequest(method, path, version, headers, body)
struct HTTPResponse(body:Text, status=200, content_type="text/plain", headers:{Text=Text}={})
diff --git a/examples/ini/CHANGES.md b/examples/ini/CHANGES.md
index 42ae752c..636f9296 100644
--- a/examples/ini/CHANGES.md
+++ b/examples/ini/CHANGES.md
@@ -1,5 +1,9 @@
# Version History
+## v1.1
+
+Version bump for Tomo syntax changes.
+
## v1.0
Initial version
diff --git a/examples/ini/ini.tm b/examples/ini/ini.tm
index 4dc27725..790b3abc 100644
--- a/examples/ini/ini.tm
+++ b/examples/ini/ini.tm
@@ -40,20 +40,20 @@ func main(path:Path, key:Text?)
")
data := parse_ini(path)
- if keys.length < 1 or keys[1] == '*'
+ if keys.length < 1 or keys[1]! == '*'
say("$data")
return
- section := keys[1].lower()
+ section := keys[1]!.lower()
section_data := data[section] or exit("
Invalid section name: \[31;1]$section\[]
Valid names: \[1]$(", ".join([k.quoted() for k in data.keys]))\[]
")
- if keys.length < 2 or keys[2] == '*'
+ if keys.length < 2 or keys[2]! == '*'
say("$section_data")
return
- section_key := keys[2].lower()
+ section_key := keys[2]!.lower()
value := section_data[section_key] or exit("
Invalid key: \[31;1]$section_key\[]
Valid keys: \[1]$(", ".join([s.quoted() for s in section_data.keys]))\[]
diff --git a/lib/base64/CHANGES.md b/lib/base64/CHANGES.md
index 42ae752c..6c67c96d 100644
--- a/lib/base64/CHANGES.md
+++ b/lib/base64/CHANGES.md
@@ -1,5 +1,9 @@
# Version History
+## v1.1
+
+Update syntax for Tomo.
+
## v1.0
Initial version
diff --git a/lib/base64/base64.tm b/lib/base64/base64.tm
index bf512a83..f31cfbc5 100644
--- a/lib/base64/base64.tm
+++ b/lib/base64/base64.tm
@@ -33,28 +33,28 @@ lang Base64
dest := Int64(1)
while src + 2 <= Int64(bytes.length)
chunk24 := (
- (Int32(bytes[src]) <<< 16) or (Int32(bytes[src+1]) <<< 8) or Int32(bytes[src+2])
+ (Int32(bytes[src]!) <<< 16) or (Int32(bytes[src+1]!) <<< 8) or Int32(bytes[src+2]!)
)
src += 3
- output[dest] = _enc[1 + ((chunk24 >>> 18) and 0b111111)]
- output[dest+1] = _enc[1 + ((chunk24 >>> 12) and 0b111111)]
- output[dest+2] = _enc[1 + ((chunk24 >>> 6) and 0b111111)]
- output[dest+3] = _enc[1 + (chunk24 and 0b111111)]
+ output[dest] = _enc[1 + ((chunk24 >>> 18) and 0b111111)]!
+ output[dest+1] = _enc[1 + ((chunk24 >>> 12) and 0b111111)]!
+ output[dest+2] = _enc[1 + ((chunk24 >>> 6) and 0b111111)]!
+ output[dest+3] = _enc[1 + (chunk24 and 0b111111)]!
dest += 4
if src + 1 == bytes.length
chunk16 := (
- (Int32(bytes[src]) <<< 8) or Int32(bytes[src+1])
+ (Int32(bytes[src]!) <<< 8) or Int32(bytes[src+1]!)
)
- output[dest] = _enc[1 + ((chunk16 >>> 10) and 0b11111)]
- output[dest+1] = _enc[1 + ((chunk16 >>> 4) and 0b111111)]
- output[dest+2] = _enc[1 + ((chunk16 <<< 2)and 0b111111)]
+ output[dest] = _enc[1 + ((chunk16 >>> 10) and 0b11111)]!
+ output[dest+1] = _enc[1 + ((chunk16 >>> 4) and 0b111111)]!
+ output[dest+2] = _enc[1 + ((chunk16 <<< 2)and 0b111111)]!
output[dest+3] = _EQUAL_BYTE
else if src == bytes.length
- chunk8 := Int32(bytes[src])
- output[dest] = _enc[1 + ((chunk8 >>> 2) and 0b111111)]
- output[dest+1] = _enc[1 + ((chunk8 <<< 4) and 0b111111)]
+ chunk8 := Int32(bytes[src]!)
+ output[dest] = _enc[1 + ((chunk8 >>> 2) and 0b111111)]!
+ output[dest+1] = _enc[1 + ((chunk8 <<< 4) and 0b111111)]!
output[dest+2] = _EQUAL_BYTE
output[dest+3] = _EQUAL_BYTE
@@ -70,10 +70,10 @@ lang Base64
dest := Int64(1)
while src + 3 <= Int64(bytes.length)
chunk24 := (
- (Int32(_dec[1+bytes[src]]) <<< 18) or
- (Int32(_dec[1+bytes[src+1]]) <<< 12) or
- (Int32(_dec[1+bytes[src+2]]) <<< 6) or
- Int32(_dec[1+bytes[src+3]])
+ (Int32(_dec[1+bytes[src]!]!) <<< 18) or
+ (Int32(_dec[1+bytes[src+1]!]!) <<< 12) or
+ (Int32(_dec[1+bytes[src+2]!]!) <<< 6) or
+ Int32(_dec[1+bytes[src+3]!]!)
)
src += 4
@@ -82,7 +82,7 @@ lang Base64
output[dest+2] = Byte(chunk24 and 0xFF)
dest += 3
- while output[-1] == 0xFF
+ while output[-1]! == 0xFF
output[] = output.to(-2)
return output[]
diff --git a/lib/json/CHANGES.md b/lib/json/CHANGES.md
index 42ae752c..6c67c96d 100644
--- a/lib/json/CHANGES.md
+++ b/lib/json/CHANGES.md
@@ -1,5 +1,9 @@
# Version History
+## v1.1
+
+Update syntax for Tomo.
+
## v1.0
Initial version
diff --git a/lib/json/json.tm b/lib/json/json.tm
index 8127ce52..ab9b95dd 100644
--- a/lib/json/json.tm
+++ b/lib/json/json.tm
@@ -79,7 +79,7 @@ enum JSON(
string ++= esc
pos += 2
else if m := text.matching_pattern($Pat/u{4 digit}/)
- string ++= Text.from_codepoints([Int32.parse(m.captures[1])!])
+ string ++= Text.from_codepoints([Int32.parse(m.captures[1]!)!])
pos += 1 + m.text.length
else
if remainder
diff --git a/lib/uuid/CHANGES.md b/lib/uuid/CHANGES.md
index 42ae752c..6c67c96d 100644
--- a/lib/uuid/CHANGES.md
+++ b/lib/uuid/CHANGES.md
@@ -1,5 +1,9 @@
# Version History
+## v1.1
+
+Update syntax for Tomo.
+
## v1.0
Initial version
diff --git a/lib/uuid/uuid.tm b/lib/uuid/uuid.tm
index f2be618e..ebc52259 100644
--- a/lib/uuid/uuid.tm
+++ b/lib/uuid/uuid.tm
@@ -4,8 +4,8 @@ use time_v1.0
lang UUID
func v4(-> UUID) # Random UUID
bytes := &random.bytes(16)
- bytes[7; unchecked] = 0x40 or (bytes[7; unchecked] and 0x0F)
- bytes[9; unchecked] = (Byte(random.int8(0x8, 0xB)) << 4) or (bytes[9; unchecked] and 0x0F)
+ bytes[7] = 0x40 or (bytes[7]! and 0x0F)
+ bytes[9] = (Byte(random.int8(0x8, 0xB)) << 4) or (bytes[9]! and 0x0F)
hex := "".join([b.hex() for b in bytes])
uuid := "$(hex.slice(1, 8))-$(hex.slice(9, 12))-$(hex.slice(13, 16))-$(hex.slice(17, -1))"
return UUID.from_text(uuid)
diff --git a/src/ast.h b/src/ast.h
index bf22c9f6..7d34e187 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -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);
diff --git a/test/enums.tm b/test/enums.tm
index 080e5d97..03eb6028 100644
--- a/test/enums.tm
+++ b/test/enums.tm
@@ -61,7 +61,7 @@ func main()
i := 1
cases := [Foo.One(1), Foo.One(2), Foo.Zero]
- while when cases[i] is One(x)
+ while when cases[i]! is One(x)
>> x
i += 1
@@ -77,7 +77,7 @@ func main()
]
= ["Zero", "Small 1", "Small 2", "Other"]
- >> expr := when cases[1] is One(y)
+ >> expr := when cases[1]! is One(y)
y + 1
else
-1
diff --git a/test/iterators.tm b/test/iterators.tm
index 08382cff..c48e572b 100644
--- a/test/iterators.tm
+++ b/test/iterators.tm
@@ -4,9 +4,8 @@ struct Pair(x:Text, y:Text)
func pairwise(strs:[Text] -> func(->Pair?))
i := 1
return func()
- if i + 1 > strs.length return none
i += 1
- return Pair(strs[i-1], strs[i])?
+ return Pair(strs[i-1] or return none, strs[i] or return none)?
func range(first:Int, last:Int -> func(->Int?))
i := first