Commits

ZyX_I committed cc1f7da

@/fwc: Added range check

  • Participants
  • Parent commits b49e49f

Comments (0)

Files changed (4)

File plugin/frawor/fwc/compiler.vim

             \   'keymis': 'key `%s'' is missing',
             \  'runfail': 'running argument failed with exception %s',
             \ 'evalfail': 'evaluating argument failed with exception %s',
+            \   'nrange': '%s is not in range [%s, %s]',
         \}, '"Error while processing check %u for %s: ".v:val'))
 let s:_messages._types=['number', 'string', 'function reference', 'list',
             \           'dictionary']
     let addedcond=0
     let idx=a:idx
     for check in a:check[1:]
+        "▶2 `func' check
         if check[0] is 'func'
             let addedcond=1
             call self.nextthrow(self.getfunc(check, curargstr).' is 0',
                         \       'funcfail', idx, '@#@')
+        "▶2 `expr' check
         elseif check[0] is 'expr'
             let addedcond=1
             call self.nextthrow(substitute(check[1], '\V@.@', curargstr, 'g').
                         \                                           ' is 0',
                         \       'exprfail', idx, '@#@')
+        "▶2 `intfunc' check
         else
             let desc=check[1:]
+            "▶3 `func'
             if desc[0] is 'func'
                 let addedcond=1
                 call self.nextthrow(self.getfunc(desc[1], curargstr).' is 0',
                             \       'funcfail', idx, '@#@')
+            "▶3 `eval'
             elseif desc[0] is 'eval'
                 let addedcond=1
                 call self.nextthrow(substitute(desc[1][1],
                             \                  '\V@.@', curargstr, 'g').' is 0',
                             \       'exprfail', idx, '@#@')
+            "▶3 `type'
             elseif desc[0] is 'type'
                 let addedcond=1
                 call self.addtypecond(desc[1], idx)
+            "▶3 `bool'
             elseif desc[0] is 'bool'
                 let addedcond=1
                 call self.nextthrow('index([0, 1], '.curargstr.')==-1',
                             \       'nbool', idx,'@#@', 'string('.curargstr.')')
+            "▶3 `range'
             elseif desc[0] is 'range'
+                let addedcond=1
+                "▶4 Determine whether we accept floating-point values
                 let acceptfloat=has('float') &&
                             \(desc[1][0] is 'float' || desc[1][1] is 'float')
                 if acceptfloat
                 else
                     call self.addtypecond([type(0)], idx)
                 endif
-                if desc[1][0] isnot 'inf'
-                    call self.nextcond('')
+                "▶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
-                " TODO
+                "▶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', idx, '@#@',
+                                \                       'string('.curargstr.')',
+                                \                       'string('.range[0].')',
+                                \                       'string('.range[1].')')
+                endif
+            "▶3 `key'
             elseif desc[0] is 'key'
                 " TODO
+            "▶3 `haskey'
             elseif desc[0] is 'haskey'
                 let addedcond=1
                 call self.addtypecond([type({})], idx)
                     call self.nextthrow('!has_key('.curargstr.', '.keystr.')',
                                 \       'keymis', idx, '@#@', keystr)
                 endif
+            "▶3 `isfunc'
             elseif desc[0] is 'isfunc'
                 let addedcond=1
                 let frefpref='string('.curargstr.')[10:11]'
                                 \       'nsfunc', idx, '@#@',
                                 \                 'string('.curargstr.')')
                 endif
+            "▶3 `isreg'
             elseif desc[0] is 'isreg'
                 call self.addtypecond([type('')], idx)
                 call self.close()
                           \.addthrow('nreg', idx, '@#@', curargstr,
                           \                  'v:exception')
                         \.up().close()
+            "▶3 `match'
             elseif desc[0] is 'match'
                 let addedcond=1
                 call self.addtypecond([type('')], idx)
                             \(self.getvar(desc[1][1])))
                 call self.nextthrow(curargstr.'!~#'.regex,
                             \       'nmatch', idx, '@#@', curargstr, regex)
+            "▶3 `dict'
             elseif desc[0] is 'dict'
                 " TODO
+            "▶3 `tuple'
             elseif desc[0] is 'tuple'
                 " TODO
+            "▶3 `either'
             elseif desc[0] is 'either'
                 " TODO
+            "▶3 `path'
             elseif desc[0] is 'path'
                 " TODO
+            "▶3 `_', `any'
             elseif desc[0] is '_' || desc[0] is 'any'
                 " Just do nothing here
             endif
+            "▲3
         endif
+        "▲2
         let idx+=1
     endfor
     if addedcond

File plugin/frawor/fwc/parser.vim

     let self.len+=len(a:c)
     return self
 endfunction
+"▶1 ungotjoin  :: &self(s)
+function s:parser.ungotjoin()
+    let joined=substitute(join(reverse(remove(self.ungot, 0, -1))),
+                \         '\w\@<! \w\@!', '', 'g')
+    if joined[-1:]=~#'^\w' && self.s=~#'^\w'
+        let joined.=' '
+    endif
+    let self.len+=len(joined)
+    let self.s=joined.self.s
+    return self
+endfunction
 "▶1 readc      :: () + self → String + self(s)
 " Gets next character or word
 function s:parser.readc()
 "    {d} :: [0-9] | "_"
 function s:parser.readflt()
     if !empty(self.ungot)
-        call self.throw('int', 'fltungetc')
+        call self.ungotjoin()
     endif
     call self.delblanks()
     let c=matchstr(self.s,

File test/fwccheck.ok

 plugin/frawor/fwc/compiler:nbool
 plugin/frawor/fwc/compiler:typefail
 plugin/frawor/fwc/compiler:nreg
+::: Section <Checks/Built-in checks/range>
+plugin/frawor/fwc/compiler:typefail
+plugin/frawor/fwc/compiler:nrange
+plugin/frawor/fwc/compiler:nrange
+plugin/frawor/fwc/compiler:nrange
 ::: Section <Checks/Built-in checks/haskey>
 plugin/frawor/fwc/compiler:typefail
 plugin/frawor/fwc/compiler:keymis

File test/fwctests.dat

 ['<a1 <a2 _>>',          'check'], range(4), 0
 ['<- <- ->>',            'check'], range(1), 0
 #▶1 Pipes
-#▶2 Function pipes
 \function s:.revstring(str)
 \    return join(reverse(split(a:str, '\v.@=')), '')
 :endfunction
+#▶2 Function pipes
 ['|*$"string"',                'filter'], ['abc'], ["'abc'"]
 ["|*$'string'",                'filter'], ['abc'], ["'abc'"]
 ['|*=function("string")',      'filter'], ['abc'], ["'abc'"]
 ['|*$"string"|*$"string"',     'filter'], ['abc'], ["'''abc'''"]
 ['|=string(@.@)|=string(@.@)', 'filter'], ['abc'], ["'''abc'''"]
 #▶1 Checks
-#▶2 Function checks
 \function s:.ordered(str)
 \    return join(sort(split(a:str, '\v.@=')), '') is a:str
 :endfunction
+#▶2 Function checks
 ['?*$"empty"', 'check'], ['abc'], 0
 ['?*$"empty"', 'check'], [''],    1
 ['?*ordered',  'check'], ['abc'], 1
 ['isreg',           'check'], ['\(abc'],            0
 ['_',               'check'], [[[[]]]],             1
 ['any',             'check'], [[[[]]]],             1
+#▶3 range
+:let s:n1=-1
+:let s:n2=1
+['range  0   2',    'check'], ['1'],                0
+['range  0   2',    'check'], [-1],                 0
+['range  0   2',    'check'], [0],                  1
+['range  0   2',    'check'], [1],                  1
+['range  0   2',    'check'], [2],                  1
+['range  0   2',    'check'], [3],                  0
+['range  0  inf',   'check'], [3],                  1
+['range inf inf',   'check'], [3],                  1
+['range inf  2',    'check'], [-1],                 1
+['range $n1 $n2',   'check'], [0],                  1
+['range $n1 $n2',   'check'], [3],                  0
 #▶3 haskey
 :let s:k1='def'
 ['haskey abc',      'check'], [""],                 0