diff --git a/lib/core/src/DynArray.ri b/lib/core/src/DynArray.ri index aadd65749..30bb59561 100644 --- a/lib/core/src/DynArray.ri +++ b/lib/core/src/DynArray.ri @@ -85,7 +85,7 @@ struct DynArray { if i + size > self.len { end_idx := if size == 1 { "..{}".fmt(i + size) } else { "" }; runtime_error( - "DynArray.delete(): index out of range (i: {}..{}, self.len: {})", + "DynArray.delete: index out of range (i: {}..{}, self.len: {})", i, end_idx, self.len ); } diff --git a/lib/core/src/TokenIterator.ri b/lib/core/src/TokenIterator.ri index b5fcf8cb9..5b5104e0b 100644 --- a/lib/core/src/TokenIterator.ri +++ b/lib/core/src/TokenIterator.ri @@ -29,7 +29,7 @@ pub struct TokenIterator { mut end := start; while end < self.buffer.len and !self.is_split_byte(self.buffer[end]) : end += 1 {} - return self.buffer[start..end]; + return self.buffer.substr(start, end); } /// Returns a slice of the remaining bytes. Does not affect iterator state. @@ -38,7 +38,7 @@ pub struct TokenIterator { mut index := self.index; while index < self.buffer.len and self.is_split_byte(self.buffer[index]) : index += 1 {} - return self.buffer[index..]; + return self.buffer.substr(index); } /// Resets the iterator to the initial token. diff --git a/lib/core/src/parse_int.ri b/lib/core/src/parse_int.ri index c8b37a68d..29369ab11 100644 --- a/lib/core/src/parse_int.ri +++ b/lib/core/src/parse_int.ri @@ -134,10 +134,10 @@ extend string { mut s0 := self; mut neg := false; if self[0] == b'+' { - s0 = self[1..]; + s0 = self.substr(1); } else if self[0] == b'-' { neg = true; - s0 = self[1..]; + s0 = self.substr(1); } // convert unsigned and check range. @@ -173,7 +173,7 @@ func underscore_ok(s_: string) -> bool { // optional sign. if s.len >= 1 and (s[0] == b'-' or s[0] == b'+') { - s = s[1..]; + s = s.substr(1); } // optional base prefix. diff --git a/lib/core/src/string.c.ri b/lib/core/src/string.c.ri index 9dae11b62..04a172951 100644 --- a/lib/core/src/string.c.ri +++ b/lib/core/src/string.c.ri @@ -60,7 +60,7 @@ pub struct string < Stringable, Hashable, Throwable { return Self(res, bytes.len); } - pub func at(self, idx: uint) -> uint8 { + func at(self, idx: uint) -> uint8 { if idx >= self.len { runtime_error("string index out of range (index: {}, len: {})", idx, self.len); } @@ -116,7 +116,7 @@ pub struct string < Stringable, Hashable, Throwable { continue; } if is_space and is_in_word { - res.push(self[word_start..word_start + word_len]); + res.push(self.substr(word_start, word_start + word_len)); is_in_word = false; word_len = 0; word_start = 0; @@ -125,7 +125,7 @@ pub struct string < Stringable, Hashable, Throwable { } if is_in_word and word_len > 0 { // collect the remainder word at the end - res.push(self[word_start..self.len]); + res.push(self.substr(word_start, self.len)); } return res; } @@ -211,7 +211,7 @@ pub struct string < Stringable, Hashable, Throwable { /// If the substring is not found, it returns the full input string. pub func all_before_of(self, sub: Self) -> Self { return if pos := self.index_of(sub) { - self[..pos] + self.substr(end: pos) } else { self }; @@ -220,7 +220,7 @@ pub struct string < Stringable, Hashable, Throwable { /// Returns the contents before the last occurrence of `sub` in the string. pub func all_before_of_last(self, sub: Self) -> Self { return if pos := self.last_index_of(sub) { - self[..pos] + self.substr(end: pos) } else { self }; @@ -230,7 +230,7 @@ pub struct string < Stringable, Hashable, Throwable { /// not found, it returns the full input string. pub func all_after_of(self, sub: Self) -> Self { return if pos := self.index_of(sub) { - self[pos + sub.len..] + self.substr(pos + sub.len) } else { self }; @@ -240,7 +240,7 @@ pub struct string < Stringable, Hashable, Throwable { /// If the substring is not found, it returns the full input string. pub func all_after_of_last(self, sub: Self) -> Self { return if pos := self.last_index_of(sub) { - self[pos + sub.len..] + self.substr(pos + sub.len) } else { self }; @@ -348,9 +348,9 @@ pub struct string < Stringable, Hashable, Throwable { /// Returns the string found between `start` string and `end` string. pub func find_between(self, start: Self, end: Self) -> Self { start_pos := self.index_of(start) ?? return emptyString; - val := self.slice(start_pos + start.len, self.len); + val := self.substr(start_pos + start.len, self.len); end_pos := val.index_of(end) ?? return val; - return val.slice(0, end_pos); + return val.substr(0, end_pos); } /// Strips any of the characters given in `cutset` from the start and end of @@ -360,7 +360,7 @@ pub struct string < Stringable, Hashable, Throwable { return self; } (pos_left, pos_right) := self.trim_indexes(cutset); - return self.slice(pos_left, pos_right); + return self.substr(pos_left, pos_right); } /// Gets the new start and end indexes of a string when any of the characters @@ -415,7 +415,7 @@ pub struct string < Stringable, Hashable, Throwable { break; } } - return self.slice_from(pos); + return self.substr(pos); } /// Strips any of the characters given in `cutset` from the right of the @@ -440,7 +440,7 @@ pub struct string < Stringable, Hashable, Throwable { break; } } - return self.slice(0, pos + 1); + return self.substr(0, pos + 1); } /// Strips any of ` `, `\n`, `\t`, `\v`, `\f`, `\r` from the start and end of @@ -519,7 +519,7 @@ pub struct string < Stringable, Hashable, Throwable { } else { self.len }; - r := self[i..end]; + r := self.substr(i, end); i += char_len - 1; r.utf32_code() } else { @@ -547,7 +547,7 @@ pub struct string < Stringable, Hashable, Throwable { i = 1; for ch in self.as_bytes() { if nth > 0 and i >= nth { - res.push(self[i..]); + res.push(self.substr(i)); break; } res.push(ch.to_ascii()); @@ -563,7 +563,7 @@ pub struct string < Stringable, Hashable, Throwable { if nth > 0 and res.len == nth - 1 { break; } - res.push(self[start..i]); + res.push(self.substr(start, i)); start = i + delim.len; i = start; } else { @@ -571,19 +571,18 @@ pub struct string < Stringable, Hashable, Throwable { } } if nth < 1 or res.len < nth { - res.push(self[start..]); + res.push(self.substr(start)); } return res; }, else -> { mut start: uint := 0; while i <= self.len { - is_delim := i + delim.len <= self.len and self[i..i + delim.len] == delim; - if is_delim { + if i + delim.len <= self.len and self.substr(i, i + delim.len) == delim { if nth > 0 and res.len == nth - 1 { break; } - res.push(self[start..i]); + res.push(self.substr(start, i)); start = i + delim.len; i = start; } else { @@ -591,7 +590,7 @@ pub struct string < Stringable, Hashable, Throwable { } } if nth < 1 or res.len < nth { - res.push(self[start..]); + res.push(self.substr(start)); } return res; } @@ -612,14 +611,14 @@ pub struct string < Stringable, Hashable, Throwable { for index, ch in self.as_bytes() { for delim_ch in delim.as_bytes() { if ch == delim_ch { - res.push(self[i..index]); + res.push(self.substr(i, index)); i = index + 1; break; } } } if i < self.len { - res.push(self[i..]); + res.push(self.substr(i)); } } return res; @@ -644,14 +643,14 @@ pub struct string < Stringable, Hashable, Throwable { res.push(if line_start == i { emptyString } else { - self[line_start..i] + self.substr(line_start, i) }); line_start = i + 1; } else if unsafe { self.ptr[i] == cr } { res.push(if line_start == i { emptyString } else { - self[line_start..i] + self.substr(line_start, i) }); if i + 1 < self.len and unsafe { self.ptr[i + 1] == lf } { line_start = i + 2; @@ -662,7 +661,7 @@ pub struct string < Stringable, Hashable, Throwable { } } if line_start < self.len { - res.push(self[line_start..]); + res.push(self.substr(line_start)); } return res; } @@ -785,27 +784,26 @@ pub struct string < Stringable, Hashable, Throwable { return true; } - func slice(self, start: uint, end: uint) -> Self { + /// Returns a portion of the current string as a reference. This does not clone + /// the returned value. + pub func substr(self, start: ?uint := none, end: ?uint := none) -> Self { unsafe { - if start > end or start > self.len or end > self.len { + start_ := start ?? 0; + end_ := end ?? self.len; + if start_ > end_ or start_ > self.len or end_ > self.len { runtime_error( - "string slice index out of range (range: {}..{}, len: {})", start, - end, self.len + "substring index out of range (range: {}..{}, len: {})", start_, + end_, self.len ); } - len := end - start; + len := end_ - start_; if len == self.len { return self; } - return Self(@ptr_add(self.ptr, start), len, is_ref: true); + return Self(@ptr_add(self.ptr, start_), len, is_ref: true); } } - #[inline] - func slice_from(self, start: uint) -> Self { - return self.slice(start, self.len); - } - pub func clone(self) -> Self { if self.len == 0 { return emptyString; diff --git a/lib/core/tests/string_test.ri b/lib/core/tests/string_test.ri index 62bbc72b5..b71c900d0 100644 --- a/lib/core/tests/string_test.ri +++ b/lib/core/tests/string_test.ri @@ -158,3 +158,11 @@ test "string.parse_int()" { true }); } + +test "string.slice()" { + str := "hello world!"; + @assert(str.substr() == str); + @assert(str.substr(5) == "world!"); + @assert(str.substr(end: 4) == "hello"); + @assert(str.substr(1, 8) == "llo wor"); +} diff --git a/lib/rivet/src/ast/CHeader.ri b/lib/rivet/src/ast/CHeader.ri index a03bc93fa..123088feb 100644 --- a/lib/rivet/src/ast/CHeader.ri +++ b/lib/rivet/src/ast/CHeader.ri @@ -9,8 +9,8 @@ import { Path } from std/fs; import ../token; -// Useful functions to get system `#define`s. -// Will soon be used to implement `extern (C) import`. +// Useful functions to get system `#define`s. Will soon be used to +// implement `extern (C) import`. pub enum CImportAction { Report { @@ -130,8 +130,8 @@ extend Table { mut is_macro := true; if has_value { if paren_idx := name.index_of_byte(b'(') { - def_args := name[paren_idx + 1..].all_before_of(")"); - name = name[..paren_idx]; + def_args := name.substr(paren_idx + 1).all_before_of(")"); + name = name.substr(end: paren_idx); if def_args.len > 0 { for arg_name in def_args.split(",") { args.push(arg_name.trim_space()); diff --git a/lib/rivet/src/ast/Decl.ri b/lib/rivet/src/ast/Decl.ri index 7ffd8a6c6..c3541fcf7 100644 --- a/lib/rivet/src/ast/Decl.ri +++ b/lib/rivet/src/ast/Decl.ri @@ -2,8 +2,6 @@ // Use of this source code is governed by an MIT license that can // be found in the LICENSE file. -import std/strings; - import ../token; pub enum Decl { diff --git a/lib/rivet/src/ast/Table.ri b/lib/rivet/src/ast/Table.ri index 8794cc6c4..fd7b8df59 100644 --- a/lib/rivet/src/ast/Table.ri +++ b/lib/rivet/src/ast/Table.ri @@ -395,7 +395,7 @@ pub struct Table { new_inputs.push(input); continue; } - exts := base_name_input[..base_name_input.len - 3].split(".")[1..]; + exts := base_name_input.substr(end: base_name_input.len - 3).split(".")[1..]; mut already_exts := @dyn_array(string, exts.len); mut should_compile := false; for ext in exts { @@ -405,9 +405,9 @@ pub struct Table { already_exts.push(ext); if ext.starts_with("d_") or ext.starts_with("notd_") { should_compile = if ext.starts_with("d_") { - ext[2..] in self.prefs.flags + ext.substr(2) in self.prefs.flags } else { - ext[2..] !in self.prefs.flags + ext.substr(4) !in self.prefs.flags }; } else if os := sys.OS.from_string(ext) { should_compile = self.prefs.target_os == os; @@ -577,4 +577,4 @@ enum BuiltinFuncCheck { arg_idx: uint; type: BuiltinFuncType; } -} \ No newline at end of file +} diff --git a/lib/rivet/src/checker/decls.ri b/lib/rivet/src/checker/decls.ri index 1e8ae5976..e580935b3 100644 --- a/lib/rivet/src/checker/decls.ri +++ b/lib/rivet/src/checker/decls.ri @@ -169,7 +169,7 @@ extend Checker { func check_func(mut self, mut func_decl: ast.Decl.Func) { if !func_decl.is_operator { name := if func_decl.is_method and func_decl.is_special_method { - func_decl.name[2..func_decl.name.len - 2] // skip `__` + func_decl.name.substr(2, func_decl.name.len - 2) // skip `__` } else { func_decl.name }; diff --git a/lib/rivet/src/checker/exprs.ri b/lib/rivet/src/checker/exprs.ri index 070b255c7..352445bb7 100644 --- a/lib/rivet/src/checker/exprs.ri +++ b/lib/rivet/src/checker/exprs.ri @@ -451,10 +451,13 @@ extend Checker { } if index.left_type == self.table.string_t { if index.index is .Range { - self.table.string_t - } else { - self.table.uint8_t + mut err := report.error_builder( + "`string` does not support slicing syntax", index.pos + ); + err.add_help("use `.substr()` instead"); + err.emit(); } + self.table.uint8_t } else { @as(ast.Type.Pointer, index.left_type).inner } @@ -887,4 +890,4 @@ extend Checker { }; return .Void(); } -} \ No newline at end of file +} diff --git a/lib/rivet/src/fmt/mod.ri b/lib/rivet/src/fmt/mod.ri index d69466e3e..8fedc7288 100644 --- a/lib/rivet/src/fmt/mod.ri +++ b/lib/rivet/src/fmt/mod.ri @@ -4,7 +4,6 @@ import std/traits; import std/strings; -import std/console; import ../ast; import ../utils; diff --git a/lib/rivet/src/lib.ri b/lib/rivet/src/lib.ri index 63248439d..cbaebdbdc 100644 --- a/lib/rivet/src/lib.ri +++ b/lib/rivet/src/lib.ri @@ -173,9 +173,9 @@ pub struct Compiler { is_super := pathx.starts_with("../"); if pathx.starts_with("./") or is_super { self.vlog(" searching module in local path"); - pathx2 := pathx[if is_super { 3 } else { 2 }..]; + pathx2 := pathx.substr(if is_super { 3 } else { 2 }); name = if last_idx := pathx2.last_index_of_byte(b'/') { - pathx2[last_idx + 1..] + pathx2.substr(last_idx + 1) } else { pathx2 }; @@ -187,12 +187,12 @@ pub struct Compiler { abspath = Path.resolve(pathx)!; mut mod_basedir := Path.dir_name(abspath) ?? abspath; if mod_basedir.ends_with("/src") { - mod_basedir = mod_basedir[..mod_basedir.len - 4]; // skip `/src` + mod_basedir = mod_basedir.substr(end: mod_basedir.len - 4); // skip `/src` } else if mod_basedir.contains("/src") { - first_part := mod_basedir[..mod_basedir.last_index_of_byte(b'/') ?? 0]; - mod_basedir = mod_basedir[..first_part.last_index_of_byte(b'/') ?? 0]; + first_part := mod_basedir.substr(end: mod_basedir.last_index_of_byte(b'/') ?? 0); + mod_basedir = mod_basedir.substr(end: first_part.last_index_of_byte(b'/') ?? 0); } - names := abspath[(mod_basedir.last_index_of_byte(b'/') ?? 0) + 1..].split( + names := abspath.substr((mod_basedir.last_index_of_byte(b'/') ?? 0) + 1).split( "/" ); full_name = if "src" in names { @@ -212,7 +212,7 @@ pub struct Compiler { } else { self.vlog(" searching module in global path"); name = if last_idx := pathx.last_index_of_byte(b'/') { - pathx[last_idx + 1..] + pathx.substr(last_idx + 1) } else { pathx }; @@ -227,7 +227,7 @@ pub struct Compiler { // support `src/` directory src_dir := if pathx.contains("/") { slash_idx := (pathx.index_of_byte(b'/') ?? 0) + 1; - Path.join(l, pathx[..slash_idx], "src", pathx[slash_idx..])! + Path.join(l, pathx.substr(end: slash_idx), "src", pathx.substr(slash_idx))! } else { Path.join(mod_path, "src")! }; diff --git a/lib/rivet/src/parser/exprs.ri b/lib/rivet/src/parser/exprs.ri index 05465049d..ca188dfa0 100644 --- a/lib/rivet/src/parser/exprs.ri +++ b/lib/rivet/src/parser/exprs.ri @@ -724,7 +724,8 @@ extend Parser { value := self.tok.lit; pos := self.tok.pos; self.next(); - return if value.len > 2 and value[..2] !in ["0x", "0o", "0b"] and value.index_of_any( + return if value.len > 2 and value.substr(end: 2) !in ["0x", "0o", "0b"] + and value.index_of_any( ".eE" ) !is none { .FloatLiteral(value, pos) diff --git a/lib/rivet/src/report/mod.ri b/lib/rivet/src/report/mod.ri index 1dc8525d0..953727a69 100644 --- a/lib/rivet/src/report/mod.ri +++ b/lib/rivet/src/report/mod.ri @@ -140,7 +140,7 @@ func formatted_single_line(pos: token.Pos) { if pos.len > 1 { sb.write_string( utils.bold( - utils.blue("~".repeat(line[start_column..end_column].runes_count() - 1)) + utils.blue("~".repeat(line.substr(start_column, end_column).runes_count() - 1)) ) ); } @@ -189,7 +189,7 @@ func write_spaces(mut sb: strings.Builder, start_column: uint, line: string) { i += 1; } else { char_len := b.len_utf8(); - sb.write_string(" ".repeat(line[i..i + char_len].runes_count())); + sb.write_string(" ".repeat(line.substr(i, i + char_len).runes_count())); i += char_len; } } diff --git a/lib/rivet/src/tokenizer/mod.ri b/lib/rivet/src/tokenizer/mod.ri index 564961608..b5b57091d 100644 --- a/lib/rivet/src/tokenizer/mod.ri +++ b/lib/rivet/src/tokenizer/mod.ri @@ -219,7 +219,7 @@ pub struct Tokenizer { func invalid_character(mut self) { len := self.text[self.pos].len_utf8(); end := utils.min(self.pos + len, self.text.len); - self.error("invalid character: `{}`".fmt(self.text[self.pos..end])); + self.error("invalid character: `{}`".fmt(self.text.substr(self.pos, end))); self.pos += len; } @@ -233,7 +233,7 @@ pub struct Tokenizer { } return ( end_idx, - @as(uint8, str[idx + 2..end_idx].parse_uint(16, 8) catch 0).to_string() + @as(uint8, str.substr(idx + 2, end_idx).parse_uint(16, 8) catch 0).to_string() ); } @@ -243,15 +243,15 @@ pub struct Tokenizer { return s; } mut ss := @dyn_array(string, escapes_pos.len * 2 + 1); - ss.push(s[..escapes_pos[escapes_pos.len - 1] - start]); + ss.push(s.substr(escapes_pos[escapes_pos.len - 1] - start)); for i, pos in escapes_pos { idx := pos - start; (end_idx, segment) := self.decode_h_escape_single(s, idx); ss.push(segment); ss.push(if i + 1 < escapes_pos.len { - s[end_idx..escapes_pos[i + 1] - start] + s.substr(end_idx, escapes_pos[i + 1] - start) } else { - s[end_idx..] + s.substr(end_idx) }); } return utils.join(ss, ""); @@ -287,17 +287,17 @@ func decode_o_escapes(s: string, start: uint, escapes_pos: []uint) -> string { } mut ss := @dyn_array(string, escapes_pos.len); // everything before the first escape code position - ss.push(s[..escapes_pos[escapes_pos.len - 1] - start]); + ss.push(s.substr(escapes_pos[escapes_pos.len - 1] - start)); for i, pos in escapes_pos { idx := pos - start; end_idx := idx + 4; // "\XXX".len == 4 ss.push( - @as(uint8, s[idx + 1..end_idx].parse_uint(8, 8) catch 0).to_string() + @as(uint8, s.substr(idx + 1, end_idx).parse_uint(8, 8) catch 0).to_string() ); ss.push(if i + 1 < escapes_pos.len { - s[end_idx..escapes_pos[i + 1] - start] + s.substr(end_idx, escapes_pos[i + 1] - start) } else { - s[end_idx..] + s.substr(end_idx) }); } return utils.join(ss, ""); @@ -305,7 +305,7 @@ func decode_o_escapes(s: string, start: uint, escapes_pos: []uint) -> string { func decode_u_escape_single(str: string, idx: uint) -> (uint, string) { end_idx := idx + 6; // "\uXXXX".len == 6 - escaped_code_point := str[idx + 2..end_idx].parse_uint(16, 32) catch 0; + escaped_code_point := str.substr(idx + 2, end_idx).parse_uint(16, 32) catch 0; return (end_idx, @as(uint32, escaped_code_point).to_string()); } @@ -317,7 +317,7 @@ func decode_unicode_escaped_rune(str: string) -> string { } else { mut ss := @dyn_array(string, 2); ss.push(segment); - ss.push(str[end_idx..]); + ss.push(str.substr(end_idx)); utils.join(ss, "") }; } @@ -325,7 +325,7 @@ func decode_unicode_escaped_rune(str: string) -> string { func trim_slash_line_break(s: string) -> string { (mut start: uint, mut ret_str) := (0, s); while idx := ret_str.index_after_of("\\\n", start) { - ret_str = ret_str[..idx].concat(ret_str[idx + 2..].trim_left(" \n\t\v\f\r")); + ret_str = ret_str.substr(end: idx).concat(ret_str.substr(idx + 2).trim_left(" \n\t\v\f\r")); start = idx; } return ret_str; @@ -344,4 +344,4 @@ func number_literal_without_separator(lit: string) -> string { } else { lit }; -} \ No newline at end of file +} diff --git a/lib/rivet/src/tokenizer/next.ri b/lib/rivet/src/tokenizer/next.ri index 5ccc842fa..6e5439d57 100644 --- a/lib/rivet/src/tokenizer/next.ri +++ b/lib/rivet/src/tokenizer/next.ri @@ -95,7 +95,7 @@ extend Tokenizer { self.line -= 1; } if (is_doc_comment and self.prefs.is_docs) or self.prefs.is_fmt { - mut comment := self.text[start_pos..end_pos]; + mut comment := self.text.substr(start_pos, end_pos); // find out if this comment is on its own line (for rivet format) mut is_separate_line_comment := true; mut j := start_pos - bytes_to_skip; @@ -147,7 +147,7 @@ extend Tokenizer { break; } if self.prefs.is_fmt { - line := self.text[start_pos + 2..end_pos]; + line := self.text.substr(start_pos + 2, end_pos); return self.new_multiline_token( .Comment, line, line.len, start_line, self.line, start_col ); @@ -298,7 +298,7 @@ extend Tokenizer { } break; } - lit := self.text[start..self.pos].clone(); + lit := self.text.substr(start, self.pos).clone(); self.pos -= 1; // fix pos return lit; } @@ -352,7 +352,7 @@ extend Tokenizer { self.pos += 1; } - lit := self.text[start..self.pos].clone(); + lit := self.text.substr(start, self.pos).clone(); self.pos -= 1; // fix pos return lit; } @@ -399,7 +399,7 @@ extend Tokenizer { self.pos += 1; } - lit := self.text[start..self.pos].clone(); + lit := self.text.substr(start, self.pos).clone(); self.pos -= 1; // fix pos return lit; } @@ -446,7 +446,7 @@ extend Tokenizer { self.pos += 1; } - lit := self.text[start..self.pos].clone(); + lit := self.text.substr(start, self.pos).clone(); self.pos -= 1; // fix pos return lit; } @@ -530,7 +530,7 @@ extend Tokenizer { "float literals should have a digit after the decimal point" ); err.add_help( - "use `{0}.0` instead of `{0}`".fmt(self.text[start..self.pos]) + "use `{0}.0` instead of `{0}`".fmt(self.text.substr(start, self.pos)) ); err.emit(); self.pos += 1; @@ -573,7 +573,7 @@ extend Tokenizer { } self.pos += 1; } - lit := self.text[start..self.pos].clone(); + lit := self.text.substr(start, self.pos).clone(); self.pos -= 1; // fix pos return lit; } @@ -610,7 +610,7 @@ extend Tokenizer { } len -= 1; - mut ch := self.text[start + 1..self.pos].clone(); + mut ch := self.text.substr(start + 1, self.pos).clone(); if self.prefs.is_fmt { return ch; } @@ -739,7 +739,7 @@ extend Tokenizer { mut lit := ""; if start <= self.pos { - lit = self.text[start..self.pos].clone(); + lit = self.text.substr(start, self.pos).clone(); if !self.prefs.is_fmt { mut segment_idx: uint := 0; mut str_segments := @dyn_array(string); @@ -752,7 +752,7 @@ extend Tokenizer { all_pos.push(pos1); } for pos1 in all_pos { - str_segments.push(lit[segment_idx..(pos1 - start)]); + str_segments.push(lit.substr(segment_idx, pos1 - start)); segment_idx = pos1 - start; if pos1 in u_escapes_pos { (end_idx, segment) := decode_u_escape_single(lit, segment_idx); @@ -767,7 +767,7 @@ extend Tokenizer { } } if segment_idx < lit.len { - str_segments.push(lit[segment_idx..]); + str_segments.push(lit.substr(segment_idx)); } lit = utils.join(str_segments, ""); } @@ -781,4 +781,4 @@ extend Tokenizer { return lit; } -} \ No newline at end of file +} diff --git a/lib/rivet/src/tokenizer/preprocessor.ri b/lib/rivet/src/tokenizer/preprocessor.ri index 1cc5dd5ee..4994360f4 100644 --- a/lib/rivet/src/tokenizer/preprocessor.ri +++ b/lib/rivet/src/tokenizer/preprocessor.ri @@ -122,7 +122,7 @@ extend Tokenizer { self.eat_to_end_of_line(); pos += self.current_pos(); self.inc_line_number(); - msg := self.text[start..self.pos].trim_space(); + msg := self.text.substr(start, self.pos).trim_space(); if kw == "error" { self.error("#error: ".concat(msg), pos); } else { diff --git a/lib/rivet/src/utils/file.ri b/lib/rivet/src/utils/file.ri index 416e94003..80ad1aa9f 100644 --- a/lib/rivet/src/utils/file.ri +++ b/lib/rivet/src/utils/file.ri @@ -25,7 +25,7 @@ pub func skip_bom(file_content: string) -> string { if file_content.len >= 3 { if file_content[0] == 0xEF and file_content[1] == 0xBB and file_content[2] == 0xBF { // skip three BOM bytes - return file_content[3..]; + return file_content.substr(3); } } return file_content; diff --git a/lib/std/src/flag/mod.ri b/lib/std/src/flag/mod.ri index 315d32290..9b4c5474b 100644 --- a/lib/std/src/flag/mod.ri +++ b/lib/std/src/flag/mod.ri @@ -294,7 +294,7 @@ pub struct FlagParser { } } len = sb.len() - len; - sb.write_fmt("{}{}", space[len..], flag.usage); + sb.write_fmt("{}{}", space.substr(len), flag.usage); if i < self.flags.len - 1 { sb.writeln(); } @@ -327,7 +327,8 @@ pub struct FlagParser { mut remaining := self.args.clone(); if !self.allow_unknown_args { for arg in remaining { - if (arg.len >= 2 and arg[..2] == "--") or (arg.len == 2 and arg[0] == b'-') { + if (arg.len >= 2 and arg.substr(end: 2) == "--") + or (arg.len == 2 and arg[0] == b'-') { throw UnknownFlagError(arg); } } @@ -422,7 +423,7 @@ pub struct FlagParser { } next_arg := self.args[i + 1]; if next_arg.len > 2 { - next_arg_rest := next_arg[..2]; + next_arg_rest := next_arg.substr(end: 2); if next_arg_rest == "--" { // It could be end of input (`--`) or another argument (`--abc`). // Both are invalid so die. @@ -435,8 +436,8 @@ pub struct FlagParser { should_skip_one = true; continue; } - if arg.len > full.len + 1 and arg[..full.len + 1] == full.concat("=") { - found_entries.push(arg[full.len + 1..]); + if arg.len > full.len + 1 and arg.substr(end: full.len + 1) == full.concat("=") { + found_entries.push(arg.substr(full.len + 1)); to_delete.push(i); continue; } @@ -470,13 +471,14 @@ pub struct FlagParser { return "true"; } } - if arg.len > full.len + 1 and arg[..full.len + 1] == full.concat("=") { + if arg.len > full.len + 1 and arg.substr(end: full.len + 1) == full.concat("=") { // flag: `abc=true` - val := arg[full.len + 1..]; + val := arg.substr(full.len + 1); self.args.delete(i); return val; } - if arg.len > 1 and arg[0] == b'-' and arg[1] != b'-' and arg.index_of_byte(short_hand) !is none { + if arg.len > 1 and arg[0] == b'-' and arg[1] != b'-' + and arg.index_of_byte(short_hand) !is none { // `-abc` is equivalent to `-a -b -c` return "true"; } diff --git a/lib/std/src/fs/Path.c.ri b/lib/std/src/fs/Path.c.ri index effc71dba..3f1022286 100644 --- a/lib/std/src/fs/Path.c.ri +++ b/lib/std/src/fs/Path.c.ri @@ -104,7 +104,7 @@ pub struct Path { return none; } - return path[..end_index]; + return path.substr(end: end_index); } /// Returns the last element of path. Trailing path separators are removed before @@ -124,10 +124,10 @@ pub struct Path { end_index += 1; while path[start_index] != SEPARATOR : start_index -= 1 { if start_index == 0 { - return path[0..end_index]; + return path.substr(0, end_index); } } - return path[start_index + 1 .. end_index]; + return path.substr(start_index + 1, end_index); } /// Return alls characters found after the last occurrence of `separatorStr`. @@ -147,7 +147,7 @@ pub struct Path { return if index == 0 or index + 1 >= filename.len { "" } else { - filename[index..] + filename.substr(index) }; } @@ -348,7 +348,7 @@ pub struct Path { buf_index += 1; } adjusted_path := if prev_sep and this_sep { - this_path[1..] + this_path.substr(1) } else { this_path }; diff --git a/lib/std/src/semver/parse.ri b/lib/std/src/semver/parse.ri index 0b0c4908f..ff4ee1809 100644 --- a/lib/std/src/semver/parse.ri +++ b/lib/std/src/semver/parse.ri @@ -19,12 +19,12 @@ struct RawVersion { mut prerelease := ""; mut metadata := ""; if plus_idx := raw_version.last_index_of_byte(b'+') { - metadata = raw_version[plus_idx + 1..]; - raw_version = raw_version[0..plus_idx]; + metadata = raw_version.substr(plus_idx + 1); + raw_version = raw_version.substr(0, plus_idx); } if hyphen_idx := raw_version.index_of_byte(b'-') { - prerelease = raw_version[hyphen_idx + 1..]; - raw_version = raw_version[0..hyphen_idx]; + prerelease = raw_version.substr(hyphen_idx + 1); + raw_version = raw_version.substr(0, hyphen_idx); } return RawVersion(prerelease, metadata, raw_version.split(".")); } diff --git a/lib/std/src/semver/range.ri b/lib/std/src/semver/range.ri index 598b4c19e..989a52026 100644 --- a/lib/std/src/semver/range.ri +++ b/lib/std/src/semver/range.ri @@ -33,21 +33,21 @@ struct Comparator { raw_version: string := match { input.starts_with(">=") -> { op = .Ge; - input[2..] + input.substr(2) }, input.starts_with("<=") -> { op = .Le; - input[2..] + input.substr(2) }, input.starts_with(">") -> { op = .Gt; - input[1..] + input.substr(1) }, input.starts_with("<") -> { op = .Lt; - input[1..] + input.substr(1) }, - input.starts_with("=") -> input[1..], + input.starts_with("=") -> input.substr(1), else -> input }; return Comparator(coerce(raw_version) catch return none, op); @@ -89,8 +89,8 @@ struct ComparatorSet { #[inline] func expand(input: string) -> ?ComparatorSet { return match input[0] { - b'~' -> expand_tilda(input[1..]), - b'^' -> expand_tilda(input[1..]), + b'~' -> expand_tilda(input.substr(1)), + b'^' -> expand_tilda(input.substr(1)), else -> { if input.contains(hyphenRangeSep) { expand_hyphen(input) diff --git a/rivetc/src/checker.py b/rivetc/src/checker.py index 600fdda52..c29219581 100644 --- a/rivetc/src/checker.py +++ b/rivetc/src/checker.py @@ -836,9 +836,9 @@ def check_expr(self, expr): if expr.left_typ == self.comp.string_t: if isinstance(expr.index, ast.RangeExpr): - expr.typ = self.comp.string_t - else: - expr.typ = self.comp.uint8_t + report.error("`string` does not support slicing syntax", expr.pos) + report.help("use `.substr()` instead") + expr.typ = self.comp.uint8_t elif hasattr(expr.left_typ, "typ"): expr.typ = expr.left_typ.typ else: diff --git a/rivetc/src/codegen/__init__.py b/rivetc/src/codegen/__init__.py index 631afc927..10d6f99d3 100644 --- a/rivetc/src/codegen/__init__.py +++ b/rivetc/src/codegen/__init__.py @@ -1577,22 +1577,7 @@ def gen_expr(self, expr, custom_tmp = None): else: end = None tmp = self.cur_fn.local_name() - if s.kind == TypeKind.String: - if end == None: - inst = ir.Inst( - ir.InstKind.Call, [ - ir.Name("_R4core6string10slice_fromM"), left, - start - ] - ) - else: - inst = ir.Inst( - ir.InstKind.Call, [ - ir.Name("_R4core6string5sliceM"), left, start, - end - ] - ) - elif s.kind == TypeKind.DynArray: + if s.kind == TypeKind.DynArray: if end == None: inst = ir.Inst( ir.InstKind.Call, [ @@ -3154,4 +3139,4 @@ def decode_escape(self, ch): return "\t" elif code == "v": return "\v" - return ch \ No newline at end of file + return ch