From 9a8f3025f54277980ab86059e7e433499d1ee431 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Fri, 24 Feb 2023 14:25:31 -0300 Subject: [PATCH] cgen: implement option fixed array (#17400) --- vlib/v/gen/c/assign.v | 80 +++++++++++++++----------- vlib/v/parser/parser.v | 11 +++- vlib/v/tests/option_fixed_array_test.v | 59 +++++++++++++++++++ 3 files changed, 113 insertions(+), 37 deletions(-) create mode 100644 vlib/v/tests/option_fixed_array_test.v diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index ea89d5e581..35966102f3 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -346,37 +346,43 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { } else if node.op == .assign && !g.pref.translated && (is_fixed_array_init || (right_sym.kind == .array_fixed && val is ast.Ident)) { // Fixed arrays - mut v_var := '' - arr_typ := styp.trim('*') - if is_fixed_array_init { - right := val as ast.ArrayInit - v_var = g.new_tmp_var() - g.write('${arr_typ} ${v_var} = ') - g.expr(right) - g.writeln(';') - } else { - right := val as ast.Ident - v_var = right.name - } - pos := g.out.len - g.expr(left) - - if g.is_arraymap_set && g.arraymap_set_pos > 0 { - g.go_back_to(g.arraymap_set_pos) - g.write(', &${v_var})') - g.is_arraymap_set = false - g.arraymap_set_pos = 0 - } else { - g.go_back_to(pos) - is_var_mut := !is_decl && left.is_auto_deref_var() - addr_left := if is_var_mut { '' } else { '&' } - g.writeln('') - g.write('memcpy(${addr_left}') + if is_fixed_array_init && var_type.has_flag(.option) { g.expr(left) - addr_val := if is_fixed_array_var { '' } else { '&' } - g.writeln(', ${addr_val}${v_var}, sizeof(${arr_typ}));') + g.write(' = ') + g.expr_with_opt(val, val_type, var_type) + } else { + mut v_var := '' + arr_typ := styp.trim('*') + if is_fixed_array_init { + right := val as ast.ArrayInit + v_var = g.new_tmp_var() + g.write('${arr_typ} ${v_var} = ') + g.expr(right) + g.writeln(';') + } else { + right := val as ast.Ident + v_var = right.name + } + pos := g.out.len + g.expr(left) + + if g.is_arraymap_set && g.arraymap_set_pos > 0 { + g.go_back_to(g.arraymap_set_pos) + g.write(', &${v_var})') + g.is_arraymap_set = false + g.arraymap_set_pos = 0 + } else { + g.go_back_to(pos) + is_var_mut := !is_decl && left.is_auto_deref_var() + addr_left := if is_var_mut { '' } else { '&' } + g.writeln('') + g.write('memcpy(${addr_left}') + g.expr(left) + addr_val := if is_fixed_array_var { '' } else { '&' } + g.writeln(', ${addr_val}${v_var}, sizeof(${arr_typ}));') + } + g.is_assign_lhs = false } - g.is_assign_lhs = false } else { is_inside_ternary := g.inside_ternary != 0 cur_line := if is_inside_ternary && is_decl { @@ -565,11 +571,17 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) { } else { '(byte*)&' } - g.write('memcpy(${final_typ_str}') - g.expr(left) - g.write(', ${final_ref_str}') - g.expr(val) - g.write(', sizeof(${typ_str}))') + if val_type.has_flag(.option) { + g.expr(left) + g.write(' = ') + g.expr(val) + } else { + g.write('memcpy(${final_typ_str}') + g.expr(left) + g.write(', ${final_ref_str}') + g.expr(val) + g.write(', sizeof(${typ_str}))') + } } else if is_decl { g.is_shared = var_type.has_flag(.shared_f) if is_fixed_array_init && !has_val { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index c53717f0a7..32534bb3db 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -2543,13 +2543,18 @@ pub fn (mut p Parser) name_expr() ast.Expr { } } } else if p.peek_tok.kind == .lpar || is_generic_call || is_generic_cast - || (is_option && p.peek_token(2).kind == .lpar) || (is_option && p.peek_tok.kind == .lsbr + || (is_option && p.peek_token(2).kind == .lpar) || (is_option && ((p.peek_tok.kind == .lsbr && p.peek_token(2).kind == .rsbr && p.peek_token(3).kind == .name - && p.peek_token(4).kind == .lpar) { + && p.peek_token(4).kind == .lpar) || (p.peek_tok.kind == .lsbr + && p.peek_token(2).kind == .number && p.peek_token(3).kind == .rsbr + && p.peek_token(4).kind == .name && p.peek_token(5).kind == .lpar))) { is_array := p.peek_tok.kind == .lsbr + is_fixed_array := is_array && p.peek_token(2).kind == .number // foo(), foo() or type() cast mut name := if is_option { - if is_array { p.peek_token(3).lit } else { p.peek_tok.lit } + if is_array { p.peek_token(if is_fixed_array { 4 } else { 3 }).lit + } else { p.peek_tok.lit + } } else { p.tok.lit } diff --git a/vlib/v/tests/option_fixed_array_test.v b/vlib/v/tests/option_fixed_array_test.v new file mode 100644 index 0000000000..60fb765720 --- /dev/null +++ b/vlib/v/tests/option_fixed_array_test.v @@ -0,0 +1,59 @@ +fn f_test(args ?[2]int) ? { + println(args) + assert args?.len == 2 +} + +fn f_arr(args ?[3]f64) ?[]f64 { + mut ret := ?[]f64(none) + ret = [-6.0] + ret?.pop() + ret? << args?[0] + ret? << args?[1] + ret? << args?[2] + return ret +} + +fn f_arr2(args ?[3]f64) ?[]f64 { + arr := args? + mut ret := []f64{} + ret << arr[0] + ret << arr[1] + ret << arr[2] + return ret +} + +fn test_simple() { + mut arr := ?[3]int(none) + println(arr) // Option(error: none) +} + +fn test_simple_assign() { + mut arr := ?[3]int(none) + assert arr == none + + arr = [1, 2, 3]! + assert arr != none + + println(arr) // Option([1, 2, 3]) +} + +fn test_array_fixed_param() { + f_test([1, 2]!) +} + +fn test_assign() { + mut a := ?[2]string(none) + assert a == none + a = ['a', 'b']! + assert a != none + a = none + assert a == none +} + +fn test_fn_call() { + assert f_arr([0.0, 1.2, 2.3]!)?.len == 3 +} + +fn test_fn_unwrap_call() { + assert f_arr2([0.0, 1.2, 2.3]!)?.len == 3 +}