From 39434155f834e0b0665826df9dd7997f8d81ad68 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 1 Apr 2020 23:23:20 +0200 Subject: [PATCH] short struct init syntax --- vlib/v/checker/checker.v | 8 +++ vlib/v/parser/parser.v | 132 +++++++++++++++++++++---------------- vlib/v/tests/struct_test.v | 4 +- 3 files changed, 86 insertions(+), 58 deletions(-) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 48f60868dd..8ac086051d 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -76,6 +76,14 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type { // c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos) // panic('') // } + if struct_init.typ == table.void_type { + // Short syntax `({foo: bar})` + if c.expected_type == table.void_type { + c.error('unexpected short struct syntax', struct_init.pos) + return table.void_type + } + struct_init.typ = c.expected_type + } typ_sym := c.table.get_type_symbol(struct_init.typ) // println('check struct $typ_sym.name') match typ_sym.kind { diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index a922e68bf2..2a1da5a35b 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -52,7 +52,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt { pref: &pref.Preferences{} scope: scope // scope: &ast.Scope{start_pos: 0, parent: 0} - + } p.init_parse_fns() p.read_first_token() @@ -71,13 +71,13 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment table: table file_name: path pref: pref // &pref.Preferences{} - + scope: &ast.Scope{ start_pos: 0 parent: 0 } // comments_mode: comments_mode - + } p.read_first_token() // p.scope = &ast.Scope{start_pos: p.tok.position(), parent: 0} @@ -548,12 +548,14 @@ pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident { return ident } -fn (p mut Parser) struct_init() ast.StructInit { - typ := p.parse_type() +fn (p mut Parser) struct_init(short_syntax bool) ast.StructInit { + typ := if short_syntax { table.void_type } else { p.parse_type() } p.expr_mod = '' // sym := p.table.get_type_symbol(typ) // p.warn('struct init typ=$sym.name') - p.check(.lcbr) + if !short_syntax { + p.check(.lcbr) + } mut field_names := []string mut exprs := []ast.Expr mut i := 0 @@ -585,7 +587,9 @@ fn (p mut Parser) struct_init() ast.StructInit { fields: field_names pos: p.tok.position() } - p.check(.rcbr) + if !short_syntax { + p.check(.rcbr) + } return node } @@ -674,7 +678,7 @@ pub fn (p mut Parser) name_expr() ast.Expr { // { // || p.table.known_type(p.tok.lit)) { - return p.struct_init() + return p.struct_init(false) // short_syntax: false } else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var) { // `Color.green` @@ -692,7 +696,7 @@ pub fn (p mut Parser) name_expr() ast.Expr { p.expr_mod = '' return ast.EnumVal{ enum_name: enum_name // lp.prepend_mod(enum_name) - + val: val pos: p.tok.position() mod: mod @@ -782,7 +786,7 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr { node = ast.SizeOf{ typ: sizeof_type // type_name: type_name - + } } .key_typeof { @@ -798,53 +802,17 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr { .lcbr { p.next() if p.tok.kind == .string { - mut keys := []ast.Expr - mut vals := []ast.Expr - for p.tok.kind != .rcbr && p.tok.kind != .eof { - // p.check(.str) - key := p.expr(0) - keys << key - p.check(.colon) - val := p.expr(0) - vals << val - if p.tok.kind == .comma { - p.next() - } - } - node = ast.MapInit{ - keys: keys - vals: vals - pos: p.tok.position() - } + node = p.map_init() } else { - name := p.check_name() - var := p.scope.find_var(name) or { - p.error('unknown variable `$name`') - return node + if p.peek_tok.kind == .pipe { + node = p.assoc() } - // println('assoc var $name typ=$var.typ') - mut fields := []string - mut vals := []ast.Expr - p.check(.pipe) - for { - fields << p.check_name() - p.check(.colon) - expr := p.expr(0) - vals << expr - if p.tok.kind == .comma { - p.check(.comma) - } - if p.tok.kind == .rcbr { - break - } + else if p.peek_tok.kind == .colon || p.tok.kind == .rcbr { + node = p.struct_init(true) // short_syntax: true } - node = ast.Assoc{ - var_name: name - fields: fields - exprs: vals - pos: p.tok.position() - typ: var.typ + else { + p.error('unexpected {') } } p.check(.rcbr) @@ -1053,7 +1021,7 @@ fn (p mut Parser) infix_expr(left ast.Expr) ast.Expr { left: left right: right // right_type: typ - + op: op pos: pos } @@ -1374,6 +1342,28 @@ fn (p mut Parser) array_init() ast.ArrayInit { } } +fn (p mut Parser) map_init() ast.MapInit { + pos := p.tok.position() + mut keys := []ast.Expr + mut vals := []ast.Expr + for p.tok.kind != .rcbr && p.tok.kind != .eof { + // p.check(.str) + key := p.expr(0) + keys << key + p.check(.colon) + val := p.expr(0) + vals << val + if p.tok.kind == .comma { + p.next() + } + } + return ast.MapInit{ + keys: keys + vals: vals + pos: pos + } +} + fn (p mut Parser) parse_number_literal() ast.Expr { lit := p.tok.lit mut node := ast.Expr{} @@ -1458,7 +1448,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl { fields << ast.Field{ name: name // typ: typ - + } exprs << expr // TODO: once consts are fixed reg here & update in checker @@ -1943,6 +1933,38 @@ fn (p mut Parser) type_decl() ast.TypeDecl { } } +fn (p mut Parser) assoc() ast.Assoc{ + var_name := p.check_name() + pos := p.tok.position() + var := p.scope.find_var(var_name) or { + p.error('unknown variable `$var_name`') + return ast.Assoc{} + } + // println('assoc var $name typ=$var.typ') + mut fields := []string + mut vals := []ast.Expr + p.check(.pipe) + for { + fields << p.check_name() + p.check(.colon) + expr := p.expr(0) + vals << expr + if p.tok.kind == .comma { + p.check(.comma) + } + if p.tok.kind == .rcbr { + break + } + } + return ast.Assoc{ + var_name: var_name + fields: fields + exprs: vals + pos: pos + typ: var.typ + } +} + fn (p &Parser) new_true_expr() ast.Expr { return ast.BoolLiteral{ val: true diff --git a/vlib/v/tests/struct_test.v b/vlib/v/tests/struct_test.v index 2210cf9c66..312e79038a 100644 --- a/vlib/v/tests/struct_test.v +++ b/vlib/v/tests/struct_test.v @@ -236,7 +236,6 @@ fn foo_config(c Config) {} fn foo2(u User) {} fn test_config() { - /* foo_config({ n: 10 def: 20 @@ -245,5 +244,4 @@ fn test_config() { foo2({ name: 'Peter' }) - */ - } +}