From 527b9e13faafeefdaaeda0dec3cd723619a3990c Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 23 Jul 2019 22:57:06 +0200 Subject: [PATCH] `key in map` syntax --- compiler/main.v | 1 + compiler/parser.v | 19 +++++++++++++------ compiler/table.v | 11 ++++------- vlib/builtin/map.v | 5 +++++ vlib/builtin/map_test.v | 1 + 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/compiler/main.v b/compiler/main.v index 8abc2a129d..ba3a11735c 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -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 =================================*/ diff --git a/compiler/parser.v b/compiler/parser.v index 4b472cad5f..60bf4f5bf0 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -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' } diff --git a/compiler/table.v b/compiler/table.v index 6256d1d05d..37f7095024 100644 --- a/compiler/table.v +++ b/compiler/table.v @@ -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] } diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 5eafc1c13b..1ed9f89c98 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -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) } diff --git a/vlib/builtin/map_test.v b/vlib/builtin/map_test.v index 3a21e4d930..b4c5edac7d 100644 --- a/vlib/builtin/map_test.v +++ b/vlib/builtin/map_test.v @@ -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`