Commits

ZyX_I committed f7ebbbb

@/fwc: Moved matchers into @/fwc/intfuncs

Comments (0)

Files changed (3)

plugin/frawor/fwc/compiler.vim

             \              'for plugin %s',
             \ 'ambprefix': 'Error while compiling FWC string: prefix `%s'' '.
             \              'already defined',
+            \  'umatcher': 'Unknown matcher: %s',
+            \    'ucheck': 'Unknown check: %s',
         \}
 call extend(s:_messages, map({
             \'decargnlst': 'decorator argument is not a List',
 if has('float')
     call add(s:_messages._types, 'float')
 endif
-"▶1 Matchers
-" {m}(args): ld::(List|Dict), str::String, [args], acceptfirst::(0|1) → str
-"          | ld::(List|Dict), str::String, [args], 2 → [String]
-let s:F.matchers={}
-"▶2 func  :: {m}(Function, args::List)
-function s:F.matchers.func(ld, str, Func, args, acceptfirst)
-    let result=call(a:Func, a:args+[a:ld, a:str], {})
-    if a:acceptfirst is 2
-        return result
-    elseif a:acceptfirst || len(result)==1
-        return result[0]
-    else
-        return 0
-    endif
-endfunction
-"▶2 exact :: {m}(ignorecase::Bool)
-function s:F.matchers.exact(ld, str, ignorecase, acceptfirst)
-    if type(a:ld)==type({})
-        if a:ignorecase
-            let list=sort(keys(a:ld))
-        else
-            return ((has_key(a:ld, a:str)==-1)?(0):(a:str))
-        endif
-    elseif !a:ignorecase
-        return ((index(a:ld, a:str)==-1)?(0):(a:str))
-    else
-        let list=a:ld
-    endif
-    let idx=index(list, a:str, 0, 1)
-    if idx==-1
-        return 0
-    elseif a:acceptfirst is 2
-        let r=[list[idx]]
-        while 1
-            let idx=index(list, a:str, idx+1, 1)
-            if idx==-1
-                break
-            else
-                call add(r, list[idx])
-            endif
-        endwhile
-        return r
-    elseif a:acceptfirst
-        return list[idx]
-    else
-        return ((index(list, a:str, idx+1, 1)==-1)?(list[idx]):(0))
-    endif
-endfunction
-"▶2 start :: {m}(ignorecase::Bool)
-function s:F.matchers.start(ld, str, ignorecase, acceptfirst)
-    if type(a:ld)==type({})
-        let list=sort(keys(a:ld))
-    else
-        let list=a:ld
-    endif
-    let r=[]
-    let lstr=len(a:str)-1
-    for value in list
-        if type(value)==type('')
-            if value is a:str
-                let r=[value]
-                break
-            elseif ((a:ignorecase)?(value[:(lstr)]==?a:str):
-                        \          (value[:(lstr)]==#a:str))
-                if a:acceptfirst is 1
-                    return value
-                elseif empty(r)
-                    call add(r, value)
-                else
-                    return 0
-                endif
-            endif
-        endif
-        unlet value
-    endfor
-    return ((a:acceptfirst is 2)?(r):(get(r, 0, 0)))
-endfunction
-"▶2 smart :: {m}()
-let s:smartfilters=[
-            \'v:val is a:str',
-            \'v:val==?a:str',
-            \'v:val=~#''\V\^''.estr',
-            \'v:val=~?''\V\^''.estr',
-            \'stridx(v:val, a:str)!=-1',
-            \'v:val=~?"\\V".estr',
-            \'v:val=~#reg',
-            \'v:val=~?reg',
-            \'v:val=~#reg2',
-            \'v:val=~?reg2',
-            \]
-function s:F.matchers.smart(ld, str, acceptfirst)
-    let estr=escape(a:str, '\')
-    let reg='\V'.join(split(estr, '\v[[:punct:]]@<=|[[:punct:]]@='), '\.\*')
-    let reg2='\V'.join(map(split(a:str,'\v\_.@='),'escape(v:val,"\\")'), '\.\*')
-    let list=filter(((type(a:ld)==type({})?(sort(keys(a:ld))):(copy(a:ld)))),
-                \   'type(v:val)=='.type(''))
-    for filter in s:smartfilters
-        let r=filter(copy(list), filter)
-        if !empty(r)
-            if a:acceptfirst is 2
-                return r
-            elseif a:acceptfirst || len(r)==1
-                return r[0]
-            else
-                return 0
-            endif
-        endif
-    endfor
-    return 0
-endfunction
 "▶1 string         :: String → String
 function s:F.string(str)
     return substitute(substitute(substitute(substitute(string(a:str),
     endif
     return r
 endfunction
+"▶1 getfunstatvar  :: varname, varinit + self → varstr + self
+function s:compiler.getfunstatvar(name, init)
+    let id=printf('%x', self.vids[a:name])
+    let self.vids[a:name]+=1
+    if !has_key(self.vars, a:name)
+        let self.vars[a:name]={}
+    endif
+    let self.vars[a:name][id]=a:init
+    return '@%@'.self.getsubs([a:name, id])
+endfunction
 "▶1 getmatcher     :: matchercontext, ldstr, strstr + self → String
 function s:compiler.getmatcher(matcher, ldstr, strstr)
-    let r='@%@.F.matchers.'.a:matcher[1][1].'('.a:ldstr.', '.a:strstr
+    let mname=a:matcher[1][1]
+    if !has_key(s:_r.FWC_intfuncs[mname], 'matcher')
+        call self._throw('umatcher', mname)
+    endif
+    let r=self.getfunstatvar('matchers', s:_r.FWC_intfuncs[mname].matcher)
+                \.'('.a:ldstr.', '.a:strstr
     if len(a:matcher[1])>3
         for arg in a:matcher[1][2:-2]
             if type(arg)==type([]) && arg[0] is 'func'
     elseif check[0] is 'expr'
         call self.nextthrow(self.getexpr(check, curargstr).' is 0',
                     \       'exprfail', a:idx)
-    "▶2 `intfunc' check
+    "▶2 Built-in checks
     else
         let desc=check[1:]
-        call call(s:_r.FWC_intfuncs[desc[0]].check, [desc, a:idx, 'check'],self)
-        if has_key(s:_r.FWC_intfuncs[desc[0]], 'optimize')
-            call call(s:_r.FWC_intfuncs[desc[0]].optimize, [a:idx], self)
+        let dname=desc[0]
+        if !has_key(s:_r.FWC_intfuncs[dname], 'check')
+            call self._throw('ucheck', dname)
+        endif
+        call call(s:_r.FWC_intfuncs[dname].check, [desc, a:idx, 'check'], self)
+        if has_key(s:_r.FWC_intfuncs[dname], 'optimize')
+            call call(s:_r.FWC_intfuncs[dname].optimize, [a:idx], self)
         endif
     endif
     "▲2
     endif
     return self.getlvarid('d.'.a:var)
 endfunction
-"▶1 getfunstatvar  :: varname, varinit + self → varstr + self
-function s:compiler.getfunstatvar(name, init)
-    let id=printf('%x', self.vids[a:name])
-    let self.vids[a:name]+=1
-    if !has_key(self.vars, a:name)
-        let self.vars[a:name]={}
-    endif
-    let self.vars[a:name][id]=a:init
-    return '@%@'.self.getsubs([a:name, id])
-endfunction
 "▶1 addprefix      :: preflist, prefix → _ + preflist
 function s:compiler.addprefix(preflist, prefix)
     if index(a:preflist, a:prefix)!=-1
                 \   'type': a:type,
                 \   'subs': [],
                 \   'vars': a:vars,
-                \   'vids': {'actions': 0, 'prefixes': 0},
+                \   'vids': {'actions': 0, 'prefixes': 0, 'matchers': 0},
                 \'argbase': '@@@',
                 \  'preva': [],
                 \   'msgs': {'savevars': [],
 "▶1 createvars     :: plugdict → id + s:lastid, s:vars
 function s:F.createvars(plugdict)
     return {
-                \ 'F': {'warn': s:_f.warn, 'throw': s:_f.throw,
-                \       'matchers': s:F.matchers},
+                \ 'F': {'warn': s:_f.warn, 'throw': s:_f.throw},
                 \ 'p': a:plugdict.g,
                 \ 'm': {'types': s:_messages._types},
                 \'os': s:_r.os,

plugin/frawor/fwc/intfuncs.vim

     return self
 endfunction
 let s:r._=s:r.any
+"▲1
+"Matchers ---------------------------------------------------------------------
+"▶1 `func'
+" Uses some other function as matcher. Function must accept list or dictionary 
+" and return a list of strings. Additional argument determines what should be 
+" done if function returns list with more then one item
+function s:r.func.matcher(ld, str, Func, args, acceptfirst)
+    let result=call(a:Func, a:args+[a:ld, a:str], {})
+    if a:acceptfirst is 2
+        return result
+    elseif a:acceptfirst || len(result)==1
+        return result[0]
+    else
+        return 0
+    endif
+endfunction
+"▶1 `exact'
+" Requires exact match. First additional argument determines whether match 
+" should be done case-insensitively, second determines whether ambigious matches 
+" should be accepted (only used if first argument is true)
+let s:r.exact={'args': ['?one']}
+function s:r.exact.matcher(ld, str, ignorecase, acceptfirst)
+    if type(a:ld)==type({})
+        if a:ignorecase
+            let list=sort(keys(a:ld))
+        else
+            return ((has_key(a:ld, a:str)==-1)?(0):(a:str))
+        endif
+    elseif !a:ignorecase
+        return ((index(a:ld, a:str)==-1)?(0):(a:str))
+    else
+        let list=a:ld
+    endif
+    let idx=index(list, a:str, 0, 1)
+    if idx==-1
+        return 0
+    elseif a:acceptfirst is 2
+        let r=[list[idx]]
+        while 1
+            let idx=index(list, a:str, idx+1, 1)
+            if idx==-1
+                break
+            else
+                call add(r, list[idx])
+            endif
+        endwhile
+        return r
+    elseif a:acceptfirst
+        return list[idx]
+    else
+        return ((index(list, a:str, idx+1, 1)==-1)?(list[idx]):(0))
+    endif
+endfunction
+"▶1 `start'
+" Requires match at the start of string. First optional arguments determines 
+" case sensitivity, second determines whether ambigious matches should be 
+" accepted (in this case first match in sorted list will be taken)
+let s:r.start={'args': ['?one']}
+function s:r.start.matcher(ld, str, ignorecase, acceptfirst)
+    if type(a:ld)==type({})
+        let list=sort(keys(a:ld))
+    else
+        let list=a:ld
+    endif
+    let r=[]
+    let lstr=len(a:str)-1
+    for value in list
+        if type(value)==type('')
+            if value is a:str
+                let r=[value]
+                break
+            elseif ((a:ignorecase)?(value[:(lstr)]==?a:str):
+                        \          (value[:(lstr)]==#a:str))
+                if a:acceptfirst is 1
+                    return value
+                elseif empty(r)
+                    call add(r, value)
+                else
+                    return 0
+                endif
+            endif
+        endif
+        unlet value
+    endfor
+    return ((a:acceptfirst is 2)?(r):(get(r, 0, 0)))
+endfunction
+"▶1 `smart'
+" `smart' matcher tries to gues what element is really ment. Additional argument 
+" determines whether ambigious match should be accepted (in this case first 
+" match in sorted list will be taken)
+let s:r.smart={'args': []}
+let s:smartfilters=[
+            \'v:val is a:str',
+            \'v:val==?a:str',
+            \'v:val=~#''\V\^''.estr',
+            \'v:val=~?''\V\^''.estr',
+            \'stridx(v:val, a:str)!=-1',
+            \'v:val=~?"\\V".estr',
+            \'v:val=~#reg',
+            \'v:val=~?reg',
+            \'v:val=~#reg2',
+            \'v:val=~?reg2',
+            \]
+function s:r.smart.matcher(ld, str, acceptfirst)
+    let estr=escape(a:str, '\')
+    let reg='\V'.join(split(estr, '\v[[:punct:]]@<=|[[:punct:]]@='), '\.\*')
+    let reg2='\V'.join(map(split(a:str,'\v\_.@='),'escape(v:val,"\\")'), '\.\*')
+    let list=filter(((type(a:ld)==type({})?(sort(keys(a:ld))):(copy(a:ld)))),
+                \   'type(v:val)=='.type(''))
+    for filter in s:smartfilters
+        let r=filter(copy(list), filter)
+        if !empty(r)
+            if a:acceptfirst is 2
+                return r
+            elseif a:acceptfirst || len(r)==1
+                return r[0]
+            else
+                return 0
+            endif
+        endif
+    endfor
+    return 0
+endfunction
 "▶1 Register resource
 call s:_f.postresource('FWC_intfuncs', s:r, 1)
 "▶1

plugin/frawor/fwc/parser.vim

             \ 'wordend': 'regular expression cannot end with %s',
             \  'noexpr': 'expected expression, but got nothing',
         \}
-"▶1 s:args
-let s:args={}
-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
-" Uses some other function as matcher. Function must accept list or dictionary 
-" and return a list of strings. Additional argument determines what should be 
-" done if function returns list with more then one item
-let s:args.matcher.func=['func', '?one']
-"▶3 matcher.exact
-" Requires exact match. First additional argument determines whether match 
-" should be done case-insensitively, second determines whether ambigious matches 
-" should be accepted (only used if first argument is true)
-let s:args.matcher.exact=['?one', '?one']
-"▶3 matcher.start
-" Requires match at the start of string. First optional arguments determines 
-" case sensitivity, second determines whether ambigious matches should be 
-" accepted (in this case first match in sorted list will be taken)
-let s:args.matcher.start=['?one', '?one']
-"▶3 matcher.smart
-" `smart' matcher tries to gues what element is really ment. Additional argument 
-" 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|List, String → String
 function s:F.getmatch(ld, str)
     if type(a:ld)==type({})
 endfunction
 "▶1 intfunc    :: &self
 " Gets pipe, func, argument or matcher that may accept one or more arguments. 
-" Arguments are described in s:args and have a form [?][*]{aname}, where {aname} 
-" is a part of get* function name, ? determines whether argument can be omitted 
-" (it really makes a difference only at the end of the string), * says that 
-" string should be scanned for a list of arguments with arbitrary length, not 
-" just for a single one
+" Arguments are described in s:_r.FWC_intfuncs.{func}.args and have a form 
+" [?][*]{aname}, where {aname} is a part of get* function name, ? determines 
+" whether argument can be omitted (it really makes a difference only at the end 
+" of the string), * says that string should be scanned for a list of arguments 
+" with arbitrary length, not just for a single one
 " Input: {funcname} [arguments]?
 "        {funcname} :: {wordchar}+
 " Output: context(intfunc, {funcname}[, contexts])
         let type.=self.type
     endif
     let c=self.readc()
-    let func=s:F.getmatch(s:args[type], c)
+    let func=s:F.getmatch(s:_r.FWC_intfuncs, c)
     if func is 0 "▶2
         call self.throw('ukfunc', c)
     endif        "▲2
     call self.addcon('intfunc', func)
+    let fargs=s:_r.FWC_intfuncs[func].args
     if type is 'matcher'
-        let fargs=s:args[type][func]
-    else
-        let fargs=s:_r.FWC_intfuncs[func].args
+        let fargs=fargs+['?one']
     endif
     for farg in fargs
         if farg[0] is '?'
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.