_memoize.lua (2027B)
1 --- Module for private utility functions 2 3 --- @alias vim.func.MemoObj { _hash: (fun(...): any), _weak: boolean?, _cache: table<any> } 4 5 --- @param argc integer? 6 --- @return fun(...): any 7 local function concat_hash(argc) 8 return function(...) 9 return table.concat({ ... }, '%%', 1, argc) 10 end 11 end 12 13 --- @param idx integer 14 --- @return fun(...): any 15 local function idx_hash(idx) 16 return function(...) 17 return select(idx, ...) 18 end 19 end 20 21 --- @param hash integer|string|fun(...): any 22 --- @return fun(...): any 23 local function resolve_hash(hash) 24 if type(hash) == 'number' then 25 hash = idx_hash(hash) 26 elseif type(hash) == 'string' then 27 local c = hash == 'concat' or hash:match('^concat%-(%d+)') 28 if c then 29 hash = concat_hash(tonumber(c)) 30 else 31 error('invalid value for hash: ' .. hash) 32 end 33 end 34 --- @cast hash -integer 35 return hash 36 end 37 38 --- @param weak boolean? 39 --- @return table 40 local create_cache = function(weak) 41 return setmetatable({}, { 42 __mode = weak ~= false and 'kv', 43 }) 44 end 45 46 --- @generic F: function 47 --- @param hash integer|string|fun(...): any 48 --- @param fn F 49 --- @param weak? boolean 50 --- @return F 51 return function(hash, fn, weak) 52 vim.validate('hash', hash, { 'number', 'string', 'function' }) 53 vim.validate('fn', fn, 'function') 54 vim.validate('weak', weak, 'boolean', true) 55 56 --- @type vim.func.MemoObj 57 local obj = { 58 _cache = create_cache(weak), 59 _hash = resolve_hash(hash), 60 _weak = weak, 61 --- @param self vim.func.MemoObj 62 clear = function(self, ...) 63 if select('#', ...) == 0 then 64 self._cache = create_cache(self._weak) 65 return 66 end 67 local key = self._hash(...) 68 self._cache[key] = nil 69 end, 70 } 71 72 return setmetatable(obj, { 73 --- @param self vim.func.MemoObj 74 __call = function(self, ...) 75 local key = self._hash(...) 76 local cache = self._cache 77 if cache[key] == nil then 78 cache[key] = vim.F.pack_len(fn(...)) 79 end 80 return vim.F.unpack_len(cache[key]) 81 end, 82 }) 83 end