`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(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 _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(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)) #define ALLOC_INIT(type, ...) (type *)memdup((type[]){ __VA_ARGS__ }, sizeof(type))
//================================== GLOBALS =================================*/ //================================== GLOBALS =================================*/

View File

@ -1970,22 +1970,29 @@ fn (p mut Parser) expression() string {
return 'int' return 'int'
} }
} }
// a in [1,2,3] // `a in [1, 2, 3]`
// `key in map`
if p.tok == .key_in { if p.tok == .key_in {
p.fgen(' ') p.fgen(' ')
p.check(.key_in) p.check(.key_in)
p.fgen(' ') p.fgen(' ')
p.gen(', ') p.gen(', ')
arr_typ := p.expression() arr_typ := p.expression()
if !arr_typ.starts_with('array_') { is_map := arr_typ.starts_with('map_')
p.error('`in` requires an array') if !arr_typ.starts_with('array_') && !is_map {
p.error('`in` requires an array/map')
} }
T := p.table.find_type(arr_typ) 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`') p.error('$arr_typ has no method `contains`')
} }
// `typ` is element type // `typ` is element's type
p.cgen.set_placeholder(ph, '_IN($typ, ') if is_map {
p.cgen.set_placeholder(ph, '_IN_MAP( ')
}
else {
p.cgen.set_placeholder(ph, '_IN($typ, ')
}
p.gen(')') p.gen(')')
return 'bool' 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 { 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) { 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) { 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}".') panic('cannot import $mod as $alias: import name $alias already in use in "${fit.file_path}".')
return return
} }
@ -715,7 +715,7 @@ fn (fit mut FileImportTable) register_alias(alias string, mod string) {
} }
fn (fit &FileImportTable) known_alias(alias string) bool { 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 { 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 { fn (fit &FileImportTable) resolve_alias(alias string) string {
if fit.imports.exists(alias) { return fit.imports[alias]
return fit.imports[alias]
}
return ''
} }

View File

@ -170,6 +170,11 @@ fn (m map) get(key string, out voidptr) bool {
} }
pub fn (m map) exists(key string) 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) 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['hi'] == 80
assert m['hello'] == 101 assert m['hello'] == 101
assert m.size == 2 assert m.size == 2
assert 'hi' in m
mut sum := 0 mut sum := 0
mut key_sum := '' mut key_sum := ''
// Test `for in` // Test `for in`