diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 028b96607f..66be4430f1 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -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})' - } 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('}') + 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 { + g.write(')'.repeat(rparen_n)) } - 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()` diff --git a/vlib/v/gen/c/json.v b/vlib/v/gen/c/json.v index cf40af0899..db30ad49bd 100644 --- a/vlib/v/gen/c/json.v +++ b/vlib/v/gen/c/json.v @@ -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}') }