parser: map or block; checker: require ref field init

pull/7416/head
Alexander Medvednikov 2020-12-19 10:28:17 +01:00
parent 3a86f27b9f
commit 1f74f83bc6
6 changed files with 46 additions and 12 deletions

View File

@ -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 }
}

View File

@ -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

View File

@ -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

View File

@ -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 {}``

View File

@ -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
}
}
}

View File

@ -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{}
}