Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- " Emulate function overloading.
- " File: overload.vim
- " Created: 2014 Aug 01
- " Last Change: 2018 Nov 18
- " Version: 0.9
- " Author: Andy Wokula <anwoku@yahoo.de>
- " License: Vim License, see :h license
- " CallOverloaded({func-dict}, {arg-list}, {dict})
- "
- " call one of the functions from {func-dict} with arguments {arg-list}.
- " The types of {arg-list} values determine which function will be called.
- " Basically, the function name is a concatenation of detected argument
- " types. {dict} becomes the dict argument of the function call.
- "
- " For example, CallOverloaded(d, ['str'], {}) will attempt to call:
- " d.S('str') (from high to low priority)
- " d.S_('str') Hints: `S' = (string)
- " d.X('str') `_' = optional arguments
- " d.X_('str') `X' = (number or string)
- " d._('str')
- " The function name imposes the function signature:
- " d.S(str)
- " d.S_(str, ...)
- " d.X(num_or_str)
- " d.X_(num_or_str, ...)
- " d._(...)
- " At least one of these functions must be defined for the call to succeed.
- " Hint: d._(...) should be defined to catch invalid arguments.
- "
- " OverloadToken({arg-list})
- "
- " return the function name you can use in the function dict to exactly
- " match the given arguments {arg-list} (list).
- " (helper func)
- "
- " Examples:
- " :echo OverloadToken(['a', 1, 2, [], {}, function('tr'), 1.2])
- " => SNNLDFR
- "
- " :echo OverloadToken([])
- " => E
- "
- " OverloadFunc({funcnames}, {ovltoken})
- "
- " return the best match for {ovltoken} within {funcnames}.
- " (helper func)
- " {funcnames} (list of string) names of the user-defined dict
- " functions, assumed to be sorted (using sort())
- " {ovltoken} (string) result of OverloadToken()
- "
- " Example:
- " :echo OverloadFunc(sort(['NS_', 'NX', 'N_']), 'NN')
- " => NX
- "
- " OverloadInfo()
- "
- " return a dict with overloading meta data.
- " (helper func)
- "
- " Notes:
- " * `X' to match (number or string) is a special case. Vim often
- " auto-converts between number and string, in which case it was annoying
- " to be urged to specify different functions. Especially because each
- " further such argument doubles the number of additional functions.
- " * Can only check against basic types ... eg cannot look inside a
- " dictionary to do some "pattern matching" etc. Will not add pattern
- " matching, but: by convention, a lot of `Is*()' functions exist to check
- " against a specific type ...
- " History:
- " 2017 Nov 03 extracted OverloadFunc(), pattern fix
- " 2017 Aug 11 added new types (untested)
- " (!) no longer call .Default()
- " 2016 Feb 16 added `X' (N => [NX], S => [SX]) ... check dict argument for
- " flag which specifies conversion of `S' and `N' to `X'
- " (number or string)
- " 2015 Oct 16 funcs `SSO' and `SO' => `SO' was called -- bug, must call
- " the most specific function => change `O' into `_'.
- " Examples:
- " asneeded\femu\sutr-dispatch-example.vim
- " SearchHierarchy(), asneeded\trial\D1845.vim
- " asneeded\trial\D2046.vim
- " Constants: {{{
- " Mapping of type() results to identifier chars (for use in function name)
- " Mnemonics: String, Number, List, Dict, Funcref, Real number
- if exists('v:t_number')
- let s:TYPEMAP = {v:t_string : 'S', v:t_number : 'N', v:t_list : 'L', v:t_dict : 'D', v:t_func : 'F', v:t_float : 'R', v:t_bool : 'B', v:t_none : 'O', v:t_job : 'J', v:t_channel : 'C'}
- else
- let s:TYPEMAP = {1: 'S', 0: 'N', 3: 'L', 4: 'D', 2: 'F', 5: 'R'}
- endif
- " optional arguments suffix (must start with a char GT any identifier char)
- let s:OPTSFX = '_'
- " name of the function to call when there are no arguments (not required)
- let s:FNEMPTY = 'E'
- " identifier char for unknown type (new type not yet recognized by this script)
- let s:TUNKNOWN = 'U'
- " identifier char for 'number or string' (must be GT 'N' and GT 'S')
- let s:NUMORSTR = 'X'
- "}}}
- func! CallOverloaded(funcdict, arglist, dict) "{{{
- let dt = OverloadToken(a:arglist)
- if has_key(a:funcdict, dt)
- let fn = dt
- else
- let fn = OverloadFunc(sort(keys(a:funcdict)), dt)
- endif
- return call(a:funcdict[fn], a:arglist, a:dict)
- endfunc "}}}
- func! OverloadToken(arglist) "{{{
- let dt = join(map(range(len(a:arglist)), 'get(s:TYPEMAP, type(a:arglist[v:val]), s:TUNKNOWN)'), "")
- return dt=="" ? s:FNEMPTY : dt
- endfunc "}}}
- func! OverloadFunc(funcnames, ftoken) "{{{
- let gft = substitute(a:ftoken, '[NS]', '[&X]', 'g')
- let pat = '^\%('. gft. '\|\%['. gft. ']'. s:OPTSFX. '\)$'
- let dt = matchstr(a:funcnames, pat)
- return dt=="" ? s:OPTSFX : dt
- endfunc "}}}
- func! OverloadInfo() "{{{
- return {'optsfx': s:OPTSFX, 'fnempty': s:FNEMPTY, 'typemap': copy(s:TYPEMAP), 'tunknown': s:TUNKNOWN, 'tnumorstr': s:NUMORSTR}
- endfunc "}}}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement