From 570a7aaaf3e06a078248bed7cd6188f91ad85a0b Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 26 Oct 2019 21:58:26 +0300 Subject: [PATCH] a[start..end] slicing --- vlib/compiler/gen_c.v | 18 ++++++++++++------ vlib/compiler/gen_js.v | 2 +- vlib/compiler/parser.v | 24 ++++++++++++++++++++---- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/vlib/compiler/gen_c.v b/vlib/compiler/gen_c.v index 62a2922790..03554b7efc 100644 --- a/vlib/compiler/gen_c.v +++ b/vlib/compiler/gen_c.v @@ -169,7 +169,7 @@ fn types_to_c(types []Type, table &Table) string { return sb.str() } -fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexCfg) { +fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) { // Erase var name we generated earlier: "int a = m, 0" // "m, 0" gets killed since we need to start from scratch. It's messy. // "m, 0" is an index expression, save it before deleting and insert later in map_get() @@ -195,15 +195,21 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexCfg) { p.gen('$index_expr ]') } else { - if cfg.is_ptr { - p.gen('( *($typ*) array_get(* $index_expr) )') - } else { - p.gen('( *($typ*) array_get($index_expr) )') + amp := if cfg.is_ptr { '&' } else { '' } + if cfg.is_slice { + p.gen(' array_slice($amp $index_expr) ') + } + else { + p.gen('( *($typ*) array_get($amp $index_expr) )') } } } else if cfg.is_str && !p.builtin_mod { - p.gen('string_at($index_expr)') + if cfg.is_slice { + p.gen('string_substr($index_expr)') + } else { + p.gen('string_at($index_expr)') + } } // Zero the string after map_get() if it's nil, numbers are automatically 0 // This is ugly, but what can I do without generics? diff --git a/vlib/compiler/gen_js.v b/vlib/compiler/gen_js.v index 9c3718f790..14278674b0 100644 --- a/vlib/compiler/gen_js.v +++ b/vlib/compiler/gen_js.v @@ -70,7 +70,7 @@ fn types_to_c(types []Type, table &Table) string { return sb.str() } -fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexCfg) { +fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) { p.cgen.cur_line = p.cgen.cur_line.replace(',', '[') + ']' } diff --git a/vlib/compiler/parser.v b/vlib/compiler/parser.v index c4844f3cf1..2dd78e6667 100644 --- a/vlib/compiler/parser.v +++ b/vlib/compiler/parser.v @@ -2091,6 +2091,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { is_arr0 := typ.starts_with('array_') is_arr := is_arr0 || typ == 'array' is_ptr := typ == 'byte*' || typ == 'byteptr' || typ.contains('*') + mut is_slice := false is_indexer := p.tok == .lsbr mut close_bracket := false index_error_tok_pos := p.token_idx @@ -2163,6 +2164,19 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { if p.cgen.cur_line.right(index_pos).replace(' ', '').int() < 0 { p.error('cannot access negative array index') } + if p.tok == .dotdot { + if is_arr { + typ = 'array_' + typ + } else if is_str { + typ = 'string' + } else { + p.error('slicing is supported by arrays and strings only') + } + is_slice = true + p.next() + p.gen(',') + p.check_types(p.expression(), 'int') + } } else { T := p.table.find_type(p.expression()) @@ -2197,6 +2211,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { return typ } } + // `m[key] = val` // TODO move this from index_expr() if (p.tok == .assign && !p.is_sql) || p.tok.is_assign() { if is_indexer && is_str && !p.builtin_mod { @@ -2216,26 +2231,27 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string { // else if p.pref.is_verbose && p.assigned_var != '' { // p.error('didnt assign') // } - // m[key]. no =, just a getter + // `m[key]`. no =, just a getter else if (is_map || is_arr || (is_str && !p.builtin_mod)) && is_indexer { - p.index_get(typ, fn_ph, IndexCfg{ + p.index_get(typ, fn_ph, IndexConfig{ is_arr: is_arr is_map: is_map is_ptr: is_ptr is_str: is_str + is_slice: is_slice }) } // else if is_arr && is_indexer{} return typ } -struct IndexCfg { +struct IndexConfig { is_map bool is_str bool is_ptr bool is_arr bool is_arr0 bool - + is_slice bool } // for debugging only