a[start..end] slicing

pull/2558/head
Alexander Medvednikov 2019-10-26 21:58:26 +03:00
parent 678ce54e70
commit 570a7aaaf3
3 changed files with 33 additions and 11 deletions

View File

@ -169,7 +169,7 @@ fn types_to_c(types []Type, table &Table) string {
return sb.str() 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" // 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" 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() // "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 ]') p.gen('$index_expr ]')
} }
else { else {
if cfg.is_ptr { amp := if cfg.is_ptr { '&' } else { '' }
p.gen('( *($typ*) array_get(* $index_expr) )') if cfg.is_slice {
} else { p.gen(' array_slice($amp $index_expr) ')
p.gen('( *($typ*) array_get($index_expr) )') }
else {
p.gen('( *($typ*) array_get($amp $index_expr) )')
} }
} }
} }
else if cfg.is_str && !p.builtin_mod { 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 // Zero the string after map_get() if it's nil, numbers are automatically 0
// This is ugly, but what can I do without generics? // This is ugly, but what can I do without generics?

View File

@ -70,7 +70,7 @@ fn types_to_c(types []Type, table &Table) string {
return sb.str() 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(',', '[') + ']' p.cgen.cur_line = p.cgen.cur_line.replace(',', '[') + ']'
} }

View File

@ -2091,6 +2091,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
is_arr0 := typ.starts_with('array_') is_arr0 := typ.starts_with('array_')
is_arr := is_arr0 || typ == 'array' is_arr := is_arr0 || typ == 'array'
is_ptr := typ == 'byte*' || typ == 'byteptr' || typ.contains('*') is_ptr := typ == 'byte*' || typ == 'byteptr' || typ.contains('*')
mut is_slice := false
is_indexer := p.tok == .lsbr is_indexer := p.tok == .lsbr
mut close_bracket := false mut close_bracket := false
index_error_tok_pos := p.token_idx 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 { if p.cgen.cur_line.right(index_pos).replace(' ', '').int() < 0 {
p.error('cannot access negative array index') 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 { else {
T := p.table.find_type(p.expression()) 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 return typ
} }
} }
// `m[key] = val`
// TODO move this from index_expr() // TODO move this from index_expr()
if (p.tok == .assign && !p.is_sql) || p.tok.is_assign() { if (p.tok == .assign && !p.is_sql) || p.tok.is_assign() {
if is_indexer && is_str && !p.builtin_mod { 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 != '' { // else if p.pref.is_verbose && p.assigned_var != '' {
// p.error('didnt assign') // 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 { 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_arr: is_arr
is_map: is_map is_map: is_map
is_ptr: is_ptr is_ptr: is_ptr
is_str: is_str is_str: is_str
is_slice: is_slice
}) })
} }
// else if is_arr && is_indexer{} // else if is_arr && is_indexer{}
return typ return typ
} }
struct IndexCfg { struct IndexConfig {
is_map bool is_map bool
is_str bool is_str bool
is_ptr bool is_ptr bool
is_arr bool is_arr bool
is_arr0 bool is_arr0 bool
is_slice bool
} }
// for debugging only // for debugging only