diff options
-rw-r--r-- | src/testdir/test_vim9_disassemble.vim | 450 | ||||
-rw-r--r-- | src/version.c | 2 |
2 files changed, 263 insertions, 189 deletions
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index 90bd67dba..74804b4cf 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -154,6 +154,37 @@ def Test_disassemble_store() res) enddef +def s:ScriptFuncStoreMember() + let locallist: list<number> = [] + locallist[0] = 123 + let localdict: dict<number> = {} + localdict["a"] = 456 +enddef + +def Test_disassemble_store_member() + let res = execute('disass s:ScriptFuncStoreMember') + assert_match('<SNR>\d*_ScriptFuncStoreMember\_s*' .. + 'let locallist: list<number> = []\_s*' .. + '\d NEWLIST size 0\_s*' .. + '\d STORE $0\_s*' .. + 'locallist\[0\] = 123\_s*' .. + '\d PUSHNR 123\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d LOAD $0\_s*' .. + '\d STORELIST\_s*' .. + 'let localdict: dict<number> = {}\_s*' .. + '\d NEWDICT size 0\_s*' .. + '\d STORE $1\_s*' .. + 'localdict\["a"\] = 456\_s*' .. + '\d\+ PUSHNR 456\_s*' .. + '\d\+ PUSHS "a"\_s*' .. + '\d\+ LOAD $1\_s*' .. + '\d\+ STOREDICT\_s*' .. + '\d\+ PUSHNR 0\_s*' .. + '\d\+ RETURN', + res) +enddef + def s:ScriptFuncUnlet() g:somevar = "value" unlet g:somevar @@ -163,46 +194,53 @@ enddef def Test_disassemble_unlet() let res = execute('disass s:ScriptFuncUnlet') - assert_match('<SNR>\d*_ScriptFuncUnlet.*' .. - 'g:somevar = "value".*' .. - '\d PUSHS "value".*' .. - '\d STOREG g:somevar.*' .. - 'unlet g:somevar.*' .. - '\d UNLET g:somevar.*' .. - 'unlet! g:somevar.*' .. - '\d UNLET! g:somevar.*' .. - 'unlet $SOMEVAR.*' .. - '\d UNLETENV $SOMEVAR.*', + assert_match('<SNR>\d*_ScriptFuncUnlet\_s*' .. + 'g:somevar = "value"\_s*' .. + '\d PUSHS "value"\_s*' .. + '\d STOREG g:somevar\_s*' .. + 'unlet g:somevar\_s*' .. + '\d UNLET g:somevar\_s*' .. + 'unlet! g:somevar\_s*' .. + '\d UNLET! g:somevar\_s*' .. + 'unlet $SOMEVAR\_s*' .. + '\d UNLETENV $SOMEVAR\_s*', res) enddef def s:ScriptFuncTry() try - echo 'yes' + echo "yes" catch /fail/ - echo 'no' + echo "no" finally - throw 'end' + throw "end" endtry enddef def Test_disassemble_try() 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.*', + assert_match('<SNR>\d*_ScriptFuncTry\_s*' .. + 'try\_s*' .. + '\d TRY catch -> \d\+, finally -> \d\+\_s*' .. + 'echo "yes"\_s*' .. + '\d PUSHS "yes"\_s*' .. + '\d ECHO 1\_s*' .. + 'catch /fail/\_s*' .. + '\d JUMP -> \d\+\_s*' .. + '\d PUSH v:exception\_s*' .. + '\d PUSHS "fail"\_s*' .. + '\d COMPARESTRING =\~\_s*' .. + '\d JUMP_IF_FALSE -> \d\+\_s*' .. + '\d CATCH\_s*' .. + 'echo "no"\_s*' .. + '\d\+ PUSHS "no"\_s*' .. + '\d\+ ECHO 1\_s*' .. + 'finally\_s*' .. + 'throw "end"\_s*' .. + '\d\+ PUSHS "end"\_s*' .. + '\d\+ THROW\_s*' .. + 'endtry\_s*' .. + '\d\+ ENDTRY', res) enddef @@ -213,18 +251,19 @@ enddef def Test_disassemble_new() 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.*', + assert_match('<SNR>\d*_ScriptFuncNew\_s*' .. + 'let ll = \[1, "two", 333\]\_s*' .. + '\d PUSHNR 1\_s*' .. + '\d PUSHS "two"\_s*' .. + '\d PUSHNR 333\_s*' .. + '\d NEWLIST size 3\_s*' .. + '\d STORE $0\_s*' .. + 'let dd = #{one: 1, two: "val"}\_s*' .. + '\d PUSHS "one"\_s*' .. + '\d PUSHNR 1\_s*' .. + '\d PUSHS "two"\_s*' .. + '\d PUSHS "val"\_s*' .. + '\d NEWDICT size 2\_s*', res) enddef @@ -258,38 +297,54 @@ enddef def Test_disassemble_call() 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_disassemble_new().*' .. - ' DCALL Test_disassemble_new(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.*', + assert_match('<SNR>\d\+_ScriptFuncCall\_s*' .. + 'changenr()\_s*' .. + '\d BCALL changenr(argc 0)\_s*' .. + '\d DROP\_s*' .. + 'char2nr("abc")\_s*' .. + '\d PUSHS "abc"\_s*' .. + '\d BCALL char2nr(argc 1)\_s*' .. + '\d DROP\_s*' .. + 'Test_disassemble_new()\_s*' .. + '\d DCALL Test_disassemble_new(argc 0)\_s*' .. + '\d DROP\_s*' .. + 'FuncWithArg(343)\_s*' .. + '\d\+ PUSHNR 343\_s*' .. + '\d\+ DCALL FuncWithArg(argc 1)\_s*' .. + '\d\+ DROP\_s*' .. + 'ScriptFuncNew()\_s*' .. + '\d\+ DCALL <SNR>\d\+_ScriptFuncNew(argc 0)\_s*' .. + '\d\+ DROP\_s*' .. + 's:ScriptFuncNew()\_s*' .. + '\d\+ DCALL <SNR>\d\+_ScriptFuncNew(argc 0)\_s*' .. + '\d\+ DROP\_s*' .. + 'UserFunc()\_s*' .. + '\d\+ UCALL UserFunc(argc 0)\_s*' .. + '\d\+ DROP\_s*' .. + 'UserFuncWithArg("foo")\_s*' .. + '\d\+ PUSHS "foo"\_s*' .. + '\d\+ UCALL UserFuncWithArg(argc 1)\_s*' .. + '\d\+ DROP\_s*' .. + 'let FuncRef = function("UserFunc")\_s*' .. + '\d\+ PUSHS "UserFunc"\_s*' .. + '\d\+ BCALL function(argc 1)\_s*' .. + '\d\+ STORE $0\_s*' .. + 'FuncRef()\_s*' .. + '\d\+ LOAD $\d\_s*' .. + '\d\+ PCALL (argc 0)\_s*' .. + '\d\+ DROP\_s*' .. + 'let FuncRefWithArg = function("UserFuncWithArg")\_s*' .. + '\d\+ PUSHS "UserFuncWithArg"\_s*' .. + '\d\+ BCALL function(argc 1)\_s*' .. + '\d\+ STORE $1\_s*' .. + 'FuncRefWithArg("bar")\_s*' .. + '\d\+ PUSHS "bar"\_s*' .. + '\d\+ LOAD $\d\_s*' .. + '\d\+ PCALL (argc 1)\_s*' .. + '\d\+ DROP\_s*' .. + 'return "yes"\_s*' .. + '\d\+ PUSHS "yes"\_s*' .. + '\d\+ RETURN', res) enddef @@ -308,21 +363,21 @@ enddef def Test_disassemble_closure() CreateRefs() let res = execute('disass g:Append') - assert_match('<lambda>\d.*' .. - 'local ..= arg.*' .. - '\d LOADOUTER $0.*' .. - '\d LOAD arg\[-1\].*' .. - '\d CONCAT.*' .. - '\d STOREOUTER $0.*' .. - '\d PUSHNR 0.*' .. - '\d RETURN.*', + assert_match('<lambda>\d\_s*' .. + 'local ..= arg\_s*' .. + '\d LOADOUTER $0\_s*' .. + '\d LOAD arg\[-1\]\_s*' .. + '\d CONCAT\_s*' .. + '\d STOREOUTER $0\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN', res) res = execute('disass g:Get') - assert_match('<lambda>\d.*' .. - 'return local.*' .. - '\d LOADOUTER $0.*' .. - '\d RETURN.*', + assert_match('<lambda>\d\_s*' .. + 'return local\_s*' .. + '\d LOADOUTER $0\_s*' .. + '\d RETURN', res) unlet g:Append @@ -342,15 +397,15 @@ enddef def Test_disassemble_pcall() let res = execute('disass s:ScriptPCall') - assert_match('<SNR>\d\+_ScriptPCall.*' .. - 'RefThis()("text").*' .. - '\d DCALL RefThis(argc 0).*' .. - '\d PUSHS "text".*' .. - '\d PCALL top (argc 1).*' .. - '\d PCALL end.*' .. - '\d DROP.*' .. - '\d PUSHNR 0.*' .. - '\d RETURN.*', + assert_match('<SNR>\d\+_ScriptPCall\_s*' .. + 'RefThis()("text")\_s*' .. + '\d DCALL RefThis(argc 0)\_s*' .. + '\d PUSHS "text"\_s*' .. + '\d PCALL top (argc 1)\_s*' .. + '\d PCALL end\_s*' .. + '\d DROP\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN', res) enddef @@ -365,24 +420,24 @@ enddef def Test_disassemble_update_instr() let res = execute('disass s:FuncWithForwardCall') - assert_match('FuncWithForwardCall.*' .. - 'return g:DefinedLater("yes").*' .. - '\d PUSHS "yes".*' .. - '\d UCALL g:DefinedLater(argc 1).*' .. - '\d CHECKTYPE string stack\[-1].*' .. - '\d RETURN.*', + assert_match('FuncWithForwardCall\_s*' .. + 'return g:DefinedLater("yes")\_s*' .. + '\d PUSHS "yes"\_s*' .. + '\d UCALL g:DefinedLater(argc 1)\_s*' .. + '\d CHECKTYPE string stack\[-1]\_s*' .. + '\d RETURN', res) " Calling the function will change UCALL into the faster DCALL assert_equal('yes', FuncWithForwardCall()) res = execute('disass s:FuncWithForwardCall') - assert_match('FuncWithForwardCall.*' .. - 'return g:DefinedLater("yes").*' .. - '\d PUSHS "yes".*' .. - '\d DCALL DefinedLater(argc 1).*' .. - '\d CHECKTYPE string stack\[-1].*' .. - '\d RETURN.*', + assert_match('FuncWithForwardCall\_s*' .. + 'return g:DefinedLater("yes")\_s*' .. + '\d PUSHS "yes"\_s*' .. + '\d DCALL DefinedLater(argc 1)\_s*' .. + '\d CHECKTYPE string stack\[-1]\_s*' .. + '\d RETURN', res) enddef @@ -393,12 +448,12 @@ enddef def Test_disassemble_call_default() let res = execute('disass FuncWithDefault') - assert_match('FuncWithDefault.*' .. - '\d PUSHS "default".*' .. - '\d STORE arg\[-1].*' .. - 'return arg.*' .. - '\d LOAD arg\[-1].*' .. - '\d RETURN.*', + assert_match('FuncWithDefault\_s*' .. + '\d PUSHS "default"\_s*' .. + '\d STORE arg\[-1]\_s*' .. + 'return arg\_s*' .. + '\d LOAD arg\[-1]\_s*' .. + '\d RETURN', res) enddef @@ -434,18 +489,27 @@ enddef def Test_disassemble_const_expr() assert_equal("\nyes", execute('call HasEval()')) let instr = execute('disassemble HasEval') - assert_match('HasEval.*' .. - 'if has("eval").*' .. - ' PUSHS "yes".*', + assert_match('HasEval\_s*' .. + 'if has("eval")\_s*' .. + 'echo "yes"\_s*' .. + '\d PUSHS "yes"\_s*' .. + '\d ECHO 1\_s*' .. + 'else\_s*' .. + 'echo "no"\_s*' .. + 'endif\_s*', instr) assert_notmatch('JUMP', instr) assert_equal("\nno", execute('call HasNothing()')) instr = execute('disassemble HasNothing') - assert_match('HasNothing.*' .. - 'if has("nothing").*' .. - 'else.*' .. - ' PUSHS "no".*', + assert_match('HasNothing\_s*' .. + 'if has("nothing")\_s*' .. + 'echo "yes"\_s*' .. + 'else\_s*' .. + 'echo "no"\_s*' .. + '\d PUSHS "no"\_s*' .. + '\d ECHO 1\_s*' .. + 'endif', instr) assert_notmatch('PUSHS "yes"', instr) assert_notmatch('JUMP', instr) @@ -453,11 +517,17 @@ def Test_disassemble_const_expr() 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").*', + 'if has("nothing")\_s*' .. + 'echo "nothing"\_s*' .. + 'elseif has("something")\_s*' .. + 'echo "something"\_s*' .. + 'elseif has("eval")\_s*' .. + 'echo "eval"\_s*' .. + '\d PUSHS "eval"\_s*' .. + '\d ECHO 1\_s*' .. + 'elseif has("less").*' .. + 'echo "less"\_s*' .. + 'endif', instr) assert_notmatch('PUSHS "nothing"', instr) assert_notmatch('PUSHS "something"', instr) @@ -473,20 +543,20 @@ enddef def Test_disassemble_function() let instr = execute('disassemble WithFunc') - assert_match('WithFunc.*' .. - 'let Funky1: func.*' .. - '0 PUSHFUNC "\[none]".*' .. - '1 STORE $0.*' .. - 'let Funky2: func = function("len").*' .. - '2 PUSHS "len".*' .. - '3 BCALL function(argc 1).*' .. - '4 STORE $1.*' .. - 'let Party2: func = funcref("UserFunc").*' .. - '\d PUSHS "UserFunc".*' .. - '\d BCALL funcref(argc 1).*' .. - '\d STORE $2.*' .. - '\d PUSHNR 0.*' .. - '\d RETURN.*', + assert_match('WithFunc\_s*' .. + 'let Funky1: func\_s*' .. + '0 PUSHFUNC "\[none]"\_s*' .. + '1 STORE $0\_s*' .. + 'let Funky2: func = function("len")\_s*' .. + '2 PUSHS "len"\_s*' .. + '3 BCALL function(argc 1)\_s*' .. + '4 STORE $1\_s*' .. + 'let Party2: func = funcref("UserFunc")\_s*' .. + '\d PUSHS "UserFunc"\_s*' .. + '\d BCALL funcref(argc 1)\_s*' .. + '\d STORE $2\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN', instr) enddef @@ -502,19 +572,19 @@ def Test_disassemble_channel() CheckFeature channel let instr = execute('disassemble WithChannel') - assert_match('WithChannel.*' .. - 'let job1: job.*' .. - '\d PUSHJOB "no process".*' .. - '\d STORE $0.*' .. - 'let job2: job = job_start("donothing").*' .. - '\d PUSHS "donothing".*' .. - '\d BCALL job_start(argc 1).*' .. - '\d STORE $1.*' .. - 'let chan1: channel.*' .. - '\d PUSHCHANNEL 0.*' .. - '\d STORE $2.*' .. - '\d PUSHNR 0.*' .. - '\d RETURN.*', + assert_match('WithChannel\_s*' .. + 'let job1: job\_s*' .. + '\d PUSHJOB "no process"\_s*' .. + '\d STORE $0\_s*' .. + 'let job2: job = job_start("donothing")\_s*' .. + '\d PUSHS "donothing"\_s*' .. + '\d BCALL job_start(argc 1)\_s*' .. + '\d STORE $1\_s*' .. + 'let chan1: channel\_s*' .. + '\d PUSHCHANNEL 0\_s*' .. + '\d STORE $2\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN', instr) enddef @@ -526,13 +596,15 @@ enddef def Test_disassemble_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].*', + assert_match('WithLambda\_s*' .. + 'let F = {a -> "X" .. a .. "X"}\_s*' .. + '\d FUNCREF <lambda>\d\+ $1\_s*' .. + '\d STORE $0\_s*' .. + 'return F("x")\_s*' .. + '\d PUSHS "x"\_s*' .. + '\d LOAD $0\_s*' .. + '\d PCALL (argc 1)\_s*' .. + '\d CHECKTYPE string stack\[-1]', instr) enddef @@ -548,20 +620,20 @@ def Test_disassemble_and_or() 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\+.*', + assert_match('AndOr\_s*' .. + 'if arg == 1 && arg != 2 || arg == 4\_s*' .. + '\d LOAD arg\[-1]\_s*' .. + '\d PUSHNR 1\_s*' .. + '\d COMPAREANY ==\_s*' .. + '\d JUMP_AND_KEEP_IF_FALSE -> \d\+\_s*' .. + '\d LOAD arg\[-1]\_s*' .. + '\d PUSHNR 2\_s*' .. + '\d COMPAREANY !=\_s*' .. + '\d JUMP_AND_KEEP_IF_TRUE -> \d\+\_s*' .. + '\d LOAD arg\[-1]\_s*' .. + '\d\+ PUSHNR 4\_s*' .. + '\d\+ COMPAREANY ==\_s*' .. + '\d\+ JUMP_IF_FALSE -> \d\+', instr) enddef @@ -576,24 +648,24 @@ enddef def Test_disassemble_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.*', + assert_match('ForLoop\_s*' .. + 'let res: list<number>\_s*' .. + '\d NEWLIST size 0\_s*' .. + '\d STORE $0\_s*' .. + 'for i in range(3)\_s*' .. + '\d STORE -1 in $1\_s*' .. + '\d PUSHNR 3\_s*' .. + '\d BCALL range(argc 1)\_s*' .. + '\d FOR $1 -> \d\+\_s*' .. + '\d STORE $2\_s*' .. + 'res->add(i)\_s*' .. + '\d LOAD $0\_s*' .. + '\d LOAD $2\_s*' .. + '\d\+ BCALL add(argc 2)\_s*' .. + '\d\+ DROP\_s*' .. + 'endfor\_s*' .. + '\d\+ JUMP -> \d\+\_s*' .. + '\d\+ DROP', instr) enddef diff --git a/src/version.c b/src/version.c index 061844786..47b276b58 100644 --- a/src/version.c +++ b/src/version.c @@ -747,6 +747,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 758, +/**/ 757, /**/ 756, |