From 1f74f83bc66fcf23e6605ea8c9e60b88dc760656 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sat, 19 Dec 2020 10:28:17 +0100 Subject: [PATCH] parser: map or block; checker: require ref field init --- vlib/builtin/map_test.v | 27 ++++++++++++++++++--------- vlib/v/ast/ast.v | 1 + vlib/v/checker/checker.v | 2 +- vlib/v/parser/fn.v | 2 +- vlib/v/parser/parser.v | 24 ++++++++++++++++++++++++ vlib/v/parser/pratt.v | 2 +- 6 files changed, 46 insertions(+), 12 deletions(-) diff --git a/vlib/builtin/map_test.v b/vlib/builtin/map_test.v index 83c5a2b934..17c359b129 100644 --- a/vlib/builtin/map_test.v +++ b/vlib/builtin/map_test.v @@ -404,9 +404,9 @@ fn test_mut_map_with_relation_op_in_fn() { fn test_map_str_after_delete() { mut m := { - 'first': 1 + 'first': 1 'second': 2 - 'third': 3 + 'third': 3 } osm := '$m' m.delete('second') @@ -429,7 +429,7 @@ fn test_modify_map_value() { fn test_map_clone() { mut nums := { - 'foo': 1, + 'foo': 1 'bar': 2 } mut nums2 := nums.clone() @@ -442,14 +442,23 @@ fn test_map_clone() { } struct MValue { - name string - misc map[string]string + name string + misc map[string]string } fn test_map_default_zero() { - m := map[string]MValue{} - v := m['unknown'] - x := v.misc['x'] - println(x) + m := map[string]MValue{} + v := m['unknown'] + x := v.misc['x'] + println(x) assert x == '' } + +fn test_map_or() { + m := { + 'first': 1 + 'second': 2 + 'third': 3 + } + // num := m['first'] or { return } +} diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index cefe86dfcc..29e1efaa76 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -524,6 +524,7 @@ pub: pos token.Position left Expr index Expr // [0], RangeExpr [start..end] or map[key] + or_expr OrExpr pub mut: left_type table.Type // array, map, fixed array is_setter bool diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index fe53336286..886e4d949e 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -591,7 +591,7 @@ pub fn (mut c Checker) struct_init(mut struct_init ast.StructInit) table.Type { continue } if field.typ.is_ptr() && !c.pref.translated { - c.warn('reference field `${type_sym.name}.$field.name` must be initialized', + c.error('reference field `${type_sym.name}.$field.name` must be initialized', struct_init.pos) } // Check for `[required]` struct attr diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 32a924323e..2e2c6f1b4d 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -54,7 +54,7 @@ pub fn (mut p Parser) call_expr(language table.Language, mod string) ast.CallExp p.next() } pos := first_pos.extend(last_pos) - mut or_stmts := []ast.Stmt{} + mut or_stmts := []ast.Stmt{} // TODO remove unnecessary allocations by just using .absent mut or_pos := p.tok.position() if p.tok.kind == .key_orelse { // `foo() or {}`` diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 535269d203..41f22e8b2e 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1326,10 +1326,34 @@ fn (mut p Parser) index_expr(left ast.Expr) ast.IndexExpr { // [expr] pos := start_pos.extend(p.tok.position()) p.check(.rsbr) + // a[i] or { ... } + if p.tok.kind == .key_orelse { + was_inside_or_expr := p.inside_or_expr + mut or_pos := p.tok.position() + p.next() + p.open_scope() + or_stmts := p.parse_block_no_scope(false) + or_pos = or_pos.extend(p.prev_tok.position()) + p.close_scope() + p.inside_or_expr = was_inside_or_expr + return ast.IndexExpr{ + left: left + index: expr + pos: pos + or_expr: ast.OrExpr{ + kind: .block + stmts: or_stmts + pos: or_pos + } + } + } return ast.IndexExpr{ left: left index: expr pos: pos + or_expr: ast.OrExpr{ + kind: .absent + } } } diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index 3207d8892c..debe374b27 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -244,7 +244,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { else { if p.tok.kind != .eof { // eof should be handled where it happens - p.error_with_pos('invalid expression: unexpected $p.tok.kind.str() token', + p.error_with_pos('invalid expression: unexpected `$p.tok.kind.str()` token', p.tok.position()) return ast.Expr{} }