short struct init syntax

pull/4180/head
Alexander Medvednikov 2020-04-01 23:23:20 +02:00
parent d9af06f2ad
commit 39434155f8
3 changed files with 86 additions and 58 deletions

View File

@ -76,6 +76,14 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
// c.error('unknown struct: $struct_init.typ.typ.name', struct_init.pos)
// panic('')
// }
if struct_init.typ == table.void_type {
// Short syntax `({foo: bar})`
if c.expected_type == table.void_type {
c.error('unexpected short struct syntax', struct_init.pos)
return table.void_type
}
struct_init.typ = c.expected_type
}
typ_sym := c.table.get_type_symbol(struct_init.typ)
// println('check struct $typ_sym.name')
match typ_sym.kind {

View File

@ -548,12 +548,14 @@ pub fn (p mut Parser) parse_ident(is_c bool) ast.Ident {
return ident
}
fn (p mut Parser) struct_init() ast.StructInit {
typ := p.parse_type()
fn (p mut Parser) struct_init(short_syntax bool) ast.StructInit {
typ := if short_syntax { table.void_type } else { p.parse_type() }
p.expr_mod = ''
// sym := p.table.get_type_symbol(typ)
// p.warn('struct init typ=$sym.name')
p.check(.lcbr)
if !short_syntax {
p.check(.lcbr)
}
mut field_names := []string
mut exprs := []ast.Expr
mut i := 0
@ -585,7 +587,9 @@ fn (p mut Parser) struct_init() ast.StructInit {
fields: field_names
pos: p.tok.position()
}
p.check(.rcbr)
if !short_syntax {
p.check(.rcbr)
}
return node
}
@ -674,7 +678,7 @@ pub fn (p mut Parser) name_expr() ast.Expr {
//
{
// || p.table.known_type(p.tok.lit)) {
return p.struct_init()
return p.struct_init(false) // short_syntax: false
}
else if p.peek_tok.kind == .dot && (p.tok.lit[0].is_capital() && !known_var) {
// `Color.green`
@ -798,53 +802,17 @@ pub fn (p mut Parser) expr(precedence int) ast.Expr {
.lcbr {
p.next()
if p.tok.kind == .string {
mut keys := []ast.Expr
mut vals := []ast.Expr
for p.tok.kind != .rcbr && p.tok.kind != .eof {
// p.check(.str)
key := p.expr(0)
keys << key
p.check(.colon)
val := p.expr(0)
vals << val
if p.tok.kind == .comma {
p.next()
}
}
node = ast.MapInit{
keys: keys
vals: vals
pos: p.tok.position()
}
node = p.map_init()
}
else {
name := p.check_name()
var := p.scope.find_var(name) or {
p.error('unknown variable `$name`')
return node
if p.peek_tok.kind == .pipe {
node = p.assoc()
}
// println('assoc var $name typ=$var.typ')
mut fields := []string
mut vals := []ast.Expr
p.check(.pipe)
for {
fields << p.check_name()
p.check(.colon)
expr := p.expr(0)
vals << expr
if p.tok.kind == .comma {
p.check(.comma)
}
if p.tok.kind == .rcbr {
break
}
else if p.peek_tok.kind == .colon || p.tok.kind == .rcbr {
node = p.struct_init(true) // short_syntax: true
}
node = ast.Assoc{
var_name: name
fields: fields
exprs: vals
pos: p.tok.position()
typ: var.typ
else {
p.error('unexpected {')
}
}
p.check(.rcbr)
@ -1374,6 +1342,28 @@ fn (p mut Parser) array_init() ast.ArrayInit {
}
}
fn (p mut Parser) map_init() ast.MapInit {
pos := p.tok.position()
mut keys := []ast.Expr
mut vals := []ast.Expr
for p.tok.kind != .rcbr && p.tok.kind != .eof {
// p.check(.str)
key := p.expr(0)
keys << key
p.check(.colon)
val := p.expr(0)
vals << val
if p.tok.kind == .comma {
p.next()
}
}
return ast.MapInit{
keys: keys
vals: vals
pos: pos
}
}
fn (p mut Parser) parse_number_literal() ast.Expr {
lit := p.tok.lit
mut node := ast.Expr{}
@ -1943,6 +1933,38 @@ fn (p mut Parser) type_decl() ast.TypeDecl {
}
}
fn (p mut Parser) assoc() ast.Assoc{
var_name := p.check_name()
pos := p.tok.position()
var := p.scope.find_var(var_name) or {
p.error('unknown variable `$var_name`')
return ast.Assoc{}
}
// println('assoc var $name typ=$var.typ')
mut fields := []string
mut vals := []ast.Expr
p.check(.pipe)
for {
fields << p.check_name()
p.check(.colon)
expr := p.expr(0)
vals << expr
if p.tok.kind == .comma {
p.check(.comma)
}
if p.tok.kind == .rcbr {
break
}
}
return ast.Assoc{
var_name: var_name
fields: fields
exprs: vals
pos: pos
typ: var.typ
}
}
fn (p &Parser) new_true_expr() ast.Expr {
return ast.BoolLiteral{
val: true

View File

@ -236,7 +236,6 @@ fn foo_config(c Config) {}
fn foo2(u User) {}
fn test_config() {
/*
foo_config({
n: 10
def: 20
@ -245,5 +244,4 @@ fn test_config() {
foo2({
name: 'Peter'
})
*/
}
}