parser: support custom fixed size ArrayInit: `[3]int{init: -1}` (#6114)
parent
5f3ced7213
commit
0f0a91fc9e
|
@ -733,7 +733,7 @@ pub struct ArrayInit {
|
||||||
pub:
|
pub:
|
||||||
pos token.Position
|
pos token.Position
|
||||||
elem_type_pos token.Position
|
elem_type_pos token.Position
|
||||||
exprs []Expr
|
exprs []Expr // `[expr, expr]` or `[expr]Type{}` for fixed array
|
||||||
is_fixed bool
|
is_fixed bool
|
||||||
has_val bool // fixed size literal `[expr, expr]!!`
|
has_val bool // fixed size literal `[expr, expr]!!`
|
||||||
mod string
|
mod string
|
||||||
|
|
|
@ -1734,6 +1734,11 @@ pub fn (mut f Fmt) array_init(it ast.ArrayInit) {
|
||||||
// `[100]byte`
|
// `[100]byte`
|
||||||
if it.is_fixed {
|
if it.is_fixed {
|
||||||
f.write(f.type_to_str(it.elem_type))
|
f.write(f.type_to_str(it.elem_type))
|
||||||
|
if it.has_default {
|
||||||
|
f.write('{init: $it.default_expr}')
|
||||||
|
} else {
|
||||||
|
f.write('{}')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ fn main() {
|
||||||
]
|
]
|
||||||
x := []int{len: 10, cap: 100, init: 1}
|
x := []int{len: 10, cap: 100, init: 1}
|
||||||
_ := expected_flags
|
_ := expected_flags
|
||||||
buf := [100]byte
|
buf := [100]byte{}
|
||||||
println(x)
|
println(x)
|
||||||
println(buf)
|
println(buf)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1499,7 +1499,20 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
if !cloned {
|
if !cloned {
|
||||||
if is_decl {
|
if is_decl {
|
||||||
if is_fixed_array_init && !has_val {
|
if is_fixed_array_init && !has_val {
|
||||||
g.write('{0}')
|
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 {
|
} else {
|
||||||
g.expr(val)
|
g.expr(val)
|
||||||
}
|
}
|
||||||
|
@ -2152,8 +2165,8 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
} else if node.op in [.eq, .ne] &&
|
} else if node.op in [.eq, .ne] &&
|
||||||
left_sym.kind == .array_fixed && right_sym.kind == .array_fixed {
|
left_sym.kind == .array_fixed && right_sym.kind == .array_fixed {
|
||||||
af := left_sym.info as table.ArrayFixed
|
info := left_sym.info as table.ArrayFixed
|
||||||
et := af.elem_type
|
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] {
|
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')
|
verror('`==` on fixed array only supported with POD element types ATM')
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,8 @@ fn (mut p Parser) array_init() ast.ArrayInit {
|
||||||
mut is_fixed := false
|
mut is_fixed := false
|
||||||
mut has_val := false
|
mut has_val := false
|
||||||
mut has_type := false
|
mut has_type := false
|
||||||
|
mut has_default := false
|
||||||
|
mut default_expr := ast.Expr{}
|
||||||
if p.tok.kind == .rsbr {
|
if p.tok.kind == .rsbr {
|
||||||
// []typ => `[]` and `typ` must be on the same line
|
// []typ => `[]` and `typ` must be on the same line
|
||||||
line_nr := p.tok.line_nr
|
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_pos = p.tok.position()
|
||||||
elem_type = p.parse_type()
|
elem_type = p.parse_type()
|
||||||
sym := p.table.get_type_symbol(elem_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
|
// result of expr so we do those in checker
|
||||||
idx := p.table.find_or_register_array(elem_type, 1, sym.mod)
|
idx := p.table.find_or_register_array(elem_type, 1, sym.mod)
|
||||||
array_type = table.new_type(idx)
|
array_type = table.new_type(idx)
|
||||||
|
@ -55,6 +57,24 @@ fn (mut p Parser) array_init() ast.ArrayInit {
|
||||||
// [100]byte
|
// [100]byte
|
||||||
elem_type = p.parse_type()
|
elem_type = p.parse_type()
|
||||||
is_fixed = true
|
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 {
|
} else {
|
||||||
if p.tok.kind == .not {
|
if p.tok.kind == .not {
|
||||||
last_pos = p.tok.position()
|
last_pos = p.tok.position()
|
||||||
|
@ -73,10 +93,8 @@ fn (mut p Parser) array_init() ast.ArrayInit {
|
||||||
}
|
}
|
||||||
mut has_len := false
|
mut has_len := false
|
||||||
mut has_cap := false
|
mut has_cap := false
|
||||||
mut has_default := false
|
|
||||||
mut len_expr := ast.Expr{}
|
mut len_expr := ast.Expr{}
|
||||||
mut cap_expr := ast.Expr{}
|
mut cap_expr := ast.Expr{}
|
||||||
mut default_expr := ast.Expr{}
|
|
||||||
if p.tok.kind == .lcbr && exprs.len == 0 {
|
if p.tok.kind == .lcbr && exprs.len == 0 {
|
||||||
// `[]int{ len: 10, cap: 100}` syntax
|
// `[]int{ len: 10, cap: 100}` syntax
|
||||||
p.next()
|
p.next()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
fn test_fixed_array_init() {
|
fn test_fixed_array_lit_init() {
|
||||||
a1 := ['1', '2', '3']!!
|
a1 := ['1', '2', '3']!!
|
||||||
assert typeof(a1) == '[3]string'
|
assert typeof(a1) == '[3]string'
|
||||||
assert '$a1' == "['1', '2', '3']"
|
assert '$a1' == "['1', '2', '3']"
|
||||||
|
@ -37,7 +37,20 @@ fn test_fixed_type_init() {
|
||||||
assert a == [2]int
|
assert a == [2]int
|
||||||
assert a == [0,0]!!
|
assert a == [0,0]!!
|
||||||
assert a == a
|
assert a == a
|
||||||
c := [3,3]!!
|
mut c := [3,3]!!
|
||||||
assert a != c
|
assert a != c
|
||||||
assert c == [3,3]!!
|
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]!!
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
fn test_fixed_array_can_be_assigned() {
|
fn test_fixed_array_can_be_assigned() {
|
||||||
x := 2.32
|
x := 2.32
|
||||||
mut v := [8]f64
|
mut v := [8]f64{}
|
||||||
assert v[1] == 0
|
assert v[1] == 0
|
||||||
v = [1.0, x, 3.0,4.0,5.0,6.0,7.0,8.0]!!
|
v = [1.0, x, 3.0,4.0,5.0,6.0,7.0,8.0]!!
|
||||||
assert v[1] == x
|
assert v[1] == x
|
||||||
v = [8]f64
|
v = [8]f64{}
|
||||||
assert v[1] == 0
|
assert v[1] == 0
|
||||||
// test slicing
|
// test slicing
|
||||||
for e in v[0..8] {
|
for e in v[0..8] {
|
||||||
assert e == 0
|
assert e == 0
|
||||||
}
|
}
|
||||||
|
v = [8]f64{init: 3.0}
|
||||||
|
assert v[1] == 3.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_fixed_array_can_be_used_in_declaration() {
|
fn test_fixed_array_can_be_used_in_declaration() {
|
||||||
|
|
Loading…
Reference in New Issue