`map := { 'foo': 'bar' }` syntax

pull/1454/head
Alexander Medvednikov 2019-08-03 09:44:08 +02:00
parent bfddb9a80f
commit a5f5b52204
4 changed files with 71 additions and 2 deletions

View File

@ -2241,6 +2241,10 @@ fn (p mut Parser) factor() string {
// everything should do next()
return p.array_init()
case Token.lcbr:
// `m := { 'one': 1 }`
if p.peek() == .str {
return p.map_init()
}
// { user | name :'new name' }
return p.assoc()
case Token.key_if:
@ -2415,7 +2419,50 @@ fn (p mut Parser) string_expr() {
}
// m := map[string]int{}
// m := { 'one': 1 }
fn (p mut Parser) map_init() string {
// m := { 'one': 1, 'two': 2 }
mut keys := []string // ['one', 'two']
mut keys_gen := '' // ' (string[]){tos2("one"), tos2("two")}
mut vals := []string // [1, 2]
mut vals_gen := ''
mut val_type := '' // 'int'
if p.tok == .lcbr {
p.check(.lcbr)
mut i := 0
for {
key := p.lit
keys << key
keys_gen += 'tos2("$key"), '
p.check(.str)
p.check(.colon)
p.cgen.start_tmp()
t := p.bool_expression()
if i == 0 {
val_type = t
}
i++
if val_type != t {
if !p.check_types_no_throw(val_type, t) {
p.error('bad map element type `$val_type` instead of `$t`')
}
}
val_expr := p.cgen.end_tmp()
vals << val_expr
vals_gen += '$val_expr, '
if p.tok == .rcbr {
p.check(.rcbr)
break
}
if p.tok == .comma {
p.check(.comma)
}
}
p.gen('new_map_init($keys.len, sizeof($val_type), ' +
'(string[]){ $keys_gen }, ($val_type []){ $vals_gen } )')
typ := 'map_$val_type'
return typ
}
p.next()
p.check(.lsbr)
key_type := p.check_name()
@ -2423,7 +2470,7 @@ fn (p mut Parser) map_init() string {
p.error('only string key maps allowed for now')
}
p.check(.rsbr)
val_type := p.check_name()
val_type = p.check_name()
if !p.table.known_type(val_type) {
p.error('map init unknown type "$val_type"')
}
@ -2435,7 +2482,7 @@ fn (p mut Parser) map_init() string {
return typ
}
// [1,2,3]
// `nums := [1, 2, 3]`
fn (p mut Parser) array_init() string {
p.is_alloc = true
p.check(.lsbr)

View File

@ -501,6 +501,9 @@ fn (p mut Parser) _check_types(got, expected string, throw bool) bool {
if got=='int' && expected=='byte*' {
return true
}
//if got=='int' && expected=='voidptr*' {
//return true
//}
// byteptr += int
if got=='int' && expected=='byteptr' {
return true

View File

@ -29,6 +29,18 @@ fn new_map(cap, elm_size int) map {
return res
}
// `m := { 'one': 1, 'two': 2 }`
fn new_map_init(cap, elm_size int, keys *string, vals voidptr) map {
mut res := map {
element_size: elm_size
root: 0
}
for i in 0 .. cap {
res._set(keys[i], vals + i * elm_size)
}
return res
}
fn new_node(key string, val voidptr, element_size int) *Node {
new_e := &Node {
key: key

View File

@ -60,6 +60,13 @@ fn test_map() {
assert a.m['two'] == 2
}
fn test_map_init() {
m := { 'one': 1, 'two': 2, 'jooo': 'sdf' }
assert m['one'] == 1
assert m['two'] == 2
assert m['three'] == 0
}
fn test_string_map() {
//m := map[string]Fn
}