mirror of
https://github.com/vlang/v.git
synced 2025-09-11 16:36:20 -04:00
json: support null sum types in decode()
This commit is contained in:
parent
b1c9941065
commit
9c0a7e7955
@ -373,8 +373,26 @@ fn (mut g Gen) gen_sumtype_enc_dec(utyp ast.Type, sym ast.TypeSymbol, mut enc st
|
||||
|
||||
// DECODING (inline)
|
||||
$if !json_no_inline_sumtypes ? {
|
||||
// Handle "key": null
|
||||
// In this case the first variant must be used (something like InvalidExpr for example)
|
||||
// An empty instance of the first variant is generated.
|
||||
// This way the user can easily check if the sum type was not provided in json ("key":null):
|
||||
// `if node.expr is InvalidExpr { ... }`
|
||||
// (Do this only for structs)
|
||||
type_tmp := g.new_tmp_var()
|
||||
dec.writeln('\tif (cJSON_IsObject(root) || (cJSON_IsArray(root) && cJSON_IsObject(root->child))) {')
|
||||
first_variant := info.variants[0]
|
||||
variant_typ := g.typ(first_variant)
|
||||
fv_sym := g.table.sym(first_variant)
|
||||
first_variant_name := fv_sym.cname
|
||||
// println('KIND=${fv_sym.kind}')
|
||||
if fv_sym.kind == .struct_ && !is_option && field_op != '->' {
|
||||
dec.writeln('/*sum type ${fv_sym.name} ret_styp=${ret_styp}*/\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('if (cJSON_IsObject(root) || (cJSON_IsArray(root) && cJSON_IsObject(root->child))) {')
|
||||
dec.writeln('\t\tcJSON* ${type_tmp} = cJSON_IsObject(root) ? js_get(root, "_type") : js_get(root->child, "_type");')
|
||||
dec.writeln('\t\tif (${type_tmp} != 0) {')
|
||||
dec.writeln('\t\t\tchar* ${type_var} = cJSON_GetStringValue(${type_tmp});')
|
||||
@ -924,6 +942,7 @@ fn gen_js_get_opt(dec_name string, field_type string, styp string, tmp string, n
|
||||
value_field_type := field_type.replace('*', '_ptr')
|
||||
dec.writeln('\t${result_name}_${value_field_type.replace('*', '_ptr')} ${tmp} = {0};')
|
||||
dec.writeln('\tif (jsonroot_${tmp}) {')
|
||||
// dec.writeln('\t\tif (jsonroot_${tmp}->type == cJSON_NULL) { puts("${name} IS JSON_NULL"); }')
|
||||
dec.writeln('\t\t${tmp} = ${dec_name}(jsonroot_${tmp});')
|
||||
dec.writeln('\t\tif (${tmp}.is_error) {')
|
||||
dec.writeln('\t\t\treturn (${result_name}_${styp}){ /*A*/ .is_error = true, .err = ${tmp}.err, .data = {0} };')
|
||||
|
@ -197,7 +197,9 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr) ast.Stmt {
|
||||
ast.Ident {
|
||||
if op == .decl_assign {
|
||||
if p.scope.known_var(lx.name) {
|
||||
return p.error_with_pos('redefinition of `${lx.name}`', lx.pos)
|
||||
if !(p.pref.translated_go && lx.name in ['err', 'ok']) {
|
||||
return p.error_with_pos('redefinition of `${lx.name}`', lx.pos)
|
||||
}
|
||||
}
|
||||
mut share := unsafe { ast.ShareType(0) }
|
||||
if mut lx.info is ast.IdentVar {
|
||||
|
@ -2900,7 +2900,10 @@ fn (mut p Parser) name_expr() ast.Expr {
|
||||
}
|
||||
} else if p.peek_tok.kind == .lcbr
|
||||
&& ((p.inside_if && lit0_is_capital && p.tok.lit.len > 1 && !known_var && language == .v)
|
||||
|| (p.inside_match_case && p.tok.kind == .name && p.peek_tok.is_next_to(p.tok))) {
|
||||
|| (p.inside_match_case && lit0_is_capital && p.tok.kind == .name
|
||||
&& p.peek_tok.is_next_to(p.tok))) {
|
||||
// XTODO check iscap
|
||||
//|| (p.inside_match_case && p.tok.kind == .name && p.peek_tok.is_next_to(p.tok))) {
|
||||
// `if a == Foo{} {...}` or `match foo { Foo{} {...} }`
|
||||
return p.struct_init(p.mod + '.' + p.tok.lit, .normal, is_option)
|
||||
} else if p.peek_tok.kind == .dot && lit0_is_capital && !known_var && language == .v {
|
||||
|
@ -125,8 +125,9 @@ pub mut:
|
||||
profile_no_inline bool // when true, @[inline] functions would not be profiled
|
||||
profile_fns []string // when set, profiling will be off by default, but inside these functions (and what they call) it will be on.
|
||||
translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
|
||||
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
|
||||
hide_auto_str bool // `v -hide-auto-str program.v`, doesn't generate str() with struct data
|
||||
translated_go bool = true // Are we running V code translated from Go? Allow err shadowing
|
||||
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
|
||||
hide_auto_str bool // `v -hide-auto-str program.v`, doesn't generate str() with struct data
|
||||
// Note: passing -cg instead of -g will set is_vlines to false and is_debug to true, thus making v generate cleaner C files,
|
||||
// which are sometimes easier to debug / inspect manually than the .tmp.c files by plain -g (when/if v line number generation breaks).
|
||||
sanitize bool // use Clang's new "-fsanitize" option
|
||||
@ -659,6 +660,10 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||
res.translated = true
|
||||
res.gc_mode = .no_gc // no gc in c2v'ed code, at least for now
|
||||
}
|
||||
'-translated-go' {
|
||||
println('got -translated-go')
|
||||
res.translated_go = true
|
||||
}
|
||||
'-m32', '-m64' {
|
||||
res.m64 = arg[2] == `6`
|
||||
res.cflags += ' ${arg}'
|
||||
|
Loading…
x
Reference in New Issue
Block a user