view src/testdir/test_vim9_disassemble.vim @ 19338:ef432264b88a v8.2.0227

patch 8.2.0227: compiling a few instructions not tested Commit: https://github.com/vim/vim/commit/c2a4b35b86fa8b28a34a9aea8ad16c87dbc6d834 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Feb 6 22:41:16 2020 +0100 patch 8.2.0227: compiling a few instructions not tested Problem: Compiling a few instructions not tested. Solution: Add more test cases.
author Bram Moolenaar <Bram@vim.org>
date Thu, 06 Feb 2020 22:45:04 +0100
parents 1cd6eab65ce0
children 8ff84bc1c89b
line wrap: on
line source

" Test the :disassemble command, and compilation as a side effect

func NotCompiled()
  echo "not"
endfunc

let s:scriptvar = 4
let g:globalvar = 'g'

def s:ScriptFuncLoad(arg: string)
  let local = 1
  buffers
  echo arg
  echo local
  echo v:version
  echo s:scriptvar
  echo g:globalvar
  echo &tabstop
  echo $ENVVAR
  echo @z
enddef

def Test_disassembleLoad()
  assert_fails('disass NoFunc', 'E1061:')
  assert_fails('disass NotCompiled', 'E1062:')

  let res = execute('disass s:ScriptFuncLoad')
  assert_match('<SNR>\d*_ScriptFuncLoad.*'
        \ .. 'buffers.*'
        \ .. ' EXEC \+buffers.*'
        \ .. ' LOAD arg\[-1\].*'
        \ .. ' LOAD $0.*'
        \ .. ' LOADV v:version.*'
        \ .. ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*'
        \ .. ' LOADG g:globalvar.*'
        \ .. ' LOADENV $ENVVAR.*'
        \ .. ' LOADREG @z.*'
        \, res)
enddef

def s:ScriptFuncPush()
  let localbool = true
  let localspec = v:none
  let localblob = 0z1234
  if has('float')
    let localfloat = 1.234
  endif
enddef

def Test_disassemblePush()
  let res = execute('disass s:ScriptFuncPush')
  assert_match('<SNR>\d*_ScriptFuncPush.*'
        \ .. 'localbool = true.*'
        \ .. ' PUSH v:true.*'
        \ .. 'localspec = v:none.*'
        \ .. ' PUSH v:none.*'
        \ .. 'localblob = 0z1234.*'
        \ .. ' PUSHBLOB 0z1234.*'
        \, res)
  if has('float')
  assert_match('<SNR>\d*_ScriptFuncPush.*'
        \ .. 'localfloat = 1.234.*'
        \ .. ' PUSHF 1.234.*'
        \, res)
  endif
enddef

def s:ScriptFuncStore()
  let localnr = 1
  localnr = 2
  let localstr = 'abc'
  localstr = 'xyz'
  v:char = 'abc'
  s:scriptvar = 'sv'
  g:globalvar = 'gv'
  &tabstop = 8
  $ENVVAR = 'ev'
  @z = 'rv'
enddef

def Test_disassembleStore()
  let res = execute('disass s:ScriptFuncStore')
  assert_match('<SNR>\d*_ScriptFuncStore.*'
        \ .. 'localnr = 2.*'
        \ .. ' STORE 2 in $0.*'
        \ .. 'localstr = ''xyz''.*'
        \ .. ' STORE $1.*'
        \ .. 'v:char = ''abc''.*'
        \ .. 'STOREV v:char.*'
        \ .. 's:scriptvar = ''sv''.*'
        \ .. ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*'
        \ .. 'g:globalvar = ''gv''.*'
        \ .. ' STOREG g:globalvar.*'
        \ .. '&tabstop = 8.*'
        \ .. ' STOREOPT &tabstop.*'
        \ .. '$ENVVAR = ''ev''.*'
        \ .. ' STOREENV $ENVVAR.*'
        \ .. '@z = ''rv''.*'
        \ .. ' STOREREG @z.*'
        \, res)
enddef

def s:ScriptFuncTry()
  try
    echo 'yes'
  catch /fail/
    echo 'no'
  finally
    throw 'end'
  endtry
enddef

def Test_disassembleTry()
  let res = execute('disass s:ScriptFuncTry')
  assert_match('<SNR>\d*_ScriptFuncTry.*'
        \ .. 'try.*'
        \ .. 'TRY catch -> \d\+, finally -> \d\+.*'
        \ .. 'catch /fail/.*'
        \ .. ' JUMP -> \d\+.*'
        \ .. ' PUSH v:exception.*'
        \ .. ' PUSHS "fail".*'
        \ .. ' COMPARESTRING =\~.*'
        \ .. ' JUMP_IF_FALSE -> \d\+.*'
        \ .. ' CATCH.*'
        \ .. 'finally.*'
        \ .. ' PUSHS "end".*'
        \ .. ' THROW.*'
        \ .. 'endtry.*'
        \ .. ' ENDTRY.*'
        \, res)
enddef

def s:ScriptFuncNew()
  let ll = [1, "two", 333]
  let dd = #{one: 1, two: "val"}
enddef

def Test_disassembleNew()
  let res = execute('disass s:ScriptFuncNew')
  assert_match('<SNR>\d*_ScriptFuncNew.*'
        \ .. 'let ll = \[1, "two", 333].*'
        \ .. 'PUSHNR 1.*'
        \ .. 'PUSHS "two".*'
        \ .. 'PUSHNR 333.*'
        \ .. 'NEWLIST size 3.*'
        \ .. 'let dd = #{one: 1, two: "val"}.*'
        \ .. 'PUSHS "one".*'
        \ .. 'PUSHNR 1.*'
        \ .. 'PUSHS "two".*'
        \ .. 'PUSHS "val".*'
        \ .. 'NEWDICT size 2.*'
        \, res)
enddef

def FuncWithArg(arg)
  echo arg
enddef

func UserFunc()
  echo 'nothing'
endfunc

func UserFuncWithArg(arg)
  echo a:arg
endfunc

def s:ScriptFuncCall(): string
  changenr()
  char2nr("abc")
  Test_disassembleNew()
  FuncWithArg(343)
  ScriptFuncNew()
  s:ScriptFuncNew()
  UserFunc()
  UserFuncWithArg("foo")
  let FuncRef = function("UserFunc")
  FuncRef()
  let FuncRefWithArg = function("UserFuncWithArg")
  FuncRefWithArg("bar")
  return "yes"
enddef

def Test_disassembleCall()
  let res = execute('disass s:ScriptFuncCall')
  assert_match('<SNR>\d\+_ScriptFuncCall.*'
        \ .. 'changenr().*'
        \ .. ' BCALL changenr(argc 0).*'
        \ .. 'char2nr("abc").*'
        \ .. ' PUSHS "abc".*'
        \ .. ' BCALL char2nr(argc 1).*'
        \ .. 'Test_disassembleNew().*'
        \ .. ' DCALL Test_disassembleNew(argc 0).*'
        \ .. 'FuncWithArg(343).*'
        \ .. ' PUSHNR 343.*'
        \ .. ' DCALL FuncWithArg(argc 1).*'
        \ .. 'ScriptFuncNew().*'
        \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
        \ .. 's:ScriptFuncNew().*'
        \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
        \ .. 'UserFunc().*'
        \ .. ' UCALL UserFunc(argc 0).*'
        \ .. 'UserFuncWithArg("foo").*'
        \ .. ' PUSHS "foo".*'
        \ .. ' UCALL UserFuncWithArg(argc 1).*'
        \ .. 'let FuncRef = function("UserFunc").*'
        \ .. 'FuncRef().*'
        \ .. ' LOAD $\d.*'
        \ .. ' PCALL (argc 0).*'
        \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*'
        \ .. 'FuncRefWithArg("bar").*'
        \ .. ' PUSHS "bar".*'
        \ .. ' LOAD $\d.*'
        \ .. ' PCALL (argc 1).*'
        \ .. 'return "yes".*'
        \ .. ' PUSHS "yes".*'
        \ .. ' RETURN.*'
        \, res)
enddef

def HasEval()
  if has("eval")
    echo "yes"
  else
    echo "no"
  endif
enddef

def HasNothing()
  if has("nothing")
    echo "yes"
  else
    echo "no"
  endif
enddef

def HasSomething()
  if has("nothing")
    echo "nothing"
  elseif has("something")
    echo "something"
  elseif has("eval")
    echo "eval"
  elseif has("less")
    echo "less"
  endif
enddef

def Test_compile_const_expr()
  assert_equal("\nyes", execute('call HasEval()'))
  let instr = execute('disassemble HasEval')
  assert_match('HasEval.*'
        \ .. 'if has("eval").*'
        \ .. ' PUSHS "yes".*'
        \, instr)
  assert_notmatch('JUMP', instr)

  assert_equal("\nno", execute('call HasNothing()'))
  instr = execute('disassemble HasNothing')
  assert_match('HasNothing.*'
        \ .. 'if has("nothing").*'
        \ .. 'else.*'
        \ .. ' PUSHS "no".*'
        \, instr)
  assert_notmatch('PUSHS "yes"', instr)
  assert_notmatch('JUMP', instr)

  assert_equal("\neval", execute('call HasSomething()'))
  instr = execute('disassemble HasSomething')
  assert_match('HasSomething.*'
        \ .. 'if has("nothing").*'
        \ .. 'elseif has("something").*'
        \ .. 'elseif has("eval").*'
        \ .. ' PUSHS "eval".*'
        \ .. 'elseif has("less").*'
        \, instr)
  assert_notmatch('PUSHS "nothing"', instr)
  assert_notmatch('PUSHS "something"', instr)
  assert_notmatch('PUSHS "less"', instr)
  assert_notmatch('JUMP', instr)
enddef

def WithLambda(): string
  let F = {a -> "X" .. a .. "X"}
  return F("x")
enddef

def Test_compile_lambda()
  assert_equal("XxX", WithLambda())
  let instr = execute('disassemble WithLambda')
  assert_match('WithLambda.*'
        \ .. 'let F = {a -> "X" .. a .. "X"}.*'
        \ .. ' FUNCREF <lambda>\d\+.*'
        \ .. 'PUSHS "x".*'
        \ .. ' LOAD $0.*'
        \ .. ' PCALL (argc 1).*'
        \ .. ' CHECKTYPE string stack\[-1].*'
        \, instr)
enddef

def AndOr(arg): string
  if arg == 1 && arg != 2 || arg == 4
    return 'yes'
  endif
  return 'no'
enddef

def Test_compile_and_or()
  assert_equal("yes", AndOr(1))
  assert_equal("no", AndOr(2))
  assert_equal("yes", AndOr(4))
  let instr = execute('disassemble AndOr')
  assert_match('AndOr.*'
        \ .. 'if arg == 1 && arg != 2 || arg == 4.*'
        \ .. '\d LOAD arg\[-1].*'
        \ .. '\d PUSHNR 1.*'
        \ .. '\d COMPAREANY ==.*'
        \ .. '\d JUMP_AND_KEEP_IF_FALSE -> \d\+.*'
        \ .. '\d LOAD arg\[-1].*'
        \ .. '\d PUSHNR 2.*'
        \ .. '\d COMPAREANY !=.*'
        \ .. '\d JUMP_AND_KEEP_IF_TRUE -> \d\+.*'
        \ .. '\d LOAD arg\[-1].*'
        \ .. '\d PUSHNR 4.*'
        \ .. '\d COMPAREANY ==.*'
        \ .. '\d JUMP_IF_FALSE -> \d\+.*'
        \, instr)
enddef

def ForLoop(): list<number>
  let res: list<number>
  for i in range(3)
    res->add(i)
  endfor
  return res
enddef

def Test_compile_for_loop()
  assert_equal([0, 1, 2], ForLoop())
  let instr = execute('disassemble ForLoop')
  assert_match('ForLoop.*'
        \ .. 'let res: list<number>.*'
        \ .. ' NEWLIST size 0.*'
        \ .. '\d STORE $0.*'
        \ .. 'for i in range(3).*'
        \ .. '\d STORE -1 in $1.*'
        \ .. '\d PUSHNR 3.*'
        \ .. '\d BCALL range(argc 1).*'
        \ .. '\d FOR $1 -> \d\+.*'
        \ .. '\d STORE $2.*'
        \ .. 'res->add(i).*'
        \ .. '\d LOAD $0.*'
        \ .. '\d LOAD $2.*'
        \ .. '\d BCALL add(argc 2).*'
        \ .. '\d DROP.*'
        \ .. 'endfor.*'
        \ .. '\d JUMP -> \d\+.*'
        \ .. '\d DROP.*'
        \, instr)
enddef

let g:number = 42

def Computing()
  let nr = 3
  let nrres = nr + 7
  nrres = nr - 7
  nrres = nr * 7
  nrres = nr / 7
  nrres = nr % 7

  let anyres = g:number + 7
  anyres = g:number - 7
  anyres = g:number * 7
  anyres = g:number / 7
  anyres = g:number % 7

  if has('float')
    let fl = 3.0
    let flres = fl + 7.0
    flres = fl - 7.0
    flres = fl * 7.0
    flres = fl / 7.0
  endif
enddef

def Test_computing()
  let instr = execute('disassemble Computing')
  assert_match('Computing.*'
        \ .. 'let nr = 3.*'
        \ .. '\d STORE 3 in $0.*'
        \ .. 'let nrres = nr + 7.*'
        \ .. '\d LOAD $0.*'
        \ .. '\d PUSHNR 7.*'
        \ .. '\d OPNR +.*'
        \ .. '\d STORE $1.*'
        \ .. 'nrres = nr - 7.*'
        \ .. '\d OPNR -.*'
        \ .. 'nrres = nr \* 7.*'
        \ .. '\d OPNR \*.*'
        \ .. 'nrres = nr / 7.*'
        \ .. '\d OPNR /.*'
        \ .. 'nrres = nr % 7.*'
        \ .. '\d OPNR %.*'
        \ .. 'let anyres = g:number + 7.*'
        \ .. '\d LOADG g:number.*'
        \ .. '\d PUSHNR 7.*'
        \ .. '\d OPANY +.*'
        \ .. '\d STORE $2.*'
        \ .. 'anyres = g:number - 7.*'
        \ .. '\d OPANY -.*'
        \ .. 'anyres = g:number \* 7.*'
        \ .. '\d OPANY \*.*'
        \ .. 'anyres = g:number / 7.*'
        \ .. '\d OPANY /.*'
        \ .. 'anyres = g:number % 7.*'
        \ .. '\d OPANY %.*'
        \, instr)
  if has('float')
    assert_match('Computing.*'
        \ .. 'let fl = 3.0.*'
        \ .. '\d PUSHF 3.0.*'
        \ .. '\d STORE $3.*'
        \ .. 'let flres = fl + 7.0.*'
        \ .. '\d LOAD $3.*'
        \ .. '\d PUSHF 7.0.*'
        \ .. '\d OPFLOAT +.*'
        \ .. '\d STORE $4.*'
        \ .. 'flres = fl - 7.0.*'
        \ .. '\d OPFLOAT -.*'
        \ .. 'flres = fl \* 7.0.*'
        \ .. '\d OPFLOAT \*.*'
        \ .. 'flres = fl / 7.0.*'
        \ .. '\d OPFLOAT /.*'
        \, instr)
  endif
enddef

" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker