mirror of
https://github.com/vlang/v.git
synced 2025-09-22 11:57:33 -04:00
cgen: fix auto_str for option values (#17910)
This commit is contained in:
parent
220b31bfba
commit
5c439b6621
@ -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): 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): Option(0)
|
||||||
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): struct {
|
[vlib/v/checker/tests/comptime_dump_fields_var_test.vv:13] val.$(field.name): struct {
|
||||||
i: 100
|
i: Option(100)
|
||||||
}
|
}
|
||||||
ok
|
ok
|
||||||
|
@ -192,13 +192,9 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string)
|
|||||||
} else {
|
} else {
|
||||||
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*(${sym.cname}*)it.data);')
|
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*(${sym.cname}*)it.data);')
|
||||||
}
|
}
|
||||||
g.auto_str_funcs.writeln('\t} else {')
|
g.auto_str_funcs.writeln('\t\treturn ${str_intp_sub('Option(%%)', 'res')};')
|
||||||
|
|
||||||
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}')
|
g.auto_str_funcs.writeln('\t}')
|
||||||
|
g.auto_str_funcs.writeln('\treturn _SLIT("Option(none)");')
|
||||||
g.auto_str_funcs.writeln('\treturn ${str_intp_sub('Option(%%)', 'res')};')
|
|
||||||
g.auto_str_funcs.writeln('}')
|
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\tres = ${tmp_str};')
|
||||||
g.auto_str_funcs.writeln('\t}')
|
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('}')
|
g.auto_str_funcs.writeln('}')
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,17 +893,20 @@ 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))
|
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
|
// manage prefix and quote symbol for the filed
|
||||||
mut quote_str := ''
|
mut quote_str := ''
|
||||||
mut prefix := ''
|
mut prefix := ''
|
||||||
sym := g.table.sym(g.unwrap_generic(field.typ))
|
sym := g.table.sym(g.unwrap_generic(field.typ))
|
||||||
|
if !is_opt_field {
|
||||||
if sym.kind == .string {
|
if sym.kind == .string {
|
||||||
quote_str = "'"
|
quote_str = "'"
|
||||||
} else if field.typ in ast.charptr_types {
|
} else if field.typ in ast.charptr_types {
|
||||||
quote_str = '\\"'
|
quote_str = '\\"'
|
||||||
prefix = 'C'
|
prefix = 'C'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if is_first {
|
if is_first {
|
||||||
// first field doesn't need \n
|
// first field doesn't need \n
|
||||||
@ -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)
|
g.get_str_fn(ftyp_noshared)
|
||||||
}
|
}
|
||||||
// with floats we use always the g representation:
|
// 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)}=')
|
fn_body.write_string('{_SLIT("${quote_str}"), ${int(base_fmt)}, {.${data_str(base_fmt)}=')
|
||||||
} else {
|
} else {
|
||||||
g_fmt := '0x' + (u32(base_fmt) | u32(0x7F) << 9).hex()
|
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)
|
field.name, sym_has_str_method, str_method_expects_ptr)
|
||||||
ftyp_nr_muls := field.typ.nr_muls()
|
ftyp_nr_muls := field.typ.nr_muls()
|
||||||
if ftyp_nr_muls > 1 || field.typ in ast.cptr_types {
|
if ftyp_nr_muls > 1 || field.typ in ast.cptr_types {
|
||||||
|
if is_opt_field {
|
||||||
|
} else {
|
||||||
func = '(voidptr) it.${field.name}'
|
func = '(voidptr) it.${field.name}'
|
||||||
caller_should_free = false
|
caller_should_free = false
|
||||||
|
}
|
||||||
} else if ftyp_noshared.is_ptr() {
|
} else if ftyp_noshared.is_ptr() {
|
||||||
// reference types can be "nil"
|
// reference types can be "nil"
|
||||||
if ftyp_noshared.has_flag(.option) {
|
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)
|
deref, _ := deref_kind(expects_ptr, field_type.is_ptr(), field_type)
|
||||||
if sym.kind == .enum_ {
|
if sym.kind == .enum_ {
|
||||||
return '${fn_name}(${deref}(it.${c_name(field_name)}))', true
|
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}'
|
obj := '${deref}it.${c_name(field_name)}${sufix}'
|
||||||
if has_custom_str {
|
if has_custom_str {
|
||||||
return '${fn_name}(${obj})', true
|
return '${fn_name}(${obj})', true
|
||||||
|
10
vlib/v/gen/c/testdata/comptime_option_call.out
vendored
10
vlib/v/gen/c/testdata/comptime_option_call.out
vendored
@ -1,10 +1,10 @@
|
|||||||
0
|
0
|
||||||
0
|
0
|
||||||
Option(error: none)
|
Option(none)
|
||||||
Option(error: none)
|
Option(none)
|
||||||
Option(error: none)
|
Option(none)
|
||||||
Option(error: none)
|
Option(none)
|
||||||
1
|
1
|
||||||
1
|
1
|
||||||
println(NIL)
|
println(NIL)
|
||||||
Option(error: none)
|
Option(none)
|
||||||
|
18
vlib/v/slow_tests/inout/struct_dump_option_fields.out
Normal file
18
vlib/v/slow_tests/inout/struct_dump_option_fields.out
Normal 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)
|
||||||
|
})
|
||||||
|
}
|
35
vlib/v/slow_tests/inout/struct_dump_option_fields.vv
Normal file
35
vlib/v/slow_tests/inout/struct_dump_option_fields.vv
Normal 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)
|
||||||
|
}
|
@ -16,11 +16,11 @@
|
|||||||
none
|
none
|
||||||
3
|
3
|
||||||
Foo{
|
Foo{
|
||||||
bar: 3
|
bar: Option(3)
|
||||||
baz: 0
|
baz: Option(none)
|
||||||
}
|
}
|
||||||
[vlib/v/slow_tests/inout/struct_field_option.vv:61] f: Foo{
|
[vlib/v/slow_tests/inout/struct_field_option.vv:61] f: Foo{
|
||||||
bar: 3
|
bar: Option(3)
|
||||||
baz: 0
|
baz: Option(none)
|
||||||
}
|
}
|
||||||
1
|
1
|
@ -24,7 +24,7 @@ fn f_arr2(args ?[3]f64) ?[]f64 {
|
|||||||
|
|
||||||
fn test_simple() {
|
fn test_simple() {
|
||||||
mut arr := ?[3]int(none)
|
mut arr := ?[3]int(none)
|
||||||
println(arr) // Option(error: none)
|
println(arr) // Option(none)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_simple_assign() {
|
fn test_simple_assign() {
|
||||||
|
@ -15,6 +15,6 @@ fn test_main() {
|
|||||||
}
|
}
|
||||||
assert a.str() == 'MyStruct2{
|
assert a.str() == 'MyStruct2{
|
||||||
valuea: 1
|
valuea: 1
|
||||||
valueb: Option(error: none)
|
valueb: Option(none)
|
||||||
}'
|
}'
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ fn test_return_err_var() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_str() {
|
fn test_str() {
|
||||||
assert '${foo()}' == 'result(1)'
|
assert '${foo()}' == 'Result(1)'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn result_void(err bool) ! {
|
fn result_void(err bool) ! {
|
||||||
|
@ -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}'
|
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')
|
return error('this is an error')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_option_err() {
|
fn test_result_err() {
|
||||||
assert '${create_option_err()}' == 'Option(error: this is an error)'
|
assert '${create_option_err()}' == 'Result(error: this is an error)'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_option_none() ?string {
|
fn create_option_none() ?string {
|
||||||
@ -341,7 +341,7 @@ fn create_option_none() ?string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_option_none() {
|
fn test_option_none() {
|
||||||
assert '${create_option_none()}' == 'Option(error: none)'
|
assert '${create_option_none()}' == 'Option(none)'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_option_string() ?string {
|
fn create_option_string() ?string {
|
||||||
|
@ -155,7 +155,7 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
|
|||||||
mut i := 0
|
mut i := 0
|
||||||
mut fields_len := 0
|
mut fields_len := 0
|
||||||
$for field in U.fields {
|
$for field in U.fields {
|
||||||
if val.$(field.name).str() != 'Option(error: none)' {
|
if val.$(field.name).str() != 'Option(none)' {
|
||||||
fields_len++
|
fields_len++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ fn (e &Encoder) encode_struct[U](val U, level int, mut wr io.Writer) ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$if field.is_option {
|
$if field.is_option {
|
||||||
is_none := value.str() == 'Option(error: none)'
|
is_none := value.str() == 'Option(none)'
|
||||||
|
|
||||||
if !is_none {
|
if !is_none {
|
||||||
e.encode_newline(level, mut wr)!
|
e.encode_newline(level, mut wr)!
|
||||||
|
Loading…
x
Reference in New Issue
Block a user