diff options
| -rw-r--r-- | examples/colorful/colorful.tm | 2 | ||||
| -rw-r--r-- | lib/json/json.tm | 4 | ||||
| -rw-r--r-- | src/compile/indexing.c | 11 | ||||
| -rw-r--r-- | src/stdlib/text.c | 5 | ||||
| -rw-r--r-- | src/stdlib/text.h | 12 | ||||
| -rw-r--r-- | src/typecheck.c | 2 | ||||
| -rw-r--r-- | test/text.tm | 3 |
7 files changed, 31 insertions, 8 deletions
diff --git a/examples/colorful/colorful.tm b/examples/colorful/colorful.tm index fed873fd..bef77dd3 100644 --- a/examples/colorful/colorful.tm +++ b/examples/colorful/colorful.tm @@ -53,7 +53,7 @@ enum _Color(Default, Bright(color:Int16), Color8Bit(color:Int16), Color24Bit(col hex := text.from(2) return none unless hex.length == 3 or hex.length == 6 if hex.length == 3 - hex = hex[1]++hex[1]++hex[2]++hex[2]++hex[3]++hex[3] + hex = hex[1]!++hex[1]!++hex[2]!++hex[2]!++hex[3]!++hex[3]! n := Int32.parse("0x" ++ hex) or return none return Color24Bit(n) else if text.matches_pattern($Pat/{1-3 digit}/) diff --git a/lib/json/json.tm b/lib/json/json.tm index ab9b95dd..1ac19426 100644 --- a/lib/json/json.tm +++ b/lib/json/json.tm @@ -65,8 +65,8 @@ enum JSON( string := "" pos := 2 escapes := {"n"="\n", "t"="\t", "r"="\r", '"'='"', "\\"="\\", "/"="/", "b"="\b", "f"="\f"} - while pos <= text.length - c := text[pos] + repeat + c := text[pos] or stop if c == '"' if remainder remainder[] = text.from(pos + 1) diff --git a/src/compile/indexing.c b/src/compile/indexing.c index cca06184..9d3501c9 100644 --- a/src/compile/indexing.c +++ b/src/compile/indexing.c @@ -73,8 +73,15 @@ Text_t compile_indexing(env_t *env, ast_t *ast, bool checked) { 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)), ", ", String(start), ", ", + String(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/stdlib/text.c b/src/stdlib/text.c index ed4023a4..f4533be5 100644 --- a/src/stdlib/text.c +++ b/src/stdlib/text.c @@ -725,7 +725,10 @@ Text_t Text$reversed(Text_t text) { } public -PUREFUNC Text_t Text$cluster(Text_t text, Int_t index) { return Text$slice(text, index, index); } +PUREFUNC OptionalText_t Text$cluster(Text_t text, Int_t index) { + Text_t slice = Text$slice(text, index, index); + return slice.length <= 0 ? NONE_TEXT : slice; +} static Text_t Text$from_components(List_t graphemes, Table_t unique_clusters) { size_t blob_size = (sizeof(int32_t[unique_clusters.entries.length]) + sizeof(uint8_t[graphemes.length])); diff --git a/src/stdlib/text.h b/src/stdlib/text.h index 5fa95675..c08e5267 100644 --- a/src/stdlib/text.h +++ b/src/stdlib/text.h @@ -41,7 +41,17 @@ Text_t Text$slice(Text_t text, Int_t first_int, Int_t last_int); Text_t Text$from(Text_t text, Int_t first); Text_t Text$to(Text_t text, Int_t last); Text_t Text$reversed(Text_t text); -Text_t Text$cluster(Text_t text, Int_t index_int); +OptionalText_t Text$cluster(Text_t text, Int_t index_int); +#define Text$cluster_checked(text_expr, index_expr, start, end) \ + ({ \ + const Text_t text = text_expr; \ + Int_t index = index_expr; \ + OptionalText_t cluster = Text$cluster(text, index); \ + if (unlikely(cluster.length < 0)) \ + fail_source(__SOURCE_FILE__, start, end, "Invalid text index: ", index, " (text has length ", \ + (int64_t)text.length, ")\n"); \ + cluster; \ + }) OptionalText_t Text$from_str(const char *str); OptionalText_t Text$from_strn(const char *str, size_t len); PUREFUNC uint64_t Text$hash(const void *text, const TypeInfo_t *); diff --git a/src/typecheck.c b/src/typecheck.c index eba12a6e..2af2408e 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -897,7 +897,7 @@ type_t *get_type(env_t *env, ast_t *ast) { if (table_type->default_value) return table_type->value_type; return Type(OptionalType, table_type->value_type); } else if (value_t->tag == TextType) { - return value_t; + return Type(OptionalType, value_t); } else { code_err(ast, "I don't know how to index ", type_to_str(indexed_t), " values"); } diff --git a/test/text.tm b/test/text.tm index ff55555d..a32db2ce 100644 --- a/test/text.tm +++ b/test/text.tm @@ -34,6 +34,9 @@ func main() >> str[9] = "é" + >> str[99] + = none + >> "\{UE9}" = "é" |
