ZyX_I avatar ZyX_I committed 8a75c79

@/fwc/compiler: Moved `optional', `prefixes', `next' and `actions' keys compilation into separate functions

Comments (0)

Files changed (1)

plugin/frawor/fwc/compiler.vim

     endif
     call add(a:preflist, a:prefix)
 endfunction
+"▶1 compoptional   :: adescr, idx, {rolvars}, {lvars} + self → {lvars}
+" {rolvars} :: caidxstr, largsstr, purgemax
+"   {lvars} :: nextsub, addedsavemsgs
+function s:compiler.compoptional(adescr, idx, caidxstr, largsstr, purgemax,
+            \                    nextsub, addedsavemsgs)
+    let addedsavemsgs=a:addedsavemsgs
+    " XXX nodefs will be still 0 when compiling next adescr. It is intentional.
+    let nodefs=empty(self.defvals)
+    let lopt=len(a:adescr.optional)
+    if lopt>1
+        let failstr=self.getlvarid('fail')
+        call self.let(failstr, 1)
+    endif
+    let addedsavemsgs=1
+    call self.addsavemsgs()
+                \.try()
+                    \.pushms('throw')
+                    \.compileadesc(a:adescr.optional[0],
+                    \              a:idx.'.0(optional)',
+                    \              (a:purgemax || a:adescr.maximum==-1))
+                    \.popms()
+                    \.addrestmsgs(1)
+    if lopt>1
+        call self.let(failstr, 0)
+    endif
+    let newsub=s:F.getsub(self.subs[-1])
+    if newsub isnot a:caidxstr
+        call self.let(a:caidxstr, newsub)
+    endif
+    call self.catch(s:cfreg)
+    if lopt==1 && has_key(a:adescr.optional[0], 'arg')
+        let defaults=reverse(map(filter(copy(a:adescr.optional[0].arg),
+                    \                   'exists("v:val[0][0]") && '.
+                    \                   'v:val[0][0] is "defval"'),
+                    \            'v:val[0][1]'))
+        let self.defvals+=defaults
+        if !empty(defaults) && nodefs
+            let base=self.argstr(0, self.subs[:-2])
+            for defvar in self.defvals
+                call self.call('insert('.base.', '.self.getvar(defvar).', '.
+                            \            a:caidxstr.')')
+            endfor
+            let ldefaults=len(self.defvals)
+            call     self.increment(a:caidxstr, ldefaults)
+                        \.increment(a:largsstr, ldefaults)
+        endif
+    endif
+    call self.up()
+    let self.subs[-1]=[a:caidxstr]
+    if lopt>1
+        let i=1
+        for opt in a:adescr.optional[1:]
+            call self.if(failstr)
+                        \.try()
+                            \.pushms('throw')
+                            \.compileadesc(opt, a:idx.'.'.i.'(optional)')
+                            \.popms()
+                            \.addrestmsgs(1)
+                            \.let(failstr, 0)
+            let newsub=s:F.getsub(self.subs[-1])
+            if newsub isnot a:caidxstr
+                call self.let(a:caidxstr, newsub)
+            endif
+            call self.catch(s:cfreg)
+                \.endif()
+            let self.subs[-1]=[a:caidxstr]
+            let i+=1
+        endfor
+    endif
+    return [[a:caidxstr], addedsavemsgs]
+endfunction
+"▶1 compprefixes   :: {comp*}
+function s:compiler.compprefixes(adescr, idx, caidxstr, largsstr, purgemax,
+            \                    nextsub, addedsavemsgs)
+    "▶2 Define variables
+    let addedsavemsgs=a:addedsavemsgs
+    let nextsub=[a:caidxstr]
+    let preflist=[]
+    let plstr=self.getfunstatvar('prefixes', preflist)
+    let prefdictstr=self.getlvarid('prefdict')
+    let base=self.argstr(0, self.subs[:-2])
+    let astr=self.getlvarid('arg')
+    let idx=a:idx.'(prefixes)'
+    let defaults=filter(copy(a:adescr.prefixes),
+                \       'exists("v:val[2][0]") && v:val[2][0] isnot "arg"')
+    let lists=filter(copy(a:adescr.prefixes), 'v:val[1].list')
+    let haslist=!empty(lists)
+    let lastliststr=self.getlvarid('lastlist')
+    let addtry=(has_key(a:adescr, 'next') || has_key(a:adescr, 'actions'))
+    "▶2 Add messages saving if required
+    if addtry
+        if !addedsavemsgs
+            call self.addsavemsgs()
+            let addedsavemsgs=1
+        endif
+        call self.try().pushms('throw')
+    endif
+    "▶2 Initialize variables inside constructed function
+    call self.let(prefdictstr, '{}')
+                \.call('insert('.base.', '.prefdictstr.', '.
+                \                s:F.getsub(nextsub).')')
+                \.increment(a:caidxstr)
+                \.increment(a:largsstr)
+    "▶2 Add default values
+    for [prefix, prefopts, defval; dummylist] in defaults
+        call self.let(prefdictstr.self.getsubs([prefix]),
+                    \ self.getvar(defval))
+    endfor
+    "▲2
+    call self.while('len('.base.')>'.a:caidxstr)
+    "▶2 Get `astr' variable
+    if haslist
+        call self.if('type('.self.argstr().')=='.type(''))
+    elseif !self.o.onlystrings
+        call self.addtypecond([type('')], idx)
+    endif
+    call self.let(astr, self.getmatcher(get(a:adescr, 'prefixesmatcher',
+                \                           s:prefdefmatcher), plstr,
+                \                       self.argstr()))
+    let removestr='remove('.base.', '.a:caidxstr.')'
+    if addtry
+        let argorigstr=self.getd('argorig')
+    endif
+    if haslist
+        call self.up().else().let(astr, 0).up().endif()
+                    \.if(astr.' isnot 0')
+    else
+        call self.nextthrow(astr.' is 0', 'pnf', idx, self.argstr())
+    endif
+    call self.increment(a:largsstr, -1)
+    if addtry
+        call self.let(argorigstr, removestr)
+    else
+        call self.call(removestr)
+    endif
+    if haslist
+        call self.up().endif()
+    endif
+    "▲2
+    for [prefix, prefopts; args] in a:adescr.prefixes
+        "▶2 Add prefix to prefix list
+        call self.addprefix(preflist, prefix)
+        if prefopts.alt
+            call self.addprefix(preflist, 'no'.prefix)
+        endif
+        "▶2 Remove default value specification if any
+        let hasdefault=0
+        if !empty(args) && args[0][0] isnot 'arg'
+            let hasdefault=1
+            call remove(args, 0)
+        endif
+        "▲2
+        let prefstr=prefdictstr.self.getsubs([prefix])
+        let prefixstr=self.string(prefix)
+        "▶2 Construct prefix condition
+        let cond=astr.' is '.prefixstr
+        if prefopts.list
+            let cond.=' || ('.astr.' is 0 && '.
+                        \   lastliststr.' is '.prefixstr.')'
+        endif
+        call self.addif(cond)
+        "▶2 Process prefix arguments
+        for i in range(1, prefopts.argnum)
+            call self.compilearg(args[i-1], idx.self.string(prefix))
+                        \.incsub()
+        endfor
+        "▶2 Move prefix arguments to prefix dictionary
+        if prefopts.argnum>0
+            call self.increment(a:largsstr, -prefopts.argnum)
+        endif
+        if prefopts.list
+            let removestr='remove('.base.', '.a:caidxstr.', '.
+                        \           a:caidxstr.'+'.(prefopts.argnum-1).')'
+            let cond='has_key('.prefdictstr.', '.prefixstr.')'
+            if hasdefault
+                let cond.=' && type('.prefstr.')=='.type([])
+            endif
+            call self.if(cond)
+                        \.increment(prefstr, removestr)
+                    \.else()
+                        \.let(prefstr, removestr)
+                    \.up()
+            call self.let(lastliststr, prefixstr)
+        else
+            if haslist
+                call self.let(lastliststr, 0)
+            endif
+            if prefopts.argnum==1
+                call self.let(prefstr, 'remove('.base.', '.a:caidxstr.')')
+            elseif prefopts.argnum>0
+                call self.let(prefstr,
+                            \'remove('.base.', '.a:caidxstr.', '.
+                            \        a:caidxstr.'+'.(prefopts.argnum-1).')')
+            else
+                call self.let(prefstr, 1)
+            endif
+        endif
+        "▲2
+        let self.subs[-1]=[a:caidxstr]
+        call self.up()
+        "▶2 Process `no{prefix}'
+        if prefopts.alt
+            call self.addif(astr.' is '.self.string('no'.prefix))
+                        \.let(prefstr, 0)
+                        \.up()
+        endif
+        "▲2
+    endfor
+    call self.up()
+    if addtry
+        call self.unlet(argorigstr).up().up().addrestmsgs(1).popms()
+            \.catch(s:cfreg)
+                \.if('exists('.string(argorigstr).')')
+                    \.call('insert('.base.', '.argorigstr.', '.a:caidxstr.')')
+                    \.increment(a:largsstr)
+                \.up()
+            \.up()
+    else
+        call self.up()
+    endif
+    return [[a:caidxstr], addedsavemsgs]
+endfunction
+"▶1 compnext       :: {comp*}
+function s:compiler.compnext(adescr, idx, caidxstr, largsstr, purgemax,
+            \                nextsub, addedsavemsgs)
+    let addedsavemsgs=a:addedsavemsgs
+    if has_key(a:adescr, 'actions')
+        if !addedsavemsgs
+            call self.addsavemsgs()
+            let addedsavemsgs=1
+        endif
+        call self.try().pushms('throw')
+    endif
+    call self.while(a:caidxstr.'<'.a:largsstr)
+                \.compilearg(a:adescr.next[0], a:idx.'.(next)')
+                \.increment(a:caidxstr)
+                \.up()
+    if has_key(a:adescr, 'actions')
+        call self.addrestmsgs(1).catch(s:cfreg).popms().up()
+    endif
+    return [[a:caidxstr], addedsavemsgs]
+endfunction
+"▶1 compactions    :: {comp*}
+function s:compiler.compactions(adescr, idx, caidxstr, largsstr, purgemax,
+            \                   nextsub, addedsavemsgs)
+    let actionstr=self.getlvarid('action')
+    let actions=filter(copy(a:adescr.actions), 'v:val[0] isnot 0')
+    let noact=get(filter(copy(a:adescr.actions), 'v:val[0] is 0'), 0, 0)
+    let fsastr=self.getfunstatvar('actions', map(copy(actions), 'v:val[0]'))
+    if noact isnot 0
+        call self.try().pushms('throw')
+    endif
+    let idx=a:idx.'(actions)'
+    if !self.o.onlystrings
+        call self.addtypecond([type('')], idx)
+    endif
+    let curargstr=self.argstr()
+    call self.let(actionstr, self.getmatcher(get(a:adescr, 'actionsmatcher',
+                \                                s:actdefmatcher),
+                \                            fsastr, curargstr))
+                \.nextthrow(actionstr.' is 0', 'anf', idx, curargstr)
+                \.let(curargstr, actionstr)
+    unlet curargstr
+    call self.incsub()
+    let astartsub=copy(self.subs[-1])
+    for action in actions
+        call self.addif(actionstr.' is '.self.string(action[0]))
+        if len(action)>1
+            call self.compileadesc(action[1],idx.'.'.self.string(action[0]))
+        endif
+        call self.let(a:caidxstr, s:F.getsub(self.subs[-1]))
+                    \.up()
+        let self.subs[-1]=copy(astartsub)
+    endfor
+    if noact isnot 0
+        call self.popms().catch(s:cfreg)
+        call self.incsub(-1)
+        if len(noact)>1
+            call self.compileadesc(noact[1], idx.'.nullact')
+                        \.let(a:caidxstr, s:F.getsub(self.subs[-1]))
+        endif
+        let self.subs[-1]=copy(astartsub)
+        call self.up().up()
+    endif
+    let self.subs[-1]=[a:caidxstr]
+    return [[a:caidxstr], a:addedsavemsgs]
+endfunction
 "▶1 compileadesc   :: adescr[, idx[, purgemax]] + self → self + self
 let s:actdefmatcher=['matcher', ['intfunc', 'start', 0, 0]]
 let s:prefdefmatcher=s:actdefmatcher
     "▲2
     let addedsavemsgs=0
     let caidxstr=self.getlvarid('caidx')
-    let caidx=[caidxstr]
     let oldsub=s:F.getsub(nextsub)
     if oldsub isnot caidxstr
         call self.let(caidxstr, oldsub)
     endif
-    let self.subs[-1]=copy(caidx)
+    let self.subs[-1]=[caidxstr]
     let largsstr=self.getlargsstr()
-    "▶2 `optional' key
-    if has_key(a:adescr, 'optional')
-        unlet nextsub
-        let nextsub=copy(caidx)
-        " XXX nodefs will be still 0 when compiling next adescr. It is 
-        " intentional.
-        let nodefs=empty(self.defvals)
-        let lopt=len(a:adescr.optional)
-        if lopt>1
-            let failstr=self.getlvarid('fail')
-            call self.let(failstr, 1)
+    let idx=get(a:000, 0, '')
+    "▶2 Following keys (optional, prefixes, next, actions)
+    for key in ['optional', 'prefixes', 'next', 'actions']
+        if has_key(a:adescr, key)
+            let [newnextsub, addedsavemsgs]=
+                        \call(self['comp'.key],
+                        \     [a:adescr, idx, caidxstr, largsstr, purgemax,
+                        \      nextsub, addedsavemsgs],
+                        \     self)
+            unlet nextsub
+            let nextsub=newnextsub
+            unlet newnextsub
         endif
-        let addedsavemsgs=1
-        call self.addsavemsgs()
-                    \.try()
-                        \.pushms('throw')
-                        \.compileadesc(a:adescr.optional[0],
-                        \              get(a:000, 0, '').'.0(optional)',
-                        \              (purgemax || a:adescr.maximum==-1))
-                        \.popms()
-                        \.addrestmsgs(1)
-        if lopt>1
-            call self.let(failstr, 0)
-        endif
-        let newsub=s:F.getsub(self.subs[-1])
-        if newsub isnot caidxstr
-            call self.let(caidxstr, newsub)
-        endif
-        call self.catch(s:cfreg)
-        if lopt==1 && has_key(a:adescr.optional[0], 'arg')
-            let defaults=reverse(map(filter(copy(a:adescr.optional[0].arg),
-                        \                   'exists("v:val[0][0]") && '.
-                        \                   'v:val[0][0] is "defval"'),
-                        \            'v:val[0][1]'))
-            let self.defvals+=defaults
-            if !empty(defaults) && nodefs
-                let base=self.argstr(0, self.subs[:-2])
-                for defvar in self.defvals
-                    call self.call('insert('.base.', '.self.getvar(defvar).', '.
-                                \            caidxstr.')')
-                endfor
-                let ldefaults=len(self.defvals)
-                call     self.increment(caidxstr, ldefaults)
-                            \.increment(largsstr, ldefaults)
-            endif
-        endif
-        call self.up()
-        let self.subs[-1]=copy(caidx)
-        if lopt>1
-            let i=1
-            for opt in a:adescr.optional[1:]
-                call self.if(failstr)
-                            \.try()
-                                \.pushms('throw')
-                                \.compileadesc(opt,
-                                \          get(a:000, 0, '').'.'.i.'(optional)')
-                                \.popms()
-                                \.addrestmsgs(1)
-                                \.let(failstr, 0)
-                let newsub=s:F.getsub(self.subs[-1])
-                if newsub isnot caidxstr
-                    call self.let(caidxstr, newsub)
-                endif
-                call self.catch(s:cfreg)
-                    \.endif()
-                let self.subs[-1]=copy(caidx)
-                let i+=1
-            endfor
-        endif
-    endif
-    "▶2 `prefixes' key
-    if has_key(a:adescr, 'prefixes')
-        "▶3 Define variables
-        unlet nextsub
-        let nextsub=copy(caidx)
-        let preflist=[]
-        let plstr=self.getfunstatvar('prefixes', preflist)
-        let prefdictstr=self.getlvarid('prefdict')
-        let base=self.argstr(0, self.subs[:-2])
-        let astr=self.getlvarid('arg')
-        let idx=get(a:000, 0, '').'(prefixes)'
-        let defaults=filter(copy(a:adescr.prefixes),
-                    \       'exists("v:val[2][0]") && v:val[2][0] isnot "arg"')
-        let lists=filter(copy(a:adescr.prefixes), 'v:val[1].list')
-        let haslist=!empty(lists)
-        let lastliststr=self.getlvarid('lastlist')
-        let addtry=(has_key(a:adescr, 'next') || has_key(a:adescr, 'actions'))
-        "▶3 Add messages saving if required
-        if addtry
-            if !addedsavemsgs
-                call self.addsavemsgs()
-                let addedsavemsgs=1
-            endif
-            call self.try().pushms('throw')
-        endif
-        "▶3 Initialize variables inside constructed function
-        call self.let(prefdictstr, '{}')
-                    \.call('insert('.base.', '.prefdictstr.', '.
-                    \                s:F.getsub(nextsub).')')
-                    \.increment(caidxstr)
-                    \.increment(largsstr)
-        "▶3 Add default values
-        for [prefix, prefopts, defval; dummylist] in defaults
-            call self.let(prefdictstr.self.getsubs([prefix]),
-                        \ self.getvar(defval))
-        endfor
-        "▲3
-        call self.while('len('.base.')>'.caidxstr)
-        "▶3 Get `astr' variable
-        if haslist
-            call self.if('type('.self.argstr().')=='.type(''))
-        elseif !self.o.onlystrings
-            call self.addtypecond([type('')], idx)
-        endif
-        call self.let(astr, self.getmatcher(get(a:adescr, 'prefixesmatcher',
-                    \                           s:prefdefmatcher), plstr,
-                    \                       self.argstr()))
-        let removestr='remove('.base.', '.caidxstr.')'
-        if addtry
-            let argorigstr=self.getd('argorig')
-        endif
-        if haslist
-            call self.up().else().let(astr, 0).up().endif()
-                        \.if(astr.' isnot 0')
-        else
-            call self.nextthrow(astr.' is 0', 'pnf', idx, self.argstr())
-        endif
-        call self.increment(largsstr, -1)
-        if addtry
-            call self.let(argorigstr, removestr)
-        else
-            call self.call(removestr)
-        endif
-        if haslist
-            call self.up().endif()
-        endif
-        "▲3
-        for [prefix, prefopts; args] in a:adescr.prefixes
-            "▶3 Add prefix to prefix list
-            call self.addprefix(preflist, prefix)
-            if prefopts.alt
-                call self.addprefix(preflist, 'no'.prefix)
-            endif
-            "▶3 Remove default value specification if any
-            let hasdefault=0
-            if !empty(args) && args[0][0] isnot 'arg'
-                let hasdefault=1
-                call remove(args, 0)
-            endif
-            "▲3
-            let prefstr=prefdictstr.self.getsubs([prefix])
-            let prefixstr=self.string(prefix)
-            "▶3 Construct prefix condition
-            let cond=astr.' is '.prefixstr
-            if prefopts.list
-                let cond.=' || ('.astr.' is 0 && '.
-                            \   lastliststr.' is '.prefixstr.')'
-            endif
-            call self.addif(cond)
-            "▶3 Process prefix arguments
-            for i in range(1, prefopts.argnum)
-                call self.compilearg(args[i-1], idx.self.string(prefix))
-                            \.incsub()
-            endfor
-            "▶3 Move prefix arguments to prefix dictionary
-            if prefopts.argnum>0
-                call self.increment(largsstr, -prefopts.argnum)
-            endif
-            if prefopts.list
-                let removestr='remove('.base.', '.caidxstr.', '.
-                            \           caidxstr.'+'.(prefopts.argnum-1).')'
-                let cond='has_key('.prefdictstr.', '.prefixstr.')'
-                if hasdefault
-                    let cond.=' && type('.prefstr.')=='.type([])
-                endif
-                call self.if(cond)
-                            \.increment(prefstr, removestr)
-                        \.else()
-                            \.let(prefstr, removestr)
-                        \.up()
-                call self.let(lastliststr, prefixstr)
-            else
-                if haslist
-                    call self.let(lastliststr, 0)
-                endif
-                if prefopts.argnum==1
-                    call self.let(prefstr, 'remove('.base.', '.caidxstr.')')
-                elseif prefopts.argnum>0
-                    call self.let(prefstr,
-                                \'remove('.base.', '.caidxstr.', '.
-                                \        caidxstr.'+'.(prefopts.argnum-1).')')
-                else
-                    call self.let(prefstr, 1)
-                endif
-            endif
-            "▲3
-            let self.subs[-1]=copy(caidx)
-            call self.up()
-            "▶3 Process `no{prefix}'
-            if prefopts.alt
-                call self.addif(astr.' is '.self.string('no'.prefix))
-                            \.let(prefstr, 0)
-                            \.up()
-            endif
-            "▲3
-        endfor
-        call self.up()
-        if addtry
-            call self.unlet(argorigstr).up().up().addrestmsgs(1).popms()
-                \.catch(s:cfreg)
-                    \.if('exists('.string(argorigstr).')')
-                        \.call('insert('.base.', '.argorigstr.', '.caidxstr.')')
-                        \.increment(largsstr)
-                    \.up()
-                \.up()
-        else
-            call self.up()
-        endif
-    endif
-    "▶2 `next' key
-    if has_key(a:adescr, 'next')
-        unlet nextsub
-        let nextsub=copy(caidx)
-        if has_key(a:adescr, 'actions')
-            if !addedsavemsgs
-                call self.addsavemsgs()
-                let addedsavemsgs=1
-            endif
-            call self.try().pushms('throw')
-        endif
-        let largsstr=self.getlargsstr()
-        call self.while(caidxstr.'<'.largsstr)
-                    \.compilearg(a:adescr.next[0], get(a:000, 0, '').'.(next)')
-                    \.increment(caidxstr)
-                    \.up()
-        if has_key(a:adescr, 'actions')
-            call self.addrestmsgs(1).catch(s:cfreg).popms().up()
-        endif
-    endif
-    "▶2 `actions' key
-    if has_key(a:adescr, 'actions')
-        unlet nextsub
-        let nextsub=copy(caidx)
-        let actionstr=self.getlvarid('action')
-        let actions=filter(copy(a:adescr.actions), 'v:val[0] isnot 0')
-        let noact=get(filter(copy(a:adescr.actions), 'v:val[0] is 0'), 0, 0)
-        let fsastr=self.getfunstatvar('actions', map(copy(actions), 'v:val[0]'))
-        if noact isnot 0
-            call self.try().pushms('throw')
-        endif
-        let idx=get(a:000, 0, '').'(actions)'
-        if !self.o.onlystrings
-            call self.addtypecond([type('')], idx)
-        endif
-        let curargstr=self.argstr()
-        call self.let(actionstr, self.getmatcher(get(a:adescr, 'actionsmatcher',
-                    \                                s:actdefmatcher),
-                    \                            fsastr, curargstr))
-                    \.nextthrow(actionstr.' is 0', 'anf', idx, curargstr)
-                    \.let(curargstr, actionstr)
-        unlet curargstr
-        call self.incsub()
-        let astartsub=copy(self.subs[-1])
-        for action in actions
-            call self.addif(actionstr.' is '.self.string(action[0]))
-            if len(action)>1
-                call self.compileadesc(action[1],idx.'.'.self.string(action[0]))
-            endif
-            call self.let(caidxstr, s:F.getsub(self.subs[-1]))
-                        \.up()
-            let self.subs[-1]=copy(astartsub)
-        endfor
-        if noact isnot 0
-            call self.popms().catch(s:cfreg)
-            call self.incsub(-1)
-            if len(noact)>1
-                call self.compileadesc(noact[1], idx.'.nullact')
-                            \.let(caidxstr, s:F.getsub(self.subs[-1]))
-            endif
-            let self.subs[-1]=copy(astartsub)
-            call self.up().up()
-        endif
-        let self.subs[-1]=copy(caidx)
-    endif
+    endfor
     "▶2 Check for processed argument length
     " XXX a:0 is checked here
     if !a:0 && type(self.subs[-1])==type([])
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.