From 36757fbe5620f42c36703aa4e261fba77ada4f40 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 15 Sep 2024 16:03:59 -0300 Subject: [PATCH 1/3] fix --- vlib/v/ast/ast.v | 1 + vlib/v/checker/checker.v | 3 +++ vlib/v/checker/fn.v | 10 ++++++---- vlib/v/fmt/fmt.v | 9 +++++++-- vlib/v/parser/expr.v | 16 +++++++++++++--- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 59faaffc480901..5f2da08dcf22dd 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -130,6 +130,7 @@ pub: pos token.Pos pub mut: typ Type + stmt Stmt = empty_stmt // for anon struct end_comments []Comment // comments that after current type node } diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 854aa497be07fb..10f3c8e7780723 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3085,6 +3085,9 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type { && c.table.cur_fn.generic_names.len == 0 { c.error('unexpected generic variable in non-generic function `${c.table.cur_fn.name}`', node.pos) + } else if node.stmt != ast.empty_stmt && node.typ == ast.void_type { + c.stmt(mut node.stmt) + node.typ = c.table.find_type_idx((node.stmt as ast.StructDecl).name) } return node.typ } diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index ccc26c0feb4820..d66aae43c5a13e 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -837,8 +837,9 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. node.pos) return ast.void_type } - expr := node.args[0].expr - if expr is ast.TypeNode { + mut expr := node.args[0].expr + if mut expr is ast.TypeNode { + expr.typ = c.expr(mut expr) mut unwrapped_typ := c.unwrap_generic(expr.typ) if c.needs_unwrap_generic_type(expr.typ) { unwrapped_typ = c.table.unwrap_generic_type(expr.typ, c.table.cur_fn.generic_names, @@ -858,8 +859,9 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. c.error('json.decode: unknown type `${sym.name}`', node.pos) } } else { - typ := expr.type_name() - c.error('json.decode: first argument needs to be a type, got `${typ}`', node.pos) + typ_name := expr.type_name() + c.error('json.decode: first argument needs to be a type, got `${typ_name}`', + node.pos) return ast.void_type } c.expected_type = ast.string_type diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 61c14da39687c2..9b804db636e34e 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -3215,8 +3215,13 @@ pub fn (mut f Fmt) string_inter_literal(node ast.StringInterLiteral) { } pub fn (mut f Fmt) type_expr(node ast.TypeNode) { - f.mark_types_import_as_used(node.typ) - f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) + if node.stmt == ast.empty_stmt { + f.mark_types_import_as_used(node.typ) + f.write(f.table.type_to_str_using_aliases(node.typ, f.mod2alias)) + } else { + f.struct_decl(ast.StructDecl{ fields: (node.stmt as ast.StructDecl).fields }, + true) + } } pub fn (mut f Fmt) type_of(node ast.TypeOf) { diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index 31965a130ab4a0..07e92fddc7979e 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -478,9 +478,19 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr { } else { if p.tok.kind == .key_struct && p.peek_tok.kind == .lcbr { - // Anonymous struct - p.next() - return p.struct_init('', .anon, false) + if p.expecting_type && p.inside_call_args { + // Anonymous struct for json.decode + tok_pos := p.tok.pos() + return ast.TypeNode{ + stmt: p.struct_decl(true) + pos: tok_pos + typ: ast.void_type + } + } else { + // Anonymous struct + p.next() + return p.struct_init('', .anon, false) + } } if p.tok.kind != .eof && !(p.tok.kind == .rsbr && p.inside_asm) { // eof should be handled where it happens From 34c4a4b94f5d7d8ab0142d2fd071c56131099ec5 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sun, 15 Sep 2024 16:04:11 -0300 Subject: [PATCH 2/3] test --- vlib/json/json_decode_anon_struct_test.v | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 vlib/json/json_decode_anon_struct_test.v diff --git a/vlib/json/json_decode_anon_struct_test.v b/vlib/json/json_decode_anon_struct_test.v new file mode 100644 index 00000000000000..fc20b70a3fc182 --- /dev/null +++ b/vlib/json/json_decode_anon_struct_test.v @@ -0,0 +1,9 @@ +import json + +fn test_main() { + json_text := '{ "a": "b" }' + b := json.decode(struct { + a string + }, json_text)!.a + assert dump(b) == 'b' +} From 90bd8edaf4b8d4745ef15e071c72934266d6cf42 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 16 Sep 2024 18:14:44 -0300 Subject: [PATCH 3/3] revert change --- vlib/v/checker/fn.v | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index d66aae43c5a13e..52e356f44be75f 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -859,9 +859,8 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. c.error('json.decode: unknown type `${sym.name}`', node.pos) } } else { - typ_name := expr.type_name() - c.error('json.decode: first argument needs to be a type, got `${typ_name}`', - node.pos) + typ := expr.type_name() + c.error('json.decode: first argument needs to be a type, got `${typ}`', node.pos) return ast.void_type } c.expected_type = ast.string_type