compiler/vlib: replace substr/left/right with `[start..end]` everywhere

pull/2562/head
joe-conigliaro 2019-10-27 18:03:15 +11:00 committed by Alexander Medvednikov
parent ed55826686
commit 59378dce46
49 changed files with 308 additions and 306 deletions

View File

@ -9,7 +9,7 @@ fn main() {
break
}
end := html.index_after('"', pos)
println(html.substr(pos, end))
println(html[pos..end])
}
}

View File

@ -69,5 +69,5 @@ fn filter_word(word string) string {
i++
}
end := i
return word.substr(start, end)
return word[start..end]
}

View File

@ -249,7 +249,7 @@ fn (gen_vc mut GenVC) generate() {
// last commit hash in v repo
last_commit_hash_v := git_log_v.find_between('commit', '\n').trim_space()
last_commit_hash_v_short := last_commit_hash_v.left(7)
last_commit_hash_v_short := last_commit_hash_v[..7]
// log some info
gen_vc.logger.debug('last commit time ($git_repo_v): ' + last_commit_time_v.format_ss())
@ -270,7 +270,7 @@ fn (gen_vc mut GenVC) generate() {
// build v.c for each os
for os_name in vc_build_oses {
vc_suffix := if os_name == 'unix' { '' } else { '_${os_name.left(3)}' }
vc_suffix := if os_name == 'unix' { '' } else { '_${os_name[..3]}' }
v_os_arg := if os_name == 'unix' { '' } else { '-os $os_name' }
c_file := 'v${vc_suffix}.c'
// try generate .c file

View File

@ -116,7 +116,7 @@ fn test_repeat() {
fn test_right() {
a := [1, 2, 3, 4]
b := a.right(1)
b := a[1..]
c := a[1..a.len]
d := a[1..]
assert b[0] == 2
@ -129,6 +129,9 @@ fn test_right() {
fn test_right_with_n_bigger_than_array_size() {
a := [1, 2, 3, 4]
// NOTE: slice syntax wont return empty array
// instead will give index out of bounds
// mut b := a[10..]
mut b := a.right(10)
assert b.len == 0
@ -143,7 +146,7 @@ fn test_right_with_n_bigger_than_array_size() {
fn test_left() {
a := [1, 2, 3]
b := a.left(2)
b := a[..2]
c := a[0..2]
d := a[..2]
assert b[0] == 1
@ -207,9 +210,9 @@ fn modify (numbers mut []int) {
fn test_mut_slice() {
mut n := [1,2,3]
modify(mut n.left(2))
modify(mut n[..2])
assert n[0] == 777
modify(mut n.right(2))
modify(mut n[2..])
assert n[2] == 777
println(n)
}

View File

@ -148,12 +148,12 @@ pub fn (s string) find_between(start, end string) string {
return ''
}
// First get everything to the right of 'start'
val := s.right(start_pos + start.len)
val := s[start_pos + start.len..]
end_pos := val.index(end)
if end_pos == -1 {
return val
}
return val.left(end_pos)
return val[..end_pos]
}
// TODO generic
@ -258,7 +258,7 @@ pub fn (s string) all_before(dot string) string {
if pos == -1 {
return s
}
return s.left(pos)
return s[..pos]
}
pub fn (s string) all_before_last(dot string) string {
@ -266,7 +266,7 @@ pub fn (s string) all_before_last(dot string) string {
if pos == -1 {
return s
}
return s.left(pos)
return s[..pos]
}
pub fn (s string) all_after(dot string) string {
@ -274,7 +274,7 @@ pub fn (s string) all_after(dot string) string {
if pos == -1 {
return s
}
return s.right(pos + dot.len)
return s[pos + dot.len..]
}
// fn (s []string) substr(a, b int) string {

View File

@ -260,7 +260,7 @@ fn test_upper() {
fn test_left_right() {
s := 'ALOHA'
assert s.left(3) == 'ALO'
assert s.right(3) == 'HA'
assert s[3..] == 'HA'
u := s.ustring()
assert u.left(3) == 'ALO'
assert u.right(3) == 'HA'

View File

@ -85,8 +85,8 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool {
mut name := ''
if flag.starts_with('linux') || flag.starts_with('darwin') || flag.starts_with('freebsd') || flag.starts_with('windows') {
pos := flag.index(' ')
fos = flag.left(pos).trim_space()
flag = flag.right(pos).trim_space()
fos = flag[..pos].trim_space()
flag = flag[pos..].trim_space()
}
for {
mut index := -1
@ -94,9 +94,9 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool {
if flag[0] == `-` {
for f in allowed_flags {
i := 1+f.len
if i <= flag.len && f == flag.substr(1,i) {
name = flag.left(i).trim_space()
flag = flag.right(i).trim_space()
if i <= flag.len && f == flag[1..i] {
name = flag[..i].trim_space()
flag = flag[i..].trim_space()
break
}
}
@ -109,17 +109,17 @@ fn (table mut Table) parse_cflag(cflag string, mod string) ?bool {
if index != -1 && flag[index] == ` ` && flag[index+1] == `-` {
for f in allowed_flags {
i := index+f.len
if i < flag.len && f == flag.substr(index, i) {
if i < flag.len && f == flag[index..i] {
index = i
break
}
}
value = flag.left(index).trim_space()
flag = flag.right(index).trim_space()
value = flag[..index].trim_space()
flag = flag[index..].trim_space()
}
else if index != -1 && index < flag.len-2 && flag[index] == `,` {
value = flag.left(index).trim_space()
flag = flag.right(index+1).trim_space()
value = flag[..index].trim_space()
flag = flag[index+1..].trim_space()
}
else {
value = flag.trim_space()

View File

@ -136,12 +136,12 @@ fn (g mut CGen) cut() string {
pos := g.cut_pos
g.cut_pos = 0
if g.is_tmp {
res := g.tmp_line.right(pos)
g.tmp_line = g.tmp_line.left(pos)
res := g.tmp_line[pos..]
g.tmp_line = g.tmp_line[..pos]
return res
}
res := g.cur_line.right(pos)
g.cur_line = g.cur_line.left(pos)
res := g.cur_line[pos..]
g.cur_line = g.cur_line[..pos]
return res
}
@ -151,13 +151,13 @@ fn (g mut CGen) set_placeholder(pos int, val string) {
}
// g.lines.set(pos, val)
if g.is_tmp {
left := g.tmp_line.left(pos)
right := g.tmp_line.right(pos)
left := g.tmp_line[..pos]
right := g.tmp_line[pos..]
g.tmp_line = '${left}${val}${right}'
return
}
left := g.cur_line.left(pos)
right := g.cur_line.right(pos)
left := g.cur_line[..pos]
right := g.cur_line[pos..]
g.cur_line = '${left}${val}${right}'
// g.genln('')
}

View File

@ -167,9 +167,9 @@ fn (p mut Parser) comp_time() {
pp.v.add_parser(pp)
tmpl_fn_body := p.cgen.lines.slice(pos + 2, p.cgen.lines.len).join('\n').clone()
end_pos := tmpl_fn_body.last_index('Builder_str( sb )') + 19 // TODO
p.cgen.lines = p.cgen.lines.left(pos)
p.cgen.lines = p.cgen.lines[..pos]
p.genln('/////////////////// tmpl start')
p.genln(tmpl_fn_body.left(end_pos))
p.genln(tmpl_fn_body[..end_pos])
p.genln('/////////////////// tmpl end')
// `app.vweb.html(index_view())`
receiver := p.cur_fn.args[0]
@ -188,7 +188,7 @@ fn (p mut Parser) chash() {
p.next()
if hash.starts_with('flag ') {
if p.first_pass() {
mut flag := hash.right(5)
mut flag := hash[5..]
// expand `@VROOT` `@VMOD` to absolute path
flag = flag.replace('@VROOT', p.vroot)
flag = flag.replace('@VMOD', v_modules_path)
@ -214,7 +214,7 @@ fn (p mut Parser) chash() {
// TODO remove after ui_mac.m is removed
else if hash.contains('embed') {
pos := hash.index('embed') + 5
file := hash.right(pos)
file := hash[pos..]
if p.pref.build_mode != .default_mode {
p.genln('#include $file')
}
@ -283,7 +283,7 @@ fn (p mut Parser) gen_array_str(typ Type) {
is_public: true
receiver_typ: typ.name
})
elm_type := typ.name.right(6)
elm_type := typ.name[6..]
elm_type2 := p.table.find_type(elm_type)
is_array := elm_type.starts_with('array_')
if is_array {
@ -350,7 +350,7 @@ fn (p mut Parser) gen_array_filter(str_typ string, method_ph int) {
}
array_int b = tmp2;
*/
val_type:=str_typ.right(6)
val_type:=str_typ[6..]
p.open_scope()
p.register_var(Var{
name: 'it'
@ -390,7 +390,7 @@ fn (p mut Parser) gen_array_map(str_typ string, method_ph int) string {
}
array_int b = tmp2;
*/
val_type:=str_typ.right(6)
val_type:=str_typ[6..]
p.open_scope()
p.register_var(Var{
name: 'it'

View File

@ -1099,11 +1099,11 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
tp := f.type_pars[i]
mut ti := e
if ti.starts_with('fn (') {
fn_args := ti.right(4).all_before(') ').split(',')
fn_args := ti[4..].all_before(') ').split(',')
mut found := false
for fa_ in fn_args {
mut fa := fa_
for fa.starts_with('array_') { fa = fa.right(6) }
for fa.starts_with('array_') { fa = fa[6..] }
if fa == tp {
r.inst[tp] = fa
found = true
@ -1114,7 +1114,7 @@ fn (p mut Parser) extract_type_inst(f &Fn, args_ []string) TypeInst {
if found { continue }
ti = ti.all_after(') ')
}
for ti.starts_with('array_') { ti = ti.right(6) }
for ti.starts_with('array_') { ti = ti[6..] }
if r.inst[tp] != '' {
if r.inst[tp] != ti {
p.error('type parameter `$tp` has type ${r.inst[tp]}, not `$ti`')
@ -1150,12 +1150,12 @@ fn (p mut Parser) replace_type_params(f &Fn, ti TypeInst) []string {
mut fr := ''
if fi.starts_with('fn (') {
fr += 'fn ('
mut fn_args := fi.right(4).all_before(') ').split(',')
mut fn_args := fi[4..].all_before(') ').split(',')
fn_args << fi.all_after(') ')
for i, fa_ in fn_args {
mut fna := fa_.trim_space()
for fna.starts_with('array_') {
fna = fna.right(6)
fna = fna[6..]
fr += 'array_'
}
if fna in ti.inst.keys() {
@ -1173,11 +1173,11 @@ fn (p mut Parser) replace_type_params(f &Fn, ti TypeInst) []string {
continue
}
for fi.starts_with('array_') {
fi = fi.right(6)
fi = fi[6..]
fr += 'array_'
}
is_varg := fi.starts_with('...')
if is_varg { fi = fi.right(3) }
if is_varg { fi = fi[3..] }
if fi in ti.inst.keys() {
mut t := ti.inst[fi]
if is_varg { t = '...$t' }
@ -1214,7 +1214,7 @@ fn (p mut Parser) fn_call_vargs(f Fn) (string, []string) {
return '', []string
}
last_arg := f.args.last()
mut varg_def_type := last_arg.typ.right(3)
mut varg_def_type := last_arg.typ[3..]
mut types := []string
mut values := []string
for p.tok != .rpar {
@ -1428,7 +1428,7 @@ fn (f &Fn) str_args(table &Table) string {
for method in interface_type.methods {
s += ', $method.typ (*${arg.typ}_${method.name})(void*'
if method.args.len > 1 {
for a in method.args.right(1) {
for a in method.args[1..] {
s += ', $a.typ'
}
}

View File

@ -17,7 +17,7 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
// `[typ] [name] = bool_expression();`
pos := p.cgen.add_placeholder()
mut typ := p.bool_expression()
if typ.starts_with('...') { typ = typ.right(3) }
if typ.starts_with('...') { typ = typ[3..] }
//p.gen('/*after expr*/')
// Option check ? or {
or_else := p.tok == .key_orelse
@ -66,7 +66,7 @@ fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
} else if typ.starts_with('[') && typ[ typ.len-1 ] != `*` {
// a fixed_array initializer, like `v := [1.1, 2.2]!!`
// ... should translate to the following in C `f32 v[2] = {1.1, 2.2};`
initializer := p.cgen.cur_line.right(pos)
initializer := p.cgen.cur_line[pos..]
if initializer.len > 0 {
p.cgen.resetln(' = {' + initializer.all_after('{') )
} else if initializer.len == 0 {
@ -175,11 +175,11 @@ fn (p mut Parser) index_get(typ string, fn_ph int, cfg IndexConfig) {
// "m, 0" is an index expression, save it before deleting and insert later in map_get()
mut index_expr := ''
if p.cgen.is_tmp {
index_expr = p.cgen.tmp_line.right(fn_ph)
p.cgen.resetln(p.cgen.tmp_line.left(fn_ph))
index_expr = p.cgen.tmp_line[fn_ph..]
p.cgen.resetln(p.cgen.tmp_line[..fn_ph])
} else {
index_expr = p.cgen.cur_line.right(fn_ph)
p.cgen.resetln(p.cgen.cur_line.left(fn_ph))
index_expr = p.cgen.cur_line[fn_ph..]
p.cgen.resetln(p.cgen.cur_line[..fn_ph])
}
// Can't pass integer literal, because map_get() requires a void*
tmp := p.get_tmp()
@ -301,9 +301,9 @@ fn (p mut Parser) gen_array_at(typ_ string, is_arr0 bool, fn_ph int) {
// array_int a; a[0]
// type is "array_int", need "int"
// typ = typ.replace('array_', '')
if is_arr0 {
typ = typ.right(6)
}
// if is_arr0 {
// typ = typ.right(6)
// }
// array a; a.first() voidptr
// type is "array", need "void*"
if typ == 'array' {
@ -377,8 +377,8 @@ fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_e
fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool,fn_ph, assign_pos int, is_cao bool) {
// `a[0] = 7`
// curline right now: `a , 0 = 7`
mut val := p.cgen.cur_line.right(assign_pos)
p.cgen.resetln(p.cgen.cur_line.left(assign_pos))
mut val := p.cgen.cur_line[assign_pos..]
p.cgen.resetln(p.cgen.cur_line[..assign_pos])
mut cao_tmp := p.cgen.cur_line
mut func := ''
if is_map {
@ -522,7 +522,7 @@ fn (p mut Parser) cast(typ string) {
fn type_default(typ string) string {
if typ.starts_with('array_') {
return 'new_array(0, 1, sizeof( ${typ.right(6)} ))'
return 'new_array(0, 1, sizeof( ${typ[6..]} ))'
}
// Always set pointers to 0
if typ.ends_with('*') {
@ -567,7 +567,7 @@ fn (p mut Parser) gen_array_push(ph int, typ, expr_type, tmp, elm_type string) {
push_call := if typ.contains('*'){'_PUSH('} else { '_PUSH(&'}
p.cgen.set_placeholder(ph, push_call)
if elm_type.ends_with('*') {
p.gen('), $tmp, ${elm_type.left(elm_type.len - 1)})')
p.gen('), $tmp, ${elm_type[..elm_type.len - 1]})')
} else {
p.gen('), $tmp, $elm_type)')
}

View File

@ -9,7 +9,7 @@ const (
fn (p mut Parser) gen_var_decl(name string, is_static bool) string {
p.gen('var $name /* typ */ = ')
mut typ := p.bool_expression()
if typ.starts_with('...') { typ = typ.right(3) }
if typ.starts_with('...') { typ = typ[3..] }
or_else := p.tok == .key_orelse
//tmp := p.get_tmp()
if or_else {
@ -149,8 +149,8 @@ fn (p mut Parser) gen_array_init(typ string, no_alloc bool, new_arr_ph int, nr_e
}
fn (p mut Parser) gen_array_set(typ string, is_ptr, is_map bool,fn_ph, assign_pos int, is_cao bool) {
mut val := p.cgen.cur_line.right(assign_pos)
p.cgen.resetln(p.cgen.cur_line.left(assign_pos))
mut val := p.cgen.cur_line[assign_pos..]
p.cgen.resetln(p.cgen.cur_line[..assign_pos])
p.gen('] =')
cao_tmp := p.cgen.cur_line
if is_cao {

View File

@ -86,7 +86,7 @@ string res = tos2("");
continue
}
name := if field.attr.starts_with('json:') {
field.attr.right(5)
field.attr[5..]
} else {
field.name
}

View File

@ -493,7 +493,7 @@ pub fn (v V) run_compiled_executable_and_exit() {
if i == 0 { continue }
if a.starts_with('-') { continue }
if a in ['run','test'] {
args_after += args.right(i+2).join(' ')
args_after += args[i+2..].join(' ')
break
}
}
@ -660,7 +660,7 @@ pub fn (v &V) get_user_files() []string {
if is_test_with_imports {
user_files << dir
pos := dir.last_index(os.path_separator)
dir = dir.left(pos) + os.path_separator// TODO why is this needed
dir = dir[..pos] + os.path_separator// TODO why is this needed
}
if dir.ends_with('.v') || dir.ends_with('.vsh') {
// Just compile one file and get parent dir
@ -743,7 +743,7 @@ pub fn get_param_after(joined_args, arg, def string) string {
if space == -1 {
space = joined_args.len
}
res := joined_args.substr(pos, space)
res := joined_args[pos..space]
return res
}
@ -777,7 +777,7 @@ pub fn new_v(args[]string) &V {
dir = dir.all_before_last(os.path_separator)
}
if dir.starts_with('.$os.path_separator') {
dir = dir.right(2)
dir = dir[2..]
}
if args.len < 2 {
dir = ''
@ -792,7 +792,7 @@ pub fn new_v(args[]string) &V {
dir.all_after('vlib'+os.path_separator)
}
else if dir.starts_with('.\\') || dir.starts_with('./') {
dir.right(2)
dir[2..]
}
else if dir.starts_with(os.path_separator) {
dir.all_after(os.path_separator)
@ -821,7 +821,7 @@ pub fn new_v(args[]string) &V {
}
// No -o provided? foo.v => foo
if out_name == 'a.out' && dir.ends_with('.v') && dir != '.v' {
out_name = dir.left(dir.len - 2)
out_name = dir[..dir.len - 2]
// Building V? Use v2, since we can't overwrite a running
// executable on Windows + the precompiled V is more
// optimized.
@ -957,7 +957,7 @@ pub fn env_vflags_and_os_args() []string {
args << os.args[0]
args << vflags.split(' ')
if os.args.len > 1 {
args << os.args.right(1)
args << os.args[1..]
}
} else{
args << os.args

View File

@ -158,7 +158,7 @@ fn find_vs(vswhere_dir string, host_arch string) ?VsInstallation {
// println('version: $version')
v := if version.ends_with('\n') {
version.left(version.len - 2)
version[..version.len - 2]
} else {
version
}

View File

@ -8,7 +8,7 @@ fn (p mut Parser) in_optimization(typ string, ph int) {
p.check(.lsbr)
mut i := 0
// Get `a` expr value (can be a string literal, not a variable)
expr := p.cgen.cur_line.right(ph)
expr := p.cgen.cur_line[ph..]
is_str := typ == 'string'
//println('!! $p.expr_var.name => $name ($typ)')
for p.tok != .rsbr && p.tok != .eof {

View File

@ -1030,7 +1030,7 @@ fn (p mut Parser) close_scope() {
//p.cur_fn.defer_text[f] = ''
}
p.cur_fn.scope_level--
p.cur_fn.defer_text = p.cur_fn.defer_text.left(p.cur_fn.scope_level + 1)
p.cur_fn.defer_text = p.cur_fn.defer_text[..p.cur_fn.scope_level + 1]
p.var_idx = i + 1
// println('close_scope new var_idx=$f.var_idx\n')
}
@ -1235,17 +1235,17 @@ fn ($v.name mut $v.typ) $p.cur_fn.name (...) {
//}
// Allow `num = 4` where `num` is an `?int`
if p.assigned_type.starts_with('Option_') &&
expr_type == p.assigned_type.right('Option_'.len) {
expr := p.cgen.cur_line.right(pos)
left := p.cgen.cur_line.left(pos)
expr_type == p.assigned_type['Option_'.len..] {
expr := p.cgen.cur_line[pos..]
left := p.cgen.cur_line[..pos]
typ := expr_type.replace('Option_', '')
p.cgen.resetln(left + 'opt_ok($expr, sizeof($typ))')
}
else if expr_type[0]==`[` {
// assignment to a fixed_array `mut a:=[3]int a=[1,2,3]!!`
expr := p.cgen.cur_line.right(pos).all_after('{').all_before('}')
left := p.cgen.cur_line.left(pos).all_before('=')
cline_pos := p.cgen.cur_line.right(pos)
expr := p.cgen.cur_line[pos..].all_after('{').all_before('}')
left := p.cgen.cur_line[..pos].all_before('=')
cline_pos := p.cgen.cur_line[pos..]
etype := cline_pos.all_before(' {')
if p.assigned_type != p.expected_type {
p.error_with_token_index( 'incompatible types: $p.assigned_type != $p.expected_type', errtok)
@ -1933,7 +1933,7 @@ fn (p mut Parser) dot(str_typ_ string, method_ph int) string {
mut str_typ := str_typ_
p.check(.dot)
is_variadic_arg := str_typ.starts_with('...')
if is_variadic_arg { str_typ = str_typ.right(3) }
if is_variadic_arg { str_typ = str_typ[3..] }
mut typ := p.find_type(str_typ)
if typ.name.len == 0 {
p.error('dot(): cannot find type `$str_typ`')
@ -1971,7 +1971,7 @@ fn (p mut Parser) dot(str_typ_ string, method_ph int) string {
}
if !typ.is_c && !p.is_c_fn_call && !has_field && !has_method && !p.first_pass() {
if typ.name.starts_with('Option_') {
opt_type := typ.name.right(7)
opt_type := typ.name[7..]
p.error('unhandled option type: `?$opt_type`')
}
//println('error in dot():')
@ -2044,7 +2044,7 @@ struct $typ.name {
}
// Array methods returning `voidptr` (like `last()`) should return element type
if method.typ == 'void*' && typ.name.starts_with('array_') {
return typ.name.right(6)
return typ.name[6..]
}
//if false && p.tok == .lsbr {
// if is_indexer {
@ -2119,7 +2119,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
// `[10]int` => `int`, `[10][3]int` => `[3]int`
if typ.contains('][') {
pos := typ.index_after('[', 1)
typ = typ.right(pos)
typ = typ[pos..]
}
else {
typ = typ.all_after(']')
@ -2138,7 +2138,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
}
if is_arr {
if is_arr0 {
typ = typ.right(6)
typ = typ[6..]
}
p.gen_array_at(typ, is_arr0, fn_ph)
}
@ -2163,7 +2163,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
if T.parent != 'int' && T.parent != 'u32' {
p.check_types(T.name, 'int')
}
if p.cgen.cur_line.right(index_pos).replace(' ', '').int() < 0 {
if p.cgen.cur_line[index_pos..].replace(' ', '').int() < 0 {
p.error('cannot access negative array index')
}
}
@ -2216,7 +2216,7 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
if is_indexer {
l := p.cgen.cur_line.trim_space()
index_val := l.right(l.last_index(' ')).trim_space()
p.cgen.resetln(l.left(fn_ph))
p.cgen.resetln(l[..fn_ph])
p.table.varg_access << VargAccess{
fn_name: p.cur_fn.name,
tok_idx: index_error_tok_pos,
@ -2337,7 +2337,7 @@ fn (p mut Parser) expression() string {
// a << 7 => int tmp = 7; array_push(&a, &tmp);
// _PUSH(&a, expression(), tmp, string)
tmp := p.get_tmp()
tmp_typ := typ.right(6)// skip "array_"
tmp_typ := typ[6..]// skip "array_"
p.check_space(.left_shift)
// Get the value we are pushing
p.gen(', (')
@ -2989,8 +2989,8 @@ fn (p mut Parser) array_init() string {
if i == 1 && p.tok == .semicolon {
p.warn('`[0 ; len]` syntax was removed. Use `[0].repeat(len)` instead')
p.check_space(.semicolon)
val := p.cgen.cur_line.right(pos)
p.cgen.resetln(p.cgen.cur_line.left(pos))
val := p.cgen.cur_line[pos..]
p.cgen.resetln(p.cgen.cur_line[..pos])
p.gen('array_repeat_old(& ($typ[]){ $val }, ')
p.check_types(p.bool_expression(), 'int')
p.gen(', sizeof($typ) )')
@ -3080,7 +3080,7 @@ fn (p mut Parser) if_st(is_expr bool, elif_depth int) string {
p.next()
p.check(.decl_assign)
option_type, expr := p.tmp_expr()// := p.bool_expression()
typ := option_type.right(7)
typ := option_type[7..]
// Option_User tmp = get_user(1);
// if (tmp.ok) {
// User user = *(User*)tmp.data;
@ -3236,7 +3236,7 @@ fn (p mut Parser) for_st() {
is_map := typ.starts_with('map_')
is_str := typ == 'string'
is_variadic_arg := typ.starts_with('...')
if is_variadic_arg { typ = typ.right(3) }
if is_variadic_arg { typ = typ[3..] }
if !is_arr && !is_str && !is_map && !is_variadic_arg {
p.error('cannot range over type `$typ`')
}
@ -3251,7 +3251,7 @@ fn (p mut Parser) for_st() {
pad := if is_arr { 6 } else { 4 }
var_typ := if is_str { 'byte' }
else if is_variadic_arg { typ }
else { typ.right(pad) }
else { typ[pad..] }
// typ = strings.Replace(typ, "_ptr", "*", -1)
mut i_var_type := 'int'
if is_variadic_arg {
@ -3297,7 +3297,7 @@ fn (p mut Parser) for_st() {
expr := p.cgen.end_tmp()
is_range := p.tok == .dotdot
is_variadic_arg := typ.starts_with('...')
if is_variadic_arg { typ = typ.right(3) }
if is_variadic_arg { typ = typ[3..] }
mut range_end := ''
if is_range {
p.check_types(typ, 'int')
@ -3329,7 +3329,7 @@ fn (p mut Parser) for_st() {
p.gen_for_range_header(i, range_end, tmp, var_type, val)
}
else if is_arr {
var_type = typ.right(6)// all after `array_`
var_type = typ[6..]// all after `array_`
p.gen_for_header(i, tmp, var_type, val)
}
else if is_str {
@ -3686,7 +3686,7 @@ fn (p mut Parser) return_st() {
mut expr_type := p.bool_expression()
// println('$p.cur_fn.name returns type $expr_type, should be $p.cur_fn.typ')
mut types := []string
mut mr_values := [p.cgen.cur_line.right(ph).trim_space()]
mut mr_values := [p.cgen.cur_line[ph..].trim_space()]
types << expr_type
for p.tok == .comma {
p.check(.comma)
@ -3715,14 +3715,14 @@ fn (p mut Parser) return_st() {
if p.cur_fn.typ.ends_with(expr_type) && !is_none &&
p.cur_fn.typ.starts_with('Option_') {
tmp := p.get_tmp()
ret := p.cgen.cur_line.right(ph)
ret := p.cgen.cur_line[ph..]
typ := expr_type.replace('Option_', '')
p.cgen.resetln('$expr_type $tmp = OPTION_CAST($expr_type)($ret);')
p.genln(deferred_text)
p.gen('return opt_ok(&$tmp, sizeof($typ))')
}
else {
ret := p.cgen.cur_line.right(ph)
ret := p.cgen.cur_line[ph..]
if deferred_text == '' || expr_type == 'void*' {
// no defer{} necessary?
@ -3928,17 +3928,17 @@ fn (p mut Parser) defer_st() {
p.genln('{')
p.statements()
p.cur_fn.defer_text.last() = p.cgen.lines.right(pos).join('\n') + p.cur_fn.defer_text.last()
p.cur_fn.defer_text.last() = p.cgen.lines[pos..].join('\n') + p.cur_fn.defer_text.last()
// Rollback p.cgen.lines
p.cgen.lines = p.cgen.lines.left(pos)
p.cgen.lines = p.cgen.lines[..pos]
p.cgen.resetln('')
}
fn (p mut Parser) check_and_register_used_imported_type(typ_name string) {
us_idx := typ_name.index('__')
if us_idx != -1 {
arg_mod := typ_name.left(us_idx)
arg_mod := typ_name[..us_idx]
if p.import_table.known_alias(arg_mod) {
p.import_table.register_used_import(arg_mod)
}

View File

@ -28,13 +28,13 @@ fn (r mut Repl) checks() bool {
in_string = !in_string
}
if r.line[i] == `{` && !in_string {
r.line = r.line.left(i + 1) + '\n' + r.line.right(i + 1)
r.line = r.line[..i + 1] + '\n' + r.line[i + 1..]
is_cut = true
i++
r.indent++
}
if r.line[i] == `}` && !in_string {
r.line = r.line.left(i) + '\n' + r.line.right(i)
r.line = r.line[..i] + '\n' + r.line[i..]
is_cut = true
i++
r.indent--
@ -77,8 +77,8 @@ pub fn run_repl() []string {
defer {
os.rm(file)
os.rm(temp_file)
os.rm(file.left(file.len - 2))
os.rm(temp_file.left(temp_file.len - 2))
os.rm(file[..file.len - 2])
os.rm(temp_file[..temp_file.len - 2])
}
mut r := Repl{}
vexe := os.args[0]

View File

@ -106,7 +106,7 @@ fn (s mut Scanner) ident_name() string {
break
}
}
name := s.text.substr(start, s.pos)
name := s.text[start..s.pos]
s.pos--
return name
}
@ -124,7 +124,7 @@ fn (s mut Scanner) ident_hex_number() string {
}
s.pos++
}
number := s.text.substr(start_pos, s.pos)
number := s.text[start_pos..s.pos]
s.pos--
return number
}
@ -145,7 +145,7 @@ fn (s mut Scanner) ident_oct_number() string {
}
s.pos++
}
number := s.text.substr(start_pos, s.pos)
number := s.text[start_pos..s.pos]
s.pos--
return number
}
@ -161,7 +161,7 @@ fn (s mut Scanner) ident_dec_number() string {
// e.g. 1..9
// we just return '1' and don't scan '..9'
if s.expect('..', s.pos) {
number := s.text.substr(start_pos, s.pos)
number := s.text[start_pos..s.pos]
s.pos--
return number
}
@ -200,7 +200,7 @@ fn (s mut Scanner) ident_dec_number() string {
}
}
number := s.text.substr(start_pos, s.pos)
number := s.text[start_pos..s.pos]
s.pos--
return number
}
@ -474,11 +474,11 @@ fn (s mut Scanner) scan() ScanRes {
s.ignore_line()
if nextc == `!` {
// treat shebang line (#!) as a comment
s.line_comment = s.text.substr(start + 1, s.pos).trim_space()
s.line_comment = s.text[start + 1..s.pos].trim_space()
s.fgenln('// shebang line "$s.line_comment"')
return s.scan()
}
hash := s.text.substr(start, s.pos)
hash := s.text[start..s.pos]
return scan_res(.hash, hash.trim_space())
}
`>` {
@ -577,7 +577,7 @@ fn (s mut Scanner) scan() ScanRes {
if nextc == `/` {
start := s.pos + 1
s.ignore_line()
s.line_comment = s.text.substr(start + 1, s.pos)
s.line_comment = s.text[start + 1..s.pos]
s.line_comment = s.line_comment.trim_space()
s.fgenln('// ${s.prev_tok.str()} "$s.line_comment"')
// Skip the comment (return the next token)
@ -608,7 +608,7 @@ fn (s mut Scanner) scan() ScanRes {
}
s.pos++
end := s.pos + 1
comm := s.text.substr(start, end)
comm := s.text[start..end]
s.fgenln(comm)
// Skip if not in fmt mode
return s.scan()
@ -706,7 +706,7 @@ fn (s mut Scanner) ident_string() string {
}
if start > s.pos{}
else {
lit = s.text.substr(start, end)
lit = s.text[start..end]
}
return lit
}
@ -732,7 +732,7 @@ fn (s mut Scanner) ident_char() string {
}
}
len--
c := s.text.substr(start + 1, s.pos)
c := s.text[start + 1..s.pos]
if len != 1 {
u := c.ustring()
if u.len != 1 {
@ -814,7 +814,7 @@ fn (s Scanner) line(n int) string {
nline_start := if n == 0 { 0 } else { s.line_ends[ n - 1 ] }
nline_end := s.line_ends[n]
if nline_start <= nline_end {
res = s.text.substr( nline_start, nline_end )
res = s.text[nline_start..nline_end]
}
}
return res.trim_right('\r\n').trim_left('\r\n')

View File

@ -13,7 +13,7 @@ fn (p mut Parser) struct_decl() {
// V can generate Objective C for integration with Cocoa
// `[objc_interface:ParentInterface]`
is_objc := p.attr.starts_with('objc_interface')
objc_parent := if is_objc { p.attr.right(15) } else { '' }
objc_parent := if is_objc { p.attr[15..] } else { '' }
// interface, union, struct
is_interface := p.tok == .key_interface
is_union := p.tok == .key_union
@ -288,7 +288,7 @@ fn (p mut Parser) struct_init(typ string) string {
// init map fields
if field_typ.starts_with('map_') {
p.gen_struct_field_init(sanitized_name)
p.gen_empty_map(field_typ.right(4))
p.gen_empty_map(field_typ[4..])
inited_fields << sanitized_name
if i != t.fields.len - 1 {
p.gen(',')

View File

@ -330,11 +330,11 @@ fn (table &Table) known_type(typ_ string) bool {
mut typ := typ_
// vararg
if typ.starts_with('...') && typ.len > 3 {
typ = typ.right(3)
typ = typ[3..]
}
// 'byte*' => look up 'byte', but don't mess up fns
if typ.ends_with('*') && !typ.contains(' ') {
typ = typ.left(typ.len - 1)
typ = typ[..typ.len - 1]
}
t := table.typesmap[typ]
return t.name.len > 0 && !t.is_placeholder
@ -560,7 +560,7 @@ fn (p &Parser) find_type(name string) Type {
fn (t &Table) find_type(name_ string) Type {
mut name := name_
if name.ends_with('*') && !name.contains(' ') {
name = name.left(name.len - 1)
name = name[..name.len - 1]
}
if !(name in t.typesmap) {
//println('ret Type')
@ -585,10 +585,10 @@ fn (p mut Parser) check_types2(got_, expected_ string, throw bool) bool {
// variadic
if expected.starts_with('...') {
expected = expected.right(3)
expected = expected[3..]
}
if got.starts_with('...') {
got = got.right(3)
got = got[3..]
}
// Allow ints to be used as floats
if got == 'int' && expected == 'f32' {
@ -906,7 +906,7 @@ fn (p &Parser) identify_typo(name string) string {
fn (table &Table) find_misspelled_fn(name string, p &Parser, min_match f32) string {
mut closest := f32(0)
mut closest_fn := ''
n1 := if name.starts_with('main__') { name.right(6) } else { name }
n1 := if name.starts_with('main__') { name[6..] } else { name }
for _, f in table.fns {
if n1.len - f.name.len > 2 || f.name.len - n1.len > 2 { continue }
if !(f.mod in ['', 'main', 'builtin']) {
@ -933,7 +933,7 @@ fn (table &Table) find_misspelled_fn(name string, p &Parser, min_match f32) stri
fn (table &Table) find_misspelled_imported_mod(name string, p &Parser, min_match f32) string {
mut closest := f32(0)
mut closest_mod := ''
n1 := if name.starts_with('main.') { name.right(5) } else { name }
n1 := if name.starts_with('main.') { name[5..] } else { name }
for alias, mod in p.import_table.imports {
if n1.len - alias.len > 2 || alias.len - n1.len > 2 { continue }
mod_alias := if alias == mod { alias } else { '$alias ($mod)' }

View File

@ -13,8 +13,8 @@ fn test_flag_parsing() {
mut base := rest
fl := if rest.starts_with('-') {
base = rest.right(2).trim_space()
rest.left(2)
base = rest[2..].trim_space()
rest[..2]
} else {
''
}
@ -28,8 +28,8 @@ fn test_flag_parsing() {
}
}
arg := if lowest != -1 {
rest = base.right(lowest).trim_space().trim(',')
base.left(lowest).trim_space().trim(',')
rest = base[lowest..].trim_space().trim(',')
base[..lowest].trim_space().trim(',')
} else {
rest = ''
base.trim_space()

View File

@ -80,7 +80,7 @@ pub fn new_options() RunnerOptions {
vexec := full_path_to_v()
mut files := []string
if os.args.len > 1 {
files = os.args.right(1)
files = os.args[1..]
} else {
files = os.walk_ext('.', '.repl')
}

View File

@ -39,7 +39,7 @@ pub fn test_v() {
return
}
args_string := args.right(1).join(' ')
args_string := args[1..].join(' ')
args_before := args_string.all_before('test ')
args_after := args_string.all_after('test ')

View File

@ -49,7 +49,7 @@ pub fn (c &AesCipher) encrypt(dst, src []byte) {
panic('crypto.aes: output not full block')
}
// if subtle.inexact_overlap(dst[:block_size], src[:block_size]) {
if subtle.inexact_overlap(dst.left(block_size), src.left(block_size)) {
if subtle.inexact_overlap(dst[..block_size], src[..block_size]) {
panic('crypto.aes: invalid buffer overlap')
}
// for now use generic version
@ -63,7 +63,7 @@ pub fn (c &AesCipher) decrypt(dst, src []byte) {
if dst.len < block_size {
panic('crypto.aes: output not full block')
}
if subtle.inexact_overlap(dst.left(block_size), src.left(block_size)) {
if subtle.inexact_overlap(dst[..block_size], src[..block_size]) {
panic('crypto.aes: invalid buffer overlap')
}
// for now use generic version

View File

@ -56,7 +56,7 @@ pub fn (x mut AesCbc) encrypt_blocks(dst mut []byte, src_ []byte) {
if dst.len < src.len {
panic('crypto.cipher: output smaller than input')
}
if subtle.inexact_overlap(dst.left(src.len), src) {
if subtle.inexact_overlap(dst[..src.len], src) {
panic('crypto.cipher: invalid buffer overlap')
}
@ -64,17 +64,17 @@ pub fn (x mut AesCbc) encrypt_blocks(dst mut []byte, src_ []byte) {
for src.len > 0 {
// Write the xor to dst, then encrypt in place.
cipher.xor_bytes(mut dst.left(x.block_size), src.left(x.block_size), iv)
x.b.encrypt(dst.left(x.block_size), dst.left(x.block_size))
cipher.xor_bytes(mut dst[..x.block_size], src[..x.block_size], iv)
x.b.encrypt(dst[..x.block_size], dst[..x.block_size])
// Move to the next block with this block as the next iv.
iv = dst.left(x.block_size)
iv = dst[..x.block_size]
if x.block_size >= src.len {
src = []byte
} else {
src = src.right(x.block_size)
src = src[x.block_size..]
}
*dst = dst.right(x.block_size)
*dst = dst[x.block_size..]
}
// Save the iv for the next crypt_blocks call.
@ -88,7 +88,7 @@ pub fn (x mut AesCbc) decrypt_blocks(dst mut []byte, src []byte) {
if dst.len < src.len {
panic('crypto.cipher: output smaller than input')
}
if subtle.inexact_overlap(dst.left(src.len), src) {
if subtle.inexact_overlap(dst[..src.len], src) {
panic('crypto.cipher: invalid buffer overlap')
}
if src.len == 0 {

View File

@ -14,8 +14,8 @@ fn test_crypto_aes() {
if ciphertext.len < aes.block_size {
panic('ciphertext too short')
}
iv := ciphertext.left(aes.block_size)
ciphertext = ciphertext.right(aes.block_size)
iv := ciphertext[..aes.block_size]
ciphertext = ciphertext[aes.block_size..]
// CBC mode always works in whole blocks.
if ciphertext.len%aes.block_size != 0 {
panic('ciphertext is not a multiple of the block size')

View File

@ -44,7 +44,7 @@ import (
// Encrypt one block from src into dst, using the expanded key xk.
fn encrypt_block_generic(xk []u32, dst, src []byte) {
_ = src[15] // early bounds check
mut s0 := binary.big_endian_u32(src.left(4))
mut s0 := binary.big_endian_u32(src[..4])
mut s1 := binary.big_endian_u32(src.slice(4, 8))
mut s2 := binary.big_endian_u32(src.slice(8, 12))
mut s3 := binary.big_endian_u32(src.slice(12, 16))
@ -87,7 +87,7 @@ fn encrypt_block_generic(xk []u32, dst, src []byte) {
s3 ^= xk[k+3]
_ = dst[15] // early bounds check
binary.big_endian_put_u32(mut dst.left(4), s0)
binary.big_endian_put_u32(mut dst[..4], s0)
binary.big_endian_put_u32(mut dst.slice(4, 8), s1)
binary.big_endian_put_u32(mut dst.slice(8, 12), s2)
binary.big_endian_put_u32(mut dst.slice(12, 16), s3)
@ -96,7 +96,7 @@ fn encrypt_block_generic(xk []u32, dst, src []byte) {
// Decrypt one block from src into dst, using the expanded key xk.
fn decrypt_block_generic(xk []u32, dst, src []byte) {
_ = src[15] // early bounds check
mut s0 := binary.big_endian_u32(src.left(4))
mut s0 := binary.big_endian_u32(src[..4])
mut s1 := binary.big_endian_u32(src.slice(4, 8))
mut s2 := binary.big_endian_u32(src.slice(8, 12))
mut s3 := binary.big_endian_u32(src.slice(12, 16))
@ -139,7 +139,7 @@ fn decrypt_block_generic(xk []u32, dst, src []byte) {
s3 ^= xk[k+3]
_ = dst[15] // early bounds check
binary.big_endian_put_u32(mut dst.left(4), s0)
binary.big_endian_put_u32(mut dst[..4], s0)
binary.big_endian_put_u32(mut dst.slice(4, 8), s1)
binary.big_endian_put_u32(mut dst.slice(8, 12), s2)
binary.big_endian_put_u32(mut dst.slice(12, 16), s3)
@ -166,7 +166,7 @@ fn expand_key_generic(key []byte, enc mut []u32, dec mut []u32) {
if 4*i >= key.len {
break
}
enc[i] = binary.big_endian_u32(key.right(4*i))
enc[i] = binary.big_endian_u32(key[4*i..])
}
for i < enc.len {

View File

@ -60,7 +60,7 @@ pub fn (d mut Digest) write(p_ []byte) ?int {
nn := p.len
d.len += u64(nn)
if d.nx > 0 {
n := copy(d.x.right(d.nx), p)
n := copy(d.x[d.nx..], p)
d.nx += n
if d.nx == block_size {
block(mut d, d.x)
@ -69,16 +69,16 @@ pub fn (d mut Digest) write(p_ []byte) ?int {
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len >= block_size {
n := p.len &~ (block_size - 1)
block(mut d, p.left(n))
block(mut d, p[..n])
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len > 0 {
@ -108,8 +108,8 @@ pub fn (d mut Digest) checksum() []byte {
mut tmp := [byte(0)].repeat(1 + 63 + 8)
tmp[0] = 0x80
pad := int((55 - int(d.len)) % u64(64)) // calculate number of padding bytes
binary.little_endian_put_u64(mut tmp.right(1+pad), d.len<<u64(3)) // append length in bits
d.write(tmp.left(1+pad+8))
binary.little_endian_put_u64(mut tmp[1+pad..], d.len<<u64(3)) // append length in bits
d.write(tmp[..1+pad+8])
// The previous write ensures that a whole number of
// blocks (i.e. a multiple of 64 bytes) have been hashed.
@ -120,9 +120,9 @@ pub fn (d mut Digest) checksum() []byte {
digest := [byte(0)].repeat(size)
binary.little_endian_put_u32(mut digest, d.s[0])
binary.little_endian_put_u32(mut digest.right(4), d.s[1])
binary.little_endian_put_u32(mut digest.right(8), d.s[2])
binary.little_endian_put_u32(mut digest.right(12), d.s[3])
binary.little_endian_put_u32(mut digest[4..], d.s[1])
binary.little_endian_put_u32(mut digest[8..], d.s[2])
binary.little_endian_put_u32(mut digest[12..], d.s[3])
return digest
}

View File

@ -21,8 +21,8 @@ fn block_generic(dig mut Digest, p []byte) {
mut d := dig.s[3]
for i := 0; i <= p.len-block_size; i += block_size {
mut q := p.right(i)
q = q.left(block_size)
mut q := p[i..]
q = q[..block_size]
// save current state
aa := a
bb := b
@ -30,22 +30,22 @@ fn block_generic(dig mut Digest, p []byte) {
dd := d
// load input block
x0 := binary.little_endian_u32(q.right(4*0x0))
x1 := binary.little_endian_u32(q.right(4*0x1))
x2 := binary.little_endian_u32(q.right(4*0x2))
x3 := binary.little_endian_u32(q.right(4*0x3))
x4 := binary.little_endian_u32(q.right(4*0x4))
x5 := binary.little_endian_u32(q.right(4*0x5))
x6 := binary.little_endian_u32(q.right(4*0x6))
x7 := binary.little_endian_u32(q.right(4*0x7))
x8 := binary.little_endian_u32(q.right(4*0x8))
x9 := binary.little_endian_u32(q.right(4*0x9))
xa := binary.little_endian_u32(q.right(4*0xa))
xb := binary.little_endian_u32(q.right(4*0xb))
xc := binary.little_endian_u32(q.right(4*0xc))
xd := binary.little_endian_u32(q.right(4*0xd))
xe := binary.little_endian_u32(q.right(4*0xe))
xf := binary.little_endian_u32(q.right(4*0xf))
x0 := binary.little_endian_u32(q[4*0x0..])
x1 := binary.little_endian_u32(q[4*0x1..])
x2 := binary.little_endian_u32(q[4*0x2..])
x3 := binary.little_endian_u32(q[4*0x3..])
x4 := binary.little_endian_u32(q[4*0x4..])
x5 := binary.little_endian_u32(q[4*0x5..])
x6 := binary.little_endian_u32(q[4*0x6..])
x7 := binary.little_endian_u32(q[4*0x7..])
x8 := binary.little_endian_u32(q[4*0x8..])
x9 := binary.little_endian_u32(q[4*0x9..])
xa := binary.little_endian_u32(q[4*0xa..])
xb := binary.little_endian_u32(q[4*0xb..])
xc := binary.little_endian_u32(q[4*0xc..])
xd := binary.little_endian_u32(q[4*0xd..])
xe := binary.little_endian_u32(q[4*0xe..])
xf := binary.little_endian_u32(q[4*0xf..])
// round 1
a = b + bits.rotate_left_32((((c^d)&b)^d)+a+x0+u32(0xd76aa478), 7)

View File

@ -63,13 +63,13 @@ pub fn (c mut Cipher) xor_key_stream(dst mut []byte, src []byte) {
if src.len == 0 {
return
}
if subtle.inexact_overlap(dst.left(src.len), src) {
if subtle.inexact_overlap(dst[..src.len], src) {
panic('crypto.rc4: invalid buffer overlap')
}
mut i := c.i
mut j := c.j
_ = dst[src.len-1]
*dst = dst.left(src.len) // eliminate bounds check from loop
*dst = dst[..src.len] // eliminate bounds check from loop
for k, v in src {
i += byte(1)
x := c.s[i]

View File

@ -64,7 +64,7 @@ pub fn (d mut Digest) write(p_ []byte) ?int {
d.len += u64(nn)
if d.nx > 0 {
n := copy(d.x.right(d.nx), p)
n := copy(d.x[d.nx..], p)
d.nx += n
if d.nx == chunk {
block(d, d.x)
@ -73,16 +73,16 @@ pub fn (d mut Digest) write(p_ []byte) ?int {
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len >= chunk {
n := p.len &~ (chunk - 1)
block(d, p.left(n))
block(d, p[..n])
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len > 0 {
@ -110,23 +110,23 @@ fn (d mut Digest) checksum() []byte {
tmp[0] = 0x80
if int(len)%64 < 56 {
d.write(tmp.left(56-int(len)%64))
d.write(tmp[..56-int(len)%64])
} else {
d.write(tmp.left(64+56-int(len)%64))
d.write(tmp[..64+56-int(len)%64])
}
// Length in bits.
len <<= 3
binary.big_endian_put_u64(mut tmp, len)
d.write(tmp.left(8))
d.write(tmp[..8])
mut digest := [byte(0)].repeat(size)
binary.big_endian_put_u32(mut digest, d.h[0])
binary.big_endian_put_u32(mut digest.right(4), d.h[1])
binary.big_endian_put_u32(mut digest.right(8), d.h[2])
binary.big_endian_put_u32(mut digest.right(12), d.h[3])
binary.big_endian_put_u32(mut digest.right(16), d.h[4])
binary.big_endian_put_u32(mut digest[4..], d.h[1])
binary.big_endian_put_u32(mut digest[8..], d.h[2])
binary.big_endian_put_u32(mut digest[12..], d.h[3])
binary.big_endian_put_u32(mut digest[16..], d.h[4])
return digest
}

View File

@ -111,7 +111,7 @@ fn block_generic(dig mut Digest, p_ []byte) {
if chunk >= p.len {
p = []byte
} else {
p = p.right(chunk)
p = p[chunk..]
}
}

View File

@ -97,7 +97,7 @@ fn (d mut Digest) write(p_ []byte) ?int {
nn := p.len
d.len += u64(nn)
if d.nx > 0 {
n := copy(d.x.right(d.nx), p)
n := copy(d.x[d.nx..], p)
d.nx += n
if d.nx == chunk {
block(mut d, d.x)
@ -106,16 +106,16 @@ fn (d mut Digest) write(p_ []byte) ?int {
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len >= chunk {
n := p.len &~ (chunk - 1)
block(mut d, p.left(n))
block(mut d, p[..n])
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len > 0 {
@ -130,7 +130,7 @@ fn (d &Digest) sum(b_in []byte) []byte {
hash := d0.checksum()
mut b_out := b_in.clone()
if d0.is224 {
for b in hash.left(size224) {
for b in hash[..size224] {
b_out << b
}
} else {
@ -147,15 +147,15 @@ fn (d mut Digest) checksum() []byte {
mut tmp := [byte(0)].repeat(64)
tmp[0] = 0x80
if int(len)%64 < 56 {
d.write(tmp.left(56-int(len)%64))
d.write(tmp[..56-int(len)%64])
} else {
d.write(tmp.left(64+56-int(len)%64))
d.write(tmp[..64+56-int(len)%64])
}
// Length in bits.
len <<= u64(3)
binary.big_endian_put_u64(mut tmp, len)
d.write(tmp.left(8))
d.write(tmp[..8])
if d.nx != 0 {
panic('d.nx != 0')
@ -164,14 +164,14 @@ fn (d mut Digest) checksum() []byte {
digest := [byte(0)].repeat(size)
binary.big_endian_put_u32(mut digest, d.h[0])
binary.big_endian_put_u32(mut digest.right(4), d.h[1])
binary.big_endian_put_u32(mut digest.right(8), d.h[2])
binary.big_endian_put_u32(mut digest.right(12), d.h[3])
binary.big_endian_put_u32(mut digest.right(16), d.h[4])
binary.big_endian_put_u32(mut digest.right(20), d.h[5])
binary.big_endian_put_u32(mut digest.right(24), d.h[6])
binary.big_endian_put_u32(mut digest[4..], d.h[1])
binary.big_endian_put_u32(mut digest[8..], d.h[2])
binary.big_endian_put_u32(mut digest[12..], d.h[3])
binary.big_endian_put_u32(mut digest[16..], d.h[4])
binary.big_endian_put_u32(mut digest[20..], d.h[5])
binary.big_endian_put_u32(mut digest[24..], d.h[6])
if !d.is224 {
binary.big_endian_put_u32(mut digest.right(28), d.h[7])
binary.big_endian_put_u32(mut digest[28..], d.h[7])
}
return digest
@ -195,7 +195,7 @@ pub fn sum224(data []byte) []byte {
d.write(data)
sum := d.checksum()
mut sum224 := [byte(0)].repeat(size224)
copy(sum224, sum.left(size224))
copy(sum224, sum[..size224])
return sum224
}

View File

@ -144,7 +144,7 @@ fn block_generic(dig mut Digest, p_ []byte) {
if chunk >= p.len {
p = []byte
} else {
p = p.right(chunk)
p = p[chunk..]
}
}

View File

@ -152,7 +152,7 @@ fn (d mut Digest) write(p_ []byte) ?int {
nn := p.len
d.len += u64(nn)
if d.nx > 0 {
n := copy(d.x.right(d.nx), p)
n := copy(d.x[d.nx..], p)
d.nx += n
if d.nx == Chunk {
block(mut d, d.x)
@ -161,16 +161,16 @@ fn (d mut Digest) write(p_ []byte) ?int {
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len >= Chunk {
n := p.len &~ (Chunk - 1)
block(mut d, p.left(n))
block(mut d, p[..n])
if n >= p.len {
p = []byte
} else {
p = p.right(n)
p = p[n..]
}
}
if p.len > 0 {
@ -186,15 +186,15 @@ fn (d mut Digest) sum(b_in []byte) []byte {
mut b_out := b_in.clone()
switch d0.function {
case crypto.Hash.sha384:
for b in hash.left(size384) {
for b in hash[..size384] {
b_out << b
}
case crypto.Hash.sha512_224:
for b in hash.left(size224) {
for b in hash[..size224] {
b_out << b
}
case crypto.Hash.sha512_256:
for b in hash.left(size256) {
for b in hash[..size256] {
b_out << b
}
default:
@ -212,17 +212,17 @@ fn (d mut Digest) checksum() []byte {
tmp[0] = 0x80
if int(len)%128 < 112 {
d.write(tmp.left(112-int(len)%128))
d.write(tmp[..112-int(len)%128])
} else {
d.write(tmp.left(128+112-int(len)%128))
d.write(tmp[..128+112-int(len)%128])
}
// Length in bits.
len <<= u64(3)
binary.big_endian_put_u64(mut tmp, u64(0)) // upper 64 bits are always zero, because len variable has type u64
binary.big_endian_put_u64(mut tmp.right(8), len)
d.write(tmp.left(16))
binary.big_endian_put_u64(mut tmp[8..], len)
d.write(tmp[..16])
if d.nx != 0 {
panic('d.nx != 0')
@ -231,14 +231,14 @@ fn (d mut Digest) checksum() []byte {
mut digest := [byte(0)].repeat(size)
binary.big_endian_put_u64(mut digest, d.h[0])
binary.big_endian_put_u64(mut digest.right(8), d.h[1])
binary.big_endian_put_u64(mut digest.right(16), d.h[2])
binary.big_endian_put_u64(mut digest.right(24), d.h[3])
binary.big_endian_put_u64(mut digest.right(32), d.h[4])
binary.big_endian_put_u64(mut digest.right(40), d.h[5])
binary.big_endian_put_u64(mut digest[8..], d.h[1])
binary.big_endian_put_u64(mut digest[16..], d.h[2])
binary.big_endian_put_u64(mut digest[24..], d.h[3])
binary.big_endian_put_u64(mut digest[32..], d.h[4])
binary.big_endian_put_u64(mut digest[40..], d.h[5])
if d.function != crypto.Hash.sha384 {
binary.big_endian_put_u64(mut digest.right(48), d.h[6])
binary.big_endian_put_u64(mut digest.right(56), d.h[7])
binary.big_endian_put_u64(mut digest[48..], d.h[6])
binary.big_endian_put_u64(mut digest[56..], d.h[7])
}
return digest
@ -257,7 +257,7 @@ pub fn sum384(data []byte) []byte {
d.write(data)
sum := d.checksum()
mut sum384 := [byte(0)].repeat(size384)
copy(sum384, sum.left(size384))
copy(sum384, sum[..size384])
return sum384
}
@ -267,7 +267,7 @@ pub fn sum512_224(data []byte) []byte {
d.write(data)
sum := d.checksum()
mut sum224 := [byte(0)].repeat(size224)
copy(sum224, sum.left(size224))
copy(sum224, sum[..size224])
return sum224
}
@ -277,7 +277,7 @@ pub fn sum512_256(data []byte) []byte {
d.write(data)
sum := d.checksum()
mut sum256 := [byte(0)].repeat(size256)
copy(sum256, sum.left(size256))
copy(sum256, sum[..size256])
return sum256
}

View File

@ -160,7 +160,7 @@ fn block_generic(dig mut Digest, p_ []byte) {
if Chunk >= p.len {
p = []byte
} else {
p = p.right(Chunk)
p = p[Chunk..]
}
}

View File

@ -80,11 +80,11 @@ fn (r mut Reader) read_line() ?string {
}
}
}
mut line := r.data.substr(r.row_pos, i)
mut line := r.data[r.row_pos..i]
r.row_pos = i+1
// normalize win line endings (remove extra \r)
if !r.is_mac_pre_osx_le && (line.len >= 1 && line[line.len-1] == `\r`) {
line = line.left(line.len-1)
line = line[..line.len-1]
}
return line
}
@ -118,28 +118,28 @@ fn (r mut Reader) read_record() ?[]string {
// last
break
}
fields << line.left(i)
line = line.right(i+1)
fields << line[..i]
line = line[i+1..]
continue
}
// quoted
else {
line = line.right(1)
line = line[1..]
i = line.index('"')
if i != -1 {
if i+1 == line.len {
// last record
fields << line.left(i)
fields << line[..i]
break
}
next := line[i+1]
if next == r.delimiter {
fields << line.left(i)
line = line.right(i)
fields << line[..i]
line = line[i..]
continue
}
}
line = line.right(1)
line = line[1..]
}
if i <= -1 && fields.len == 0 {
return err_invalid_delim

View File

@ -46,8 +46,8 @@ pub fn (w mut Writer) write(record []string) ?bool {
i = field.len
}
w.sb.write(field.left(i))
field = field.right(i)
w.sb.write(field[..i])
field = field[i..]
if field.len > 0 {
z := field[0]
@ -57,7 +57,7 @@ pub fn (w mut Writer) write(record []string) ?bool {
case `\r` || `\n`:
w.sb.write(le)
}
field = field.right(1)
field = field[1..]
}
}
w.sb.write('"')

View File

@ -133,8 +133,8 @@ fn (fs mut FlagParser) parse_value(n string, ab byte) ?string {
} else {
panic('Missing argument for \'$n\'')
}
} else if a.len > c.len && c == a.left(c.len) && a.substr(c.len, c.len+1) == '=' {
val := a.right(c.len+1)
} else if a.len > c.len && c == a[..c.len] && a[c.len..c.len+1] == '=' {
val := a[c.len+1..]
fs.args.delete(i)
return val
}
@ -162,8 +162,8 @@ fn (fs mut FlagParser) parse_bool_value(n string, ab byte) ?string {
fs.args.delete(i)
return val
}
} else if a.len > c.len && c == a.left(c.len) && a.substr(c.len, c.len+1) == '=' {
val := a.right(c.len+1)
} else if a.len > c.len && c == a[..c.len] && a[c.len..c.len+1] == '=' {
val := a[c.len+1..]
fs.args.delete(i)
return val
}
@ -349,7 +349,7 @@ pub fn (fs FlagParser) usage() string {
space := if flag_desc.len > SPACE.len-2 {
'\n$SPACE'
} else {
SPACE.right(flag_desc.len)
SPACE[flag_desc.len..]
}
abbr_desc := if f.abbr == `\0` { '' } else { ' -${tos(f.abbr, 1)}\n' }
use += '${abbr_desc}${flag_desc}${space}${f.usage}\n'
@ -368,8 +368,8 @@ pub fn (fs FlagParser) usage() string {
// error handling is up to the application developer
pub fn (fs FlagParser) finalize() ?[]string {
for a in fs.args {
if a.left(2) == '--' {
return error('Unknown argument \'${a.right(2)}\'')
if a.len >= 2 && a[..2] == '--' {
return error('Unknown argument \'${a[2..]}\'')
}
}
if fs.args.len < fs.min_free_args && fs.min_free_args > 0 {

View File

@ -42,7 +42,7 @@ fn (s mut ChunkScanner) skip_crlf() {
fn (s mut ChunkScanner) read_chunk(chunksize int) string {
startpos := s.pos
s.pos += chunksize
return s.text.substr(startpos, s.pos)
return s.text[startpos..s.pos]
}
pub fn decode(text string) string {

View File

@ -188,10 +188,10 @@ fn parse_response(resp string) Response {
if nl_pos == -1 {
break
}
h := resp.substr(old_pos + 1, nl_pos)
h := resp[old_pos + 1..nl_pos]
// End of headers
if h.len <= 1 {
text = resp.right(nl_pos + 1)
text = resp[nl_pos + 1..]
break
}
i++
@ -202,8 +202,8 @@ fn parse_response(resp string) Response {
//if h.contains('Content-Type') {
//continue
//}
key := h.left(pos)
val := h.right(pos + 2)
key := h[..pos]
val := h[pos + 2..]
headers[key] = val.trim_space()
}

View File

@ -161,9 +161,9 @@ fn unescape(s_ string, mode EncodingMode) ?string {
}
n++
if i+2 >= s.len || !ishex(s[i+1]) || !ishex(s[i+2]) {
s = s.right(i)
s = s[i..]
if s.len > 3 {
s = s.left(3)
s = s[..3]
}
return error(error_msg(err_msg_escape, s))
}
@ -173,8 +173,8 @@ fn unescape(s_ string, mode EncodingMode) ?string {
// But https://tools.ietf.org/html/rfc6874#section-2
// introduces %25 being allowed to escape a percent sign
// in IPv6 scoped-address literals. Yay.
if mode == .encode_host && unhex(s[i+1]) < 8 && s.substr(i, i+3) != '%25' {
return error(error_msg(err_msg_escape, s.substr(i, i+3)))
if mode == .encode_host && unhex(s[i+1]) < 8 && s[i..i+3] != '%25' {
return error(error_msg(err_msg_escape, s[i..i+3]))
}
if mode == .encode_zone {
// RFC 6874 says basically 'anything goes' for zone identifiers
@ -185,19 +185,18 @@ fn unescape(s_ string, mode EncodingMode) ?string {
// to introduce bytes you couldn't just write directly.
// But Windows puts spaces here! Yay.
v := byte(unhex(s[i+1])<<byte(4) | unhex(s[i+2]))
if s.substr(i, i+3) != '%25' && v != ` ` && should_escape(v, .encode_host) {
error(error_msg(err_msg_escape, s.substr(i, i+3)))
if s[i..i+3] != '%25' && v != ` ` && should_escape(v, .encode_host) {
error(error_msg(err_msg_escape, s[i..i+3]))
}
}
i += 3
}
`+`{
has_plus = mode == .encode_query_component
i++
} else {
if (mode == .encode_host || mode == .encode_zone) && s[i] < 0x80 && should_escape(s[i], mode) {
error(error_msg('invalid character in host name', s.substr(i, i+1)))
error(error_msg('invalid character in host name', s[i..i+1]))
}
i++
}
@ -266,7 +265,7 @@ fn escape(s string, mode EncodingMode) string {
required := s.len + 2*hex_count
if required <= buf.len {
t = buf.left(required)
t = buf[..required]
} else {
t = [byte(0)].repeat(required)
}
@ -400,7 +399,7 @@ fn split_by_scheme(rawurl string) ?[]string {
if i == 0 {
return error(error_msg('missing protocol scheme', ''))
}
return [rawurl.left(i), rawurl.right(i+1)]
return [rawurl[..i], rawurl[i+1..]]
}
else {
// we have encountered an invalid character,
@ -427,9 +426,9 @@ fn split(s string, sep byte, cutc bool) (string, string) {
return s, ''
}
if cutc {
return s.left(i), s.right(i+1)
return s[..i], s[i+1..]
}
return s.left(i), s.right(i)
return s[..i], s[i..]
}
// parse parses rawurl into a URL structure.
@ -492,9 +491,9 @@ fn parse_url(rawurl string, via_request bool) ?URL {
url.scheme = url.scheme.to_lower()
// if rest.ends_with('?') && strings.count(rest, '?') == 1 {
if rest.ends_with('?') && !rest.left(1).contains('?') {
if rest.ends_with('?') && !rest[..1].contains('?') {
url.force_query = true
rest = rest.left(rest.len-1)
rest = rest[..rest.len-1]
} else {
r, raw_query := split(rest, `?`, true)
rest = r
@ -526,7 +525,7 @@ fn parse_url(rawurl string, via_request bool) ?URL {
}
if ((url.scheme != '' || !via_request) && !rest.starts_with('///')) && rest.starts_with('//') {
authority, r := split(rest.right(2), `/`, false)
authority, r := split(rest[2..], `/`, false)
rest = r
a := parse_authority(authority) or {
return error(err)
@ -559,7 +558,7 @@ fn parse_authority(authority string) ?ParseAuthorityRes {
}
host = h
} else {
h := parse_host(authority.right(i+1)) or {
h := parse_host(authority[i+1..]) or {
return error(err)
}
host = h
@ -567,7 +566,7 @@ fn parse_authority(authority string) ?ParseAuthorityRes {
if i < 0 {
return ParseAuthorityRes{host: host}
}
mut userinfo := authority.left(i)
mut userinfo := authority[..i]
if !valid_userinfo(userinfo) {
return error(error_msg('invalid userinfo', ''))
}
@ -605,7 +604,7 @@ fn parse_host(host string) ?string {
if i < 0 {
return error(error_msg('missing \']\' in host', ''))
}
mut colon_port := host.right(i+1)
mut colon_port := host[i+1..]
if !valid_optional_port(colon_port) {
return error(error_msg('invalid port $colon_port after host ', ''))
}
@ -616,22 +615,22 @@ fn parse_host(host string) ?string {
// can only %-encode non-ASCII bytes.
// We do impose some restrictions on the zone, to avoid stupidity
// like newlines.
zone := host.left(i).index('%25')
zone := host[..i].index('%25')
if zone >= 0 {
host1 := unescape(host.left(zone), .encode_host) or {
host1 := unescape(host[..zone], .encode_host) or {
return err
}
host2 := unescape(host.substr(zone, i), .encode_zone) or {
host2 := unescape(host[zone..i], .encode_zone) or {
return err
}
host3 := unescape(host.right(i), .encode_host) or {
host3 := unescape(host[i..], .encode_host) or {
return err
}
return host1 + host2 + host3
} else {
i = host.last_index(':')
if i != -1 {
colon_port = host.right(i)
colon_port = host[i..]
if !valid_optional_port(colon_port) {
return error(error_msg('invalid port $colon_port after host ', ''))
}
@ -728,7 +727,7 @@ fn valid_optional_port(port string) bool {
if port[0] != `:` {
return false
}
for b in port.right(1) {
for b in port[1..] {
if b < `0` || b > `9` {
return false
}
@ -790,7 +789,7 @@ pub fn (u &URL) str() string {
// preceded by a dot-segment (e.g., './this:that') to make a relative-
// path reference.
i := path.index_byte(`:`)
if i > -1 && path.left(i).index_byte(`/`) == -1 {
if i > -1 && path[..i].index_byte(`/`) == -1 {
buf.write('./')
}
}
@ -845,8 +844,8 @@ fn parse_query_values(m mut Values, query string) ?bool {
mut key := q
mut i := key.index_any('&;')
if i >= 0 {
q = key.right(i+1)
key = key.left(i)
q = key[i+1..]
key = key[..i]
} else {
q = ''
}
@ -856,8 +855,8 @@ fn parse_query_values(m mut Values, query string) ?bool {
mut value := ''
i = key.index('=')
if i >= 0 {
value = key.right(i+1)
key = key.left(i)
value = key[i+1..]
key = key[..i]
}
k := query_unescape(key) or {
had_error = true
@ -913,7 +912,7 @@ fn resolve_path(base, ref string) string {
full = base
} else if ref[0] != `/` {
i := base.last_index('/')
full = base.left(i+1) + ref
full = base[..i+1] + ref
} else {
full = ref
}
@ -929,7 +928,7 @@ fn resolve_path(base, ref string) string {
}
'..' {
if dst.len > 0 {
dst = dst.left(dst.len-1)
dst = dst[..dst.len-1]
}
} else {
dst << elem
@ -1049,13 +1048,13 @@ fn split_host_port(hostport string) (string, string) {
mut port := ''
colon := host.last_index_byte(`:`)
if colon != -1 && valid_optional_port(host.right(colon)) {
port = host.right(colon+1)
host = host.left(colon)
if colon != -1 && valid_optional_port(host[colon..]) {
port = host[colon+1..]
host = host[..colon]
}
if host.starts_with('[') && host.ends_with(']') {
host = host.substr(1, host.len-1)
host = host[1..host.len-1]
}
return host, port

View File

@ -495,7 +495,7 @@ pub fn ext(path string) string {
if pos == -1 {
return ''
}
return path.right(pos)
return path[pos..]
}
@ -508,7 +508,7 @@ pub fn dir(path string) string {
if pos == -1 {
return '.'
}
return path.left(pos)
return path[..pos]
}
fn path_sans_ext(path string) string {
@ -516,7 +516,7 @@ fn path_sans_ext(path string) string {
if pos == -1 {
return path
}
return path.left(pos)
return path[..pos]
}
@ -525,7 +525,7 @@ pub fn basedir(path string) string {
if pos == -1 {
return path
}
return path.left(pos + 1)
return path[..pos + 1]
}
pub fn filename(path string) string {

View File

@ -141,10 +141,10 @@ pub fn parse_int(_s string, base int, _bit_size int) i64 {
// Pick off leading sign.
mut neg := false
if s[0] == `+` {
s = s.right(1)
s = s[1..]
} else if s[0] == `-` {
neg = true
s = s.right(1)
s = s[1..]
}
// Convert unsigned and check range.

View File

@ -44,13 +44,13 @@ pub fn dice_coefficient(s1, s2 string) f32 {
b := if a == s1 { s2 } else { s1 }
mut first_bigrams := map[string]int
for i := 0; i < a.len-1; i++ {
bigram := a.substr(i, i+2)
bigram := a[i..i+2]
q := if bigram in first_bigrams { first_bigrams[bigram]+1 } else { 1 }
first_bigrams[bigram] = q
}
mut intersection_size := 0
for i := 0; i < b.len-1; i++ {
bigram := b.substr(i, i+2)
bigram := b[i..i+2]
count := if bigram in first_bigrams { first_bigrams[bigram] } else { 0 }
if count > 0 {
first_bigrams[bigram] = count - 1

View File

@ -185,7 +185,7 @@ pub fn (t Time) format() string {
pub fn (t Time) smonth() string {
i := t.month - 1
return months_string.substr(i * 3, (i + 1) * 3)
return months_string[i * 3..(i + 1) * 3]
}
// 21:04
@ -287,13 +287,13 @@ pub fn parse(s string) Time {
println('bad time format')
return now()
}
symd := s.left(pos)
symd := s[..pos]
ymd := symd.split('-')
if ymd.len != 3 {
println('bad time format')
return now()
}
shms := s.right(pos)
shms := s[pos..]
hms := shms.split(':')
hour := hms[0]
minute := hms[1]
@ -382,7 +382,7 @@ pub fn (t Time) day_of_week() int {
// weekday_str() returns the current day in string (upto 3 characters)
pub fn (t Time) weekday_str() string {
i := t.day_of_week() - 1
return days_string.substr(i * 3, (i + 1) * 3)
return days_string[i * 3..(i + 1) * 3]
}
struct C.timeval {

View File

@ -47,7 +47,7 @@ _ = header
if line.contains('@if ') {
s.writeln(STR_END)
pos := line.index('@if')
s.writeln('if ' + line.right(pos + 4) + '{')
s.writeln('if ' + line[pos + 4..] + '{')
s.writeln(STR_START)
}
else if line.contains('@end') {
@ -63,7 +63,7 @@ _ = header
else if line.contains('@for') {
s.writeln(STR_END)
pos := line.index('@for')
s.writeln('for ' + line.right(pos + 4) + '{')
s.writeln('for ' + line[pos + 4..] + '{')
s.writeln(STR_START)
}
else if !in_css && line.contains('.') && line.ends_with('{') {

View File

@ -116,7 +116,7 @@ pub fn run<T>(app T, port int) {
conn.close()
return
}
mut action := vals[1].right(1).all_before('/')
mut action := vals[1][1..].all_before('/')
if action.contains('?') {
action = action.all_before('?')
}
@ -177,7 +177,7 @@ fn (ctx mut Context) parse_form(s string) {
}
pos := s.index('\r\n\r\n')
if pos > -1 {
mut str_form := s.substr(pos, s.len)
mut str_form := s[pos..s.len]
str_form = str_form.replace('+', ' ')
words := str_form.split('&')
for word in words {
@ -208,9 +208,9 @@ fn (ctx mut Context) scan_static_directory(directory_path, mount_path string) {
for i > 0 {
i--
if flag {
ext = file.substr(i, i + 1) + ext
ext = file[i..i + 1] + ext
}
if file.substr(i, i + 1) == '.' {
if file[i..i + 1] == '.' {
flag = false
}
}