Commits

ZyX_I committed 4254f74

@/fwc: Renamed fwc_compile to fwc.compile, added fwc.del, made fwc.compile return function identifier as well

  • Participants
  • Parent commits c7b516f

Comments (0)

Files changed (7)

 ------------------------------------------------------------------------------
 3.7. @/fwc/compiler features                           *frawor-f-fwc/compiler*
 
-fwc_compile : function ({FWCstring}, {type})            *frawor-f-fwc_compile*
+                                                        *frawor-f-fwc.compile*
+fwc.compile : function ({FWCstring}, {type}[, {gdict}])
             + unload
         Create a function out of {FWCstring} code. This function takes a list 
         of values (unless |fwc-o-only| is enabled) and returns either 
         (possibly modified) its argument (or 0) when {type} is "filter", or 
-        a boolean value when {type} is "check".
+        a boolean value when {type} is "check". {gdict} overrides value of 
+        script-local dictionary.
+        Returns a tuple with created function and its internal resources 
+        identifier which can be then passed to |frawor-f-fwc.del|.
         Note that created function will be anonymous dictionary function, so 
         you will need to supply a dictionary when you call it even though it 
         does not use this dictionary. See |Dictionary-function| and 
         description of the third argument to |call()|.
 
+fwc.del : function ({FWCid})                                *frawor-f-fwc.del*
+        Delete resources used by function with given ID.
+
 ------------------------------------------------------------------------------
 3.8. plugin/frawor/mappings features                *frawor-f-frawor/mappings*
 
         this function will be called with an argument list as an only 
         argument. Check is considered passed when this function returns 1 and 
         failed when this function returns 0.
-        If checker is a string, then it is passed to |frawor-f-fwc_compile| 
+        If checker is a string, then it is passed to |frawor-f-fwc.compile| 
         with "check" as a second argument, then generated function is 
         returned. Consider using FWC decorator (|frawor-de-FWC|) instead.
 
         this function will be called with an argument list as an only 
         argument. If function returns a |List|, then it will be used as a new 
         argument list. Function should return 0 if some error occured.
-        If filter is a string, then it is passed to |frawor-f-fwc_compile| 
+        If filter is a string, then it is passed to |frawor-f-fwc.compile| 
         with "filter" as a second argument, then generated function is 
         returned. Consider using FWC decorator (|frawor-de-FWC|) instead.
 

plugin/frawor/checks.vim

                 \            'plugin %s: ID is not a string',
             \}
 endif
+"▶1 freeres      :: {f}
+function s:F.freeres(plugdict, fdict)
+    call map(a:fdict.FWCids, 's:_f.fwc.del(v:val)')
+endfunction
 "▶1 conschecker feature
 "▶2 conschecker  :: {f}, checker → chkfunc + ?
 function s:F.conschecker(plugdict, fdict, Chk)
         endif
         return a:Chk
     elseif type(a:Chk)==type('')
-        return s:_f.fwc_compile(a:Chk, 'check', a:plugdict.g)
+        let d={}
+        let [d.F, id]=s:_f.fwc.compile(a:Chk, 'check', a:plugdict.g)
+        call add(a:fdict.FWCids, id)
+        return d.F
     else
         call s:_f.throw('uchecker', a:plugdict.id)
     endif
 endfunction
 "▶2 Register feature
-call s:_f.newfeature('conschecker', {'cons': s:F.conschecker})
+call s:_f.newfeature('conschecker', {'cons': s:F.conschecker,
+            \                      'unload': s:F.freeres,
+            \                        'init': {'FWCids': []}})
 "▶1 consfilter feature
 "▶2 consfilter  :: {f}, filter → filfunc + ?
 function s:F.consfilter(plugdict, fdict, Fil)
         endif
         return a:Fil
     elseif type(a:Fil)==type('')
-        return s:_f.fwc_compile(a:Fil, 'filter', a:plugdict.g)
+        let d={}
+        let [d.F, id]=s:_f.fwc.compile(a:Fil, 'filter', a:plugdict.g)
+        call add(a:fdict.FWCids, id)
+        return d.F
     else
         call s:_f.throw('ufilter', a:plugdict.id)
     endif
 endfunction
 "▶2 Register feature
-call s:_f.newfeature('consfilter', {'cons': s:F.consfilter})
+call s:_f.newfeature('consfilter', {'cons': s:F.consfilter,
+            \                     'unload': s:F.freeres,
+            \                       'init': {'FWCids': []}})
 "▶1 Decorators: checker and filter
 let s:F.de={}
 "▶2 checker

plugin/frawor/fwc/compiler.vim

             \    '3ndict': 'third argument is not a Dictionary',
             \}, '"Error while compiling function for plugin %s: ".v:val'))
 call extend(s:_messages, map({
+            \    'donstr': 'first argument is not a String',
+            \    'dundef': 'unknown function %s',
+            \   'dnowner': 'function %s was compiled for plugin %s',
+        \}, '"Error while deleting function resources for plugin %s: ".v:val'))
+call extend(s:_messages, map({
             \'decargnlst': 'decorator argument is not a List',
             \    'largn2': 'expected two elements in list, but got %u',
             \     '1nstr': 'first element in list is not a String',
     endif
     return [t.o, t.tolist()]
 endfunction
-"▶1 createvars      :: gdict → id + s:lastid, s:vars
+"▶1 createvars      :: gdict → id + s:lastid, s:FWCs
 function s:F.createvars(gdict)
     return {
                 \ 'F': {'warn': s:_f.warn, 'throw': s:_f.throw},
                 \ 'm': {'types': s:_messages._types},
             \}
 endfunction
-"▶1 makefunc        :: {f}, String, type[, gdict] → Fref + s:lastid, s:vars
+"▶1 fwc feature
+let s:F.fwc={}
+"▶2 fwc.compile     :: {f}, FWCstring, type[, gdict] → FWCid, Fref + s:FWCs
 let s:lastid=0
-let s:vars={}
+let s:FWCs={}
 let s:types=['check', 'filter', 'complete']
-function s:F.makefunc(plugdict, fdict, string, type, ...)
-    "▶2 Check arguments
+function s:F.fwc.compile(plugdict, fdict, string, type, ...)
+    "▶3 Check arguments
     if type(a:string)!=type('')
         call s:_f.throw('onstr', a:plugdict.id)
     elseif type(a:type)!=type('')
     elseif a:0 && type(a:1)!=type({})
         call s:_f.throw('3ndict', a:plugdict.id)
     endif
-    "▲2
+    "▲3
     let d={}
     let id=printf('%s%X', a:type, s:lastid)
+    let FWC  =    {'id': id,
+                \'plid': a:plugdict.id,
+                \'vars': s:F.createvars(get(a:000, 0, a:plugdict.g)),}
     let s:lastid+=1
-    let s:vars[id]=s:F.createvars(get(a:000, 0, a:plugdict.g))
     call add(a:fdict.ids, id)
-    let [opts, lines]=s:F.compstr(s:vars[id], a:string, a:type, 1)
+    let [opts, lines]=s:F.compstr(FWC.vars, a:string, a:type, 1)
     if opts.only
         call insert(lines, 'let d={"arg": a:args}')
     elseif has_key(opts, 'requiresd')
         call insert(lines, 'let d={}')
     endif
-    execute "function d.f(args)\n    ".
+    execute "function FWC.f(args)\n    ".
                 \substitute(substitute(substitute(substitute(
                 \join(lines, "\n    "),
                 \'@@@', ((opts.only)?('d.arg'):
                 \                    ('a:args')), 'g'),
-                \'@%@', 's:vars.'.id,    'g'),
-                \'@-@', 'variants',      'g'),
-                \'@$@', '',              'g')."\n".
+                \'@%@', 's:FWCs.'.id.'.vars',     'g'),
+                \'@-@', 'variants',               'g'),
+                \'@$@', '',                       'g')."\n".
             \"endfunction"
-    return d.f
+    let s:FWCs[id]=FWC
+    return [FWC.f, id]
 endfunction
-"▶1 delids          :: {f}
+"▶2 fwc.del         :: {f}, FWCid
+function s:F.removefunc(plugdict, fdict, FWCid)
+    "▶3 Check arguments
+    if type(a:FWCid)!=type('')
+        call s:_f.throw('donstr', a:plugdict.id)
+    elseif !has_key(s:FWCs, a:FWCid)
+        call s:_f.throw('dundef', a:plugdict.id, a:FWCid)
+    elseif s:FWCs[a:FWCid].plid isnot a:plugdict.id
+        call s:_f.throw('dnowner', a:plugdict.id, a:FWCid, s:FWCs[a:FWCid].plid)
+    endif
+    "▲3
+    call filter(a:fdict.ids, 'v:val isnot a:FWCid')
+    unlet s:FWCs[a:FWCid]
+endfunction
+"▶2 delids          :: {f}
 function s:F.delids(plugdict, fdict)
-    call map(a:fdict.ids, 'remove(s:vars, v:val)')
+    call map(a:fdict.ids, 'remove(s:FWCs, v:val)')
 endfunction
-"▶1 Register feature
-call s:_f.newfeature('fwc_compile', {'cons': s:F.makefunc,
-            \                      'unload': s:F.delids,
-            \                        'init': {'ids': []}})
+"▶2 Register feature
+call s:_f.newfeature('fwc', {'cons': s:F.fwc,
+            \              'unload': s:F.delids,
+            \                'init': {'ids': []}})
 "▶1 makedec         :: plugdict, fname, arg
 function s:F.makedec(plugdict, fname, arg)
     "▶2 Check arguments
 call s:_f.adddecorator('FWC', s:F.makedec)
 "▶1
 " TODO implement recursive structures checking
-call frawor#Lockvar(s:, 'lastid,vars')
+call frawor#Lockvar(s:, 'lastid,FWCs')
 " vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80

test/rtp/plugin/fwccheck.vim

     let [compargs, arg, result]=eval('['.line.']')
     let savedarg=deepcopy(arg)
     if !empty($DEBUGTEST)
-        debug let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        debug let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         debug let realres=call(ChFunc, [arg], {})
     else
-        let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         let realres=call(ChFunc, [arg], {})
     endif
     if type(realres)!=type(result) || realres!=result

test/rtp/plugin/fwccomplete-os.vim

     let compargs=[FWC, FWCtype]
     let result=ToList(line)
     if !empty($DEBUGTEST)
-        debug let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        debug let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         debug let realres=call(ChFunc, copy(args), {})
     else
-        let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         let realres=call(ChFunc, copy(args), {})
     endif
     if type(realres)!=type(result) || realres!=result

test/rtp/plugin/fwccomplete-redir.vim

     let compargs=[FWC, FWCtype]
     let result=ToList(line)
     if !empty($DEBUGTEST)
-        debug let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        debug let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         debug let realres=call(ChFunc, copy(args), {})
     else
-        let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         let realres=call(ChFunc, copy(args), {})
     endif
     if type(realres)!=type(result) || realres!=result

test/rtp/plugin/fwccomplete.vim

     let compargs=[FWC, FWCtype]
     let result=ToList(line)
     if !empty($DEBUGTEST)
-        debug let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        debug let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         debug let realres=call(ChFunc, copy(args), {})
     else
-        let ChFunc=call(s:_f.fwc_compile, compargs, {})
+        let ChFunc=call(s:_f.fwc.compile, compargs, {})[0]
         let realres=call(ChFunc, copy(args), {})
     endif
     if type(realres)!=type(result) || realres!=result