diff --git a/.gitignore b/.gitignore index e2cdcbd8d1..ae03092d40 100644 --- a/.gitignore +++ b/.gitignore @@ -155,3 +155,4 @@ bench/vectors/obj autofuzz.log .project.gf +.aider* diff --git a/cmd/tools/changelog_helper.v b/cmd/tools/changelog_helper.v index f0d88605f0..3fe71e7676 100644 --- a/cmd/tools/changelog_helper.v +++ b/cmd/tools/changelog_helper.v @@ -311,7 +311,7 @@ fn (l Line) write_at_category(txt string) ?string { title := category_map[l.category] title_pos := txt.index(title)? // Find the position of the ### category title - pos := txt.index_after('\n', title_pos + 1) + pos := txt.index_after('\n', title_pos + 1) or { return none } first_half := txt[..pos] second_half := txt[pos..] if txt.contains(l.text) { diff --git a/cmd/tools/vpm/common.v b/cmd/tools/vpm/common.v index 8f84a85828..27c4086ba5 100644 --- a/cmd/tools/vpm/common.v +++ b/cmd/tools/vpm/common.v @@ -104,24 +104,18 @@ fn get_all_modules() []string { mut start_token := "' // get the start index of the module entry - mut start_index := s.index_after(start_token, read_len) + mut start_index := s.index_after(start_token, read_len) or { -1 } if start_index == -1 { start_token = ' s.len { + return none + } + + mut strt := start + if start < 0 { + strt = 0 + } + if start >= s.len { + return none + } + mut i := strt + + for i < s.len { + mut j := 0 + mut ii := i + for j < p.len && s[ii] == p[j] { + j++ + ii++ + } + + if j == p.len { + return i + } + i++ + } + return none +} + +pub fn (s string) index_after_(p string, start int) int { if p.len > s.len { return -1 } diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 48415eba16..14c3cb9bc1 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -392,7 +392,7 @@ pub fn (s string) replace(rep string, with string) string { } mut idx := 0 for { - idx = s.index_after(rep, idx) + idx = s.index_after_(rep, idx) if idx == -1 { break } @@ -463,7 +463,7 @@ pub fn (s string) replace_each(vals []string) string { with := vals[rep_i + 1] for { - idx = s_.index_after(rep, idx) + idx = s_.index_after_(rep, idx) if idx == -1 { break } @@ -1352,7 +1352,36 @@ fn (s string) index_last_(p string) int { // index_after returns the position of the input string, starting search from `start` position. @[direct_array_access] -pub fn (s string) index_after(p string, start int) int { +pub fn (s string) index_after(p string, start int) ?int { + if p.len > s.len { + return none + } + mut strt := start + if start < 0 { + strt = 0 + } + if start >= s.len { + return none + } + mut i := strt + for i < s.len { + mut j := 0 + mut ii := i + for j < p.len && unsafe { s.str[ii] == p.str[j] } { + j++ + ii++ + } + if j == p.len { + return i + } + i++ + } + return none +} + +// index_after_ returns the position of the input string, starting search from `start` position. +@[direct_array_access] +pub fn (s string) index_after_(p string, start int) int { if p.len > s.len { return -1 } @@ -1429,7 +1458,7 @@ pub fn (s string) count(substr string) int { mut i := 0 for { - i = s.index_after(substr, i) + i = s.index_after_(substr, i) if i == -1 { return n } diff --git a/vlib/encoding/csv/reader.v b/vlib/encoding/csv/reader.v index f9e78a2b27..3055a0c7da 100644 --- a/vlib/encoding/csv/reader.v +++ b/vlib/encoding/csv/reader.v @@ -95,11 +95,11 @@ fn (mut r Reader) read_line() !string { return &EndOfFileError{} } le := if r.is_mac_pre_osx_le { '\r' } else { '\n' } - mut i := r.data.index_after(le, r.row_pos) + mut i := r.data.index_after(le, r.row_pos) or { -1 } if i == -1 { if r.row_pos == 0 { // check for pre osx mac line endings - i = r.data.index_after('\r', r.row_pos) + i = r.data.index_after('\r', r.row_pos) or { -1 } if i != -1 { r.is_mac_pre_osx_le = true } else { diff --git a/vlib/net/http/util.v b/vlib/net/http/util.v index 52e8c913e4..d90b17ef8a 100644 --- a/vlib/net/http/util.v +++ b/vlib/net/http/util.v @@ -8,9 +8,6 @@ module http // "GET / HTTP/1.1" => ["GET" "/" "HTTP/1.1"] fn fast_request_words(line string) (int, int) { space1 := line.index(' ') or { return 0, 0 } - space2 := line.index_after(' ', space1 + 1) - if space2 == -1 { - return 0, 0 - } + space2 := line.index_after(' ', space1 + 1) or { return 0, 0 } return space1, space2 } diff --git a/vlib/v/ast/cflags.v b/vlib/v/ast/cflags.v index 8913ead423..d18ff7df78 100644 --- a/vlib/v/ast/cflags.v +++ b/vlib/v/ast/cflags.v @@ -64,7 +64,7 @@ pub fn (mut t Table) parse_cflag(cflg string, mod string, ctimedefines []string) if has_next { break } - index = flag.index_after(' -', index + 1) + index = flag.index_after(' -', index + 1) or { -1 } } if index == -1 { value = flag.trim_space() diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4a8f7fa212..b86d5e0874 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3367,15 +3367,17 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } c.check_any_type(to_type, to_sym, node.pos) - if (to_sym.is_number() && from_sym.name == 'JS.Number') - || (to_sym.is_number() && from_sym.name == 'JS.BigInt') - || (to_sym.is_string() && from_sym.name == 'JS.String') - || (to_type.is_bool() && from_sym.name == 'JS.Boolean') - || (from_type.is_bool() && to_sym.name == 'JS.Boolean') - || (from_sym.is_number() && to_sym.name == 'JS.Number') - || (from_sym.is_number() && to_sym.name == 'JS.BigInt') - || (from_sym.is_string() && to_sym.name == 'JS.String') { - return to_type + if c.pref.backend.is_js() { + if (to_sym.is_number() && from_sym.name == 'JS.Number') + || (to_sym.is_number() && from_sym.name == 'JS.BigInt') + || (to_sym.is_string() && from_sym.name == 'JS.String') + || (to_type.is_bool() && from_sym.name == 'JS.Boolean') + || (from_type.is_bool() && to_sym.name == 'JS.Boolean') + || (from_sym.is_number() && to_sym.name == 'JS.Number') + || (from_sym.is_number() && to_sym.name == 'JS.BigInt') + || (from_sym.is_string() && to_sym.name == 'JS.String') { + return to_type + } } if !c.expected_type.has_flag(.generic) && to_sym.name.len == 1 diff --git a/vlib/v/eval/expr.c.v b/vlib/v/eval/expr.c.v index f6bb2856cc..4fd2698f88 100644 --- a/vlib/v/eval/expr.c.v +++ b/vlib/v/eval/expr.c.v @@ -579,12 +579,15 @@ pub fn (mut e Eval) expr(expr ast.Expr, expecting ast.Type) Object { } e.error('unhandled index expression ${left}[ ${index} ]') } + ast.OrExpr { + e.error('unhandled expression ${typeof(expr).name}') + } ast.AnonFn, ast.ArrayDecompose, ast.AsCast, ast.Assoc, ast.AtExpr, ast.CTempVar, ast.ChanInit, ast.Comment, ast.ComptimeCall, ast.ComptimeSelector, ast.ComptimeType, ast.ConcatExpr, ast.DumpExpr, ast.EmptyExpr, ast.EnumVal, ast.GoExpr, ast.SpawnExpr, ast.IfGuardExpr, ast.IsRefType, ast.Likely, ast.LockExpr, ast.MapInit, ast.MatchExpr, - ast.Nil, ast.None, ast.OffsetOf, ast.OrExpr, ast.RangeExpr, ast.SelectExpr, ast.SqlExpr, - ast.TypeNode, ast.TypeOf, ast.LambdaExpr { + ast.Nil, ast.None, ast.OffsetOf, ast.RangeExpr, ast.SelectExpr, ast.SqlExpr, ast.TypeNode, + ast.TypeOf, ast.LambdaExpr { e.error('unhandled expression ${typeof(expr).name}') } } diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 533a78cc3b..54ecb37609 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -1506,10 +1506,7 @@ fn trim_slash_line_break(s string) string { mut ret_str := s for { // find the position of the first `\` followed by a newline, after `start`: - idx := ret_str.index_after('\\\n', start) - if idx == -1 { - break - } + idx := ret_str.index_after('\\\n', start) or { break } start = idx // Here, ret_str[idx] is \, and ret_str[idx+1] is newline. // Depending on the number of backslashes before the newline, we should either