sumtype cast func, add param

This commit is contained in:
kbkpbot 2025-08-16 17:18:35 +08:00
parent 167fa07207
commit 43c20c41ff
2 changed files with 38 additions and 55 deletions

View file

@ -2805,9 +2805,10 @@ fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
} else {
// g.definitions.writeln('${g.static_modifier} inline ${exp_cname} ${fun.fn_name}(${got_cname}* x);')
// sb.writeln('${g.static_modifier} inline ${exp_cname} ${fun.fn_name}(${got_cname}* x) {')
g.definitions.writeln('${exp_cname} ${fun.fn_name}(${got_cname}* x);')
sb.writeln('${exp_cname} ${fun.fn_name}(${got_cname}* x) {')
sb.writeln('\t${got_cname}* ptr = memdup(x, sizeof(${got_cname}));')
g.definitions.writeln('${exp_cname} ${fun.fn_name}(${got_cname}* x, bool is_mut);')
sb.writeln('${exp_cname} ${fun.fn_name}(${got_cname}* x, bool is_mut) {')
sb.writeln('\t${got_cname}* ptr = x;')
sb.writeln('\tif (!is_mut) { ptr = memdup(x, sizeof(${got_cname})); }')
}
for embed_hierarchy in g.table.get_embeds(got_sym) {
// last embed in the hierarchy
@ -2827,14 +2828,8 @@ fn (mut g Gen) write_sumtype_casting_fn(fun SumtypeCastingFn) {
sb.writeln('\t${embed_cname}* ${embed_name}_ptr = memdup(${accessor}, sizeof(${embed_cname}));')
}
sb.write_string('\treturn (${exp_cname}){ ._${variant_name} = ptr, ._typ = ${type_idx}')
g.write_sumtype_casting_fn_common_fields(mut sb, exp_sym, got_cname, got_sym, 'ptr')
sb.writeln('};\n}')
g.auto_fn_definitions << sb.str()
}
fn (mut g Gen) write_sumtype_casting_fn_common_fields(mut sb strings.Builder, exp_sym ast.TypeSymbol, got_cname string, got_sym ast.TypeSymbol, ptr_name string) {
for field in (exp_sym.info as ast.SumType).fields {
mut ptr := ptr_name
mut ptr := 'ptr'
mut type_cname := got_cname
_, embed_types := g.table.find_field_from_embeds(got_sym, field.name) or {
ast.StructField{}, []ast.Type{}
@ -2847,28 +2842,26 @@ fn (mut g Gen) write_sumtype_casting_fn_common_fields(mut sb strings.Builder, ex
field_styp := g.styp(field.typ)
if got_sym.kind in [.sum_type, .interface] {
// the field is already a wrapped pointer; we shouldn't wrap it once again
sb.write_string(', .${c_name(field.name)} = ${ptr}->${field.name}')
sb.write_string(', .${c_name(field.name)} = ptr->${field.name}')
} else {
sb.write_string(', .${c_name(field.name)} = (${field_styp}*)((char*)${ptr} + __offsetof_ptr(${ptr}, ${type_cname}, ${c_name(field.name)}))')
}
}
sb.writeln('};\n}')
g.auto_fn_definitions << sb.str()
}
fn (mut g Gen) call_cfn_for_casting_expr(fname string, expr ast.Expr, exp ast.Type, got ast.Type, exp_styp string,
got_is_ptr bool, got_is_fn bool, got_styp string) {
mut rparen_n := 1
mut mutable_idx := 0
mut mutable_is_mut_arg_pos := 0
is_not_ptr_and_fn := !got_is_ptr && !got_is_fn
is_sumtype_cast := !got_is_fn && fname.contains('_to_sumtype_')
is_comptime_variant := is_not_ptr_and_fn && expr is ast.Ident
&& g.comptime.is_comptime_variant_var(expr)
if exp.is_ptr() {
if is_sumtype_cast && g.expected_arg_mut && expr in [ast.Ident, ast.SelectorExpr] {
g.write('&(${exp_styp.trim_right('*')}){._${got_styp.trim_right('*')}=')
rparen_n = 0
mutable_idx = got.idx()
} else if (expr is ast.UnsafeExpr && expr.expr is ast.Nil) || got == ast.nil_type {
if (expr is ast.UnsafeExpr && expr.expr is ast.Nil) || got == ast.nil_type {
g.write('(void*)0')
return
} else {
@ -2878,6 +2871,7 @@ fn (mut g Gen) call_cfn_for_casting_expr(fname string, expr ast.Expr, exp ast.Ty
} else {
g.write('${fname}(')
}
mutable_is_mut_arg_pos = rparen_n
if is_not_ptr_and_fn {
is_cast_fixed_array_init := expr is ast.CastExpr
&& (expr.expr is ast.ArrayInit && expr.expr.is_fixed)
@ -2918,25 +2912,14 @@ fn (mut g Gen) call_cfn_for_casting_expr(fname string, expr ast.Expr, exp ast.Ty
g.expr(expr)
g.left_is_opt = old_left_is_opt
}
if mutable_idx != 0 {
g.write(', ._typ=${mutable_idx}')
// setup other common fields in sumtype
mut sb := strings.new_builder(256)
got_sym, exp_sym := g.table.sym(got), g.table.sym(exp)
got_cname := g.get_sumtype_variant_type_name(got, got_sym)
mutable_sumtype_ptr_name := g.expr_string(expr)
ptr_name := if got_is_ptr {
'(${mutable_sumtype_ptr_name})'
if is_sumtype_cast {
// the `_to_sumtype_` family of functions last `is_mut` param
g.write(')'.repeat(rparen_n - mutable_is_mut_arg_pos))
g.write(', ${exp.is_ptr()}')
g.write(')'.repeat(mutable_is_mut_arg_pos))
} else {
'(&(${mutable_sumtype_ptr_name}))'
}
g.write_sumtype_casting_fn_common_fields(mut sb, exp_sym, got_cname, got_sym,
ptr_name)
g.write(sb.str())
g.write('}')
}
g.write(')'.repeat(rparen_n))
}
}
// use instead of expr() when you need a var to use as reference
@ -3118,7 +3101,7 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
g.expr(expr)
g.writeln(';')
g.write2(stmt_str, ' ')
g.write('${fname}(&${tmp_var})')
g.write('${fname}(&${tmp_var}, ${unwrapped_expected_type.is_ptr()})')
return
} else {
g.call_cfn_for_casting_expr(fname, expr, expected_type, got_type,
@ -3523,7 +3506,7 @@ fn (mut g Gen) gen_clone_assignment(var_type ast.Type, val ast.Expr, typ ast.Typ
g.write('}, sizeof(${shared_styp}))')
}
if is_sumtype {
g.write('))')
g.write('), false)')
}
} else if right_sym.kind == .string {
// `str1 = str2` => `str1 = str2.clone()`

View file

@ -381,8 +381,8 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
if fv_sym.kind == .struct && !is_option && field_op != '->' {
dec.writeln('\tif (root->type == cJSON_NULL) { ')
dec.writeln('\t\tstruct ${first_variant_name} empty = {0};')
dec.writeln('res = ${variant_typ}_to_sumtype_${ret_styp}(&empty); } \n else ')
// dec.writeln('res = ${variant_typ}_to_sumtype_${sym.cname}(&empty); } \n else ')
dec.writeln('res = ${variant_typ}_to_sumtype_${ret_styp}(&empty, false); } \n else ')
// dec.writeln('res = ${variant_typ}_to_sumtype_${sym.cname}(&empty, false); } \n else ')
}
//
dec.writeln('if (cJSON_IsObject(root) || (cJSON_IsArray(root) && cJSON_IsObject(root->child))) {')
@ -409,7 +409,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
// Helpers for decoding
g.get_sumtype_casting_fn(variant, typ)
g.definitions.writeln('static inline ${sym.cname} ${variant_typ}_to_sumtype_${sym.cname}(${variant_typ}* x);')
g.definitions.writeln('static inline ${sym.cname} ${variant_typ}_to_sumtype_${sym.cname}(${variant_typ}* x, bool is_mut);')
// ENCODING
enc.writeln('\tif (${var_data}${field_op}_typ == ${int(variant.idx())}) {')
@ -485,9 +485,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
dec.writeln('\t\t${variant_typ} value = *(${variant_typ}*)(${tmp}.data);')
}
if is_option {
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${variant_typ}_to_sumtype_${sym.cname}(&value) }, (${option_name}*)&res, sizeof(${sym.cname}));')
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${variant_typ}_to_sumtype_${sym.cname}(&value, false) }, (${option_name}*)&res, sizeof(${sym.cname}));')
} else {
dec.writeln('\t\tres = ${variant_typ}_to_sumtype_${ret_styp}(&value);')
dec.writeln('\t\tres = ${variant_typ}_to_sumtype_${ret_styp}(&value, false);')
}
dec.writeln('\t}')
} $else {
@ -498,10 +498,10 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
if utyp.has_flag(.option) {
dec.writeln('\t\t\t\t${prefix}res.state = 0;')
tmp_time_var := g.new_tmp_var()
dec.writeln('\t\t\t\t${g.base_type(utyp)} ${tmp_time_var} = ${variant_typ}_to_sumtype_${sym.cname}(&${tmp});')
dec.writeln('\t\t\t\t${g.base_type(utyp)} ${tmp_time_var} = ${variant_typ}_to_sumtype_${sym.cname}(&${tmp}, false);')
dec.writeln('\t\t\t\tvmemcpy(&${prefix}res.data, ${tmp_time_var}._time__Time, sizeof(${variant_typ}));')
} else {
dec.writeln('\t\t\t\t${prefix}res = ${variant_typ}_to_sumtype_${sym.cname}(&${tmp});')
dec.writeln('\t\t\t\t${prefix}res = ${variant_typ}_to_sumtype_${sym.cname}(&${tmp}, false);')
}
dec.writeln('\t\t\t}')
} else if !is_js_prim(variant_typ) && variant_sym.kind != .enum {
@ -512,9 +512,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
dec.writeln('\t\t\t\t\treturn (${result_name}_${ret_styp}){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t\t}')
if is_option {
dec.writeln('\t\t\t\t_option_ok(&(${sym.cname}[]){ ${variant_typ}_to_sumtype_${sym.cname}((${variant_typ}*)${tmp}.data) }, (${option_name}*)&res, sizeof(${sym.cname}));')
dec.writeln('\t\t\t\t_option_ok(&(${sym.cname}[]){ ${variant_typ}_to_sumtype_${sym.cname}((${variant_typ}*)${tmp}.data, false) }, (${option_name}*)&res, sizeof(${sym.cname}));')
} else {
dec.writeln('\t\t\t\t${prefix}res = ${variant_typ}_to_sumtype_${sym.cname}((${variant_typ}*)${tmp}.data);')
dec.writeln('\t\t\t\t${prefix}res = ${variant_typ}_to_sumtype_${sym.cname}((${variant_typ}*)${tmp}.data, false);')
}
dec.writeln('\t\t\t}')
}
@ -536,7 +536,7 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
var_t := 'bool'
dec.writeln('\t\tif (cJSON_IsBool(root)) {')
dec.writeln('\t\t\t${var_t} value = ${js_dec_name(var_t)}(root);')
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value, false);')
dec.writeln('\t\t}')
}
@ -552,9 +552,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
dec.writeln('\t\tif (cJSON_IsNumber(root)) {')
dec.writeln('\t\t\t${var_t} value = ${js_dec_name('u64')}(root);')
if utyp.has_flag(.option) {
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value, false) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
} else {
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value, false);')
}
dec.writeln('\t\t}')
}
@ -568,9 +568,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
dec.writeln('\t\tif (cJSON_IsString(root)) {')
dec.writeln('\t\t\t${var_t} value = ${js_dec_name(var_t)}(root);')
if utyp.has_flag(.option) {
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value, false) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
} else {
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value, false);')
}
dec.writeln('\t\t}')
}
@ -592,9 +592,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
dec.writeln('\t\t\t\treturn (${result_name}_${ret_styp}){ .is_error = true, .err = ${tmp}.err, .data = {0} };')
dec.writeln('\t\t\t}')
if utyp.has_flag(.option) {
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}((${var_t}*)${tmp}.data) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}((${var_t}*)${tmp}.data, false) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
} else {
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}((${var_t}*)${tmp}.data);')
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}((${var_t}*)${tmp}.data, false);')
}
dec.writeln('\t\t}')
}
@ -611,9 +611,9 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
dec.writeln('\t\tif (cJSON_IsNumber(root)) {')
dec.writeln('\t\t\t${var_t} value = ${js_dec_name(var_t)}(root);')
if utyp.has_flag(.option) {
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
dec.writeln('\t\t\t_option_ok(&(${sym.cname}[]){ ${var_t}_to_sumtype_${sym.cname}(&value, false) }, (${option_name}*)&${prefix}res, sizeof(${sym.cname}));')
} else {
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value);')
dec.writeln('\t\t\t${prefix}res = ${var_t}_to_sumtype_${sym.cname}(&value, false);')
}
dec.writeln('\t\t}')
}