From 4d1307f29bcc0605bb8f3463015a5b81c1ab1c8a Mon Sep 17 00:00:00 2001 From: ChAoS_UnItY <43753315+ChAoSUnItY@users.noreply.github.com> Date: Fri, 15 Oct 2021 08:57:49 +0800 Subject: [PATCH] all: index accessor in array init expression (#12181) --- doc/docs.md | 8 ++++ vlib/v/ast/ast.v | 1 + vlib/v/gen/c/array.v | 74 +++++++++++++++++++++++++++++++ vlib/v/gen/js/js.v | 6 +-- vlib/v/parser/containers.v | 34 ++++++++++++++ vlib/v/tests/array_with_it_test.v | 5 +++ 6 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/array_with_it_test.v diff --git a/doc/docs.md b/doc/docs.md index 6b173e78bd..ca3df8fd54 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -692,6 +692,14 @@ arrays there is a second initialization syntax: ```v mut a := []int{len: 10000, cap: 30000, init: 3} ``` + +You can initialize the array by accessing the it variable as shown here: + +```v +mut square := []int{len: 6, init: it * it} +// square == [0, 1, 4, 9, 16, 25] +``` + This creates an array of 10000 `int` elements that are all initialized with `3`. Memory space is reserved for 30000 elements. The parameters `len`, `cap` and `init` are optional; `len` defaults to `0` and `init` to the default initialization of the element type (`0` diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 20f85b4a83..0e4dd49dea 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -1136,6 +1136,7 @@ pub: has_len bool has_cap bool has_default bool + has_it bool // true if temp variable it is used pub mut: expr_types []Type // [Dog, Cat] // also used for interface_types elem_type Type // element type diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index c148e03d05..9ad3a201e8 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -51,6 +51,80 @@ fn (mut g Gen) array_init(node ast.ArrayInit) { noscan := g.check_noscan(elem_type.typ) if node.exprs.len == 0 { is_default_array := elem_type.unaliased_sym.kind == .array && node.has_default + if node.has_it { // []int{len: 6, init: it * it} when variable it is used in init expression + g.inside_lambda = true + tmp := g.new_tmp_var() + mut s := g.go_before_stmt(0) + s_ends_with_ln := s.ends_with('\n') + s = s.trim_space() + ret_typ := g.typ(node.typ) + elem_typ := g.typ(node.elem_type) + g.empty_line = true + g.write('$ret_typ $tmp =') + if is_default_array { + g.write('__new_array_with_array_default${noscan}(') + } else { + g.write('__new_array_with_default${noscan}(') + } + if node.has_len { + g.expr(node.len_expr) + g.write(', ') + } else { + g.write('0, ') + } + if node.has_cap { + g.expr(node.cap_expr) + g.write(', ') + } else { + g.write('0, ') + } + if elem_type.unaliased_sym.kind == .function { + g.write('sizeof(voidptr), ') + } else { + g.write('sizeof($elem_styp), ') + } + if is_default_array { + g.write('($elem_styp[]){') + g.expr(node.default_expr) + g.write('}[0])') + } else if node.has_len && node.elem_type == ast.string_type { + g.write('&($elem_styp[]){') + g.write('_SLIT("")') + g.write('})') + } else if node.has_len && elem_type.unaliased_sym.kind in [.array, .map] { + g.write('(voidptr)&($elem_styp[]){') + g.write(g.type_default(node.elem_type)) + g.write('}[0])') + } else { + g.write('0)') + } + if g.is_shared { + g.write('}, sizeof($shared_styp))') + } else if is_amp { + g.write(')') + } + g.writeln(';') + g.writeln('{') + g.indent++ + g.writeln('$elem_typ* pelem = ($elem_typ*)${tmp}.data;') + g.writeln('for(int it=0; it<${tmp}.len; it++, pelem++) {') + g.indent++ + g.write('*pelem = ') + g.expr(node.default_expr) + g.writeln(';') + g.indent-- + g.writeln('}') + g.indent-- + g.writeln('}') + if s_ends_with_ln { + g.writeln(s) + } else { + g.write(s) + } + g.write(tmp) + g.inside_lambda = false + return + } if is_default_array { g.write('__new_array_with_array_default${noscan}(') } else { diff --git a/vlib/v/gen/js/js.v b/vlib/v/gen/js/js.v index a625ceff53..fbc39bde16 100644 --- a/vlib/v/gen/js/js.v +++ b/vlib/v/gen/js/js.v @@ -1812,13 +1812,11 @@ fn (mut g JsGen) gen_array_init_expr(it ast.ArrayInit) { if it.has_len { t1 := g.new_tmp_var() - t2 := g.new_tmp_var() g.writeln('(function(length) {') g.inc_indent() g.writeln('const $t1 = [];') - g.write('for (let $t2 = 0; $t2 < length') - - g.writeln('; $t2++) {') + g.write('for (let it = 0; it < length') + g.writeln('; it++) {') g.inc_indent() g.write('${t1}.push(') if it.has_default { diff --git a/vlib/v/parser/containers.v b/vlib/v/parser/containers.v index 1b22ca854f..8c64afb0cb 100644 --- a/vlib/v/parser/containers.v +++ b/vlib/v/parser/containers.v @@ -20,6 +20,7 @@ fn (mut p Parser) array_init() ast.ArrayInit { mut has_val := false mut has_type := false mut has_default := false + mut has_it := false mut default_expr := ast.empty_expr() if p.tok.kind == .rsbr { last_pos = p.tok.position() @@ -79,8 +80,19 @@ fn (mut p Parser) array_init() ast.ArrayInit { return ast.ArrayInit{} } p.check(.colon) + p.open_scope() has_default = true + p.scope_register_it_as_index() default_expr = p.expr(0) + has_it = if var := p.scope.find_var('it') { + mut variable := var + is_used := variable.is_used + variable.is_used = true + is_used + } else { + false + } + p.close_scope() } last_pos = p.tok.position() p.check(.rcbr) @@ -127,8 +139,19 @@ fn (mut p Parser) array_init() ast.ArrayInit { cap_expr = p.expr(0) } 'init' { + p.open_scope() has_default = true + p.scope_register_it_as_index() default_expr = p.expr(0) + has_it = if var := p.scope.find_var('it') { + mut variable := var + is_used := variable.is_used + variable.is_used = true + is_used + } else { + false + } + p.close_scope() } else { p.error('wrong field `$key`, expecting `len`, `cap`, or `init`') @@ -157,6 +180,7 @@ fn (mut p Parser) array_init() ast.ArrayInit { len_expr: len_expr has_cap: has_cap has_default: has_default + has_it: has_it cap_expr: cap_expr default_expr: default_expr } @@ -188,3 +212,13 @@ fn (mut p Parser) map_init() ast.MapInit { pre_cmnts: pre_cmnts } } + +fn (mut p Parser) scope_register_it_as_index() { + p.scope.objects['it'] = ast.Var{ // override it variable if it already exist, else create it variable + name: 'it' + pos: p.tok.position() + typ: ast.int_type + is_mut: false + is_used: false + } +} diff --git a/vlib/v/tests/array_with_it_test.v b/vlib/v/tests/array_with_it_test.v new file mode 100644 index 0000000000..758f1f932b --- /dev/null +++ b/vlib/v/tests/array_with_it_test.v @@ -0,0 +1,5 @@ +fn test_array_with_it() { + assert [0, 1, 4, 9, 16, 25] == []int{len: 6, init: it * it} + assert [1, 2, 3, 4, 5] == []int{len: 5, init: it + 1} + assert [5, 4, 3, 2, 1] == []int{len: 5, init: 5 - it} +}