summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/testdir/test_vim9_disassemble.vim450
-rw-r--r--src/version.c2
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,