parser: support custom fixed size ArrayInit: `[3]int{init: -1}` (#6114)

pull/6137/head
Nick Treleaven 2020-08-15 10:01:54 +01:00 committed by GitHub
parent 5f3ced7213
commit 0f0a91fc9e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 12 deletions

View File

@ -733,7 +733,7 @@ pub struct ArrayInit {
pub:
pos token.Position
elem_type_pos token.Position
exprs []Expr
exprs []Expr // `[expr, expr]` or `[expr]Type{}` for fixed array
is_fixed bool
has_val bool // fixed size literal `[expr, expr]!!`
mod string

View File

@ -1734,6 +1734,11 @@ pub fn (mut f Fmt) array_init(it ast.ArrayInit) {
// `[100]byte`
if it.is_fixed {
f.write(f.type_to_str(it.elem_type))
if it.has_default {
f.write('{init: $it.default_expr}')
} else {
f.write('{}')
}
}
}

View File

@ -11,7 +11,7 @@ fn main() {
]
x := []int{len: 10, cap: 100, init: 1}
_ := expected_flags
buf := [100]byte
buf := [100]byte{}
println(x)
println(buf)
}

View File

@ -1499,7 +1499,20 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
if !cloned {
if is_decl {
if is_fixed_array_init && !has_val {
if val is ast.ArrayInit {
if val.has_default {
g.write('{$val.default_expr')
info := right_sym.info as table.ArrayFixed
for _ in 1 .. info.size {
g.write(', $val.default_expr')
}
g.write('}')
} else {
g.write('{0}')
}
} else {
g.write('{0}')
}
} else {
g.expr(val)
}
@ -2152,8 +2165,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
g.write(')')
} else if node.op in [.eq, .ne] &&
left_sym.kind == .array_fixed && right_sym.kind == .array_fixed {
af := left_sym.info as table.ArrayFixed
et := af.elem_type
info := left_sym.info as table.ArrayFixed
et := info.elem_type
if !et.is_ptr() && !et.is_pointer() && !et.is_number() && et.idx() !in [table.bool_type_idx, table.char_type_idx] {
verror('`==` on fixed array only supported with POD element types ATM')
}

View File

@ -19,6 +19,8 @@ fn (mut p Parser) array_init() ast.ArrayInit {
mut is_fixed := false
mut has_val := false
mut has_type := false
mut has_default := false
mut default_expr := ast.Expr{}
if p.tok.kind == .rsbr {
// []typ => `[]` and `typ` must be on the same line
line_nr := p.tok.line_nr
@ -28,7 +30,7 @@ fn (mut p Parser) array_init() ast.ArrayInit {
elem_type_pos = p.tok.position()
elem_type = p.parse_type()
sym := p.table.get_type_symbol(elem_type)
// this is set here becasue its a known type, others could be the
// this is set here because it's a known type, others could be the
// result of expr so we do those in checker
idx := p.table.find_or_register_array(elem_type, 1, sym.mod)
array_type = table.new_type(idx)
@ -55,6 +57,24 @@ fn (mut p Parser) array_init() ast.ArrayInit {
// [100]byte
elem_type = p.parse_type()
is_fixed = true
if p.tok.kind == .lcbr {
p.next()
if p.tok.kind != .rcbr {
pos := p.tok.position()
n := p.check_name()
if n != 'init' {
p.error_with_pos('expected `init:`, not `$n`', pos)
}
p.check(.colon)
has_default = true
default_expr = p.expr(0)
}
last_pos = p.tok.position()
p.check(.rcbr)
}
else {
// p.warn_with_pos('use e.g. `x := [1]Type{}` instead of `x := [1]Type`', last_pos)
}
} else {
if p.tok.kind == .not {
last_pos = p.tok.position()
@ -73,10 +93,8 @@ fn (mut p Parser) array_init() ast.ArrayInit {
}
mut has_len := false
mut has_cap := false
mut has_default := false
mut len_expr := ast.Expr{}
mut cap_expr := ast.Expr{}
mut default_expr := ast.Expr{}
if p.tok.kind == .lcbr && exprs.len == 0 {
// `[]int{ len: 10, cap: 100}` syntax
p.next()

View File

@ -1,4 +1,4 @@
fn test_fixed_array_init() {
fn test_fixed_array_lit_init() {
a1 := ['1', '2', '3']!!
assert typeof(a1) == '[3]string'
assert '$a1' == "['1', '2', '3']"
@ -37,7 +37,20 @@ fn test_fixed_type_init() {
assert a == [2]int
assert a == [0,0]!!
assert a == a
c := [3,3]!!
mut c := [3,3]!!
assert a != c
assert c == [3,3]!!
c = [2]int
assert a == c
}
fn test_fixed_custom_init() {
a := [2]byte{init: 7}
assert a == [byte(7), 7]!!
mut b := [3]int{}
assert b == [0,0,0]!!
// assign
b = [3]int{init:5}
assert b == [5,5,5]!!
}

View File

@ -1,15 +1,17 @@
fn test_fixed_array_can_be_assigned() {
x := 2.32
mut v := [8]f64
mut v := [8]f64{}
assert v[1] == 0
v = [1.0, x, 3.0,4.0,5.0,6.0,7.0,8.0]!!
assert v[1] == x
v = [8]f64
v = [8]f64{}
assert v[1] == 0
// test slicing
for e in v[0..8] {
assert e == 0
}
v = [8]f64{init: 3.0}
assert v[1] == 3.0
}
fn test_fixed_array_can_be_used_in_declaration() {