ZyX_I avatar ZyX_I committed de807cf

@frawor: speed improvements, some unload/feature ordering fixes

Comments (0)

Files changed (2)

plugin/frawor.vim

 let s:F={}
 let s:_functions=[]
 "▶2 s:
-let s:selfdeps={}
+let s:deplen={}
 let s:pls={} " Plugin dictionaries
 let s:loading={}
 let s:features={}
                     \             a:shadowdict.consargs, '')
     endif
 endfunction
-"▶1 addcons         :: plugdict + s:f.cons → + p:_f
-function s:F.addcons(plugdict)
-    let shadowdict=s:shadow[a:plugdict.id]
-    for feature in sort(values(s:f.cons), function('s:FeatComp'))
-        if has_key(a:plugdict.dependencies, feature.plid)
-            let a:plugdict.g._f[feature.name]=s:F.createcons(a:plugdict,
-                        \                                    shadowdict,
-                        \                                    feature)
-        endif
-    endfor
-endfunction
-"▶1 featcomp        :: feature, feature + s:selfdeps → -1|0|1
+"▶1 featcomp        :: feature, feature + s:deplen → -1|0|1
 function s:FeatComp(feature1, feature2)
     let plid1=a:feature1.plid
     let plid2=a:feature2.plid
-    let idx1=s:selfdeps[plid1]
-    let idx2=s:selfdeps[plid2]
-    if idx1==idx2
+    let dl1=s:deplen[plid1]
+    let dl2=s:deplen[plid2]
+    if dl1==dl2
         if plid1 is# plid2
             return ((a:feature1.id>a:feature2.id)?(1):(-1))
         endif
         return ((plid1>plid2)?(1):(-1))
     endif
-    return ((idx1>idx2)?(1):(-1))
+    return ((dl1<dl2)?(1):(-1))
 endfunction
 " " Can't add s:FeatComp to _functions because it is required for unloadplugin 
 " " to  work and thus should not be removed by unloadpre event
 " let function('s:FeatComp')=function('s:FeatComp')
+"▶1 addcons         :: plugdict + s:f.cons → + p:_f
+function s:F.addcons(plugdict)
+    let shadowdict=s:shadow[a:plugdict.id]
+    for feature in sort(filter(values(s:f.cons),
+                \              'has_key(a:plugdict.dependencies, v:val.plid)'),
+                \       function('s:FeatComp'))
+        let a:plugdict.g._f[feature.name]=s:F.createcons(a:plugdict, shadowdict,
+                    \                                    feature)
+    endfor
+endfunction
 "▶1 getfeatures     :: plugdict, {: feature} → [feature]
 function s:F.getfeatures(plugdict, featuresdict)
     return sort(filter(values(a:featuresdict),
 function s:F.runfeatures(plugdict, key)
     let fdicts=s:shadow[a:plugdict.id].features
     let fnames={}
-    for feature in s:F.getfeatures(a:plugdict, s:f[a:key])
-        if has_key(fnames, feature.name)
-            continue
-        endif
+    for feature in filter(s:F.getfeatures(a:plugdict, s:f[a:key]),
+                \         '!has_key(fnames, v:val.name)')
         let fnames[feature.name]=feature
         call call(feature[a:key], [a:plugdict, fdicts[feature.name]], {})
     endfor
 "▶1 initfeatures    :: plugdict + shadowdict → + shadowdict
 function s:F.initfeatures(plugdict)
     let fdicts=s:shadow[a:plugdict.id].features
-    for feature in s:F.getfeatures(a:plugdict, s:features)
-        if has_key(fdicts, feature.name)
-            continue
-        endif
+    for feature in filter(s:F.getfeatures(a:plugdict, s:features),
+                \         '!has_key(fdicts, v:val.name)')
         let fdict={}
         let fdicts[feature.name]=fdict
         if has_key(feature, 'init')
         endif
     endfor
 endfunction
+"▶1 updatedeplen    :: plugdict + s:deplen → + s:deplen
+function s:F.updatedeplen(plugdict)
+    " XXX max([])=0
+    let s:deplen[a:plugdict.id]=max(map(keys(a:plugdict.dependencies),
+                \                       '((v:val is# a:plugdict.id)?'.
+                \                           '(0):'.
+                \                           '(get(s:deplen, v:val, 0)))'))+1
+endfunction
 "▶1 newplugin       :: version, sid, file, dependencies, oneload, g → +s:pls,
 function s:F.newplugin(version, sid, file, dependencies, oneload, g)
     "▶2 Checking whether a:file is a string
     let shadowdict.features={}
     let shadowdict.loadedfs={}
     let s:shadow[plugdict.id]=shadowdict
-    "▶3 Locking shadow dictionary
+    "▶3 Locking shadowdict
     lockvar 1 shadowdict
     "▶2 Constructing _frawor dictionary
     let plugdict.g._frawor={
     "▲2
     let s:pls[plid]=plugdict
     let s:shadow[plid]=shadowdict
-    let s:selfdeps={}
-    call map(s:F.getordereddeps(s:pls[s:_frawor.id]),
-                \'extend(s:selfdeps, {v:val.id : v:key})')
+    call s:F.updatedeplen(plugdict)
     call s:F.initfeatures(plugdict)
     let plugdict.g._pluginloaded=0
     if a:oneload
-        call s:F.loadplugin(plid)
+        call s:F.loadplugin(plugdict)
     else
         call s:F.addcons(plugdict)
     endif
     "▲2
     return a:feature
 endfunction
+"▶1 getdeps         :: plugdict, hasdep::{plid: _} + s:dependents,… → [plugdict]
+function s:F.getdeps(plugdict, hasdep)
+    let r=[a:plugdict]
+    let a:hasdep[a:plugdict.id]=1
+    for dplid in keys(get(s:dependents, a:plugdict.id, {}))
+        " XXX cannot use filter() as a:hasdep gets modified by s:F.getdeps
+        if !has_key(a:hasdep, dplid)
+            let a:hasdep[dplid]=1
+            let r+=s:F.getdeps(s:pls[dplid], a:hasdep)
+        endif
+    endfor
+    return r
+endfunction
+"▶1 depcomp         :: plugdict, plugdict + s:dependents → -1|0|1
+" Makes plugins which are being less depended on first in a list when passed as 
+" a second argument to sort()
+function s:DepComp(plugdict1, plugdict2)
+    let plid1=a:plugdict1.id
+    let plid2=a:plugdict2.id
+    let dl1=s:deplen[plid1]
+    let dl2=s:deplen[plid2]
+    if dl1==dl2
+        if plid1 is# plid2
+            return ((a:plugdict1.id>a:plugdict2.id)?(1):(-1))
+        endif
+        return ((plid1>plid2)?(1):(-1))
+    endif
+    return ((dl1<dl2)?(1):(-1))
+endfunction
+let s:_functions+=['s:DepComp']
 "▶1 getordereddeps  :: plugdict + s:dependents → [plugdict]
 function s:F.getordereddeps(plugdict)
-    let deps=sort(s:F.getdeps(a:plugdict, {}), function('s:DepComp'))
-    let ordered=[]
-    let withdeps=[]
-    call map(deps, 'add(((empty(get(s:dependents, v:val.id, {})))?'.
-                \           '(ordered):'.
-                \           '(withdeps)), '.
-                \      'v:val)')
-    let orderedids=map(copy(ordered), 'v:val.id')
-    unlet deps
-    while !empty(withdeps)
-        let removedsmth=0
-        let i=0
-        while i<len(withdeps)
-            if empty(filter(keys(get(s:dependents, withdeps[i].id, {})),
-                        \   'index(orderedids, v:val)==-1'))
-                call add(ordered,    withdeps[i])
-                call add(orderedids, withdeps[i].id)
-                call remove(withdeps, i)
-                let removedsmth=1
-            else
-                let i+=1
-            endif
-        endwhile
-        if !removedsmth && !empty(withdeps)
-            call add(ordered,    withdeps[0])
-            call add(orderedids, withdeps[0].id)
-            call remove(withdeps, 0)
-        endif
-    endwhile
-    return ordered
+    return sort(s:F.getdeps(a:plugdict, {}), function('s:DepComp'))
 endfunction
 "▶1 loadplugin      :: Either plugdict plid → 0|1|2 + plugdict, …
 function s:F.loadplugin(plid)
                     call s:_f.throw('reqfailed', dplid, plid)
                 endif
             endfor
+            call s:F.updatedeplen(plugdict)
             "▶2 Running features
             for feature in s:F.getfeatures(plugdict, s:features)
                 call s:F.addfeature(plugdict, feature, 1)
     endif
     return 1
 endfunction
-"▶1 getdeps         :: plugdict, hasdep::{plid: _} + s:dependents,… → [plugdict]
-function s:F.getdeps(plugdict, hasdep)
-    let r=[a:plugdict]
-    let a:hasdep[a:plugdict.id]=1
-    for dplugdict in map(keys(get(s:dependents, a:plugdict.id, {})),
-                \        's:pls[v:val]')
-        if !has_key(a:hasdep, dplugdict.id)
-            let a:hasdep[dplugdict.id]=1
-            let r+=s:F.getdeps(dplugdict, a:hasdep)
-        endif
-    endfor
-    return r
-endfunction
-"▶1 depcomp         :: plugdict, plugdict + s:dependents → -1|0|1
-" Makes plugins which are being less depended on first in a list when passed as 
-" a second argument to sort()
-function s:DepComp(plugdict1, plugdict2)
-    let depnum1=len(keys(get(s:dependents, a:plugdict1.id, {})))
-    let depnum2=len(keys(get(s:dependents, a:plugdict2.id, {})))
-    return ((depnum1>depnum2)?
-                \(1):
-                \((depnum1<depnum2)?
-                \   (-1):
-                \   ((a:plugdict1.id>a:plugdict2.id)?
-                \       (1):
-                \       (-1))))
-endfunction
-let s:_functions+=['s:DepComp']
 "▶1 unloadplugin    :: Either plugdict plid + … → [filename]
 " Returns a list of files that should be sourced to load plugin back
 function s:F.unloadplugin(plid)
             lockvar! plugdict.status
             "▶2 Clear references to this plugin
             unlet s:pls[plugdict.id]
-            unlet s:selfdeps[plugdict.id]
             if has_key(s:dependents, plugdict.id)
                 unlet s:dependents[plugdict.id]
             endif
     let feature.escapedid=substitute(string(feature.id), '\n', '''."\n".''','g')
     "▶2 Adding keys that hold functions
     let addedsomething=0
-    for key in s:featfunckeys
-        if has_key(a:fopts, key)
-            if key is# 'cons'
-                if type(a:fopts[key])==type({})
-                    call s:F.recdictmap(deepcopy(a:fopts[key]),
-                                \'s:F.isfunc(v:val, '.
-                                \           '"cons.".join(path+[v:key], "."), '.
-                                \            string(feature.name).', '.
-                                \            string(feature.plid).')')
-                else
-                    call s:F.isfunc(a:fopts[key], key, feature.name,
-                                \   feature.plid)
-                endif
+    for key in filter(copy(s:featfunckeys), 'has_key(a:fopts, v:val)')
+        if key is# 'cons'
+            if type(a:fopts[key])==type({})
+                call s:F.recdictmap(deepcopy(a:fopts[key]),
+                            \'s:F.isfunc(v:val, '.
+                            \           '"cons.".join(path+[v:key], "."), '.
+                            \            string(feature.name).', '.
+                            \            string(feature.plid).')')
             else
-                call s:F.isfunc(a:fopts[key], key, feature.name, feature.plid)
+                call s:F.isfunc(a:fopts[key], key, feature.name,
+                            \   feature.plid)
             endif
-            let feature[key]=a:fopts[key]
-            let s:f[key][feature.id]=feature
-            let addedsomething=1
+        else
+            call s:F.isfunc(a:fopts[key], key, feature.name, feature.plid)
         endif
+        let feature[key]=a:fopts[key]
+        let s:f[key][feature.id]=feature
+        let addedsomething=1
     endfor
     "▶3 Must have added something
     if !addedsomething
             endfor
         endif
         unlet s:features[feature.id]
-        for featdict in values(s:f)
-            if has_key(featdict, feature.id)
-                unlet featdict[feature.id]
-            endif
+        for featdict in filter(values(s:f), 'has_key(v:val, feature.id)')
+            unlet featdict[feature.id]
         endfor
     endfor
 endfunction
 endfunction
 call s:_f.newfeature('throw', {'cons': s:F.throw})
 "▶1
-call frawor#Lockvar(s:, 'dependents,features,f,selfdeps,loading,shadow,pls,'.
-            \           'rtpcache,dircache')
+call frawor#Lockvar(s:, 'dependents,features,f,loading,shadow,pls,'.
+            \           'rtpcache,dircache,deplen')
 lockvar 1 f
 " vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80

test/reload-frawor.ok

 load: plugin/frawor/tcl
 register: plugin/writefile-feature
 load: plugin/writefile-feature
-unloadpre: autoload/frawor
-unloadpre: plugin/frawor/base64
+unloadpre: plugin/frawor/history
+unloadpre: plugin/frawor/mappings
+unloadpre: plugin/frawor/decorators/altervars
+unloadpre: plugin/frawor/options
+unloadpre: plugin/frawor/checks
 unloadpre: plugin/frawor/commands
+unloadpre: plugin/frawor/fwc
+unloadpre: plugin/frawor/fwc/compiler
+unloadpre: plugin/frawor/fwc/parser
+unloadpre: plugin/frawor/fwc/intfuncs
 unloadpre: plugin/frawor/functions
-unloadpre: plugin/frawor/history
 unloadpre: plugin/frawor/lua
-unloadpre: plugin/frawor/mappings
 unloadpre: plugin/frawor/perl
 unloadpre: plugin/frawor/python
 unloadpre: plugin/frawor/ruby
+unloadpre: plugin/frawor/signs
+unloadpre: plugin/frawor/tcl
+unloadpre: plugin/frawor/decorators
+unloadpre: plugin/frawor/fwc/constructor
+unloadpre: plugin/frawor/fwc/topconstructs
+unloadpre: plugin/frawor/os
 unloadpre: plugin/frawor/table
-unloadpre: plugin/frawor/tcl
 unloadpre: plugin/ignoredeps-feature
-unloadpre: plugin/frawor/options
+unloadpre: autoload/frawor
+unloadpre: plugin/frawor/autocommands
+unloadpre: plugin/frawor/base64
+unloadpre: plugin/frawor/resources
 unloadpre: plugin/writefile-feature
-unloadpre: plugin/frawor/autocommands
-unloadpre: plugin/frawor/fwc/compiler
-unloadpre: plugin/frawor/fwc/constructor
-unloadpre: plugin/frawor/fwc/parser
-unloadpre: plugin/frawor/fwc/intfuncs
-unloadpre: plugin/frawor/fwc/topconstructs
-unloadpre: plugin/frawor/signs
-unloadpre: plugin/frawor/os
-unloadpre: plugin/frawor/checks
-unloadpre: plugin/frawor/fwc
-unloadpre: plugin/frawor/decorators/altervars
-unloadpre: plugin/frawor/decorators
-unloadpre: plugin/frawor/resources
 unloadpre: plugin/frawor
-unload: autoload/frawor
-unload: plugin/frawor/base64
+unload: plugin/frawor/history
+unload: plugin/frawor/mappings
+unload: plugin/frawor/decorators/altervars
+unload: plugin/frawor/options
+unload: plugin/frawor/checks
 unload: plugin/frawor/commands
+unload: plugin/frawor/fwc
+unload: plugin/frawor/fwc/compiler
+unload: plugin/frawor/fwc/parser
+unload: plugin/frawor/fwc/intfuncs
 unload: plugin/frawor/functions
-unload: plugin/frawor/history
 unload: plugin/frawor/lua
-unload: plugin/frawor/mappings
 unload: plugin/frawor/perl
 unload: plugin/frawor/python
 unload: plugin/frawor/ruby
+unload: plugin/frawor/signs
+unload: plugin/frawor/tcl
+unload: plugin/frawor/decorators
+unload: plugin/frawor/fwc/constructor
+unload: plugin/frawor/fwc/topconstructs
+unload: plugin/frawor/os
 unload: plugin/frawor/table
-unload: plugin/frawor/tcl
 unload: plugin/ignoredeps-feature
 _unload
 register: plugin/frawor/autocommands
 load: plugin/frawor/autocommands
-register: plugin/frawor/checks
-load: plugin/frawor/checks
-register: plugin/frawor/fwc/parser
-load: plugin/frawor/fwc/parser
+register: autoload/frawor
+load: autoload/frawor
+register: plugin/frawor/base64
 register: plugin/frawor
 load: plugin/frawor
+register: plugin/frawor/resources
+load: plugin/frawor/resources
+register: plugin/writefile-feature
+load: plugin/writefile-feature
+register: plugin/ignoredeps-feature
+load: plugin/ignoredeps-feature
+register: plugin/frawor/table
+register: plugin/frawor/os
+load: plugin/frawor/os
+register: plugin/frawor/fwc/topconstructs
+load: plugin/frawor/fwc/topconstructs
+register: plugin/frawor/fwc/constructor
+load: plugin/frawor/fwc/constructor
+register: plugin/frawor/decorators
+load: plugin/frawor/decorators
+register: plugin/frawor/tcl
+load: plugin/frawor/tcl
 register: plugin/frawor/signs
 load: plugin/frawor/signs
-register: plugin/frawor/decorators
-load: plugin/frawor/decorators
-register: plugin/frawor/os
-load: plugin/frawor/os
-register: plugin/frawor/resources
-load: plugin/frawor/resources
-register: plugin/ignoredeps-feature
-load: plugin/ignoredeps-feature
-register: plugin/frawor/fwc/constructor
-load: plugin/frawor/fwc/constructor
-register: autoload/frawor
-load: autoload/frawor
-register: plugin/frawor/decorators/altervars
-load: plugin/frawor/decorators/altervars
-register: plugin/frawor/options
-load: plugin/frawor/options
-register: plugin/frawor/fwc/intfuncs
-load: plugin/frawor/fwc/intfuncs
-register: plugin/frawor/fwc/topconstructs
-load: plugin/frawor/fwc/topconstructs
-register: plugin/frawor/fwc
-load: plugin/frawor/fwc
-register: plugin/frawor/fwc/compiler
-load: plugin/frawor/fwc/compiler
-register: plugin/writefile-feature
-load: plugin/writefile-feature
-register: plugin/frawor/tcl
-load: plugin/frawor/tcl
-register: plugin/frawor/table
 register: plugin/frawor/ruby
 load: plugin/frawor/ruby
 register: plugin/frawor/python
 load: plugin/frawor/python
 register: plugin/frawor/perl
 load: plugin/frawor/perl
+register: plugin/frawor/lua
+load: plugin/frawor/lua
+register: plugin/frawor/functions
+load: plugin/frawor/functions
+register: plugin/frawor/fwc/intfuncs
+load: plugin/frawor/fwc/intfuncs
+register: plugin/frawor/fwc/parser
+load: plugin/frawor/fwc/parser
+register: plugin/frawor/fwc/compiler
+load: plugin/frawor/fwc/compiler
+register: plugin/frawor/fwc
+load: plugin/frawor/fwc
+register: plugin/frawor/commands
+load: plugin/frawor/commands
+register: plugin/frawor/checks
+load: plugin/frawor/checks
+register: plugin/frawor/options
+load: plugin/frawor/options
+register: plugin/frawor/decorators/altervars
+load: plugin/frawor/decorators/altervars
 register: plugin/frawor/mappings
 load: plugin/frawor/mappings
-register: plugin/frawor/lua
-load: plugin/frawor/lua
 register: plugin/frawor/history
-load: plugin/frawor/history
-register: plugin/frawor/functions
-load: plugin/frawor/functions
-register: plugin/frawor/commands
-load: plugin/frawor/commands
-register: plugin/frawor/base64
+load: plugin/frawor/history
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.