mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen, json: fix option ptr declaration and dumping (#18119)
This commit is contained in:
parent
a82fc5bea0
commit
1c3af091f7
@ -185,15 +185,24 @@ fn (mut g Gen) gen_str_for_option(typ ast.Type, styp string, str_fn_name string)
|
||||
g.auto_str_funcs.writeln('string indent_${str_fn_name}(${styp} it, int indent_count) {')
|
||||
g.auto_str_funcs.writeln('\tstring res;')
|
||||
g.auto_str_funcs.writeln('\tif (it.state == 0) {')
|
||||
deref := if typ.is_ptr() { '**(${sym.cname}**)&' } else { '*(${sym.cname}*)' }
|
||||
if sym.kind == .string {
|
||||
tmp_res := '${parent_str_fn_name}(*(${sym.cname}*)it.data)'
|
||||
g.auto_str_funcs.writeln('\t\tres = ${str_intp_sq(tmp_res)};')
|
||||
if typ.nr_muls() > 1 {
|
||||
g.auto_str_funcs.writeln('\t\tres = ptr_str(*(${sym.cname}**)&it.data);')
|
||||
} else {
|
||||
tmp_res := '${parent_str_fn_name}(${deref}it.data)'
|
||||
g.auto_str_funcs.writeln('\t\tres = ${str_intp_sq(tmp_res)};')
|
||||
}
|
||||
} else if should_use_indent_func(sym.kind) && !sym_has_str_method {
|
||||
g.auto_str_funcs.writeln('\t\tres = indent_${parent_str_fn_name}(*(${sym.cname}*)it.data, indent_count);')
|
||||
g.auto_str_funcs.writeln('\t\tres = indent_${parent_str_fn_name}(${deref}it.data, indent_count);')
|
||||
} else if sym.kind == .function {
|
||||
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}();')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(*(${sym.cname}*)it.data);')
|
||||
if typ.nr_muls() > 1 {
|
||||
g.auto_str_funcs.writeln('\t\tres = ptr_str(*(${sym.cname}**)&it.data);')
|
||||
} else {
|
||||
g.auto_str_funcs.writeln('\t\tres = ${parent_str_fn_name}(${deref}it.data);')
|
||||
}
|
||||
}
|
||||
g.auto_str_funcs.writeln('\t\treturn ${str_intp_sub('Option(%%)', 'res')};')
|
||||
g.auto_str_funcs.writeln('\t}')
|
||||
@ -962,13 +971,14 @@ fn (mut g Gen) gen_str_for_struct(info ast.Struct, lang ast.Language, styp strin
|
||||
} else if ftyp_noshared.is_ptr() {
|
||||
// reference types can be "nil"
|
||||
if ftyp_noshared.has_flag(.option) {
|
||||
funcprefix += 'isnil(&it.${field_name})'
|
||||
funcprefix += 'isnil(&it.${field_name}) || isnil(&it.${field_name}.data)'
|
||||
} else {
|
||||
funcprefix += 'isnil(it.${field_name})'
|
||||
}
|
||||
funcprefix += ' ? _SLIT("nil") : '
|
||||
// struct, floats and ints have a special case through the _str function
|
||||
if sym.kind !in [.struct_, .alias, .enum_, .sum_type, .map, .interface_]
|
||||
if !ftyp_noshared.has_flag(.option)
|
||||
&& sym.kind !in [.struct_, .alias, .enum_, .sum_type, .map, .interface_]
|
||||
&& !field.typ.is_int_valptr() && !field.typ.is_float_valptr() {
|
||||
funcprefix += '*'
|
||||
}
|
||||
|
@ -1099,6 +1099,8 @@ fn (g Gen) option_type_text(styp string, base string) string {
|
||||
'u8'
|
||||
} else if base.starts_with('anon_fn') {
|
||||
'void*'
|
||||
} else if base.starts_with('_option_') {
|
||||
base.replace('*', '')
|
||||
} else {
|
||||
if base.starts_with('struct ') && !base.ends_with('*') { '${base}*' } else { base }
|
||||
}
|
||||
@ -1116,6 +1118,8 @@ fn (g Gen) result_type_text(styp string, base string) string {
|
||||
'u8'
|
||||
} else if base.starts_with('anon_fn') {
|
||||
'void*'
|
||||
} else if base.starts_with('_option_') {
|
||||
base.replace('*', '')
|
||||
} else {
|
||||
if base.starts_with('struct ') && !base.ends_with('*') { '${base}*' } else { base }
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ import strings
|
||||
fn (mut g Gen) gen_json_for_type(typ ast.Type) {
|
||||
utyp := g.unwrap_generic(typ)
|
||||
sym := g.table.sym(utyp)
|
||||
if is_js_prim(sym.name) && !utyp.has_flag(.option) {
|
||||
if is_js_prim(sym.name) && !utyp.has_flag(.option) && !typ.is_ptr() {
|
||||
return
|
||||
}
|
||||
g.json_types << utyp
|
||||
@ -45,7 +45,11 @@ fn (mut g Gen) gen_jsons() {
|
||||
sym := g.table.sym(utyp)
|
||||
styp := g.typ(utyp)
|
||||
ret_styp := styp.replace('*', '_ptr')
|
||||
if utyp.is_ptr() && utyp.has_flag(.option) {
|
||||
g.register_option(utyp.set_nr_muls(0))
|
||||
}
|
||||
g.register_result(utyp)
|
||||
|
||||
// decode_TYPE funcs receive an actual cJSON* object to decode
|
||||
// cJSON_Parse(str) call is added by the compiler
|
||||
// Codegen decoder
|
||||
@ -118,7 +122,9 @@ ${dec_fn_dec} {
|
||||
enc.writeln('
|
||||
${enc_fn_dec} {
|
||||
\tcJSON *o;')
|
||||
if sym.kind == .array || sym.kind == .array_fixed {
|
||||
if is_js_prim(sym.name) && utyp.is_ptr() {
|
||||
g.gen_prim_enc_dec(utyp, mut enc, mut dec)
|
||||
} else if sym.kind == .array || sym.kind == .array_fixed {
|
||||
array_size := if sym.kind == .array_fixed {
|
||||
(sym.info as ast.ArrayFixed).size
|
||||
} else {
|
||||
@ -262,12 +268,42 @@ fn (mut g Gen) gen_enum_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc strin
|
||||
|
||||
[inline]
|
||||
fn (mut g Gen) gen_prim_enc_dec(typ ast.Type, mut enc strings.Builder, mut dec strings.Builder) {
|
||||
type_str := g.typ(typ.clear_flag(.option))
|
||||
encode_name := js_enc_name(type_str)
|
||||
enc.writeln('\to = ${encode_name}(val);')
|
||||
if typ.is_ptr() {
|
||||
type_str := g.typ(typ.clear_flag(.option).set_nr_muls(typ.nr_muls() - 1))
|
||||
type_str_0 := g.typ(typ.clear_flag(.option).set_nr_muls(0))
|
||||
encode_name := js_enc_name(type_str_0)
|
||||
dec_name := js_dec_name(type_str)
|
||||
if typ.has_flag(.option) {
|
||||
enc.writeln('\to = ${encode_name}(${'*'.repeat(typ.nr_muls() + 1)}(${type_str_0}${'*'.repeat(typ.nr_muls())}*)&val.data);')
|
||||
} else {
|
||||
enc.writeln('\to = ${encode_name}(${'*'.repeat(typ.nr_muls())}val);')
|
||||
}
|
||||
|
||||
dec_name := js_dec_name(type_str)
|
||||
dec.writeln('\tres = ${dec_name}(root);')
|
||||
if typ.nr_muls() > 1 {
|
||||
g.gen_json_for_type(typ.clear_flag(.option).set_nr_muls(typ.nr_muls() - 1))
|
||||
if typ.has_flag(.option) {
|
||||
tmp_var := g.new_tmp_var()
|
||||
dec.writeln('${type_str}* ${tmp_var} = HEAP(${type_str}, *(${type_str}*) ${dec_name}(root).data);')
|
||||
dec.writeln('\t_option_ok(&(${type_str}*[]) { &(*(${tmp_var})) }, (${option_name}*)&res, sizeof(${type_str}*));')
|
||||
} else {
|
||||
dec.writeln('\tres = HEAP(${type_str}, *(${type_str}*) ${dec_name}(root).data);')
|
||||
}
|
||||
} else {
|
||||
if typ.has_flag(.option) {
|
||||
tmp_var := g.new_tmp_var()
|
||||
dec.writeln('${type_str}* ${tmp_var} = HEAP(${type_str}, ${dec_name}(root));')
|
||||
dec.writeln('\t_option_ok(&(${type_str}*[]) { &(*(${tmp_var})) }, (${option_name}*)&res, sizeof(${type_str}*));')
|
||||
} else {
|
||||
dec.writeln('\tres = HEAP(${type_str}, ${dec_name}(root));')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
type_str := g.typ(typ.clear_flag(.option))
|
||||
encode_name := js_enc_name(type_str)
|
||||
dec_name := js_dec_name(type_str)
|
||||
enc.writeln('\to = ${encode_name}(val);')
|
||||
dec.writeln('\tres = ${dec_name}(root);')
|
||||
}
|
||||
}
|
||||
|
||||
[inline]
|
||||
|
47
vlib/v/tests/option_ptr_ptr_test.v
Normal file
47
vlib/v/tests/option_ptr_ptr_test.v
Normal file
@ -0,0 +1,47 @@
|
||||
import json
|
||||
|
||||
[heap]
|
||||
struct Foo {
|
||||
a &int
|
||||
b &string
|
||||
c &f64
|
||||
d &&int
|
||||
e &&&string
|
||||
}
|
||||
|
||||
struct FooOption {
|
||||
mut:
|
||||
a ?&int
|
||||
b ?&string
|
||||
c ?&f64
|
||||
d ?&&int
|
||||
e ?&&&string
|
||||
}
|
||||
|
||||
fn test_ptr() {
|
||||
data := '{ "a": 123, "b": "foo", "c": 1.2, "d": 321, "e": "bar"}'
|
||||
foo := json.decode(Foo, data)!
|
||||
println(foo)
|
||||
|
||||
assert dump(*foo.a) == 123
|
||||
assert dump(*foo.b) == 'foo'
|
||||
assert dump(*foo.c) == 1.2
|
||||
assert dump(**foo.d) == 321
|
||||
assert dump(***foo.e) == 'bar'
|
||||
|
||||
assert dump(json.encode(foo)) == '{"a":123,"b":"foo","c":1.2,"d":321,"e":"bar"}'
|
||||
}
|
||||
|
||||
fn test_option_ptr() ? {
|
||||
data := '{ "a": 123, "b": "foo", "c": 1.2, "d": 321, "e": "bar"}'
|
||||
foo := json.decode(FooOption, data) or { return none }
|
||||
println(foo)
|
||||
|
||||
assert dump(*foo.a?) == 123
|
||||
assert dump(*foo.b?) == 'foo'
|
||||
assert dump(*foo.c?) == 1.2
|
||||
assert dump(**foo.d?) == 321
|
||||
assert dump(***foo.e?) == 'bar'
|
||||
|
||||
assert dump(json.encode(foo)) == '{"a":123,"b":"foo","c":1.2,"d":321,"e":"bar"}'
|
||||
}
|
Loading…
Reference in New Issue
Block a user