1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix auto_str for option values (#17910)

This commit is contained in:
Felipe Pena 2023-04-10 00:56:57 -03:00 committed by GitHub
parent 220b31bfba
commit 5c439b6621
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 93 additions and 36 deletions

View File

@ -3,6 +3,6 @@
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): 1
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): Option(0)
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): struct {
i: 100
i: Option(100)
}
ok

View File

@ -192,13 +192,9 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string)
} else {
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*(${sym.cname}*)it.data);')
}
g.auto_str_funcs.writeln('\t} else {')
tmp_str := str_intp_sub('error: %%', 'IError_str(it.err)')
g.auto_str_funcs.writeln('\t\tres = ${tmp_str};')
g.auto_str_funcs.writeln('\t\treturn ${str_intp_sub('Option(%%)', 'res')};')
g.auto_str_funcs.writeln('\t}')
g.auto_str_funcs.writeln('\treturn ${str_intp_sub('Option(%%)', 'res')};')
g.auto_str_funcs.writeln('\treturn _SLIT("Option(none)");')
g.auto_str_funcs.writeln('}')
}
@ -231,7 +227,7 @@ fn (mut g Gen) gen_str_for_result(typ ast.Type, styp string, str_fn_name string)
g.auto_str_funcs.writeln('\t\tres = ${tmp_str};')
g.auto_str_funcs.writeln('\t}')
g.auto_str_funcs.writeln('\treturn ${str_intp_sub('result(%%)', 'res')};')
g.auto_str_funcs.writeln('\treturn ${str_intp_sub('Result(%%)', 'res')};')
g.auto_str_funcs.writeln('}')
}
@ -897,16 +893,19 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string,
''
}
base_fmt := g.type_to_fmt(g.unwrap_generic(field.typ))
is_opt_field := field.typ.has_flag(.option)
// manage prefix and quote symbol for the filed
mut quote_str := ''
mut prefix := ''
sym := g.table.sym(g.unwrap_generic(field.typ))
if sym.kind == .string {
quote_str = "'"
} else if field.typ in ast.charptr_types {
quote_str = '\\"'
prefix = 'C'
if !is_opt_field {
if sym.kind == .string {
quote_str = "'"
} else if field.typ in ast.charptr_types {
quote_str = '\\"'
prefix = 'C'
}
}
if is_first {
@ -937,7 +936,9 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string,
g.get_str_fn(ftyp_noshared)
}
// with floats we use always the g representation:
if sym.kind !in [.f32, .f64] {
if is_opt_field {
fn_body.write_string('{_SLIT("${quote_str}"), ${c.si_s_code}, {.d_s=')
} else if sym.kind !in [.f32, .f64] {
fn_body.write_string('{_SLIT("${quote_str}"), ${int(base_fmt)}, {.${data_str(base_fmt)}=')
} else {
g_fmt := '0x' + (u32(base_fmt) | u32(0x7F) << 9).hex()
@ -949,8 +950,11 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, styp string, typ_str string,
field.name, sym_has_str_method, str_method_expects_ptr)
ftyp_nr_muls := field.typ.nr_muls()
if ftyp_nr_muls > 1 || field.typ in ast.cptr_types {
func = '(voidptr) it.${field.name}'
caller_should_free = false
if is_opt_field {
} else {
func = '(voidptr) it.${field.name}'
caller_should_free = false
}
} else if ftyp_noshared.is_ptr() {
// reference types can be "nil"
if ftyp_noshared.has_flag(.option) {
@ -1004,7 +1008,7 @@ fn struct_auto_str_func(sym &ast.TypeSymbol, _field_type ast.Type, fn_name strin
deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type)
if sym.kind == .enum_ {
return '${fn_name}(${deref}(it.${c_name(field_name)}))', true
} else if should_use_indent_func(sym.kind) {
} else if _field_type.has_flag(.option) || should_use_indent_func(sym.kind) {
obj := '${deref}it.${c_name(field_name)}${sufix}'
if has_custom_str {
return '${fn_name}(${obj})', true

View File

@ -1,10 +1,10 @@
0
0
Option(error: none)
Option(error: none)
Option(error: none)
Option(error: none)
Option(none)
Option(none)
Option(none)
Option(none)
1
1
println(NIL)
Option(error: none)
Option(none)

View File

@ -0,0 +1,18 @@
Test{
a: Option(none)
b: Option(none)
c: Option(none)
d: &Option(none)
e: Option(none)
f: Option(none)
g: Option(none)
h: &Option(none)
i: Option(none)
j: Option(none)
k: []
l: []
m: []
n: Option(Other{
a: Option(none)
})
}

View File

@ -0,0 +1,35 @@
type Alias = int
type SumType = int | string
enum Abc {
a
b
c
}
struct Other {
a ?int
}
struct Test {
a ?int
b ?string
c ?[]int
d ?&int
e ?Alias
f ?SumType
g ?Other
h ?&&int
i ?Abc
j ?fn (int)
k []?int
l []?string
m []?Other
n ?Other = Other{}
}
fn main() {
t := Test{}
println(t)
}

View File

@ -16,11 +16,11 @@
none
3
Foo{
bar: 3
baz: 0
bar: Option(3)
baz: Option(none)
}
[vlib/v/slow_tests/inout/struct_field_option.vv:61] f: Foo{
bar: 3
baz: 0
bar: Option(3)
baz: Option(none)
}
1
1

View File

@ -24,7 +24,7 @@ fn f_arr2(args ?[3]f64) ?[]f64 {
fn test_simple() {
mut arr := ?[3]int(none)
println(arr) // Option(error: none)
println(arr) // Option(none)
}
fn test_simple_assign() {

View File

@ -15,6 +15,6 @@ fn test_main() {
}
assert a.str() == 'MyStruct2{
valuea: 1
valueb: Option(error: none)
valueb: Option(none)
}'
}

View File

@ -21,7 +21,7 @@ fn test_return_err_var() {
}
fn test_str() {
assert '${foo()}' == 'result(1)'
assert '${foo()}' == 'Result(1)'
}
fn result_void(err bool) ! {

View File

@ -328,12 +328,12 @@ fn test_multi_generic_struct() {
assert x.str() == 'MultiGenericStruct[TestStruct, TestStruct]{\n t: TestStruct{\n x: 0\n }\n x: TestStruct{\n x: 0\n }\n}'
}
fn create_option_err() ?string {
fn create_option_err() !string {
return error('this is an error')
}
fn test_option_err() {
assert '${create_option_err()}' == 'Option(error: this is an error)'
fn test_result_err() {
assert '${create_option_err()}' == 'Result(error: this is an error)'
}
fn create_option_none() ?string {
@ -341,7 +341,7 @@ fn create_option_none() ?string {
}
fn test_option_none() {
assert '${create_option_none()}' == 'Option(error: none)'
assert '${create_option_none()}' == 'Option(none)'
}
fn create_option_string() ?string {

View File

@ -155,7 +155,7 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
mut i := 0
mut fields_len := 0
$for field in U.fields {
if val.$(field.name).str() != 'Option(error: none)' {
if val.$(field.name).str() != 'Option(none)' {
fields_len++
}
}
@ -171,7 +171,7 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
}
$if field.is_option {
is_none := value.str() == 'Option(error: none)'
is_none := value.str() == 'Option(none)'
if !is_none {
e.encode_newline(level, mut wr)!