From a075ce160e0286fd75a1db6a4a70a2e100dda3cd Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Sun, 27 Oct 2019 17:36:04 +1100 Subject: [PATCH] compiler: add `[..2]` & `[2..]` support for slices --- vlib/builtin/array.v | 6 ++++++ vlib/builtin/array_test.v | 6 ++++++ vlib/builtin/string.v | 6 ++++++ vlib/builtin/string_test.v | 4 ++++ vlib/compiler/gen_c.v | 4 ++-- vlib/compiler/parser.v | 31 +++++++++++++++++++++++-------- 6 files changed, 47 insertions(+), 10 deletions(-) diff --git a/vlib/builtin/array.v b/vlib/builtin/array.v index 5dce844737..5db5a8f3ea 100644 --- a/vlib/builtin/array.v +++ b/vlib/builtin/array.v @@ -146,6 +146,12 @@ pub fn (s array) right(n int) array { return s.slice(n, s.len) } +// used internally for [2..4] +fn (s array) slice2(start, _end int, end_max bool) array { + end := if end_max { s.len } else { _end } + return s.slice(start, end) +} + pub fn (s array) slice(start, _end int) array { mut end := _end if start > end { diff --git a/vlib/builtin/array_test.v b/vlib/builtin/array_test.v index 9863f5cef0..7c959c21f0 100644 --- a/vlib/builtin/array_test.v +++ b/vlib/builtin/array_test.v @@ -118,10 +118,13 @@ fn test_right() { a := [1, 2, 3, 4] b := a.right(1) c := a[1..a.len] + d := a[1..] assert b[0] == 2 assert b[1] == 3 assert c[0] == 2 assert c[1] == 3 + assert d[0] == 2 + assert d[1] == 3 } fn test_right_with_n_bigger_than_array_size() { @@ -142,10 +145,13 @@ fn test_left() { a := [1, 2, 3] b := a.left(2) c := a[0..2] + d := a[..2] assert b[0] == 1 assert b[1] == 2 assert c[0] == 1 assert c[1] == 2 + assert d[0] == 1 + assert d[1] == 2 } fn test_slice() { diff --git a/vlib/builtin/string.v b/vlib/builtin/string.v index 4418a77215..0d0ac10699 100644 --- a/vlib/builtin/string.v +++ b/vlib/builtin/string.v @@ -394,6 +394,12 @@ pub fn (s string) right(n int) string { return s.substr(n, s.len) } +// used internally for [2..4] +fn (s string) substr2(start, _end int, end_max bool) string { + end := if end_max { s.len } else { _end } + return s.substr(start, end) +} + // substr pub fn (s string) substr(start, end int) string { if start > end || start > s.len || end > s.len || start < 0 || end < 0 { diff --git a/vlib/builtin/string_test.v b/vlib/builtin/string_test.v index e4c9b362d2..e2206c75ec 100644 --- a/vlib/builtin/string_test.v +++ b/vlib/builtin/string_test.v @@ -210,6 +210,10 @@ fn test_runes() { assert s2.substr(1, 4) == 'riv' assert s2[1..4].len == 3 assert s2[1..4] == 'riv' + assert s2[..4].len == 4 + assert s2[..4] == 'priv' + assert s2[2..].len == 4 + assert s2[2..] == 'ivet' assert u.substr(1, 4).len == 6 assert u.substr(1, 4) == 'рив' assert s2.substr(1, 2) == 'r' diff --git a/vlib/compiler/gen_c.v b/vlib/compiler/gen_c.v index b1e9dd9b55..782864e45f 100644 --- a/vlib/compiler/gen_c.v +++ b/vlib/compiler/gen_c.v @@ -197,7 +197,7 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) { else { ref := if cfg.is_ptr { '*' } else { '' } if cfg.is_slice { - p.gen(' array_slice($ref $index_expr) ') + p.gen(' array_slice2($ref $index_expr) ') } else { p.gen('( *($typ*) array_get($ref $index_expr) )') @@ -206,7 +206,7 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) { } else if cfg.is_str && !p.builtin_mod { if cfg.is_slice { - p.gen('string_substr($index_expr)') + p.gen('string_substr2($index_expr)') } else { p.gen('string_at($index_expr)') } diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index f0e8bb8399..2440e05c7f 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -2155,14 +2155,21 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { } // expression inside [ ] if is_arr || is_str { - index_pos := p.cgen.cur_line.len - T := p.table.find_type(p.expression()) - // Allows only i8-64 and byte-64 to be used when accessing an array - if T.parent != 'int' && T.parent != 'u32' { - p.check_types(T.name, 'int') + // [2.. + if p.tok != .dotdot { + index_pos := p.cgen.cur_line.len + T := p.table.find_type(p.expression()) + // Allows only i8-64 and byte-64 to be used when accessing an array + if T.parent != 'int' && T.parent != 'u32' { + p.check_types(T.name, 'int') + } + if p.cgen.cur_line.right(index_pos).replace(' ', '').int() < 0 { + p.error('cannot access negative array index') + } } - if p.cgen.cur_line.right(index_pos).replace(' ', '').int() < 0 { - p.error('cannot access negative array index') + // [.. + else { + p.gen('0') } if p.tok == .dotdot { if is_arr { @@ -2175,7 +2182,15 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { is_slice = true p.next() p.gen(',') - p.check_types(p.expression(), 'int') + // ..4] + if p.tok != .rsbr { + p.check_types(p.expression(), 'int') + p.gen(', false') + } + // ..] + else { + p.gen('-1, true') + } } } else {