mirror of
https://github.com/vlang/v.git
synced 2025-09-09 15:27:05 -04:00
This commit is contained in:
parent
26837d4862
commit
2fbb3df9fa
@ -2569,18 +2569,28 @@ fn (mut g Gen) expr_with_var(expr ast.Expr, expected_type ast.Type) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// expr_with_fixed_array generates code for fixed array initialization with expr which requires tmp var
|
// expr_with_fixed_array generates code for fixed array initialization with expr which requires tmp var
|
||||||
fn (mut g Gen) expr_with_fixed_array(expr ast.ArrayInit, got_type_raw ast.Type, expected_type ast.Type) string {
|
fn (mut g Gen) expr_with_fixed_array(expr ast.Expr, got_type_raw ast.Type, expected_type ast.Type) string {
|
||||||
stmt_str := g.go_before_last_stmt().trim_space()
|
stmt_str := g.go_before_last_stmt().trim_space()
|
||||||
g.empty_line = true
|
g.empty_line = true
|
||||||
tmp_var := g.new_tmp_var()
|
tmp_var := g.new_tmp_var()
|
||||||
styp := g.styp(expected_type)
|
styp := g.styp(expected_type)
|
||||||
g.writeln('${styp} ${tmp_var};')
|
if expr is ast.ArrayInit {
|
||||||
// [ foo(), foo() ]!
|
g.writeln('${styp} ${tmp_var};')
|
||||||
val_typ := g.table.value_type(got_type_raw)
|
// [ foo(), foo() ]!
|
||||||
for i, item_expr in expr.exprs {
|
val_typ := g.table.value_type(got_type_raw)
|
||||||
g.write('memcpy(${tmp_var}[${i}], ')
|
for i, item_expr in expr.exprs {
|
||||||
g.expr(item_expr)
|
g.write('memcpy(${tmp_var}[${i}], ')
|
||||||
g.writeln(', sizeof(${g.styp(val_typ)}));')
|
g.expr(item_expr)
|
||||||
|
g.writeln(', sizeof(${g.styp(val_typ)}));')
|
||||||
|
}
|
||||||
|
} else if expr is ast.CallExpr {
|
||||||
|
// return var.call() where returns is option/result fixed array
|
||||||
|
g.writeln('${styp} ${tmp_var} = {0};')
|
||||||
|
g.write('memcpy(&${tmp_var}.data, ')
|
||||||
|
g.expr(expr)
|
||||||
|
g.writeln(', sizeof(${g.base_type(expected_type)}));')
|
||||||
|
} else {
|
||||||
|
g.expr(expr)
|
||||||
}
|
}
|
||||||
g.write(stmt_str)
|
g.write(stmt_str)
|
||||||
return tmp_var
|
return tmp_var
|
||||||
@ -5792,22 +5802,46 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fn_return_is_option && !expr_type_is_opt && return_sym.name != option_name {
|
if fn_return_is_option && !expr_type_is_opt && return_sym.name != option_name {
|
||||||
styp := g.base_type(fn_ret_type)
|
if fn_return_is_fixed_array && (expr0 in [ast.StructInit, ast.CallExpr, ast.CastExpr]
|
||||||
g.writeln('${ret_typ} ${tmpvar};')
|
|| (expr0 is ast.ArrayInit && expr0.has_callexpr))
|
||||||
g.write('_option_ok(&(${styp}[]) { ')
|
&& g.table.final_sym(node.types[0]).kind == .array_fixed {
|
||||||
if !g.unwrap_generic(fn_ret_type).is_ptr() && node.types[0].is_ptr() {
|
styp := g.styp(fn_ret_type.clear_option_and_result())
|
||||||
if !(node.exprs[0] is ast.Ident && !g.is_amp) {
|
if expr0 is ast.CallExpr {
|
||||||
g.write('*')
|
tmp_var := g.expr_with_fixed_array(expr0, node.types[0], fn_ret_type)
|
||||||
|
g.writeln('${ret_typ} ${tmpvar} = ${tmp_var};')
|
||||||
|
} else {
|
||||||
|
g.writeln('${ret_typ} ${tmpvar} = (${ret_typ}){ .state=0, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION} };')
|
||||||
|
if expr0 is ast.StructInit {
|
||||||
|
g.write('memcpy(${tmpvar}.data, ')
|
||||||
|
tmp_var := g.expr_with_opt(expr0, node.types[0], fn_ret_type)
|
||||||
|
g.writeln('.data, sizeof(${styp}));')
|
||||||
|
if tmp_var != '' {
|
||||||
|
g.writeln('${tmpvar}.state = ${tmp_var}.state;')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g.write('memcpy(${tmpvar}.data, ')
|
||||||
|
g.expr(expr0)
|
||||||
|
g.writeln(', sizeof(${styp}));')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if return_sym.kind == .array_fixed && expr0 !is ast.ArrayInit {
|
|
||||||
info := return_sym.info as ast.ArrayFixed
|
|
||||||
g.fixed_array_var_init(g.expr_string(expr0), expr0.is_auto_deref_var(),
|
|
||||||
info.elem_type, info.size)
|
|
||||||
} else {
|
} else {
|
||||||
g.expr_with_cast(expr0, node.types[0], fn_ret_type.clear_option_and_result())
|
g.writeln('${ret_typ} ${tmpvar};')
|
||||||
|
styp := g.base_type(fn_ret_type)
|
||||||
|
g.write('_option_ok(&(${styp}[]) { ')
|
||||||
|
if !g.unwrap_generic(fn_ret_type).is_ptr() && node.types[0].is_ptr() {
|
||||||
|
if !(node.exprs[0] is ast.Ident && !g.is_amp) {
|
||||||
|
g.write('*')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if return_sym.kind == .array_fixed && expr0 !is ast.ArrayInit {
|
||||||
|
info := return_sym.info as ast.ArrayFixed
|
||||||
|
g.fixed_array_var_init(g.expr_string(expr0), expr0.is_auto_deref_var(),
|
||||||
|
info.elem_type, info.size)
|
||||||
|
} else {
|
||||||
|
g.expr_with_cast(expr0, node.types[0], fn_ret_type.clear_option_and_result())
|
||||||
|
}
|
||||||
|
g.writeln(' }, (${option_name}*)(&${tmpvar}), sizeof(${styp}));')
|
||||||
}
|
}
|
||||||
g.writeln(' }, (${option_name}*)(&${tmpvar}), sizeof(${styp}));')
|
|
||||||
g.write_defer_stmts_when_needed()
|
g.write_defer_stmts_when_needed()
|
||||||
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
|
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
|
||||||
g.writeln('return ${tmpvar};')
|
g.writeln('return ${tmpvar};')
|
||||||
|
@ -451,6 +451,7 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
|
|||||||
g.writeln('\tif (${t_var}.state != 0) break;')
|
g.writeln('\tif (${t_var}.state != 0) break;')
|
||||||
val := if node.val_var in ['', '_'] { g.new_tmp_var() } else { node.val_var }
|
val := if node.val_var in ['', '_'] { g.new_tmp_var() } else { node.val_var }
|
||||||
val_styp := g.styp(ret_typ.clear_option_and_result())
|
val_styp := g.styp(ret_typ.clear_option_and_result())
|
||||||
|
ret_is_fixed_array := g.table.sym(ret_typ).is_array_fixed()
|
||||||
if node.val_is_mut {
|
if node.val_is_mut {
|
||||||
if ret_typ.has_flag(.option) {
|
if ret_typ.has_flag(.option) {
|
||||||
g.writeln('\t${val_styp}* ${val} = (${val_styp}*)${t_var}.data;')
|
g.writeln('\t${val_styp}* ${val} = (${val_styp}*)${t_var}.data;')
|
||||||
@ -458,7 +459,12 @@ fn (mut g Gen) for_in_stmt(node_ ast.ForInStmt) {
|
|||||||
g.writeln('\t${val_styp} ${val} = (${val_styp})${t_var}.data;')
|
g.writeln('\t${val_styp} ${val} = (${val_styp})${t_var}.data;')
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
g.writeln('\t${val_styp} ${val} = *(${val_styp}*)${t_var}.data;')
|
if ret_is_fixed_array {
|
||||||
|
g.writeln('\t${val_styp} ${val} = {0};')
|
||||||
|
g.write('\tmemcpy(${val}, ${t_var}.data, sizeof(${val_styp}));')
|
||||||
|
} else {
|
||||||
|
g.writeln('\t${val_styp} ${val} = *(${val_styp}*)${t_var}.data;')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if node.kind == .aggregate {
|
} else if node.kind == .aggregate {
|
||||||
for_type := (g.table.sym(node.cond_type).info as ast.Aggregate).types[g.aggregate_type_idx]
|
for_type := (g.table.sym(node.cond_type).info as ast.Aggregate).types[g.aggregate_type_idx]
|
||||||
|
@ -687,7 +687,7 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua
|
|||||||
g.fixed_array_var_init(g.expr_string(sfield.expr), is_auto_deref_var,
|
g.fixed_array_var_init(g.expr_string(sfield.expr), is_auto_deref_var,
|
||||||
field_unwrap_sym.info.elem_type, field_unwrap_sym.info.size)
|
field_unwrap_sym.info.elem_type, field_unwrap_sym.info.size)
|
||||||
}
|
}
|
||||||
ast.CallExpr {
|
ast.CastExpr, ast.CallExpr {
|
||||||
tmp_var := g.expr_with_var(sfield.expr, sfield.expected_type)
|
tmp_var := g.expr_with_var(sfield.expr, sfield.expected_type)
|
||||||
g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type,
|
g.fixed_array_var_init(tmp_var, false, field_unwrap_sym.info.elem_type,
|
||||||
field_unwrap_sym.info.size)
|
field_unwrap_sym.info.size)
|
||||||
|
35
vlib/v/tests/options/option_array_fixed_test.v
Normal file
35
vlib/v/tests/options/option_array_fixed_test.v
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
type Arr = [4]u8
|
||||||
|
|
||||||
|
fn foo(a int) ?Arr {
|
||||||
|
if a > 0 {
|
||||||
|
return Arr([u8(1), 2, 3, 4]!)
|
||||||
|
}
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar(a int) !Arr {
|
||||||
|
if a > 0 {
|
||||||
|
return Arr([u8(1), 2, 3, 4]!)
|
||||||
|
}
|
||||||
|
return error('')
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
f := foo(1) or { Arr([u8(0), 0, 0, 0]!) }
|
||||||
|
dump(f)
|
||||||
|
assert f == [u8(1), 2, 3, 4]!
|
||||||
|
|
||||||
|
ff := foo(0)
|
||||||
|
dump(ff)
|
||||||
|
assert ff == none
|
||||||
|
|
||||||
|
b := bar(1) or { Arr([u8(0), 0, 0, 0]!) }
|
||||||
|
dump(f)
|
||||||
|
assert b == [u8(1), 2, 3, 4]!
|
||||||
|
|
||||||
|
bb := bar(0) or { Arr([u8(0), 0, 0, 0]!) }
|
||||||
|
dump(bb)
|
||||||
|
assert bb == [u8(0), 0, 0, 0]!
|
||||||
|
}
|
52
vlib/v/tests/options/option_fixed_array_2_test.v
Normal file
52
vlib/v/tests/options/option_fixed_array_2_test.v
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
module main
|
||||||
|
|
||||||
|
import encoding.binary
|
||||||
|
|
||||||
|
type Addr = [4]u8
|
||||||
|
|
||||||
|
fn Addr.from_u32(a u32) Addr {
|
||||||
|
mut bytes := [4]u8{}
|
||||||
|
binary.big_endian_put_u32_fixed(mut bytes, a)
|
||||||
|
return Addr(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (a Addr) str() string {
|
||||||
|
return '${a[0]}.${a[1]}.${a[2]}.${a[3]}'
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (a Addr) u32() u32 {
|
||||||
|
return binary.big_endian_u32_fixed(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Net {
|
||||||
|
netaddr Addr
|
||||||
|
broadcast Addr
|
||||||
|
mut:
|
||||||
|
h u32
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut n Net) next() ?Addr {
|
||||||
|
if n.h >= n.broadcast.u32() + 1 {
|
||||||
|
return none
|
||||||
|
}
|
||||||
|
defer {
|
||||||
|
n.h++
|
||||||
|
}
|
||||||
|
return Addr.from_u32(n.h)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
net := Net{
|
||||||
|
netaddr: Addr([u8(172), 16, 16, 0]!)
|
||||||
|
broadcast: Addr([u8(172), 16, 16, 3]!)
|
||||||
|
h: u32(2886733824)
|
||||||
|
}
|
||||||
|
mut rets := []string{}
|
||||||
|
for addr in net {
|
||||||
|
rets << addr.str()
|
||||||
|
}
|
||||||
|
assert rets[0] == '172.16.16.0'
|
||||||
|
assert rets[1] == '172.16.16.1'
|
||||||
|
assert rets[2] == '172.16.16.2'
|
||||||
|
assert rets[3] == '172.16.16.3'
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user