From 38e0aa350d02c799d4aa86cbfaed42abe701ea88 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 3 Jan 2021 14:55:06 +0000 Subject: [PATCH] checker: support non-string map.keys method (#7760) --- vlib/builtin/map.v | 4 ++-- vlib/builtin/map_test.v | 1 + vlib/v/checker/checker.v | 16 ++++++++++++++-- vlib/v/gen/fn.v | 4 ++++ 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/vlib/builtin/map.v b/vlib/builtin/map.v index 5c980595e4..c01aa8b13f 100644 --- a/vlib/builtin/map.v +++ b/vlib/builtin/map.v @@ -646,7 +646,7 @@ pub fn (m &map) keys() []string { } // Returns all keys in the map. -pub fn (m &map) keys_1() array { +fn (m &map) keys_1() array { mut keys := __new_array(m.len, 0, m.key_bytes) mut item := unsafe { byteptr(keys.data) } if m.key_values.deletes == 0 { @@ -674,7 +674,7 @@ pub fn (m &map) keys_1() array { // warning: only copies keys, does not clone [unsafe] -pub fn (d &DenseArray) clone() DenseArray { +fn (d &DenseArray) clone() DenseArray { res := DenseArray{ key_bytes: d.key_bytes value_bytes: d.value_bytes diff --git a/vlib/builtin/map_test.v b/vlib/builtin/map_test.v index 037c2c89cc..8c0889cee9 100644 --- a/vlib/builtin/map_test.v +++ b/vlib/builtin/map_test.v @@ -492,6 +492,7 @@ fn test_int_keys() { same := mc == m assert same assert mc.len == 3 + assert mc.keys() == [3,4,5] mut all := []int{} for k, v in mc { assert m[k] == v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 5f3056c431..8218d9fb32 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1256,9 +1256,21 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type { call_expr.return_type = table.int_type } return call_expr.return_type - } else if left_type_sym.kind == .map && method_name == 'clone' { - call_expr.return_type = left_type + } else if left_type_sym.kind == .map && method_name in ['clone', 'keys'] { + mut ret_type := table.void_type + match method_name { + 'clone' { + ret_type = left_type + } + 'keys' { + info := left_type_sym.info as table.Map + typ := c.table.find_or_register_array(info.key_type, 1) + ret_type = table.Type(typ) + } + else {} + } call_expr.receiver_type = left_type.to_ptr() + call_expr.return_type = ret_type return call_expr.return_type } else if left_type_sym.kind == .array && method_name in ['first', 'last', 'pop'] { info := left_type_sym.info as table.Array diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index f1b5c3ff6d..3afd1d8c7b 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -408,6 +408,10 @@ fn (mut g Gen) method_call(node ast.CallExpr) { if node.name in ['close', 'try_pop', 'try_push'] { name = 'sync__Channel_$node.name' } + } else if left_sym.kind == .map { + if node.name == 'keys' { + name = 'map_keys_1' + } } // Check if expression is: arr[a..b].clone(), arr[a..].clone() // if so, then instead of calling array_clone(&array_slice(...))