mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
cgen,json: fix default initialization of structs with options (#23263)
This commit is contained in:
parent
f27181e81b
commit
80bae08c9a
3 changed files with 69 additions and 33 deletions
20
vlib/json/tests/json_decode_option_alias_test.v
Normal file
20
vlib/json/tests/json_decode_option_alias_test.v
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import json
|
||||||
|
|
||||||
|
struct Empty {}
|
||||||
|
|
||||||
|
struct SomeStruct {
|
||||||
|
random_field_a ?string
|
||||||
|
random_field_b ?string
|
||||||
|
empty_field ?Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
type Alias = SomeStruct
|
||||||
|
|
||||||
|
fn test_main() {
|
||||||
|
data := json.decode(Alias, '{"empty_field":{}}')!
|
||||||
|
assert data.str() == 'Alias(SomeStruct{
|
||||||
|
random_field_a: Option(none)
|
||||||
|
random_field_b: Option(none)
|
||||||
|
empty_field: Option(none)
|
||||||
|
})'
|
||||||
|
}
|
|
@ -7096,16 +7096,19 @@ fn c_fn_name(name_ string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) type_default_sumtype(typ_ ast.Type, sym ast.TypeSymbol) string {
|
fn (mut g Gen) type_default_sumtype(typ_ ast.Type, sym ast.TypeSymbol) string {
|
||||||
|
if typ_.has_flag(.option) {
|
||||||
|
return '(${g.styp(typ_)}){.state=2, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION}}'
|
||||||
|
}
|
||||||
first_typ := g.unwrap_generic((sym.info as ast.SumType).variants[0])
|
first_typ := g.unwrap_generic((sym.info as ast.SumType).variants[0])
|
||||||
first_sym := g.table.sym(first_typ)
|
first_sym := g.table.sym(first_typ)
|
||||||
first_styp := g.styp(first_typ)
|
first_styp := g.styp(first_typ)
|
||||||
first_field := g.get_sumtype_variant_name(first_typ, first_sym)
|
first_field := g.get_sumtype_variant_name(first_typ, first_sym)
|
||||||
default_str := if first_typ.has_flag(.option) {
|
default_str := if first_typ.has_flag(.option) {
|
||||||
'(${first_styp}){ .state=2, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION} }'
|
'(${first_styp}){.state=2, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION}}'
|
||||||
} else if first_sym.info is ast.Struct && first_sym.info.is_empty_struct() {
|
} else if first_sym.info is ast.Struct && first_sym.info.is_empty_struct() {
|
||||||
'{EMPTY_STRUCT_INITIALIZATION}'
|
'{EMPTY_STRUCT_INITIALIZATION}'
|
||||||
} else {
|
} else {
|
||||||
g.type_default(first_typ)
|
g.type_default_no_sumtype(first_typ)
|
||||||
}
|
}
|
||||||
if default_str[0] == `{` {
|
if default_str[0] == `{` {
|
||||||
return '(${g.styp(typ_)}){._${first_field}=HEAP(${first_styp}, ((${first_styp})${default_str})),._typ=${int(first_typ)}}'
|
return '(${g.styp(typ_)}){._${first_field}=HEAP(${first_styp}, ((${first_styp})${default_str})),._typ=${int(first_typ)}}'
|
||||||
|
@ -7114,9 +7117,22 @@ fn (mut g Gen) type_default_sumtype(typ_ ast.Type, sym ast.TypeSymbol) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
|
fn (mut g Gen) type_default_no_sumtype(typ_ ast.Type) string {
|
||||||
|
return g.type_default_impl(typ_, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
fn (mut g Gen) type_default(typ_ ast.Type) string {
|
fn (mut g Gen) type_default(typ_ ast.Type) string {
|
||||||
|
return g.type_default_impl(typ_, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) type_default_impl(typ_ ast.Type, decode_sumtype bool) string {
|
||||||
typ := g.unwrap_generic(typ_)
|
typ := g.unwrap_generic(typ_)
|
||||||
if typ.has_option_or_result() {
|
if typ.has_flag(.option) {
|
||||||
|
return '(${g.styp(typ)}){.state=2, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION}}'
|
||||||
|
}
|
||||||
|
if typ.has_flag(.result) {
|
||||||
return '{0}'
|
return '{0}'
|
||||||
}
|
}
|
||||||
// Always set pointers to 0
|
// Always set pointers to 0
|
||||||
|
@ -7139,7 +7155,7 @@ fn (mut g Gen) type_default(typ_ ast.Type) string {
|
||||||
return '{0}'
|
return '{0}'
|
||||||
}
|
}
|
||||||
.sum_type {
|
.sum_type {
|
||||||
return '{0}' // g.type_default_sumtype(typ, sym)
|
return if decode_sumtype { g.type_default_sumtype(typ, sym) } else { '{0}' }
|
||||||
}
|
}
|
||||||
.interface, .multi_return, .thread {
|
.interface, .multi_return, .thread {
|
||||||
return '{0}'
|
return '{0}'
|
||||||
|
@ -7210,7 +7226,7 @@ fn (mut g Gen) type_default(typ_ ast.Type) string {
|
||||||
for field in info.fields {
|
for field in info.fields {
|
||||||
field_sym := g.table.sym(field.typ)
|
field_sym := g.table.sym(field.typ)
|
||||||
if field.has_default_expr
|
if field.has_default_expr
|
||||||
|| field_sym.kind in [.array, .map, .string, .bool, .alias, .i8, .i16, .int, .i64, .u8, .u16, .u32, .u64, .f32, .f64, .char, .voidptr, .byteptr, .charptr, .struct, .chan, .sum_type] {
|
|| field_sym.kind in [.enum, .array_fixed, .array, .map, .string, .bool, .alias, .i8, .i16, .int, .i64, .u8, .u16, .u32, .u64, .f32, .f64, .char, .voidptr, .byteptr, .charptr, .struct, .chan, .sum_type] {
|
||||||
if sym.language == .c && !field.has_default_expr {
|
if sym.language == .c && !field.has_default_expr {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -7255,13 +7271,25 @@ fn (mut g Gen) type_default(typ_ ast.Type) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
expr_str = g.expr_string(field.default_expr)
|
default_str := g.expr_string(field.default_expr)
|
||||||
|
if default_str.count('\n') > 1 {
|
||||||
|
g.type_default_vars.writeln(default_str.all_before_last('\n'))
|
||||||
|
expr_str = default_str.all_after_last('\n')
|
||||||
|
} else {
|
||||||
|
expr_str = default_str
|
||||||
|
}
|
||||||
}
|
}
|
||||||
init_str += '.${field_name} = ${expr_str},'
|
init_str += '.${field_name} = ${expr_str},'
|
||||||
} else {
|
} else {
|
||||||
zero_str := if field_sym.language == .v && field_sym.info is ast.Struct
|
zero_str := if field_sym.language == .v && field_sym.info is ast.Struct
|
||||||
&& field_sym.info.is_empty_struct() {
|
&& field_sym.info.is_empty_struct() {
|
||||||
'{EMPTY_STRUCT_INITIALIZATION}'
|
'{EMPTY_STRUCT_INITIALIZATION}'
|
||||||
|
} else if field_sym.kind == .sum_type {
|
||||||
|
if decode_sumtype {
|
||||||
|
g.type_default_sumtype(field.typ, field_sym)
|
||||||
|
} else {
|
||||||
|
'{0}'
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.type_default(field.typ)
|
g.type_default(field.typ)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,35 +58,23 @@ fn (mut g Gen) gen_jsons() {
|
||||||
|
|
||||||
mut init_styp := '${styp} res'
|
mut init_styp := '${styp} res'
|
||||||
if utyp.has_flag(.option) {
|
if utyp.has_flag(.option) {
|
||||||
if sym.kind == .struct && !utyp.is_ptr() {
|
|
||||||
init_styp += ' = '
|
|
||||||
g.set_current_pos_as_last_stmt_pos()
|
|
||||||
pos := g.out.len
|
|
||||||
g.expr_with_tmp_var(ast.Expr(ast.StructInit{ typ: utyp, typ_str: styp }),
|
|
||||||
utyp, utyp, 'res')
|
|
||||||
init_styp = g.out.cut_to(pos).trim_space()
|
|
||||||
} else {
|
|
||||||
none_str := g.expr_string(ast.None{})
|
none_str := g.expr_string(ast.None{})
|
||||||
init_styp += ' = (${styp}){ .state=2, .err=${none_str}, .data={EMPTY_STRUCT_INITIALIZATION} }'
|
init_styp += ' = (${styp}){ .state=2, .err=${none_str}, .data={EMPTY_STRUCT_INITIALIZATION} }'
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if sym.kind == .struct {
|
if !utyp.is_ptr() {
|
||||||
init_styp += ' = '
|
init_styp += ' = '
|
||||||
g.set_current_pos_as_last_stmt_pos()
|
g.set_current_pos_as_last_stmt_pos()
|
||||||
pos := g.out.len
|
pos := g.out.len
|
||||||
g.write(init_styp)
|
g.write(g.type_default(utyp))
|
||||||
if utyp.is_ptr() {
|
init_generated := g.out.cut_to(pos).trim_space()
|
||||||
ptr_styp := g.styp(utyp.set_nr_muls(utyp.nr_muls() - 1))
|
if g.type_default_vars.len > 0 {
|
||||||
g.write('HEAP(${ptr_styp}, ')
|
saved_init := init_styp
|
||||||
|
init_styp = g.type_default_vars.bytestr()
|
||||||
|
init_styp += '\n'
|
||||||
|
init_styp += saved_init
|
||||||
|
g.type_default_vars.clear()
|
||||||
}
|
}
|
||||||
g.expr(ast.Expr(ast.StructInit{
|
init_styp += init_generated
|
||||||
typ: utyp.set_nr_muls(0)
|
|
||||||
typ_str: styp
|
|
||||||
}))
|
|
||||||
if utyp.is_ptr() {
|
|
||||||
g.write(')')
|
|
||||||
}
|
|
||||||
init_styp = g.out.cut_to(pos).trim_space()
|
|
||||||
} else if utyp.is_ptr() {
|
} else if utyp.is_ptr() {
|
||||||
ptr_styp := g.styp(utyp.set_nr_muls(utyp.nr_muls() - 1))
|
ptr_styp := g.styp(utyp.set_nr_muls(utyp.nr_muls() - 1))
|
||||||
init_styp += ' = HEAP(${ptr_styp}, {0})'
|
init_styp += ' = HEAP(${ptr_styp}, {0})'
|
||||||
|
@ -645,9 +633,9 @@ fn (mut g Gen) gen_prim_type_validation(name string, typ ast.Type, tmp string, i
|
||||||
if type_check == '' {
|
if type_check == '' {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dec.writeln('if (!(${type_check})) {')
|
dec.writeln('\t\tif (!(${type_check})) {')
|
||||||
dec.writeln('\treturn (${ret_styp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("type mismatch for field \'${name}\', expecting `${g.table.type_to_str(typ)}` type, got: "), json__json_print(jsonroot_${tmp}))), .data = {0} };')
|
dec.writeln('\t\t\treturn (${ret_styp}){ .is_error = true, .err = _v_error(string__plus(_SLIT("type mismatch for field \'${name}\', expecting `${g.table.type_to_str(typ)}` type, got: "), json__json_print(jsonroot_${tmp}))), .data = {0} };')
|
||||||
dec.writeln('}')
|
dec.writeln('\t\t}')
|
||||||
}
|
}
|
||||||
|
|
||||||
@[inline]
|
@[inline]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue