diff --git a/cmd/tools/vtest-fixed.v b/cmd/tools/vtest-fixed.v index cace4867d0..77f468313b 100644 --- a/cmd/tools/vtest-fixed.v +++ b/cmd/tools/vtest-fixed.v @@ -13,7 +13,6 @@ const ( 'vlib/net/http/http_test.v', 'vlib/regex/regex_test.v', 'vlib/v/tests/enum_bitfield_test.v', - 'vlib/v/tests/fixed_array_test.v', 'vlib/v/tests/num_lit_call_method_test.v', 'vlib/v/tests/pointers_test.v', 'vlib/v/tests/type_test.v', diff --git a/vlib/encoding/base64/base64.v b/vlib/encoding/base64/base64.v index d28d4f81d1..2503c5a7a7 100644 --- a/vlib/encoding/base64/base64.v +++ b/vlib/encoding/base64/base64.v @@ -11,7 +11,7 @@ const ( 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 63, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, 49, 50, 51]!! + 47, 48, 49, 50, 51] ending_table = [0, 2, 1] enc_table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' diff --git a/vlib/glm/glm.v b/vlib/glm/glm.v index 86cab45c78..002ca21eaa 100644 --- a/vlib/glm/glm.v +++ b/vlib/glm/glm.v @@ -266,7 +266,7 @@ pub fn identity3() []f32 { 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, - ] ! + ] return res } diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 231872b0a6..c0bb87c8ad 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -635,6 +635,7 @@ pub: pos token.Position exprs []Expr is_fixed bool + has_val bool mod string mut: elem_type table.Type diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 438091ca3f..f7c3697168 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -998,8 +998,13 @@ pub fn (mut c Checker) array_init(array_init mut ast.ArrayInit) table.Type { c.error('expected array element with type `$elem_type_sym.name`', array_init.pos) } } - idx := c.table.find_or_register_array(elem_type, 1) - array_init.typ = table.new_type(idx) + if array_init.is_fixed { + idx := c.table.find_or_register_array_fixed(elem_type, array_init.exprs.len, 1) + array_init.typ = table.new_type(idx) + } else { + idx := c.table.find_or_register_array(elem_type, 1) + array_init.typ = table.new_type(idx) + } array_init.elem_type = elem_type } else if array_init.is_fixed && array_init.exprs.len == 1 && array_init.elem_type != table.void_type { // [50]byte diff --git a/vlib/v/checker/tests/inout/cannot_assign_array.out b/vlib/v/checker/tests/inout/cannot_assign_array.out index b75c16adf3..76ac8d3327 100644 --- a/vlib/v/checker/tests/inout/cannot_assign_array.out +++ b/vlib/v/checker/tests/inout/cannot_assign_array.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/inout/cannot_assign_array.v:9:11: error: cannot assign `array_f64` to variable `ctx.vb` of type `string` +vlib/v/checker/tests/inout/cannot_assign_array.v:9:11: error: cannot assign `array_fixed_f64_8` to variable `ctx.vb` of type `string` 7| mut ctx := Context{} 8| x := 2.32 9| ctx.vb = [1.1, x, 3.3, 4.4, 5.0, 6.0, 7.0, 8.9]!! diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 0a70921964..8145429d24 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -845,8 +845,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } else { right_sym := g.table.get_type_symbol(assign_stmt.right_types[i]) mut is_fixed_array_init := false + mut has_val := false match val { - ast.ArrayInit { is_fixed_array_init = it.is_fixed } + ast.ArrayInit { + is_fixed_array_init = it.is_fixed + has_val = it.has_val + } else {} } is_decl := assign_stmt.op == .decl_assign @@ -863,7 +867,12 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { } } if is_fixed_array_init { - g.write('= {0}') + if has_val { + g.write(' = ') + g.expr(val) + } else { + g.write(' = {0}') + } } else { g.write(' = ') if !is_decl { @@ -972,6 +981,14 @@ fn (mut g Gen) expr(node ast.Expr) { g.write('\n})') } } else { + g.write('{') + for i, expr in it.exprs { + g.expr(expr) + if i != it.exprs.len - 1 { + g.write(', ') + } + } + g.write('}') } } ast.AsCast { @@ -1265,32 +1282,43 @@ fn (mut g Gen) assign_expr(node ast.AssignExpr) { g.write(' = string_add(') str_add = true } - g.assign_op = node.op - g.expr(node.left) - // arr[i] = val => `array_set(arr, i, val)`, not `array_get(arr, i) = val` - if !g.is_array_set && !str_add { - g.write(' $node.op.str() ') - } else if str_add { - g.write(', ') - } - g.is_assign_lhs = false right_sym := g.table.get_type_symbol(node.right_type) - // left_sym := g.table.get_type_symbol(node.left_type) - mut cloned := false - // !g.is_array_set - if g.autofree && right_sym.kind in [.array, .string] { - if g.gen_clone_assignment(node.val, right_sym, false) { - cloned = true + if right_sym.kind == .array_fixed && node.op == .assign { + right := node.val as ast.ArrayInit + for j, expr in right.exprs { + g.expr(node.left) + g.write('[$j] = ') + g.expr(expr) + g.writeln(';') + } + } else { + g.assign_op = node.op + g.expr(node.left) + // arr[i] = val => `array_set(arr, i, val)`, not `array_get(arr, i) = val` + if !g.is_array_set && !str_add { + g.write(' $node.op.str() ') + } else if str_add { + g.write(', ') + } + g.is_assign_lhs = false + //right_sym := g.table.get_type_symbol(node.right_type) + // left_sym := g.table.get_type_symbol(node.left_type) + mut cloned := false + // !g.is_array_set + if g.autofree && right_sym.kind in [.array, .string] { + if g.gen_clone_assignment(node.val, right_sym, false) { + cloned = true + } + } + if !cloned { + g.expr_with_cast(node.val, node.right_type, node.left_type) + } + if g.is_array_set { + g.write(' })') + g.is_array_set = false + } else if str_add { + g.write(')') } - } - if !cloned { - g.expr_with_cast(node.val, node.right_type, node.left_type) - } - if g.is_array_set { - g.write(' })') - g.is_array_set = false - } else if str_add { - g.write(')') } g.right_is_opt = false } diff --git a/vlib/v/parser/containers.v b/vlib/v/parser/containers.v index bff05735df..ba087c9df1 100644 --- a/vlib/v/parser/containers.v +++ b/vlib/v/parser/containers.v @@ -16,6 +16,7 @@ fn (mut p Parser) array_init() ast.ArrayInit { mut elem_type := table.void_type mut exprs := []ast.Expr mut is_fixed := false + mut has_val := false if p.tok.kind == .rsbr { // []typ => `[]` and `typ` must be on the same line line_nr := p.tok.line_nr @@ -47,21 +48,23 @@ fn (mut p Parser) array_init() ast.ArrayInit { } last_pos = p.tok.position() p.check(.rsbr) - // [100]byte if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr { + // [100]byte elem_type = p.parse_type() is_fixed = true + } else { + if p.tok.kind == .not { + last_pos = p.tok.position() + p.next() + } + if p.tok.kind == .not { + last_pos = p.tok.position() + p.next() + is_fixed = true + has_val = true + } } } - // ! - if p.tok.kind == .not { - last_pos = p.tok.position() - p.next() - } - if p.tok.kind == .not { - last_pos = p.tok.position() - p.next() - } if p.tok.kind == .lcbr && exprs.len == 0 { // `[]int{ len: 10, cap: 100}` syntax p.next() @@ -85,6 +88,7 @@ fn (mut p Parser) array_init() ast.ArrayInit { } return ast.ArrayInit{ is_fixed: is_fixed + has_val: has_val mod: p.mod elem_type: elem_type typ: array_type diff --git a/vlib/v/tests/fixed_array_init_test.v b/vlib/v/tests/fixed_array_init_test.v new file mode 100644 index 0000000000..c990e23138 --- /dev/null +++ b/vlib/v/tests/fixed_array_init_test.v @@ -0,0 +1,33 @@ +fn test_fixed_array_init() { + a1 := ['1', '2', '3']!! + assert typeof(a1) == '[3]string' + assert '$a1' == '["1", "2", "3"]' + + a2 := ['a', 'b']!! + assert typeof(a2) == '[2]string' + assert '$a2' == '["a", "b"]' + + c1 := [1, 2, 3]!! + assert typeof(c1) == '[3]int' + assert '$c1' == '[1, 2, 3]' + + c2 := [i16(1), 2, 3]!! + assert typeof(c2) == '[3]i16' + assert '$c2' == '[1, 2, 3]' + + mut c3 := [i64(1), 2, 3]!! + assert typeof(c3) == '[3]i64' + assert '$c3' == '[1, 2, 3]' + + mut c4 := [u64(1), 2, 3]!! + assert typeof(c4) == '[3]u64' + assert '$c4' == '[1, 2, 3]' + + mut d1 := [1.1, 2.2, 3.3]!! + assert typeof(d1) == '[3]f64' + assert '$d1' == '[1.1, 2.2, 3.3]' + + mut d2 := [f32(1.1), 2.2, 3.3]!! + assert typeof(d2) == '[3]f32' + assert '$d2' == '[1.1, 2.2, 3.3]' +}