parser: new array init syntax

pull/4613/head
Alexander Medvednikov 2020-04-26 17:28:43 +02:00
parent cd45e9ea48
commit f23948010a
4 changed files with 73 additions and 32 deletions

View File

@ -724,6 +724,7 @@ fn test_left_shift_precendence() {
}
fn test_array_with_cap() {
a := []int{cap:10, len:1 }
//assert a.len == 1
a4 := []int{cap:10, len:1 }
assert a4.len == 1
assert a4.cap == 10
}

View File

@ -635,6 +635,10 @@ pub:
is_fixed bool
has_val bool
mod string
len_expr Expr
has_len bool
has_cap bool
cap_expr Expr
mut:
elem_type table.Type
typ table.Type

View File

@ -963,33 +963,7 @@ fn (mut g Gen) expr(node ast.Expr) {
// println('cgen expr() line_nr=$node.pos.line_nr')
match node {
ast.ArrayInit {
type_sym := g.table.get_type_symbol(it.typ)
if type_sym.kind != .array_fixed {
// elem_sym := g.table.get_type_symbol(it.elem_type)
elem_type_str := g.typ(it.elem_type)
if it.exprs.len == 0 {
// use __new_array to fix conflicts when the name of the variable is new_array
g.write('__new_array($it.exprs.len, $it.exprs.len, sizeof($elem_type_str))')
} else {
len := it.exprs.len
g.write('new_array_from_c_array($len, $len, sizeof($elem_type_str), ')
g.write('($elem_type_str[$len]){\n\t\t')
for expr in it.exprs {
g.expr(expr)
g.write(', ')
}
g.write('\n})')
}
} else {
g.write('{')
for i, expr in it.exprs {
g.expr(expr)
if i != it.exprs.len - 1 {
g.write(', ')
}
}
g.write('}')
}
g.array_init(it)
}
ast.AsCast {
g.as_cast(it)
@ -3346,3 +3320,45 @@ ${interface_name} I_${cctype}_to_${interface_name}(${cctype} x) {
}
return sb.str()
}
fn (mut g Gen) array_init(it ast.ArrayInit) {
type_sym := g.table.get_type_symbol(it.typ)
if type_sym.kind != .array_fixed {
// elem_sym := g.table.get_type_symbol(it.elem_type)
elem_type_str := g.typ(it.elem_type)
if it.exprs.len == 0 {
g.write('__new_array(')
if it.has_len {
g.expr(it.len_expr)
g.write(', ')
} else {
g.write('0, ')
}
if it.has_cap {
g.expr(it.cap_expr)
g.write(', ')
} else {
g.write('0, ')
}
g.write('sizeof($elem_type_str))')
} else {
len := it.exprs.len
g.write('new_array_from_c_array($len, $len, sizeof($elem_type_str), ')
g.write('($elem_type_str[$len]){\n\t\t')
for expr in it.exprs {
g.expr(expr)
g.write(', ')
}
g.write('\n})')
}
} else {
g.write('{')
for i, expr in it.exprs {
g.expr(expr)
if i != it.exprs.len - 1 {
g.write(', ')
}
}
g.write('}')
}
}

View File

@ -70,16 +70,32 @@ fn (mut p Parser) array_init() ast.ArrayInit {
if exprs.len == 0 && p.tok.kind != .lcbr && has_type {
p.warn_with_pos('use `x := []Type{}` instead of `x := []Type`', last_pos)
}
mut has_len := false
mut has_cap := false
mut len_expr := ast.Expr{}
mut cap_expr := ast.Expr{}
if p.tok.kind == .lcbr && exprs.len == 0 {
// `[]int{ len: 10, cap: 100}` syntax
p.next()
for p.tok.kind != .rcbr {
key := p.check_name()
p.check(.colon)
if key !in ['len', 'cap', 'init'] {
p.error('wrong field `$key`, expecting `len`, `cap`, or `init`')
match key {
'len' {
has_len = true
len_expr = p.expr(0)
}
'cap' {
has_cap = true
cap_expr = p.expr(0)
}
'default' {
p.expr(0)
}
else {
p.error('wrong field `$key`, expecting `len`, `cap`, or `default`')
}
}
p.expr(0)
if p.tok.kind != .rcbr {
p.check(.comma)
}
@ -99,6 +115,10 @@ fn (mut p Parser) array_init() ast.ArrayInit {
typ: array_type
exprs: exprs
pos: pos
has_len: has_len
len_expr: len_expr
has_cap: has_cap
cap_expr: cap_expr
}
}