Commits

ZyX_I committed 0f935fb

Moved built-in checks and pipes into a separate module

Comments (0)

Files changed (9)

plugin/frawor/fwc/compiler.vim

 endif
 execute frawor#Setup('0.0', {'@/fwc/parser'     : '0.0',
             \                '@/fwc/constructor': '0.0',
+            \                '@/fwc/intfuncs'   : '0.0',
             \                '@/os'             : '0.0',
             \                '@/decorators'     : '0.0'}, 1)
 let s:compiler={}
 let s:pipechecks={
             \'substitute': ['intfunc', 'type',   [type('')]],
             \      'take': ['intfunc', 'type',   [type('')]],
-            \       'run': ['intfunc', 'isfunc', 0         ],
-            \      'earg': ['intfunc', 'type',   [type('')]],
-            \     'tuple': ['intfunc', 'type',   [type([])]],
             \      'list': ['intfunc', 'type',   [type([])]],
             \      'dict': ['intfunc', 'type',   [type({})]],
         \}
         if has_key(s:pipechecks, desc[0])
             call self.compilecheck(['check', s:pipechecks[desc[0]]], a:idx)
         endif
-        "▶3 `func', `eval'
-        if desc[0] is 'func' || desc[0] is 'eval'
-            call self.compilepipe(desc, a:idx)
-        "▶3 `if'
-        elseif desc[0] is 'if'
-            let condstr=self.getlvarid('cond')
-            call self.try()
-                        \.pushms('throwignore')
-                        \.compilearg(desc[1], a:idx.'(cond)', 'check')
-                        \.popms()
-                        \.let(condstr, 1)
-                    \.up().catch(s:cfreg)
-                        \.let(condstr, 0)
-                    \.up()
-            if len(desc[2])>1
-                call self.addif(condstr).compilearg(desc[2],a:idx.'(if)','pipe')
-                            \.up()
-                if len(desc[3])>1
-                    call self.addif()
-                                \.compilearg(desc[3], a:idx.'(else)', 'pipe')
-                                \.up()
-                endif
-            else
-                call self.addif('!'.condstr)
-                            \.compilearg(desc[3], a:idx.'(else)', 'pipe')
-                            \.up()
-            endif
-            call self.up()
-        "▶3 `run'
-        elseif desc[0] is 'run'
-            call self.try()
-                        \.let(curargstr, 'call('.curargstr.', '.
-                        \                          self.getvar(desc[1]).', {})')
-                    \.up().catch()
-                        \.addthrow('runfail', 1, a:idx, 'v:exception')
-        "▶3 `earg'
-        elseif desc[0] is 'earg'
-            call self.try()
-                        \.let(curargstr, 'eval('.curargstr.')')
-                    \.up().catch()
-                        \.addthrow('evalfail', 1, a:idx, 'v:exception')
-        "▶3 `tuple'
-        elseif desc[0] is 'tuple'
-            call self.nextthrow('len('.curargstr.')!='.len(desc[1]),
-                        \       'invlstlen', a:idx, len(desc[1]),
-                        \                    'len('.curargstr.')')
-                        \.addtuple(desc, a:idx, 'pipe')
-        "▶3 `list'
-        elseif desc[0] is 'list'
-            call self.addlist(desc, a:idx, 'pipe')
-        "▶3 `dict'
-        elseif desc[0] is 'dict'
-            call self.adddict(desc, a:idx, 'pipe')
-        "▶3 `in', `key'
-        elseif desc[0] is 'in' || desc[0] is 'key'
-            if len(desc)==2 || (desc[2][1][0] is 'intfunc' &&
-                        \       desc[2][1][1] is 'exact' &&
-                        \       desc[2][1][2] is 0)
-                call self.compilecheck(['check', a:pipe[1]], a:idx)
-            else
-                let matchstr=self.getlvarid('match')
-                call self.addtypecond([type('')], a:idx)
-                            \.let(matchstr,self.getmatcher(desc[2],
-                            \                              self.getvar(desc[1]),
-                            \                              curargstr))
-                            \.nextthrow(matchstr.' is 0',
-                            \           'nmatch', a:idx, curargstr)
-                            \.let(curargstr, matchstr)
-            endif
-        "▶3 `take'
-        elseif desc[0] is 'take'
-            let varstr=self.getvar(desc[1])
-            let matchstr=self.getlvarid('match')
-            call self.addtypecond([type('')], a:idx)
-                        \.let(matchstr, self.getmatcher(desc[2], varstr,
-                        \                               curargstr))
-                        \.nextthrow(matchstr.' is 0', 'nmatch',a:idx,curargstr)
-                        \.let(curargstr, varstr.'['.matchstr.']')
-        "▶3 `substitute'
-        elseif desc[0] is 'substitute'
-            call self.let(curargstr, 'substitute('.curargstr.', '.
-                        \((type(desc[1][1])==type(''))?
-                        \       (s:F.string(desc[1][1])):
-                        \       (self.getvar(desc[1][1]))).', '.
-                        \join(map(desc[2:], 'self.compilestring(v:val)'), ', ').
-                        \')')
-        "▶3 `bool'
-        elseif desc[0] is 'bool'
-            call self.let(curargstr, '!empty('.curargstr.')')
-        "▶3 `value'
-        elseif desc[0] is 'value'
-            call self.witharg(self.getvar(desc[1], 1))
-                        \.compilearg(desc[2], a:idx.'(value)', 'pipe')
-                        \.without()
-        "▲3
+        if has_key(s:_r.FWC_intfuncs[desc[0]], 'pipe')
+            call call(s:_r.FWC_intfuncs[desc[0]].pipe, [desc,a:idx,'pipe'],self)
         else
-            call self.compilecheck(['check', a:pipe[1]], a:idx)
+            call call(s:_r.FWC_intfuncs[desc[0]].check,[desc,a:idx,'pipe'],self)
         endif
     endif
     "▲2
     let subidxs[-1]+=1
     return join(subidxs, '.')
 endfunction
-"▶1 optnot         :: &self(idx)
-" XXX low-level hacks here
-function s:compiler.optnot(idx)
-    if len(self.l[1])==2
-                \&& len(self.l[1][0])>2
-                \&& self.l[1][0][0] is 'if'
-                \&& ((self.l[1][0][-1] is 'endif'
-                \  && self.l[1][0][-3] isnot 'else')
-                \ || (self.l[1][0][-2] isnot 'else'))
-        let conditions=[]
-        let iftree=copy(self.l[1][0])
-        while !empty(iftree)
-            let type=remove(iftree, 0)
-            if type is 'if' || type is 'elseif'
-                let [condition, block]=remove(iftree, 0, 1)
-                if block!=#[['throw', s:cfstr]]
-                    return self
-                endif
-                call add(conditions, condition)
-            elseif type is 'endif'
-                break
-            else
-                return self
-            endif
-        endwhile
-        call remove(self.l, 0, -1)
-        call self.add('if', 0, [])
-        call self.nextthrow('!('.join(conditions, ' || ').')', 'notfail', a:idx)
-        call remove(self.l, 1, 3)
-    endif
-    return self
-endfunction
 "▶1 compilecheck   :: checkcontext, idx + self → self + self
 function s:compiler.compilecheck(check, idx)
     let curargstr=self.argstr()
     "▶2 `intfunc' check
     else
         let desc=check[1:]
-        "▶3 `func'
-        if desc[0] is 'func'
-            call self.nextthrow(self.getfunc(desc[1], 0, curargstr).' is 0',
-                        \       'funcfail', a:idx)
-        "▶3 `eval'
-        elseif desc[0] is 'eval'
-            call self.nextthrow(self.getexpr(desc[1], curargstr).' is 0',
-                        \       'exprfail', a:idx)
-        "▶3 `not'
-        elseif desc[0] is 'not'
-            call self.try()
-                        \.pushms('throwignore')
-                        \.compilearg(desc[1], a:idx.'(not)')
-                        \.popms()
-                        \.throw("'NOTFAIL'")
-                    \.catch(s:cfreg).up()
-                    \.catch('\v^NOTFAIL$')
-                        \.addthrow('notfail', 1, a:idx)
-                        \.optnot(a:idx)
-        "▶3 `either'
-        elseif desc[0] is 'either'
-            let sucstr=self.getlvarid('succeeded')
-            let msglenstr=self.getlvarid('msglen')
-            let pmsglenstr=self.getlvarid('pmsglen')
-            call self.let(sucstr, 1).pushms('throw').addsavemsgs()
-            if !empty(desc[1])
-                call self.try()
-                            \.compilearg(desc[1][0], a:idx.'(either).0',
-                            \            'check')
-                        \.up().catch(s:cfreg)
-                            \.let(sucstr, 0).up()
-            endif
-            let i=1
-            for arg in desc[1][1:]
-                call self.addif('!'.sucstr)
-                            \.let(sucstr, 1)
-                            \.try()
-                                \.compilearg(arg, a:idx.'(either).'.i,'check')
-                            \.up().catch(s:cfreg)
-                                \.let(sucstr, 0)
-                            \.up()
-                        \.up()
-                let i+=1
-            endfor
-            call self.addif(sucstr).addrestmsgs().up().popms()
-                        \.addif().addthrow('eitherfail', 1, a:idx).up().up()
-        "▶3 `tuple'
-        elseif desc[0] is 'tuple'
-            call self.addtypecond([type([])], a:idx)
-                        \.nextthrow('len('.curargstr.')!='.len(desc[1]),
-                        \           'invlstlen', a:idx, len(desc[1]),
-                        \                        'len('.curargstr.')')
-                        \.addtuple(desc, a:idx, 'check')
-        "▶3 `list'
-        elseif desc[0] is 'list'
-            call self.addtypecond([type([])], a:idx).addlist(desc,a:idx,'check')
-        "▶3 `dict'
-        elseif desc[0] is 'dict'
-            call self.addtypecond([type({})], a:idx).adddict(desc,a:idx,'check')
-        "▶3 `in'
-        elseif desc[0] is 'in'
-            call self.nextthrow('index('.self.getvar(desc[1]).', '.
-                        \                curargstr.')==-1',
-                        \       'ninlist', a:idx)
-        "▶3 `key'
-        elseif desc[0] is 'key'
-            call self.addtypecond([type('')], a:idx)
-                        \.nextthrow('!has_key('.self.getvar(desc[1]).', '.
-                        \                       curargstr.')',
-                        \           'nindict', a:idx, curargstr)
-        "▶3 `haskey'
-        elseif desc[0] is 'haskey'
-            call self.addtypecond([type({})], a:idx)
-            if len(desc[1])>1
-                let keys='['.join(map(copy(desc[1]),
-                            \         'type(v:val)==type("")?'.
-                            \               's:F.string(v:val):'.
-                            \               'self.getvar(v:val)'),
-                            \', ').']'
-                let absentkeys='filter('.keys.', '.
-                            \          string('!has_key('.curargstr.', '.
-                            \                           'v:val)').')'
-                call self.nextthrow('!empty('.absentkeys.')',
-                            \       'keysmis', a:idx,
-                            \                  'join('.absentkeys.', ", ")')
-            elseif !empty(desc[1])
-                let keystr=((type(desc[1][0])==type(''))?
-                            \       (s:F.string(desc[1][0])):
-                            \       (self.getvar(desc[1][0])))
-                call self.nextthrow('!has_key('.curargstr.', '.keystr.')',
-                            \       'keymis', a:idx, keystr)
-            endif
-        "▶3 `range'
-        elseif desc[0] is 'range'
-            "▶4 Determine whether we accept floating-point values
-            let acceptfloat=has('float') &&
-                        \(desc[1][0] is 'float' || desc[1][1] is 'float')
-            if acceptfloat
-                call self.addtypecond([type(0), type(0.0)], a:idx)
-            else
-                call self.addtypecond([type(0)], a:idx)
-            endif
-            "▶4 Obtain range borders
-            let range=map(desc[1:],
-                        \'((v:val[0] is "inf" || v:val[0] is "nan")?'.
-                        \   '(""):'.
-                        \   '((v:val[0] is "number"||v:val[0] is "float")?'.
-                        \       '(v:val[1]):'.
-                        \       '(self.getvar(v:val))))')
-            if type(range[0])!=type('') && type(range[1])!=type('')
-                        \&& range[0]>range[1]
-                call reverse(range)
-            endif
-            "▶4 Construct condition
-            let cond=''
-            call map(range, '((type(v:val)=='.type('').')?'.
-                        \               '(v:val):'.
-                        \               '(string(v:val)))')
-            if range[0] isnot ''
-                let cond.=range[0].'>'.curargstr
-            endif
-            if range[1] isnot ''
-                if !empty(cond)
-                    let cond.=' || '
-                endif
-                let cond.=curargstr.'>'.range[1]
-            endif
-            "▶4 Add condition to result
-            if !empty(cond)
-                call self.nextthrow(cond, 'nrange', a:idx,
-                            \                       'string('.curargstr.')',
-                            \                       'string('.range[0].')',
-                            \                       'string('.range[1].')')
-            endif
-        "▶3 `match'
-        elseif desc[0] is 'match'
-            let regex=((type(desc[1][1])==type(''))?
-                        \(s:F.string(desc[1][1])):
-                        \(self.getvar(desc[1][1])))
-            call self.addtypecond([type('')], a:idx)
-                        \.nextthrow(curargstr.'!~#'.regex,
-                        \           'nregmatch', a:idx, curargstr, regex)
-        "▶3 `path'
-        elseif desc[0] is 'path'
-            call self.addtypecond([type('')], a:idx)
-            let spec=desc[1]
-            if spec[0] is 'd'
-                let spec=spec[1:]
-                if spec[0] is 'w'
-                    call self.nextthrow('filewritable('.curargstr.')!=2',
-                                \       'nwrite', a:idx, curargstr)
-                    let spec=spec[1:]
-                elseif spec[0] is 'W'
-                    call self.nextthrow('filewritable('.curargstr.')!=2 &&'.
-                                \      '(@%@.os.path.exists('.curargstr.')'.
-                                \       '|| filewritable('.
-                                \               '@%@.os.path.dirname('.
-                                \                        curargstr.'))!=2)',
-                                \      'nowrite', a:idx, curargstr)
-                    let spec=spec[1:]
-                elseif spec[0] is 'p'
-                    call self.addpathp(a:idx)
-                                \.nextthrow('!@%@.os.path.isdir('.
-                                \                             curargstr.')',
-                                \           'isdir', a:idx, curargstr)
-                    let spec=spec[1:]
-                else
-                    call self.nextthrow('!@%@.os.path.isdir('.curargstr.')',
-                                \       'isdir', a:idx, curargstr)
-                endif
-            else
-                let fileonly=0
-                if spec[0] is 'f'
-                    let spec=spec[1:]
-                    let fileonly=1
-                endif
-                if fileonly
-                    if spec[0] is 'r'
-                        call self.nextthrow('!filereadable('.curargstr.')',
-                                    \       'nread', a:idx, curargstr)
-                        let spec=spec[1:]
-                    elseif spec[-1:] isnot 'x'
-                        call self.nextthrow('@%@.os.path.isdir('.
-                                    \                         curargstr.')',
-                                    \       'isfile', a:idx, curargstr)
-                    endif
-                endif
-                if spec[0] is 'w'
-                    call self.nextthrow('!filewritable('.curargstr.')',
-                                \       'nwrite', a:idx, curargstr)
-                    let spec=spec[1:]
-                elseif spec[0] is 'W'
-                    call self.nextthrow('!filewritable('.curargstr.') &&'.
-                                \      '(@%@.os.path.exists('.curargstr.')'.
-                                \       '|| filewritable('.
-                                \               '@%@.os.path.dirname('.
-                                \                        curargstr.'))!=2)',
-                                \      'nowrite', a:idx, curargstr)
-                    let spec=spec[1:]
-                elseif spec[0] is 'p'
-                    call self.addpathp(a:idx)
-                    let spec=spec[1:]
-                endif
-                if spec is 'x'
-                    call self.nextthrow('!executable('.curargstr.')',
-                                \       'nexecable', a:idx, curargstr)
-                endif
-            endif
-        "▶3 `type'
-        elseif desc[0] is 'type'
-            call self.addtypecond(desc[1], a:idx)
-        "▶3 `isfunc'
-        elseif desc[0] is 'isfunc'
-            let frefpref='string('.curargstr.')[10:11]'
-            if desc[1]
-                call self.addtypecond([2], a:idx)
-                call self.nextthrow('!exists('.string('*'.curargstr).') ||'.
-                            \                       frefpref.' is "s:"',
-                            \       'nfunc', a:idx,
-                            \                'string('.curargstr.')[10:-3]')
-            else
-                call self.nextthrow('!((type('.curargstr.')==2 && '.
-                            \         'exists('.string('*'.curargstr).')&&'.
-                            \          frefpref.' isnot "s:") '.
-                            \        '|| (type('.curargstr.')=='.type('').
-                            \            '&& '.curargstr.'=~#'.
-                            \             '''\v^%(%([sla]@!\w:)?%(\w|\.)+|'.
-                            \                    '%(s@!\w:)?\w+|'.
-                            \                    '%(<SNR>\w+))$'''.
-                            \            '&& exists("*".'.curargstr.')))',
-                            \       'nsfunc', a:idx, 'string('.curargstr.')')
-            endif
-        "▶3 `isreg'
-        elseif desc[0] is 'isreg'
-            call self.addtypecond([type('')], a:idx)
-                        \.try().call('matchstr("", '.curargstr.')').up()
-                        \.catch().addthrow('nreg', 1, a:idx, curargstr,
-                        \                  'v:exception')
-        "▶3 `bool'
-        elseif desc[0] is 'bool'
-            call self.nextthrow('index([0, 1], '.curargstr.')==-1',
-                        \       'nbool', a:idx, 'string('.curargstr.')')
-        "▶3 `is'
-        elseif desc[0] is 'is'
-            let var=self.getvar(desc[1])
-            call self.nextthrow(curargstr.' isnot '.var,
-                        \       'isnot', a:idx, var,
-                        \                'string('.curargstr.')')
-        "▶3 `value'
-        elseif desc[0] is 'value'
-            call self.witharg(self.getvar(desc[1], 1))
-                        \.compilearg(desc[2], a:idx.'(value)', 'check')
-                        \.without()
-        "▶3 `_', `any'
-        elseif desc[0] is '_' || desc[0] is 'any'
-            " Just do nothing here
-        endif
-        "▲3
+        call call(s:_r.FWC_intfuncs[desc[0]].check, [desc, a:idx, 'check'],self)
     endif
     "▲2
     return self

plugin/frawor/fwc/intfuncs.vim

+"▶1 Header
+scriptencoding utf-8
+if exists('s:_pluginloaded') || exists('g:fraworOptions._donotload') ||
+            \exists('g:frawor__donotload')
+    finish
+endif
+execute frawor#Setup('0.0', {'@/resources': '0.0'}, 1)
+let s:r={}
+let s:cf='CHECKFAILED'
+let s:cfstr=string(s:cf)
+let s:cfreg='\v^'.s:cf.'$'
+"▶1 string         :: String → String
+function s:F.string(str)
+    return substitute(substitute(substitute(substitute(string(a:str),
+                \"@",      '''."\\x40".''', 'g'),
+                \"\n",     '''."\\n".''',   'g'),
+                \"^''\\.", '',              '' ),
+                \"\\.''$", '',              '' )
+endfunction
+"▶1 `func', `eval'
+let s:r.func={'args': ['func']}
+" Checks whether result of running {func}({argument}) isnot 0
+function s:r.func.check(desc, idx, type)
+    return self['compile'.a:type](a:desc, a:idx)
+endfunction
+" Replaces {argument} with the result of running {func}({argument})
+let s:r.func.pipe=s:r.func.check
+" Replaces {argument} with the result of evaluating {expr}
+" Checks whether result of running eval({expr}) isnot 0
+let s:r.eval=copy(s:r.func)
+let s:r.eval.args=['expr']
+"▶1 `if'
+" Processes argument if condition is met. Third argument describes the `else' 
+" clause.
+let s:r.if={'args': ['arg', 'arg', 'arg']}
+function s:r.if.pipe(desc, idx, type)
+    let condstr=self.getlvarid('cond')
+    call self.try()
+                \.pushms('throwignore')
+                \.compilearg(a:desc[1], a:idx.'(cond)', 'check')
+                \.popms()
+                \.let(condstr, 1)
+            \.up().catch(s:cfreg)
+                \.let(condstr, 0)
+            \.up()
+    if len(a:desc[2])>1
+        call self.addif(condstr).compilearg(a:desc[2],a:idx.'(if)','pipe')
+                    \.up()
+        if len(a:desc[3])>1
+            call self.addif()
+                        \.compilearg(a:desc[3], a:idx.'(else)', 'pipe')
+                        \.up()
+        endif
+    else
+        call self.addif('!'.condstr)
+                    \.compilearg(a:desc[3], a:idx.'(else)', 'pipe')
+                    \.up()
+    endif
+    return self.up()
+endfunction
+"▶1 `run'
+" Replaces {argument} with the result of calling itself with {var} as argument 
+" list
+let s:r.run={'args': ['var']}
+function s:r.run.pipe(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.compilecheck(['check', ['intfunc', 'isfunc', 0]], a:idx)
+            \.try()
+                \.let(curargstr, 'call('.curargstr.', '.
+                \                                self.getvar(a:desc[1]).', {})')
+            \.up().catch()
+                \.addthrow('runfail', 1, a:idx, 'v:exception')
+endfunction
+"▶1 `earg'
+" Replaces {argument} with the result of evaluating itself
+let s:r.earg={'args': []}
+function s:r.earg.pipe(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.compilecheck(['check', ['infunc', 'type', [type('')]]], a:idx)
+            \.try()
+                \.let(curargstr, 'eval('.curargstr.')')
+            \.up().catch()
+                \.addthrow('evalfail', 1, a:idx, 'v:exception')
+endfunction
+"▶1 `not'
+let s:r.not={'args': ['arg']}
+"▶2 optimize
+" XXX low-level hacks here
+function s:r.not.optimize(idx)
+    if len(self.l[1])==2
+                \&& len(self.l[1][0])>2
+                \&& self.l[1][0][0] is 'if'
+                \&& ((self.l[1][0][-1] is 'endif'
+                \  && self.l[1][0][-3] isnot 'else')
+                \ || (self.l[1][0][-2] isnot 'else'))
+        let conditions=[]
+        let iftree=copy(self.l[1][0])
+        while !empty(iftree)
+            let type=remove(iftree, 0)
+            if type is 'if' || type is 'elseif'
+                let [condition, block]=remove(iftree, 0, 1)
+                if block!=#[['throw', s:cfstr]]
+                    return self
+                endif
+                call add(conditions, condition)
+            elseif type is 'endif'
+                break
+            else
+                return self
+            endif
+        endwhile
+        call remove(self.l, 0, -1)
+        call self.add('if', 0, [])
+        call self.nextthrow('!('.join(conditions, ' || ').')', 'notfail', a:idx)
+        call remove(self.l, 1, 3)
+    endif
+    return self
+endfunction
+"▲2
+function s:r.not.check(desc, idx, type)
+    call self.try()
+                \.pushms('throwignore')
+                \.compilearg(a:desc[1], a:idx.'(not)')
+                \.popms()
+                \.throw("'NOTFAIL'")
+            \.catch(s:cfreg).up()
+            \.catch('\v^NOTFAIL$')
+                \.addthrow('notfail', 1, a:idx)
+    return call(s:r.not.optimize, [a:idx], self)
+endfunction
+"▶1 `either'
+" Checks whether {argument} matches one of given specifications
+let s:r.either={'args': ['*arg']}
+function s:r.either.check(desc, idx, type)
+    let sucstr=self.getlvarid('succeeded')
+    call self.let(sucstr, 1).pushms('throw').addsavemsgs()
+    if !empty(a:desc[1])
+        call self.try()
+                    \.compilearg(a:desc[1][0], a:idx.'(either).0',
+                    \            'check')
+                \.up().catch(s:cfreg)
+                    \.let(sucstr, 0).up()
+    endif
+    let i=1
+    for arg in a:desc[1][1:]
+        call self.addif('!'.sucstr)
+                    \.let(sucstr, 1)
+                    \.try()
+                        \.compilearg(arg, a:idx.'(either).'.i,'check')
+                    \.up().catch(s:cfreg)
+                        \.let(sucstr, 0)
+                    \.up()
+                \.up()
+        let i+=1
+    endfor
+    call self.addif(sucstr).addrestmsgs().up().popms()
+                \.addif().addthrow('eitherfail', 1, a:idx).up().up()
+endfunction
+"▶1 `tuple'
+let s:r.tuple={'args': ['*arg']}
+" Checks whether {argument} is a list with a fixed length and each element 
+" matching given specification
+function s:r.tuple.check(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.addtypecond([type([])], a:idx)
+                \.nextthrow('len('.curargstr.')!='.len(a:desc[1]),
+                \           'invlstlen', a:idx, len(a:desc[1]),
+                \                        'len('.curargstr.')')
+                \.addtuple(a:desc, a:idx, a:type)
+endfunction
+" Checks whether {argument} is a list with a fixed length and then process given 
+" pipes for each of the arguments
+let s:r.tuple.pipe=s:r.tuple.check
+"▶1 `list'
+let s:r.list={'args': ['arg']}
+" Checks whether {argument} is a list where each item matches given 
+" specification
+function s:r.list.check(desc, idx, type)
+    return self.addtypecond([type([])], a:idx).addlist(a:desc, a:idx, a:type)
+endfunction
+" Checks whether {argument} is a list and then filter each item using given 
+" specification
+let s:r.list.pipe=s:r.list.check
+"▶1 `dict'
+let s:r.dict={'args': ['ddescr']}
+" Checks whether {argument} is a dictionary matching given {ddescr}
+function s:r.dict.check(desc, idx, type)
+    return self.addtypecond([type({})], a:idx).adddict(a:desc, a:idx, a:type)
+endfunction
+" Checks whether {argument} is a dictionary and transform it using given 
+" {ddescr}
+let s:r.dict.pipe=s:r.dict.check
+"▶1 `in'
+let s:r.in={'args': ['var', '?omtchr']}
+" Checks whether {argument} is inside list {var}. Matcher is ignored
+function s:r.in.check(desc, idx, type)
+    return self.nextthrow('index('.self.getvar(a:desc[1]).', '.
+                \                  self.argstr().')==-1',
+                \         'ninlist', a:idx)
+endfunction
+" Picks up first element from {var}::List that matches {argument}. If {matcher} 
+" is absent then {argument} may be of any type. In other case it should be 
+" string.
+function s:r.in.pipe(desc, idx, type)
+    let curargstr=self.argstr()
+    if len(a:desc)==2 || (a:desc[2][1][0] is 'intfunc' &&
+                \         a:desc[2][1][1] is 'exact' &&
+                \         a:desc[2][1][2] is 0)
+        return self.compilecheck(['check', ['intfunc']+a:desc], a:idx)
+    else
+        let matchstr=self.getlvarid('match')
+        return self.addtypecond([type('')], a:idx)
+                    \.let(matchstr,self.getmatcher(a:desc[2],
+                    \                              self.getvar(a:desc[1]),
+                    \                              curargstr))
+                    \.nextthrow(matchstr.' is 0',
+                    \           'nmatch', a:idx, curargstr)
+                    \.let(curargstr, matchstr)
+    endif
+endfunction
+"▶1 `key'
+let s:r.key={'args': ['var', '?omtchr']}
+" Checks whether {argument} is a key of {var}. Matcher is ignored
+function s:r.key.check(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.addtypecond([type('')], a:idx)
+                \.nextthrow('!has_key('.self.getvar(a:desc[1]).', '.
+                \                       curargstr.')',
+                \           'nindict', a:idx, curargstr)
+endfunction
+" Picks up first key from {var}::Dictionary that matches {argument}
+let s:r.key.pipe=s:r.in.pipe
+"▶1 `take'
+" Replaces {argument} with value of the first key from {var}::Dictionary that 
+" matches {argument}
+let s:r.take={'args': ['var', 'matcher']}
+function s:r.take.pipe(desc, idx, type)
+    let curargstr=self.argstr()
+    let varstr=self.getvar(a:desc[1])
+    let matchstr=self.getlvarid('match')
+    return self.addtypecond([type('')], a:idx)
+                \.let(matchstr, self.getmatcher(a:desc[2], varstr,
+                \                               curargstr))
+                \.nextthrow(matchstr.' is 0', 'nmatch', a:idx, curargstr)
+                \.let(curargstr, varstr.'['.matchstr.']')
+endfunction
+"▶1 `substitute'
+" Runs substitute on {argument}
+let s:r.substitute={'args': ['reg', 'string', 'string']}
+function s:r.substitute.pipe(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.let(curargstr, 'substitute('.curargstr.', '.
+                \((type(a:desc[1][1])==type(''))?
+                \       (s:F.string(a:desc[1][1])):
+                \       (self.getvar(a:desc[1][1]))).', '.
+                \join(map(a:desc[2:], 'self.compilestring(v:val)'), ', ').')')
+endfunction
+"▶1 `haskey'
+" Checks whether {argument} is a dictionary with given keys
+let s:r.haskey={'args': ['*string']}
+function s:r.haskey.check(desc, idx, type)
+    call self.addtypecond([type({})], a:idx)
+    if len(a:desc[1])>1
+        let keys='['.join(map(copy(a:desc[1]),
+                    \         'type(v:val)==type("")?'.
+                    \               's:F.string(v:val):'.
+                    \               'self.getvar(v:val)'), ', ').']'
+        let absentkeys='filter('.keys.', '.
+                    \          string('!has_key('.self.argstr().', v:val)').')'
+        return self.nextthrow('!empty('.absentkeys.')',
+                    \         'keysmis', a:idx,
+                    \                    'join('.absentkeys.', ", ")')
+    elseif !empty(a:desc[1])
+        let keystr=((type(a:desc[1][0])==type(''))?
+                    \       (s:F.string(a:desc[1][0])):
+                    \       (self.getvar(a:desc[1][0])))
+        return self.nextthrow('!has_key('.self.argstr().', '.keystr.')',
+                    \         'keymis', a:idx, keystr)
+    endif
+endfunction
+"▶1 `range'
+" Checks whether {argument} is in given range
+let s:r.range={'args': ['number', 'number']}
+function s:r.range.check(desc, idx, type)
+    let curargstr=self.argstr()
+    "▶4 Determine whether we accept floating-point values
+    let acceptfloat=has('float') &&
+                \(a:desc[1][0] is 'float' || a:desc[1][1] is 'float')
+    if acceptfloat
+        call self.addtypecond([type(0), type(0.0)], a:idx)
+    else
+        call self.addtypecond([type(0)], a:idx)
+    endif
+    "▶4 Obtain range borders
+    let range=map(a:desc[1:],
+                \'((v:val[0] is "inf" || v:val[0] is "nan")?'.
+                \   '(""):'.
+                \   '((v:val[0] is "number"||v:val[0] is "float")?'.
+                \       '(v:val[1]):'.
+                \       '(self.getvar(v:val))))')
+    if type(range[0])!=type('') && type(range[1])!=type('') && range[0]>range[1]
+        call reverse(range)
+    endif
+    "▶4 Construct condition
+    let cond=''
+    call map(range, '((type(v:val)=='.type('').')?'.
+                \               '(v:val):'.
+                \               '(string(v:val)))')
+    if range[0] isnot ''
+        let cond.=range[0].'>'.curargstr
+    endif
+    if range[1] isnot ''
+        if !empty(cond)
+            let cond.=' || '
+        endif
+        let cond.=curargstr.'>'.range[1]
+    endif
+    "▶4 Add condition to result
+    if !empty(cond)
+        call self.nextthrow(cond, 'nrange', a:idx,
+                    \                       'string('.curargstr.')',
+                    \                       'string('.range[0].')',
+                    \                       'string('.range[1].')')
+    endif
+    return self
+endfunction
+"▶1 `match'
+" Checks whether {argument} is a string that matches {reg}
+let s:r.match={'args': ['reg']}
+function s:r.match.check(desc, idx, type)
+    let regex=((type(a:desc[1][1])==type(''))?
+                \(s:F.string(a:desc[1][1])):
+                \(self.getvar(a:desc[1][1])))
+    let curargstr=self.argstr()
+    return self.addtypecond([type('')], a:idx)
+                \.nextthrow(curargstr.'!~#'.regex,
+                \           'nregmatch', a:idx, curargstr, regex)
+endfunction
+"▶1 `path'
+" Checks whether {argument} is a path matching given specification
+let s:r.path={'args': ['path']}
+function s:r.path.check(desc, idx, type)
+    let curargstr=self.argstr()
+    call self.addtypecond([type('')], a:idx)
+    let spec=a:desc[1]
+    if spec[0] is 'd'
+        let spec=spec[1:]
+        if spec[0] is 'w'
+            call self.nextthrow('filewritable('.curargstr.')!=2',
+                        \       'nwrite', a:idx, curargstr)
+            let spec=spec[1:]
+        elseif spec[0] is 'W'
+            call self.nextthrow('filewritable('.curargstr.')!=2 &&'.
+                        \      '(@%@.os.path.exists('.curargstr.')'.
+                        \       '|| filewritable('.
+                        \               '@%@.os.path.dirname('.
+                        \                        curargstr.'))!=2)',
+                        \      'nowrite', a:idx, curargstr)
+            let spec=spec[1:]
+        elseif spec[0] is 'p'
+            call self.addpathp(a:idx)
+                        \.nextthrow('!@%@.os.path.isdir('.
+                        \                             curargstr.')',
+                        \           'isdir', a:idx, curargstr)
+            let spec=spec[1:]
+        else
+            call self.nextthrow('!@%@.os.path.isdir('.curargstr.')',
+                        \       'isdir', a:idx, curargstr)
+        endif
+    else
+        let fileonly=0
+        if spec[0] is 'f'
+            let spec=spec[1:]
+            let fileonly=1
+        endif
+        if fileonly
+            if spec[0] is 'r'
+                call self.nextthrow('!filereadable('.curargstr.')',
+                            \       'nread', a:idx, curargstr)
+                let spec=spec[1:]
+            elseif spec[-1:] isnot 'x'
+                call self.nextthrow('@%@.os.path.isdir('.
+                            \                         curargstr.')',
+                            \       'isfile', a:idx, curargstr)
+            endif
+        endif
+        if spec[0] is 'w'
+            call self.nextthrow('!filewritable('.curargstr.')',
+                        \       'nwrite', a:idx, curargstr)
+            let spec=spec[1:]
+        elseif spec[0] is 'W'
+            call self.nextthrow('!filewritable('.curargstr.') &&'.
+                        \      '(@%@.os.path.exists('.curargstr.')'.
+                        \       '|| filewritable('.
+                        \               '@%@.os.path.dirname('.
+                        \                        curargstr.'))!=2)',
+                        \      'nowrite', a:idx, curargstr)
+            let spec=spec[1:]
+        elseif spec[0] is 'p'
+            call self.addpathp(a:idx)
+            let spec=spec[1:]
+        endif
+        if spec is 'x'
+            call self.nextthrow('!executable('.curargstr.')',
+                        \       'nexecable', a:idx, curargstr)
+        endif
+    endif
+    return self
+endfunction
+"▶1 `type'
+" Checks whether {argument} has one of given types
+let s:r.type={'args': ['*type']}
+function s:r.type.check(desc, idx, type)
+    return self.addtypecond(a:desc[1], a:idx)
+endfunction
+"▶1 `isfunc'
+" Checks whether {argument} is a callable function reference. Additional 
+" argument determines whether strings should not be accepted
+let s:r.isfunc={'args': ['?one']}
+function s:r.isfunc.check(desc, idx, type)
+    let curargstr=self.argstr()
+    let frefpref='string('.curargstr.')[10:11]'
+    if a:desc[1]
+        call self.addtypecond([2], a:idx)
+        call self.nextthrow('!exists('.string('*'.curargstr).') ||'.
+                    \                       frefpref.' is "s:"',
+                    \       'nfunc', a:idx,
+                    \                'string('.curargstr.')[10:-3]')
+    else
+        call self.nextthrow('!((type('.curargstr.')==2 && '.
+                    \         'exists('.string('*'.curargstr).')&&'.
+                    \          frefpref.' isnot "s:") '.
+                    \        '|| (type('.curargstr.')=='.type('').
+                    \            '&& '.curargstr.'=~#'.
+                    \             '''\v^%(%([sla]@!\w:)?%(\w|\.)+|'.
+                    \                    '%(s@!\w:)?\w+|'.
+                    \                    '%(<SNR>\w+))$'''.
+                    \            '&& exists("*".'.curargstr.')))',
+                    \       'nsfunc', a:idx, 'string('.curargstr.')')
+    endif
+    return self
+endfunction
+"▶1 `isreg'
+" Checks whether {argument} is a valid regular expression
+let s:r.isreg={'args': []}
+function s:r.isreg.check(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.addtypecond([type('')], a:idx)
+                \.try().call('matchstr("", '.curargstr.')').up()
+                \.catch().addthrow('nreg', 1, a:idx, curargstr, 'v:exception')
+endfunction
+"▶1 `bool'
+let s:r.bool={'args': []}
+" Checks whether {argument} is either 0 or 1
+function s:r.bool.check(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.nextthrow('index([0, 1], '.curargstr.')==-1',
+                \         'nbool', a:idx, 'string('.curargstr.')')
+endfunction
+" Transforms {argument} to 0 if it is empty and to 1 otherwise
+function s:r.bool.pipe(desc, idx, type)
+    let curargstr=self.argstr()
+    return self.let(curargstr, '!empty('.curargstr.')')
+endfunction
+"▶1 `is'
+" Checks whether {argument} is {var}
+let s:r.is={'args': ['var']}
+function s:r.is.check(desc, idx, type)
+    let var=self.getvar(a:desc[1])
+    let curargstr=self.argstr()
+    return self.nextthrow(curargstr.' isnot '.var,
+                \         'isnot', a:idx, var, 'string('.curargstr.')')
+endfunction
+"▶1 `value'
+" Overrides current value
+let s:r.value={'args': ['var', 'arg']}
+function s:r.value.check(desc, idx, type)
+    call self.witharg(self.getvar(a:desc[1], 1))
+                \.compilearg(a:desc[2], a:idx.'(value)', a:type)
+                \.without()
+endfunction
+"▶1 `any', `_'
+" Unconditionally accepts {argument}
+let s:r.any={'args': []}
+function s:r.any.check(...)
+    return self
+endfunction
+let s:r._=s:r.any
+"▶1 Register resource
+call s:_f.postresource('FWC_intfuncs', s:r, 1)
+"▶1
+call frawor#Lockvar(s:, '')
+" vim: fmr=▶,▲ sw=4 ts=4 sts=4 et tw=80

plugin/frawor/fwc/parser.vim

             \exists('g:frawor__donotload')
     finish
 endif
-execute frawor#Setup('0.0', {'@/resources': '0.0'}, 1)
+execute frawor#Setup('0.0', {'@/resources': '0.0',
+            \             '@/fwc/intfuncs': '0.0'}, 1)
 let s:parser={}
 "▶1 Define messages
 let s:_messages={
         \}
 "▶1 s:args
 let s:args={}
-"▶2 pipe
-let s:args.pipe={}
-"▶3 pipe.func
-" Replaces {argument} with the result of running {func}({argument})
-let s:args.pipe.func=['func']
-"▶3 pipe.eval
-" Replaces {argument} with the result of evaluating {expr}
-let s:args.pipe.eval=['expr']
-"▶3 pipe.if
-" Processes argument if condition is met. Third argument describes the `else' 
-" clause.
-let s:args.pipe.if=['arg', 'arg', 'arg']
-"▶3 pipe.run
-" Replaces {argument} with the result of calling itself with {var} as argument 
-" list
-let s:args.pipe.run=['var']
-"▶3 pipe.earg
-" Replaces {argument} with the result of evaluating itself
-let s:args.pipe.earg=[]
-"▶3 pipe.tuple
-" Checks whether {argument} is a list with a fixed length and then process given 
-" pipes for each of the arguments
-let s:args.pipe.tuple=['*arg']
-"▶3 pipe.list
-" Checks whether {argument} is a list and then filter each item using given 
-" specification
-let s:args.pipe.list=['arg']
-"▶3 pipe.dict
-" Checks whether {argument} is a dictionary and transform it using given 
-" {ddescr}
-let s:args.pipe.dict=['ddescr']
-"▶3 pipe.in
-" Picks up first element from {var}::List that matches {argument}. If {matcher} 
-" is absent then {argument} may be of any type. In other case it should be 
-" string.
-let s:args.pipe.in=['var', '?omtchr']
-"▶3 pipe.key
-" Picks up first key from {var}::Dictionary that matches {argument}
-let s:args.pipe.key=['var', '?omtchr']
-"▶3 pipe.take
-" Replaces {argument} with value of the first key from {var}::Dictionary that 
-" matches {argument}
-let s:args.pipe.take=['var', 'matcher']
-"▶3 pipe.substitute
-" Runs substitute on {argument}
-let s:args.pipe.substitute=['reg', 'string', 'string']
-"▶3 pipe.bool
-" Transforms {argument} to 0 if it is empty and to 1 otherwise
-let s:args.pipe.bool=[]
-"▶3 pipe.value
-" Overrides current value
-let s:args.pipe.value=['var', 'arg']
-"▶2 check
-let s:args.check={}
-"▶3 check.func
-" Checks whether result of running {func}({argument}) isnot 0
-let s:args.check.func=['func']
-"▶3 check.eval
-" Checks whether result of running eval({expr}) isnot 0
-let s:args.check.eval=['expr']
-"▶3 check.not
-let s:args.check.not=['arg']
-"▶3 check.either
-" Checks whether {argument} matches one of given specifications
-let s:args.check.either=['*arg']
-"▶3 check.tuple
-" Checks whether {argument} is a list with a fixed length and each element 
-" matching given specification
-let s:args.check.tuple=['*arg']
-"▶3 check.list
-" Checks whether {argument} is a list where each item matches given 
-" specification
-let s:args.check.list=['arg']
-"▶3 check.dict
-" Checks whether {argument} is a dictionary matching given {ddescr}
-let s:args.check.dict=['ddescr']
-"▶3 check.in
-" Checks whether {argument} is inside list {var}. Matcher is ignored
-let s:args.check.in=['var', '?omtchr']
-"▶3 check.key
-" Checks whether {argument} is a key of {var}. Matcher is ignored
-let s:args.check.key=['var', '?omtchr']
-"▶3 check.haskey
-" Checks whether {argument} is a dictionary with given keys
-let s:args.check.haskey=['*string']
-"▶3 check.range
-" Checks whether {argument} is in given range
-let s:args.check.range=['number', 'number']
-"▶3 check.match
-" Checks whether {argument} is a string that matches {reg}
-let s:args.check.match=['reg']
-"▶3 check.path
-" Checks whether {argument} is a path matching given specification
-let s:args.check.path=['path']
-"▶3 check.type
-" Checks whether {argument} has one of given types
-let s:args.check.type=['*type']
-"▶3 check.isfunc
-" Checks whether {argument} is a callable function reference. Additional 
-" argument determines whether strings should not be accepted
-let s:args.check.isfunc=['?one']
-"▶3 check.isreg
-" Checks whether {argument} is a valid regular expression
-let s:args.check.isreg=[]
-"▶3 check.bool
-" Checks whether {argument} is either 0 or 1
-let s:args.check.bool=[]
-"▶3 check.is
-" Checks whether {argument} is {var}
-let s:args.check.is=['var']
-"▶3 check.value
-" Overrides current value
-let s:args.check.value=['var', 'arg']
-"▶3 check._, check.any
-" Unconditionally accepts {argument}
-let s:args.check._=[]
-let s:args.check.any=s:args.check._
-"▶2 arg
-let s:args.argcheck=copy(s:args.check)
-let s:args.argfilter=extend(copy(s:args.check), s:args.pipe)
+let s:args.pipe=keys(filter(copy(s:_r.FWC_intfuncs), 'has_key(v:val, "pipe")'))
+let s:args.check=keys(filter(copy(s:_r.FWC_intfuncs), 'has_key(v:val,"check")'))
+let s:args.argcheck=s:args.check
+let s:args.argfilter=s:args.check+s:args.pipe
 "▶2 matcher
 let s:args.matcher={}
 "▶3 matcher.func
 " determines whether ambigious match should be accepted (in this case first 
 " match in sorted list will be taken)
 let s:args.matcher.smart=['?one']
-"▶1 getmatch   :: Dict, String → String
-function s:F.getmatch(dict, str)
-    if has_key(a:dict, a:str)
-        return a:str
+"▶1 getmatch   :: Dict|List, String → String
+function s:F.getmatch(ld, str)
+    if type(a:ld)==type({})
+        return has_key(a:ld, a:str)? a:str : 0
+    else
+        return index(a:ld, a:str)==-1? 0 : a:str
     endif
-    let lstr=len(a:str)-1
-    return get(filter(sort(keys(a:dict)), 'v:val[:'.lstr.'] is a:str'), 0, 0)
 endfunction
 "▶1 add        :: &self
 " Adds an element to current context
         call self.throw('ukfunc', c)
     endif        "▲2
     call self.addcon('intfunc', func)
-    let fargs=get(s:args[type], func, [])
+    if type is 'matcher'
+        let fargs=s:args[type][func]
+    else
+        let fargs=s:_r.FWC_intfuncs[func].args
+    endif
     for farg in fargs
         if farg[0] is '?'
             let farg=farg[1:]

test/global-functions-reload.ok

 1      echo 1
    endfunction
 
-   function <SNR>23_testFunction()
+   function <SNR>24_testFunction()
 1      echo 2
    endfunction
 
 1      echo 1
    endfunction
 
-   function <SNR>23_testFunction()
+   function <SNR>24_testFunction()
 1      echo 2
    endfunction

test/ignoredeps-feature.ok

 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/python
 load: plugin/frawor/python
 register: plugin/frawor/functions

test/reload-frawor.ok

 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/python
 load: plugin/frawor/python
 register: plugin/frawor/functions
 unloadpre: plugin/frawor/fwc/compiler
 unloadpre: plugin/frawor/fwc/constructor
 unloadpre: plugin/frawor/fwc/parser
+unloadpre: plugin/frawor/fwc/intfuncs
 unloadpre: plugin/frawor/decorators
 unloadpre: plugin/frawor/os
 unloadpre: plugin/frawor/resources
 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: plugin/frawor
+load: plugin/frawor
 register: plugin/frawor/decorators
 load: plugin/frawor/decorators
-register: plugin/frawor/autocommands
-load: plugin/frawor/autocommands
+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: plugin/frawor/os
-load: plugin/frawor/os
 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/compiler
+load: plugin/frawor/fwc/compiler
 register: plugin/writefile-feature
 load: plugin/writefile-feature
-register: plugin/frawor/options
-load: plugin/frawor/options
-register: plugin/frawor/fwc/parser
-load: plugin/frawor/fwc/parser
-register: plugin/frawor
-load: plugin/frawor
-register: plugin/frawor/fwc/compiler
-load: plugin/frawor/fwc/compiler
-register: plugin/frawor/resources
-load: plugin/frawor/resources
-register: plugin/frawor/checks
-load: plugin/frawor/checks
-register: plugin/frawor/decorators/altervars
-load: plugin/frawor/decorators/altervars
 register: plugin/frawor/tcl
 load: plugin/frawor/tcl
 register: plugin/frawor/ruby

test/reload-ignoredeps.ok

 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/python
 load: plugin/frawor/python
 register: plugin/frawor/functions
 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/python
 load: plugin/frawor/python
 register: plugin/frawor/functions

test/reload-writefile.ok

 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/python
 load: plugin/frawor/python
 register: plugin/frawor/functions
 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/python
 load: plugin/frawor/python
 register: plugin/frawor/functions

test/unload-self.ok

 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/unload-self-feature
 load: plugin/unload-self-feature
 register: plugin/frawor/python
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.