`key in map` syntax

pull/1279/head^2
Alexander Medvednikov 2019-07-23 22:57:06 +02:00
parent bd95f5bf8f
commit 527b9e13fa
5 changed files with 24 additions and 13 deletions

View File

@ -244,6 +244,7 @@ typedef map map_string;
#define _PUSH(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push(arr, &tmp);}
#define _PUSH_MANY(arr, val, tmp, tmp_typ) {tmp_typ tmp = (val); array__push_many(arr, tmp.data, tmp.len);}
#define _IN(typ, val, arr) array_##typ##_contains(arr, val)
#define _IN_MAP(val, m) map__exists(m, val)
#define ALLOC_INIT(type, ...) (type *)memdup((type[]){ __VA_ARGS__ }, sizeof(type))
//================================== GLOBALS =================================*/

View File

@ -1970,22 +1970,29 @@ fn (p mut Parser) expression() string {
return 'int'
}
}
// a in [1,2,3]
// `a in [1, 2, 3]`
// `key in map`
if p.tok == .key_in {
p.fgen(' ')
p.check(.key_in)
p.fgen(' ')
p.gen(', ')
arr_typ := p.expression()
if !arr_typ.starts_with('array_') {
p.error('`in` requires an array')
is_map := arr_typ.starts_with('map_')
if !arr_typ.starts_with('array_') && !is_map {
p.error('`in` requires an array/map')
}
T := p.table.find_type(arr_typ)
if !T.has_method('contains') {
if !is_map && !T.has_method('contains') {
p.error('$arr_typ has no method `contains`')
}
// `typ` is element type
p.cgen.set_placeholder(ph, '_IN($typ, ')
// `typ` is element's type
if is_map {
p.cgen.set_placeholder(ph, '_IN_MAP( ')
}
else {
p.cgen.set_placeholder(ph, '_IN($typ, ')
}
p.gen(')')
return 'bool'
}

View File

@ -699,7 +699,7 @@ fn new_file_import_table(file_path string) *FileImportTable {
}
fn (fit &FileImportTable) known_import(mod string) bool {
return fit.imports.exists(mod) || fit.is_aliased(mod)
return mod in fit.imports || fit.is_aliased(mod)
}
fn (fit mut FileImportTable) register_import(mod string) {
@ -707,7 +707,7 @@ fn (fit mut FileImportTable) register_import(mod string) {
}
fn (fit mut FileImportTable) register_alias(alias string, mod string) {
if fit.imports.exists(alias) {
if alias in fit.imports {
panic('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".')
return
}
@ -715,7 +715,7 @@ fn (fit mut FileImportTable) register_alias(alias string, mod string) {
}
fn (fit &FileImportTable) known_alias(alias string) bool {
return fit.imports.exists(alias)
return alias in fit.imports
}
fn (fit &FileImportTable) is_aliased(mod string) bool {
@ -728,8 +728,5 @@ fn (fit &FileImportTable) is_aliased(mod string) bool {
}
fn (fit &FileImportTable) resolve_alias(alias string) string {
if fit.imports.exists(alias) {
return fit.imports[alias]
}
return ''
return fit.imports[alias]
}

View File

@ -170,6 +170,11 @@ fn (m map) get(key string, out voidptr) bool {
}
pub fn (m map) exists(key string) bool {
panic('map.exists(key) was removed from the language. Use `key in map` instead.')
return false
}
fn (m map) _exists(key string) bool {
return !isnil(m.root) && m.root.find2(key, m.element_size)
}

View File

@ -21,6 +21,7 @@ fn test_map() {
assert m['hi'] == 80
assert m['hello'] == 101
assert m.size == 2
assert 'hi' in m
mut sum := 0
mut key_sum := ''
// Test `for in`