mirror of
https://github.com/vlang/v.git
synced 2025-09-13 01:16:02 -04:00
cgen: fix C struct sumtype support (#21129)
This commit is contained in:
parent
360886bfd9
commit
d49fd0f4a7
@ -72,7 +72,7 @@ fn (mut g Gen) gen_sumtype_equality_fn(left_type ast.Type) string {
|
||||
for typ in info.variants {
|
||||
variant := g.unwrap(typ)
|
||||
fn_builder.writeln('\tif (${left_typ} == ${int(variant.typ)}) {')
|
||||
name := '_${g.get_sumtype_variant_name(variant.typ, variant.sym.cname)}'
|
||||
name := '_${g.get_sumtype_variant_name(variant.typ, variant.sym)}'
|
||||
|
||||
left_arg := g.read_field(left_type, name, 'a')
|
||||
right_arg := g.read_field(left_type, name, 'b')
|
||||
|
@ -440,8 +440,13 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, typ_str
|
||||
typ_name := g.typ(typ)
|
||||
mut func_name := g.get_str_fn(typ)
|
||||
sym := g.table.sym(typ)
|
||||
is_c_struct := sym.is_c_struct()
|
||||
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
|
||||
deref := if sym_has_str_method && str_method_expects_ptr { ' ' } else { '*' }
|
||||
deref := if is_c_struct || (sym_has_str_method && str_method_expects_ptr) {
|
||||
' '
|
||||
} else {
|
||||
'*'
|
||||
}
|
||||
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||
func_name = 'indent_${func_name}'
|
||||
}
|
||||
@ -460,7 +465,7 @@ fn (mut g Gen) gen_str_for_union_sum_type(info ast.SumType, styp string, typ_str
|
||||
fn_builder.write_string('\t\tcase ${int(typ)}: return ${res};\n')
|
||||
} else {
|
||||
mut val := '${func_name}(${deref}(${typ_name}*)x._${g.get_sumtype_variant_name(typ,
|
||||
sym.cname)}'
|
||||
sym)}'
|
||||
if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||
val += ', indent_count'
|
||||
}
|
||||
|
@ -915,10 +915,22 @@ pub fn (mut g Gen) finish() {
|
||||
}
|
||||
}
|
||||
|
||||
// get_sumtype_variant_type_name returns the variant type name according to its type
|
||||
@[inline]
|
||||
pub fn (mut g Gen) get_sumtype_variant_type_name(typ ast.Type, sym ast.TypeSymbol) string {
|
||||
return if typ.has_flag(.option) {
|
||||
'_option_${sym.cname}'
|
||||
} else if sym.is_c_struct() {
|
||||
g.cc_type(typ, true)
|
||||
} else {
|
||||
sym.cname
|
||||
}
|
||||
}
|
||||
|
||||
// get_sumtype_variant_name returns the variant name according to its type
|
||||
@[inline]
|
||||
pub fn (mut g Gen) get_sumtype_variant_name(typ ast.Type, name string) string {
|
||||
return if typ.has_flag(.option) { '_option_${name}' } else { name }
|
||||
pub fn (mut g Gen) get_sumtype_variant_name(typ ast.Type, sym ast.TypeSymbol) string {
|
||||
return if typ.has_flag(.option) { '_option_${sym.cname}' } else { sym.cname }
|
||||
}
|
||||
|
||||
pub fn (mut g Gen) write_typeof_functions() {
|
||||
@ -937,7 +949,7 @@ pub fn (mut g Gen) write_typeof_functions() {
|
||||
for v in sum_info.variants {
|
||||
subtype := g.table.sym(v)
|
||||
g.writeln('\tif( sidx == _v_type_idx_${g.get_sumtype_variant_name(v,
|
||||
subtype.cname)}() ) return "${util.strip_main_name(subtype.name)}";')
|
||||
subtype)}() ) return "${util.strip_main_name(subtype.name)}";')
|
||||
}
|
||||
g.writeln('\treturn "unknown ${util.strip_main_name(sym.name)}";')
|
||||
} else {
|
||||
@ -2317,10 +2329,10 @@ fn (mut g Gen) get_sumtype_casting_fn(got_ ast.Type, exp_ ast.Type) string {
|
||||
cname := if exp == ast.int_type_idx {
|
||||
ast.int_type_name
|
||||
} else {
|
||||
g.get_sumtype_variant_name(exp_, exp_sym.cname)
|
||||
g.get_sumtype_variant_name(exp_, exp_sym)
|
||||
}
|
||||
// fn_name := '${got_sym.cname}_to_sumtype_${exp_sym.cname}'
|
||||
fn_name := '${g.get_sumtype_variant_name(got_, got_sym.cname)}_to_sumtype_${cname}/*KEK*/'
|
||||
fn_name := '${g.get_sumtype_variant_name(got_, got_sym)}_to_sumtype_${cname}/*KEK*/'
|
||||
if got == exp || g.sumtype_definitions[i] {
|
||||
return fn_name
|
||||
}
|
||||
@ -2349,10 +2361,11 @@ fn (mut g Gen) get_sumtype_casting_fn(got_ ast.Type, exp_ ast.Type) string {
|
||||
fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
|
||||
got, exp := fun.got, fun.exp
|
||||
got_sym, exp_sym := g.table.sym(got), g.table.sym(exp)
|
||||
mut got_cname, exp_cname := g.get_sumtype_variant_name(got, got_sym.cname), exp_sym.cname
|
||||
mut got_cname, exp_cname := g.get_sumtype_variant_type_name(got, got_sym), exp_sym.cname
|
||||
mut type_idx := g.type_sidx(got)
|
||||
mut sb := strings.new_builder(128)
|
||||
mut is_anon_fn := false
|
||||
mut variant_name := g.get_sumtype_variant_name(got, got_sym)
|
||||
if got_sym.info is ast.FnType {
|
||||
got_name := 'fn ${g.table.fn_type_source_signature(got_sym.info.func)}'
|
||||
got_cname = 'anon_fn_${g.table.fn_type_signature(got_sym.info.func)}'
|
||||
@ -2362,8 +2375,9 @@ fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
|
||||
variant_sym := g.table.sym(variant)
|
||||
if variant_sym.info is ast.FnType {
|
||||
if g.table.fn_type_source_signature(variant_sym.info.func) == g.table.fn_type_source_signature(got_sym.info.func) {
|
||||
got_cname = variant_sym.cname
|
||||
type_idx = variant.idx().str()
|
||||
variant_name = g.get_sumtype_variant_name(variant, variant_sym)
|
||||
got_cname = g.get_sumtype_variant_type_name(variant, variant_sym)
|
||||
type_idx = int(variant).str()
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -2393,7 +2407,7 @@ fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
|
||||
// if the variable is not used, the C compiler will optimize it away
|
||||
sb.writeln('\t${embed_cname}* ${embed_name}_ptr = memdup(${accessor}, sizeof(${embed_cname}));')
|
||||
}
|
||||
sb.write_string('\treturn (${exp_cname}){ ._${got_cname} = ptr, ._typ = ${type_idx}')
|
||||
sb.write_string('\treturn (${exp_cname}){ ._${variant_name} = ptr, ._typ = ${type_idx}')
|
||||
for field in (exp_sym.info as ast.SumType).fields {
|
||||
mut ptr := 'ptr'
|
||||
mut type_cname := got_cname
|
||||
@ -4751,7 +4765,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
if node.obj.ct_type_var == .smartcast {
|
||||
ctyp := g.unwrap_generic(g.comptime.get_comptime_var_type(node))
|
||||
cur_variant_sym := g.table.sym(ctyp)
|
||||
variant_name := g.get_sumtype_variant_name(ctyp, cur_variant_sym.cname)
|
||||
variant_name := g.get_sumtype_variant_name(ctyp, cur_variant_sym)
|
||||
g.write('._${variant_name}')
|
||||
if node.obj.is_unwrapped {
|
||||
g.write('.data')
|
||||
@ -4759,7 +4773,7 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
} else if obj_sym.kind == .sum_type {
|
||||
variant_typ := g.unwrap_generic(node.obj.smartcasts.last())
|
||||
cast_sym := g.table.sym(g.unwrap_generic(node.obj.smartcasts.last()))
|
||||
variant_name := g.get_sumtype_variant_name(variant_typ, cast_sym.cname)
|
||||
variant_name := g.get_sumtype_variant_name(variant_typ, cast_sym)
|
||||
g.write('._${variant_name}')
|
||||
}
|
||||
g.write(')')
|
||||
@ -4841,11 +4855,11 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
if node.obj.is_unwrapped {
|
||||
ctyp = ctyp.set_flag(.option)
|
||||
g.write('${dot}_${g.get_sumtype_variant_name(ctyp,
|
||||
cur_variant_sym.cname)}')
|
||||
cur_variant_sym)}')
|
||||
g.write(').data')
|
||||
} else {
|
||||
g.write('${dot}_${g.get_sumtype_variant_name(ctyp,
|
||||
cur_variant_sym.cname)}')
|
||||
cur_variant_sym)}')
|
||||
}
|
||||
} else if !is_option_unwrap
|
||||
&& obj_sym.kind in [.sum_type, .interface_] {
|
||||
@ -6524,7 +6538,7 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||
for variant in sym.info.variants {
|
||||
variant_sym := g.table.sym(variant)
|
||||
mut var := if variant.has_flag(.option) { variant } else { variant.ref() }
|
||||
variant_name := g.get_sumtype_variant_name(variant, variant_sym.cname)
|
||||
variant_name := g.get_sumtype_variant_name(variant, variant_sym)
|
||||
if variant_sym.info is ast.FnType {
|
||||
if variant_sym.info.is_anon {
|
||||
var = variant
|
||||
|
@ -10,3 +10,13 @@ typedef struct Test2 {
|
||||
typedef struct Test1 {
|
||||
Test2 a;
|
||||
} Test1;
|
||||
|
||||
/////
|
||||
|
||||
typedef struct Foo {
|
||||
int a;
|
||||
} Foo;
|
||||
|
||||
typedef struct Bar {
|
||||
int a;
|
||||
} Bar;
|
||||
|
22
vlib/v/tests/c_structs/cstruct_sumtype_test.v
Normal file
22
vlib/v/tests/c_structs/cstruct_sumtype_test.v
Normal file
@ -0,0 +1,22 @@
|
||||
#include "@VMODROOT/cstruct.h"
|
||||
|
||||
const the_string = 'the string'
|
||||
|
||||
@[typedef]
|
||||
struct C.Foo {
|
||||
a int
|
||||
}
|
||||
|
||||
struct C.Bar {
|
||||
a int
|
||||
}
|
||||
|
||||
type Baz = C.Bar | C.Foo
|
||||
|
||||
fn test_cstruct() {
|
||||
a := Baz(C.Foo{
|
||||
a: 1000
|
||||
})
|
||||
dump(a)
|
||||
assert (a as C.Foo).a == 1000
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user