From cd4f7101f7c1e946cbb0e402c957c624c499ef65 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 7 Feb 2021 02:43:51 +0000 Subject: [PATCH] parser: support short struct update syntax `{...ident,` (#8613) --- doc/docs.md | 4 +++- vlib/v/parser/pratt.v | 3 ++- vlib/v/tests/struct_test.v | 4 +++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/docs.md b/doc/docs.md index 0958a12e73..bebf315d87 100644 --- a/doc/docs.md +++ b/doc/docs.md @@ -1633,6 +1633,8 @@ Only more complex types such as arrays and maps may be modified. Use `user.register()` or `user = register(user)` instead of `register(mut user)`. +#### Struct update syntax + V makes it easy to return a modified version of an object: ```v @@ -1644,7 +1646,7 @@ struct User { fn register(u User) User { return { - u | + ...u is_registered: true } } diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index f3cb27ab45..d8f9b31761 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -246,7 +246,8 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { // it should be a struct if p.peek_tok.kind == .pipe { node = p.assoc() - } else if p.peek_tok.kind == .colon || p.tok.kind in [.rcbr, .comment] { + } else if (p.tok.kind == .name && p.peek_tok.kind == .colon) + || p.tok.kind in [.rcbr, .comment, .ellipsis] { node = p.struct_init(true) // short_syntax: true } else if p.tok.kind == .name { p.next() diff --git a/vlib/v/tests/struct_test.v b/vlib/v/tests/struct_test.v index 8eba8b8a0f..b7ae7c1c31 100644 --- a/vlib/v/tests/struct_test.v +++ b/vlib/v/tests/struct_test.v @@ -164,12 +164,14 @@ fn test_assoc_with_vars() { def2 := Def{ a: 12 } - merged := Def{ + mut merged := Def{ ...def2 a: 42 } assert merged.a == 42 assert merged.b == 7 + merged = {...def2, b: 9} + assert merged == Def{12, 9} def3 := &Def{ 100, 200 } merged1 := Def{...(*def3)}