blob: ea012b744e98424c4010b6d9421c9c919c9f091c [file] [log] [blame]
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001" Test the :disassemble command, and compilation as a side effect
2
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +01003source check.vim
4
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01005func NotCompiled()
6 echo "not"
7endfunc
8
9let s:scriptvar = 4
10let g:globalvar = 'g'
Bram Moolenaard3aac292020-04-19 14:32:17 +020011let b:buffervar = 'b'
12let w:windowvar = 'w'
13let t:tabpagevar = 't'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010014
15def s:ScriptFuncLoad(arg: string)
16 let local = 1
17 buffers
18 echo arg
19 echo local
Bram Moolenaar8a1c1012020-05-07 14:07:25 +020020 echo &lines
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010021 echo v:version
22 echo s:scriptvar
23 echo g:globalvar
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020024 echo get(g:, "global")
Bram Moolenaard3aac292020-04-19 14:32:17 +020025 echo b:buffervar
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020026 echo get(b:, "buffer")
Bram Moolenaard3aac292020-04-19 14:32:17 +020027 echo w:windowvar
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020028 echo get(w:, "window")
Bram Moolenaard3aac292020-04-19 14:32:17 +020029 echo t:tabpagevar
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020030 echo get(t:, "tab")
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010031 echo &tabstop
32 echo $ENVVAR
33 echo @z
34enddef
35
Bram Moolenaarf2460a32020-02-07 22:09:54 +010036def Test_disassemble_load()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010037 assert_fails('disass NoFunc', 'E1061:')
38 assert_fails('disass NotCompiled', 'E1062:')
Bram Moolenaar21456cd2020-02-13 21:29:32 +010039 assert_fails('disass', 'E471:')
40 assert_fails('disass [', 'E475:')
Bram Moolenaar9b7bf9e2020-07-11 22:14:59 +020041 assert_fails('disass 234', 'E129:')
42 assert_fails('disass <XX>foo', 'E129:')
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010043
44 let res = execute('disass s:ScriptFuncLoad')
Bram Moolenaar675f7162020-04-12 22:53:54 +020045 assert_match('<SNR>\d*_ScriptFuncLoad.*' ..
46 'buffers.*' ..
47 ' EXEC \+buffers.*' ..
48 ' LOAD arg\[-1\].*' ..
49 ' LOAD $0.*' ..
Bram Moolenaar8a1c1012020-05-07 14:07:25 +020050 ' LOADOPT &lines.*' ..
Bram Moolenaar675f7162020-04-12 22:53:54 +020051 ' LOADV v:version.*' ..
52 ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*' ..
53 ' LOADG g:globalvar.*' ..
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020054 'echo get(g:, "global")\_s*' ..
55 '\d\+ LOAD g:\_s*' ..
56 '\d\+ PUSHS "global"\_s*' ..
57 '\d\+ BCALL get(argc 2).*' ..
Bram Moolenaard3aac292020-04-19 14:32:17 +020058 ' LOADB b:buffervar.*' ..
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020059 'echo get(b:, "buffer")\_s*' ..
60 '\d\+ LOAD b:\_s*' ..
61 '\d\+ PUSHS "buffer"\_s*' ..
62 '\d\+ BCALL get(argc 2).*' ..
Bram Moolenaard3aac292020-04-19 14:32:17 +020063 ' LOADW w:windowvar.*' ..
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020064 'echo get(w:, "window")\_s*' ..
65 '\d\+ LOAD w:\_s*' ..
66 '\d\+ PUSHS "window"\_s*' ..
67 '\d\+ BCALL get(argc 2).*' ..
Bram Moolenaard3aac292020-04-19 14:32:17 +020068 ' LOADT t:tabpagevar.*' ..
Bram Moolenaar2f8ce0a2020-07-19 19:47:35 +020069 'echo get(t:, "tab")\_s*' ..
70 '\d\+ LOAD t:\_s*' ..
71 '\d\+ PUSHS "tab"\_s*' ..
72 '\d\+ BCALL get(argc 2).*' ..
Bram Moolenaar675f7162020-04-12 22:53:54 +020073 ' LOADENV $ENVVAR.*' ..
74 ' LOADREG @z.*',
75 res)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010076enddef
77
Bram Moolenaarcfe435d2020-04-25 20:02:55 +020078def s:EditExpand()
79 let filename = "file"
80 let filenr = 123
81 edit the`=filename``=filenr`.txt
82enddef
83
84def Test_disassemble_exec_expr()
85 let res = execute('disass s:EditExpand')
86 assert_match('<SNR>\d*_EditExpand.*' ..
87 ' let filename = "file".*' ..
88 '\d PUSHS "file".*' ..
89 '\d STORE $0.*' ..
90 ' let filenr = 123.*' ..
91 '\d STORE 123 in $1.*' ..
92 ' edit the`=filename``=filenr`.txt.*' ..
93 '\d PUSHS "edit the".*' ..
94 '\d LOAD $0.*' ..
95 '\d LOAD $1.*' ..
96 '\d 2STRING stack\[-1\].*' ..
97 '\d PUSHS ".txt".*' ..
98 '\d EXECCONCAT 4.*' ..
99 '\d PUSHNR 0.*' ..
100 '\d RETURN',
101 res)
102enddef
103
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100104def s:ScriptFuncPush()
105 let localbool = true
106 let localspec = v:none
107 let localblob = 0z1234
108 if has('float')
109 let localfloat = 1.234
110 endif
111enddef
112
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100113def Test_disassemble_push()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100114 let res = execute('disass s:ScriptFuncPush')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200115 assert_match('<SNR>\d*_ScriptFuncPush.*' ..
116 'localbool = true.*' ..
117 ' PUSH v:true.*' ..
118 'localspec = v:none.*' ..
119 ' PUSH v:none.*' ..
120 'localblob = 0z1234.*' ..
121 ' PUSHBLOB 0z1234.*',
122 res)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100123 if has('float')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200124 assert_match('<SNR>\d*_ScriptFuncPush.*' ..
125 'localfloat = 1.234.*' ..
126 ' PUSHF 1.234.*',
127 res)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100128 endif
129enddef
130
131def s:ScriptFuncStore()
132 let localnr = 1
133 localnr = 2
134 let localstr = 'abc'
135 localstr = 'xyz'
136 v:char = 'abc'
137 s:scriptvar = 'sv'
138 g:globalvar = 'gv'
Bram Moolenaard3aac292020-04-19 14:32:17 +0200139 b:buffervar = 'bv'
140 w:windowvar = 'wv'
141 t:tabpagevar = 'tv'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100142 &tabstop = 8
143 $ENVVAR = 'ev'
144 @z = 'rv'
145enddef
146
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100147def Test_disassemble_store()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100148 let res = execute('disass s:ScriptFuncStore')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200149 assert_match('<SNR>\d*_ScriptFuncStore.*' ..
150 'let localnr = 1.*' ..
151 'localnr = 2.*' ..
152 ' STORE 2 in $0.*' ..
153 'let localstr = ''abc''.*' ..
154 'localstr = ''xyz''.*' ..
155 ' STORE $1.*' ..
156 'v:char = ''abc''.*' ..
157 'STOREV v:char.*' ..
158 's:scriptvar = ''sv''.*' ..
159 ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*' ..
160 'g:globalvar = ''gv''.*' ..
161 ' STOREG g:globalvar.*' ..
Bram Moolenaard3aac292020-04-19 14:32:17 +0200162 'b:buffervar = ''bv''.*' ..
163 ' STOREB b:buffervar.*' ..
164 'w:windowvar = ''wv''.*' ..
165 ' STOREW w:windowvar.*' ..
166 't:tabpagevar = ''tv''.*' ..
167 ' STORET t:tabpagevar.*' ..
Bram Moolenaar675f7162020-04-12 22:53:54 +0200168 '&tabstop = 8.*' ..
169 ' STOREOPT &tabstop.*' ..
170 '$ENVVAR = ''ev''.*' ..
171 ' STOREENV $ENVVAR.*' ..
172 '@z = ''rv''.*' ..
173 ' STOREREG @z.*',
174 res)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100175enddef
176
Bram Moolenaarcb790402020-05-15 20:53:00 +0200177def s:ScriptFuncStoreMember()
178 let locallist: list<number> = []
179 locallist[0] = 123
180 let localdict: dict<number> = {}
181 localdict["a"] = 456
182enddef
183
184def Test_disassemble_store_member()
185 let res = execute('disass s:ScriptFuncStoreMember')
186 assert_match('<SNR>\d*_ScriptFuncStoreMember\_s*' ..
187 'let locallist: list<number> = []\_s*' ..
188 '\d NEWLIST size 0\_s*' ..
189 '\d STORE $0\_s*' ..
190 'locallist\[0\] = 123\_s*' ..
191 '\d PUSHNR 123\_s*' ..
192 '\d PUSHNR 0\_s*' ..
193 '\d LOAD $0\_s*' ..
194 '\d STORELIST\_s*' ..
195 'let localdict: dict<number> = {}\_s*' ..
196 '\d NEWDICT size 0\_s*' ..
197 '\d STORE $1\_s*' ..
198 'localdict\["a"\] = 456\_s*' ..
199 '\d\+ PUSHNR 456\_s*' ..
200 '\d\+ PUSHS "a"\_s*' ..
201 '\d\+ LOAD $1\_s*' ..
202 '\d\+ STOREDICT\_s*' ..
203 '\d\+ PUSHNR 0\_s*' ..
204 '\d\+ RETURN',
205 res)
206enddef
207
Bram Moolenaar0779fab2020-06-18 22:18:18 +0200208def s:ListAssign()
209 let x: string
210 let y: string
211 let l: list<any>
212 [x, y; l] = g:stringlist
213enddef
214
215def Test_disassemble_list_assign()
216 let res = execute('disass s:ListAssign')
217 assert_match('<SNR>\d*_ListAssign\_s*' ..
218 'let x: string\_s*' ..
219 '\d PUSHS "\[NULL\]"\_s*' ..
220 '\d STORE $0\_s*' ..
221 'let y: string\_s*' ..
222 '\d PUSHS "\[NULL\]"\_s*' ..
223 '\d STORE $1\_s*' ..
224 'let l: list<any>\_s*' ..
225 '\d NEWLIST size 0\_s*' ..
226 '\d STORE $2\_s*' ..
227 '\[x, y; l\] = g:stringlist\_s*' ..
228 '\d LOADG g:stringlist\_s*' ..
229 '\d CHECKTYPE list stack\[-1\]\_s*' ..
230 '\d CHECKLEN >= 2\_s*' ..
231 '\d\+ ITEM 0\_s*' ..
232 '\d\+ CHECKTYPE string stack\[-1\]\_s*' ..
233 '\d\+ STORE $0\_s*' ..
234 '\d\+ ITEM 1\_s*' ..
235 '\d\+ CHECKTYPE string stack\[-1\]\_s*' ..
236 '\d\+ STORE $1\_s*' ..
237 '\d\+ SLICE 2\_s*' ..
238 '\d\+ STORE $2\_s*' ..
239 '\d\+ PUSHNR 0\_s*' ..
240 '\d\+ RETURN',
241 res)
242enddef
243
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200244def s:ScriptFuncUnlet()
245 g:somevar = "value"
246 unlet g:somevar
247 unlet! g:somevar
Bram Moolenaar7bdaea62020-04-19 18:27:26 +0200248 unlet $SOMEVAR
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200249enddef
250
251def Test_disassemble_unlet()
252 let res = execute('disass s:ScriptFuncUnlet')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200253 assert_match('<SNR>\d*_ScriptFuncUnlet\_s*' ..
254 'g:somevar = "value"\_s*' ..
255 '\d PUSHS "value"\_s*' ..
256 '\d STOREG g:somevar\_s*' ..
257 'unlet g:somevar\_s*' ..
258 '\d UNLET g:somevar\_s*' ..
259 'unlet! g:somevar\_s*' ..
260 '\d UNLET! g:somevar\_s*' ..
261 'unlet $SOMEVAR\_s*' ..
262 '\d UNLETENV $SOMEVAR\_s*',
Bram Moolenaard72c1bf2020-04-19 16:28:59 +0200263 res)
264enddef
265
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100266def s:ScriptFuncTry()
267 try
Bram Moolenaarcb790402020-05-15 20:53:00 +0200268 echo "yes"
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100269 catch /fail/
Bram Moolenaarcb790402020-05-15 20:53:00 +0200270 echo "no"
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100271 finally
Bram Moolenaarcb790402020-05-15 20:53:00 +0200272 throw "end"
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100273 endtry
274enddef
275
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100276def Test_disassemble_try()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100277 let res = execute('disass s:ScriptFuncTry')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200278 assert_match('<SNR>\d*_ScriptFuncTry\_s*' ..
279 'try\_s*' ..
280 '\d TRY catch -> \d\+, finally -> \d\+\_s*' ..
281 'echo "yes"\_s*' ..
282 '\d PUSHS "yes"\_s*' ..
283 '\d ECHO 1\_s*' ..
284 'catch /fail/\_s*' ..
285 '\d JUMP -> \d\+\_s*' ..
286 '\d PUSH v:exception\_s*' ..
287 '\d PUSHS "fail"\_s*' ..
288 '\d COMPARESTRING =\~\_s*' ..
289 '\d JUMP_IF_FALSE -> \d\+\_s*' ..
290 '\d CATCH\_s*' ..
291 'echo "no"\_s*' ..
292 '\d\+ PUSHS "no"\_s*' ..
293 '\d\+ ECHO 1\_s*' ..
294 'finally\_s*' ..
295 'throw "end"\_s*' ..
296 '\d\+ PUSHS "end"\_s*' ..
297 '\d\+ THROW\_s*' ..
298 'endtry\_s*' ..
299 '\d\+ ENDTRY',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200300 res)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100301enddef
302
303def s:ScriptFuncNew()
304 let ll = [1, "two", 333]
305 let dd = #{one: 1, two: "val"}
306enddef
307
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100308def Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100309 let res = execute('disass s:ScriptFuncNew')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200310 assert_match('<SNR>\d*_ScriptFuncNew\_s*' ..
311 'let ll = \[1, "two", 333\]\_s*' ..
312 '\d PUSHNR 1\_s*' ..
313 '\d PUSHS "two"\_s*' ..
314 '\d PUSHNR 333\_s*' ..
315 '\d NEWLIST size 3\_s*' ..
316 '\d STORE $0\_s*' ..
317 'let dd = #{one: 1, two: "val"}\_s*' ..
318 '\d PUSHS "one"\_s*' ..
319 '\d PUSHNR 1\_s*' ..
320 '\d PUSHS "two"\_s*' ..
321 '\d PUSHS "val"\_s*' ..
322 '\d NEWDICT size 2\_s*',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200323 res)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100324enddef
325
Bram Moolenaar6e949782020-04-13 17:21:00 +0200326def FuncWithArg(arg: any)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100327 echo arg
328enddef
329
330func UserFunc()
331 echo 'nothing'
332endfunc
333
334func UserFuncWithArg(arg)
335 echo a:arg
336endfunc
337
338def s:ScriptFuncCall(): string
339 changenr()
340 char2nr("abc")
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100341 Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100342 FuncWithArg(343)
343 ScriptFuncNew()
344 s:ScriptFuncNew()
345 UserFunc()
346 UserFuncWithArg("foo")
347 let FuncRef = function("UserFunc")
348 FuncRef()
349 let FuncRefWithArg = function("UserFuncWithArg")
350 FuncRefWithArg("bar")
351 return "yes"
352enddef
353
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100354def Test_disassemble_call()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100355 let res = execute('disass s:ScriptFuncCall')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200356 assert_match('<SNR>\d\+_ScriptFuncCall\_s*' ..
357 'changenr()\_s*' ..
358 '\d BCALL changenr(argc 0)\_s*' ..
359 '\d DROP\_s*' ..
360 'char2nr("abc")\_s*' ..
361 '\d PUSHS "abc"\_s*' ..
362 '\d BCALL char2nr(argc 1)\_s*' ..
363 '\d DROP\_s*' ..
364 'Test_disassemble_new()\_s*' ..
365 '\d DCALL Test_disassemble_new(argc 0)\_s*' ..
366 '\d DROP\_s*' ..
367 'FuncWithArg(343)\_s*' ..
368 '\d\+ PUSHNR 343\_s*' ..
369 '\d\+ DCALL FuncWithArg(argc 1)\_s*' ..
370 '\d\+ DROP\_s*' ..
371 'ScriptFuncNew()\_s*' ..
372 '\d\+ DCALL <SNR>\d\+_ScriptFuncNew(argc 0)\_s*' ..
373 '\d\+ DROP\_s*' ..
374 's:ScriptFuncNew()\_s*' ..
375 '\d\+ DCALL <SNR>\d\+_ScriptFuncNew(argc 0)\_s*' ..
376 '\d\+ DROP\_s*' ..
377 'UserFunc()\_s*' ..
378 '\d\+ UCALL UserFunc(argc 0)\_s*' ..
379 '\d\+ DROP\_s*' ..
380 'UserFuncWithArg("foo")\_s*' ..
381 '\d\+ PUSHS "foo"\_s*' ..
382 '\d\+ UCALL UserFuncWithArg(argc 1)\_s*' ..
383 '\d\+ DROP\_s*' ..
384 'let FuncRef = function("UserFunc")\_s*' ..
385 '\d\+ PUSHS "UserFunc"\_s*' ..
386 '\d\+ BCALL function(argc 1)\_s*' ..
387 '\d\+ STORE $0\_s*' ..
388 'FuncRef()\_s*' ..
389 '\d\+ LOAD $\d\_s*' ..
390 '\d\+ PCALL (argc 0)\_s*' ..
391 '\d\+ DROP\_s*' ..
392 'let FuncRefWithArg = function("UserFuncWithArg")\_s*' ..
393 '\d\+ PUSHS "UserFuncWithArg"\_s*' ..
394 '\d\+ BCALL function(argc 1)\_s*' ..
395 '\d\+ STORE $1\_s*' ..
396 'FuncRefWithArg("bar")\_s*' ..
397 '\d\+ PUSHS "bar"\_s*' ..
398 '\d\+ LOAD $\d\_s*' ..
399 '\d\+ PCALL (argc 1)\_s*' ..
400 '\d\+ DROP\_s*' ..
401 'return "yes"\_s*' ..
402 '\d\+ PUSHS "yes"\_s*' ..
403 '\d\+ RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200404 res)
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100405enddef
406
Bram Moolenaarb68b3462020-05-06 21:06:30 +0200407def s:CreateRefs()
408 let local = 'a'
409 def Append(arg: string)
410 local ..= arg
411 enddef
412 g:Append = Append
413 def Get(): string
414 return local
415 enddef
416 g:Get = Get
417enddef
418
419def Test_disassemble_closure()
420 CreateRefs()
421 let res = execute('disass g:Append')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200422 assert_match('<lambda>\d\_s*' ..
423 'local ..= arg\_s*' ..
424 '\d LOADOUTER $0\_s*' ..
425 '\d LOAD arg\[-1\]\_s*' ..
426 '\d CONCAT\_s*' ..
427 '\d STOREOUTER $0\_s*' ..
428 '\d PUSHNR 0\_s*' ..
429 '\d RETURN',
Bram Moolenaarb68b3462020-05-06 21:06:30 +0200430 res)
431
432 res = execute('disass g:Get')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200433 assert_match('<lambda>\d\_s*' ..
434 'return local\_s*' ..
435 '\d LOADOUTER $0\_s*' ..
436 '\d RETURN',
Bram Moolenaarb68b3462020-05-06 21:06:30 +0200437 res)
438
439 unlet g:Append
440 unlet g:Get
441enddef
442
Bram Moolenaar8ed04582020-02-22 19:07:28 +0100443
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200444def EchoArg(arg: string): string
445 return arg
446enddef
447def RefThis(): func
448 return function('EchoArg')
449enddef
450def s:ScriptPCall()
451 RefThis()("text")
452enddef
453
454def Test_disassemble_pcall()
455 let res = execute('disass s:ScriptPCall')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200456 assert_match('<SNR>\d\+_ScriptPCall\_s*' ..
457 'RefThis()("text")\_s*' ..
458 '\d DCALL RefThis(argc 0)\_s*' ..
459 '\d PUSHS "text"\_s*' ..
460 '\d PCALL top (argc 1)\_s*' ..
461 '\d PCALL end\_s*' ..
462 '\d DROP\_s*' ..
463 '\d PUSHNR 0\_s*' ..
464 '\d RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200465 res)
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200466enddef
467
468
Bram Moolenaara26b9702020-04-18 19:53:28 +0200469def s:FuncWithForwardCall(): string
470 return g:DefinedLater("yes")
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100471enddef
472
473def DefinedLater(arg: string): string
474 return arg
475enddef
476
477def Test_disassemble_update_instr()
Bram Moolenaara26b9702020-04-18 19:53:28 +0200478 let res = execute('disass s:FuncWithForwardCall')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200479 assert_match('FuncWithForwardCall\_s*' ..
480 'return g:DefinedLater("yes")\_s*' ..
481 '\d PUSHS "yes"\_s*' ..
Bram Moolenaar822ba242020-05-24 23:00:18 +0200482 '\d DCALL DefinedLater(argc 1)\_s*' ..
Bram Moolenaarcb790402020-05-15 20:53:00 +0200483 '\d RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200484 res)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100485
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +0200486 # Calling the function will change UCALL into the faster DCALL
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100487 assert_equal('yes', FuncWithForwardCall())
488
Bram Moolenaara26b9702020-04-18 19:53:28 +0200489 res = execute('disass s:FuncWithForwardCall')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200490 assert_match('FuncWithForwardCall\_s*' ..
491 'return g:DefinedLater("yes")\_s*' ..
492 '\d PUSHS "yes"\_s*' ..
493 '\d DCALL DefinedLater(argc 1)\_s*' ..
Bram Moolenaarcb790402020-05-15 20:53:00 +0200494 '\d RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200495 res)
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100496enddef
497
498
Bram Moolenaar8ed04582020-02-22 19:07:28 +0100499def FuncWithDefault(arg: string = 'default'): string
500 return arg
501enddef
502
503def Test_disassemble_call_default()
504 let res = execute('disass FuncWithDefault')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200505 assert_match('FuncWithDefault\_s*' ..
506 '\d PUSHS "default"\_s*' ..
507 '\d STORE arg\[-1]\_s*' ..
508 'return arg\_s*' ..
509 '\d LOAD arg\[-1]\_s*' ..
510 '\d RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200511 res)
Bram Moolenaar8ed04582020-02-22 19:07:28 +0100512enddef
513
514
Bram Moolenaar158906c2020-02-06 20:39:45 +0100515def HasEval()
516 if has("eval")
517 echo "yes"
518 else
519 echo "no"
520 endif
521enddef
522
523def HasNothing()
524 if has("nothing")
525 echo "yes"
526 else
527 echo "no"
528 endif
529enddef
530
531def HasSomething()
532 if has("nothing")
533 echo "nothing"
534 elseif has("something")
535 echo "something"
536 elseif has("eval")
537 echo "eval"
538 elseif has("less")
539 echo "less"
540 endif
541enddef
542
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100543def Test_disassemble_const_expr()
Bram Moolenaar158906c2020-02-06 20:39:45 +0100544 assert_equal("\nyes", execute('call HasEval()'))
545 let instr = execute('disassemble HasEval')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200546 assert_match('HasEval\_s*' ..
547 'if has("eval")\_s*' ..
548 'echo "yes"\_s*' ..
549 '\d PUSHS "yes"\_s*' ..
550 '\d ECHO 1\_s*' ..
551 'else\_s*' ..
552 'echo "no"\_s*' ..
553 'endif\_s*',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200554 instr)
Bram Moolenaar158906c2020-02-06 20:39:45 +0100555 assert_notmatch('JUMP', instr)
556
557 assert_equal("\nno", execute('call HasNothing()'))
558 instr = execute('disassemble HasNothing')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200559 assert_match('HasNothing\_s*' ..
560 'if has("nothing")\_s*' ..
561 'echo "yes"\_s*' ..
562 'else\_s*' ..
563 'echo "no"\_s*' ..
564 '\d PUSHS "no"\_s*' ..
565 '\d ECHO 1\_s*' ..
566 'endif',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200567 instr)
Bram Moolenaar158906c2020-02-06 20:39:45 +0100568 assert_notmatch('PUSHS "yes"', instr)
569 assert_notmatch('JUMP', instr)
570
571 assert_equal("\neval", execute('call HasSomething()'))
572 instr = execute('disassemble HasSomething')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200573 assert_match('HasSomething.*' ..
Bram Moolenaarcb790402020-05-15 20:53:00 +0200574 'if has("nothing")\_s*' ..
575 'echo "nothing"\_s*' ..
576 'elseif has("something")\_s*' ..
577 'echo "something"\_s*' ..
578 'elseif has("eval")\_s*' ..
579 'echo "eval"\_s*' ..
580 '\d PUSHS "eval"\_s*' ..
581 '\d ECHO 1\_s*' ..
582 'elseif has("less").*' ..
583 'echo "less"\_s*' ..
584 'endif',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200585 instr)
Bram Moolenaar158906c2020-02-06 20:39:45 +0100586 assert_notmatch('PUSHS "nothing"', instr)
587 assert_notmatch('PUSHS "something"', instr)
588 assert_notmatch('PUSHS "less"', instr)
589 assert_notmatch('JUMP', instr)
590enddef
591
Bram Moolenaarefd88552020-06-18 20:50:10 +0200592def ReturnInIf(): string
593 if g:cond
594 return "yes"
595 else
596 return "no"
597 endif
598enddef
599
600def Test_disassemble_return_in_if()
601 let instr = execute('disassemble ReturnInIf')
602 assert_match('ReturnInIf\_s*' ..
603 'if g:cond\_s*' ..
604 '0 LOADG g:cond\_s*' ..
605 '1 JUMP_IF_FALSE -> 4\_s*' ..
606 'return "yes"\_s*' ..
607 '2 PUSHS "yes"\_s*' ..
608 '3 RETURN\_s*' ..
609 'else\_s*' ..
610 ' return "no"\_s*' ..
611 '4 PUSHS "no"\_s*' ..
612 '5 RETURN$',
613 instr)
614enddef
615
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100616def WithFunc()
Bram Moolenaar5deeb3f2020-04-05 17:08:17 +0200617 let Funky1: func
618 let Funky2: func = function("len")
619 let Party2: func = funcref("UserFunc")
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100620enddef
621
622def Test_disassemble_function()
623 let instr = execute('disassemble WithFunc')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200624 assert_match('WithFunc\_s*' ..
625 'let Funky1: func\_s*' ..
626 '0 PUSHFUNC "\[none]"\_s*' ..
627 '1 STORE $0\_s*' ..
628 'let Funky2: func = function("len")\_s*' ..
629 '2 PUSHS "len"\_s*' ..
630 '3 BCALL function(argc 1)\_s*' ..
631 '4 STORE $1\_s*' ..
632 'let Party2: func = funcref("UserFunc")\_s*' ..
633 '\d PUSHS "UserFunc"\_s*' ..
634 '\d BCALL funcref(argc 1)\_s*' ..
635 '\d STORE $2\_s*' ..
636 '\d PUSHNR 0\_s*' ..
637 '\d RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200638 instr)
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100639enddef
640
641if has('channel')
642 def WithChannel()
643 let job1: job
644 let job2: job = job_start("donothing")
645 let chan1: channel
646 enddef
647endif
648
649def Test_disassemble_channel()
650 CheckFeature channel
651
652 let instr = execute('disassemble WithChannel')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200653 assert_match('WithChannel\_s*' ..
654 'let job1: job\_s*' ..
655 '\d PUSHJOB "no process"\_s*' ..
656 '\d STORE $0\_s*' ..
657 'let job2: job = job_start("donothing")\_s*' ..
658 '\d PUSHS "donothing"\_s*' ..
659 '\d BCALL job_start(argc 1)\_s*' ..
660 '\d STORE $1\_s*' ..
661 'let chan1: channel\_s*' ..
662 '\d PUSHCHANNEL 0\_s*' ..
663 '\d STORE $2\_s*' ..
664 '\d PUSHNR 0\_s*' ..
665 '\d RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200666 instr)
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100667enddef
668
Bram Moolenaar777770f2020-02-06 21:27:08 +0100669def WithLambda(): string
670 let F = {a -> "X" .. a .. "X"}
671 return F("x")
672enddef
673
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100674def Test_disassemble_lambda()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100675 assert_equal("XxX", WithLambda())
676 let instr = execute('disassemble WithLambda')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200677 assert_match('WithLambda\_s*' ..
678 'let F = {a -> "X" .. a .. "X"}\_s*' ..
679 '\d FUNCREF <lambda>\d\+ $1\_s*' ..
680 '\d STORE $0\_s*' ..
681 'return F("x")\_s*' ..
682 '\d PUSHS "x"\_s*' ..
683 '\d LOAD $0\_s*' ..
684 '\d PCALL (argc 1)\_s*' ..
Bram Moolenaar822ba242020-05-24 23:00:18 +0200685 '\d RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200686 instr)
Bram Moolenaarbfd65582020-07-13 18:18:00 +0200687
688 let name = substitute(instr, '.*\(<lambda>\d\+\).*', '\1', '')
689 instr = execute('disassemble ' .. name)
690 assert_match('<lambda>\d\+\_s*' ..
691 'return "X" .. a .. "X"\_s*' ..
692 '\d PUSHS "X"\_s*' ..
693 '\d LOAD arg\[-1\]\_s*' ..
694 '\d 2STRING stack\[-1\]\_s*' ..
695 '\d CONCAT\_s*' ..
696 '\d PUSHS "X"\_s*' ..
697 '\d CONCAT\_s*' ..
698 '\d RETURN',
699 instr)
Bram Moolenaar777770f2020-02-06 21:27:08 +0100700enddef
701
Bram Moolenaar38ddf332020-07-31 22:05:04 +0200702def NestedOuter()
703 def g:Inner()
704 echomsg "inner"
705 enddef
706enddef
707
708def Test_nested_func()
709 let instr = execute('disassemble NestedOuter')
710 assert_match('NestedOuter\_s*' ..
711 'def g:Inner()\_s*' ..
712 'echomsg "inner"\_s*' ..
713 'enddef\_s*' ..
714 '\d NEWFUNC <lambda>\d\+ Inner\_s*' ..
715 '\d PUSHNR 0\_s*' ..
716 '\d RETURN',
717 instr)
718enddef
719
Bram Moolenaar6e949782020-04-13 17:21:00 +0200720def AndOr(arg: any): string
Bram Moolenaar777770f2020-02-06 21:27:08 +0100721 if arg == 1 && arg != 2 || arg == 4
722 return 'yes'
723 endif
724 return 'no'
725enddef
726
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100727def Test_disassemble_and_or()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100728 assert_equal("yes", AndOr(1))
729 assert_equal("no", AndOr(2))
730 assert_equal("yes", AndOr(4))
731 let instr = execute('disassemble AndOr')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200732 assert_match('AndOr\_s*' ..
733 'if arg == 1 && arg != 2 || arg == 4\_s*' ..
734 '\d LOAD arg\[-1]\_s*' ..
735 '\d PUSHNR 1\_s*' ..
736 '\d COMPAREANY ==\_s*' ..
737 '\d JUMP_AND_KEEP_IF_FALSE -> \d\+\_s*' ..
738 '\d LOAD arg\[-1]\_s*' ..
739 '\d PUSHNR 2\_s*' ..
740 '\d COMPAREANY !=\_s*' ..
741 '\d JUMP_AND_KEEP_IF_TRUE -> \d\+\_s*' ..
742 '\d LOAD arg\[-1]\_s*' ..
743 '\d\+ PUSHNR 4\_s*' ..
744 '\d\+ COMPAREANY ==\_s*' ..
745 '\d\+ JUMP_IF_FALSE -> \d\+',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200746 instr)
Bram Moolenaar777770f2020-02-06 21:27:08 +0100747enddef
748
Bram Moolenaar04d05222020-02-06 22:06:54 +0100749def ForLoop(): list<number>
750 let res: list<number>
751 for i in range(3)
752 res->add(i)
753 endfor
754 return res
755enddef
756
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100757def Test_disassemble_for_loop()
Bram Moolenaar04d05222020-02-06 22:06:54 +0100758 assert_equal([0, 1, 2], ForLoop())
759 let instr = execute('disassemble ForLoop')
Bram Moolenaarcb790402020-05-15 20:53:00 +0200760 assert_match('ForLoop\_s*' ..
761 'let res: list<number>\_s*' ..
762 '\d NEWLIST size 0\_s*' ..
763 '\d STORE $0\_s*' ..
764 'for i in range(3)\_s*' ..
765 '\d STORE -1 in $1\_s*' ..
766 '\d PUSHNR 3\_s*' ..
767 '\d BCALL range(argc 1)\_s*' ..
768 '\d FOR $1 -> \d\+\_s*' ..
769 '\d STORE $2\_s*' ..
770 'res->add(i)\_s*' ..
771 '\d LOAD $0\_s*' ..
772 '\d LOAD $2\_s*' ..
773 '\d\+ BCALL add(argc 2)\_s*' ..
774 '\d\+ DROP\_s*' ..
775 'endfor\_s*' ..
776 '\d\+ JUMP -> \d\+\_s*' ..
777 '\d\+ DROP',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200778 instr)
Bram Moolenaar04d05222020-02-06 22:06:54 +0100779enddef
780
Bram Moolenaar0ad3e892020-07-05 21:38:11 +0200781def ForLoopEval(): string
782 let res = ""
783 for str in eval('["one", "two"]')
784 res ..= str
785 endfor
786 return res
787enddef
788
789def Test_disassemble_for_loop_eval()
790 assert_equal('onetwo', ForLoopEval())
791 let instr = execute('disassemble ForLoopEval')
792 assert_match('ForLoopEval\_s*' ..
793 'let res = ""\_s*' ..
794 '\d PUSHS ""\_s*' ..
795 '\d STORE $0\_s*' ..
796 'for str in eval(''\["one", "two"\]'')\_s*' ..
797 '\d STORE -1 in $1\_s*' ..
798 '\d PUSHS "\["one", "two"\]"\_s*' ..
799 '\d BCALL eval(argc 1)\_s*' ..
800 '\d CHECKTYPE list stack\[-1\]\_s*' ..
801 '\d FOR $1 -> \d\+\_s*' ..
802 '\d STORE $2\_s*' ..
803 'res ..= str\_s*' ..
804 '\d\+ LOAD $0\_s*' ..
805 '\d\+ LOAD $2\_s*' ..
806 '\d\+ CHECKTYPE string stack\[-1\]\_s*' ..
807 '\d\+ CONCAT\_s*' ..
808 '\d\+ STORE $0\_s*' ..
809 'endfor\_s*' ..
810 '\d\+ JUMP -> 6\_s*' ..
811 '\d\+ DROP\_s*' ..
812 'return res\_s*' ..
813 '\d\+ LOAD $0\_s*' ..
814 '\d\+ RETURN',
815 instr)
816enddef
817
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100818let g:number = 42
819
820def Computing()
821 let nr = 3
822 let nrres = nr + 7
823 nrres = nr - 7
824 nrres = nr * 7
825 nrres = nr / 7
826 nrres = nr % 7
827
828 let anyres = g:number + 7
829 anyres = g:number - 7
830 anyres = g:number * 7
831 anyres = g:number / 7
832 anyres = g:number % 7
833
834 if has('float')
835 let fl = 3.0
836 let flres = fl + 7.0
837 flres = fl - 7.0
838 flres = fl * 7.0
839 flres = fl / 7.0
840 endif
841enddef
842
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100843def Test_disassemble_computing()
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100844 let instr = execute('disassemble Computing')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200845 assert_match('Computing.*' ..
846 'let nr = 3.*' ..
847 '\d STORE 3 in $0.*' ..
848 'let nrres = nr + 7.*' ..
849 '\d LOAD $0.*' ..
850 '\d PUSHNR 7.*' ..
851 '\d OPNR +.*' ..
852 '\d STORE $1.*' ..
853 'nrres = nr - 7.*' ..
854 '\d OPNR -.*' ..
855 'nrres = nr \* 7.*' ..
856 '\d OPNR \*.*' ..
857 'nrres = nr / 7.*' ..
858 '\d OPNR /.*' ..
859 'nrres = nr % 7.*' ..
860 '\d OPNR %.*' ..
861 'let anyres = g:number + 7.*' ..
862 '\d LOADG g:number.*' ..
863 '\d PUSHNR 7.*' ..
864 '\d OPANY +.*' ..
865 '\d STORE $2.*' ..
866 'anyres = g:number - 7.*' ..
867 '\d OPANY -.*' ..
868 'anyres = g:number \* 7.*' ..
869 '\d OPANY \*.*' ..
870 'anyres = g:number / 7.*' ..
871 '\d OPANY /.*' ..
872 'anyres = g:number % 7.*' ..
873 '\d OPANY %.*',
874 instr)
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100875 if has('float')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200876 assert_match('Computing.*' ..
877 'let fl = 3.0.*' ..
878 '\d PUSHF 3.0.*' ..
879 '\d STORE $3.*' ..
880 'let flres = fl + 7.0.*' ..
881 '\d LOAD $3.*' ..
882 '\d PUSHF 7.0.*' ..
883 '\d OPFLOAT +.*' ..
884 '\d STORE $4.*' ..
885 'flres = fl - 7.0.*' ..
886 '\d OPFLOAT -.*' ..
887 'flres = fl \* 7.0.*' ..
888 '\d OPFLOAT \*.*' ..
889 'flres = fl / 7.0.*' ..
890 '\d OPFLOAT /.*',
891 instr)
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100892 endif
893enddef
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100894
Bram Moolenaaree2e52a2020-02-19 14:17:18 +0100895def AddListBlob()
896 let reslist = [1, 2] + [3, 4]
897 let resblob = 0z1122 + 0z3344
898enddef
899
900def Test_disassemble_add_list_blob()
901 let instr = execute('disassemble AddListBlob')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200902 assert_match('AddListBlob.*' ..
903 'let reslist = \[1, 2] + \[3, 4].*' ..
904 '\d PUSHNR 1.*' ..
905 '\d PUSHNR 2.*' ..
906 '\d NEWLIST size 2.*' ..
907 '\d PUSHNR 3.*' ..
908 '\d PUSHNR 4.*' ..
909 '\d NEWLIST size 2.*' ..
910 '\d ADDLIST.*' ..
911 '\d STORE $.*.*' ..
912 'let resblob = 0z1122 + 0z3344.*' ..
913 '\d PUSHBLOB 0z1122.*' ..
914 '\d PUSHBLOB 0z3344.*' ..
915 '\d ADDBLOB.*' ..
916 '\d STORE $.*',
917 instr)
Bram Moolenaaree2e52a2020-02-19 14:17:18 +0100918enddef
919
920let g:aa = 'aa'
921def ConcatString(): string
922 let res = g:aa .. "bb"
923 return res
924enddef
925
926def Test_disassemble_concat()
927 let instr = execute('disassemble ConcatString')
Bram Moolenaar675f7162020-04-12 22:53:54 +0200928 assert_match('ConcatString.*' ..
929 'let res = g:aa .. "bb".*' ..
930 '\d LOADG g:aa.*' ..
931 '\d PUSHS "bb".*' ..
932 '\d 2STRING stack\[-2].*' ..
933 '\d CONCAT.*' ..
934 '\d STORE $.*',
935 instr)
Bram Moolenaaree2e52a2020-02-19 14:17:18 +0100936 assert_equal('aabb', ConcatString())
937enddef
938
Bram Moolenaar747f11a2020-07-19 18:38:37 +0200939def StringIndex(): number
940 let s = "abcd"
941 let res = s[1]
942 return res
943enddef
944
945def Test_disassemble_string_index()
946 let instr = execute('disassemble StringIndex')
947 assert_match('StringIndex\_s*' ..
948 'let s = "abcd"\_s*' ..
949 '\d PUSHS "abcd"\_s*' ..
950 '\d STORE $0\_s*' ..
951 'let res = s\[1]\_s*' ..
952 '\d LOAD $0\_s*' ..
953 '\d PUSHNR 1\_s*' ..
954 '\d STRINDEX\_s*' ..
955 '\d STORE $1\_s*',
956 instr)
957 assert_equal('b', StringIndex())
958enddef
959
Bram Moolenaaree2e52a2020-02-19 14:17:18 +0100960def ListIndex(): number
961 let l = [1, 2, 3]
962 let res = l[1]
963 return res
964enddef
965
966def Test_disassemble_list_index()
967 let instr = execute('disassemble ListIndex')
Bram Moolenaar4902ab12020-05-15 19:21:31 +0200968 assert_match('ListIndex\_s*' ..
969 'let l = \[1, 2, 3]\_s*' ..
970 '\d PUSHNR 1\_s*' ..
971 '\d PUSHNR 2\_s*' ..
972 '\d PUSHNR 3\_s*' ..
973 '\d NEWLIST size 3\_s*' ..
974 '\d STORE $0\_s*' ..
975 'let res = l\[1]\_s*' ..
976 '\d LOAD $0\_s*' ..
977 '\d PUSHNR 1\_s*' ..
Bram Moolenaar747f11a2020-07-19 18:38:37 +0200978 '\d LISTINDEX\_s*' ..
Bram Moolenaar4902ab12020-05-15 19:21:31 +0200979 '\d STORE $1\_s*',
Bram Moolenaar675f7162020-04-12 22:53:54 +0200980 instr)
Bram Moolenaaree2e52a2020-02-19 14:17:18 +0100981 assert_equal(2, ListIndex())
982enddef
983
984def DictMember(): number
985 let d = #{item: 1}
986 let res = d.item
Bram Moolenaar4902ab12020-05-15 19:21:31 +0200987 res = d["item"]
Bram Moolenaaree2e52a2020-02-19 14:17:18 +0100988 return res
989enddef
990
991def Test_disassemble_dict_member()
992 let instr = execute('disassemble DictMember')
Bram Moolenaar4902ab12020-05-15 19:21:31 +0200993 assert_match('DictMember\_s*' ..
994 'let d = #{item: 1}\_s*' ..
995 '\d PUSHS "item"\_s*' ..
996 '\d PUSHNR 1\_s*' ..
997 '\d NEWDICT size 1\_s*' ..
998 '\d STORE $0\_s*' ..
999 'let res = d.item\_s*' ..
1000 '\d\+ LOAD $0\_s*' ..
1001 '\d\+ MEMBER item\_s*' ..
1002 '\d\+ STORE $1\_s*' ..
1003 'res = d\["item"\]\_s*' ..
1004 '\d\+ LOAD $0\_s*' ..
1005 '\d\+ PUSHS "item"\_s*' ..
1006 '\d\+ MEMBER\_s*' ..
1007 '\d\+ STORE $1\_s*',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001008 instr)
Bram Moolenaaree2e52a2020-02-19 14:17:18 +01001009 call assert_equal(1, DictMember())
1010enddef
1011
1012def NegateNumber(): number
1013 let nr = 9
1014 let plus = +nr
1015 let res = -nr
1016 return res
1017enddef
1018
1019def Test_disassemble_negate_number()
1020 let instr = execute('disassemble NegateNumber')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001021 assert_match('NegateNumber\_s*' ..
1022 'let nr = 9\_s*' ..
1023 '\d STORE 9 in $0\_s*' ..
1024 'let plus = +nr\_s*' ..
1025 '\d LOAD $0\_s*' ..
1026 '\d CHECKNR\_s*' ..
1027 '\d STORE $1\_s*' ..
1028 'let res = -nr\_s*' ..
1029 '\d LOAD $0\_s*' ..
1030 '\d NEGATENR\_s*' ..
1031 '\d STORE $2\_s*',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001032 instr)
Bram Moolenaaree2e52a2020-02-19 14:17:18 +01001033 call assert_equal(-9, NegateNumber())
1034enddef
1035
1036def InvertBool(): bool
1037 let flag = true
1038 let invert = !flag
1039 let res = !!flag
1040 return res
1041enddef
1042
1043def Test_disassemble_invert_bool()
1044 let instr = execute('disassemble InvertBool')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001045 assert_match('InvertBool\_s*' ..
1046 'let flag = true\_s*' ..
1047 '\d PUSH v:true\_s*' ..
1048 '\d STORE $0\_s*' ..
1049 'let invert = !flag\_s*' ..
1050 '\d LOAD $0\_s*' ..
1051 '\d INVERT (!val)\_s*' ..
1052 '\d STORE $1\_s*' ..
1053 'let res = !!flag\_s*' ..
1054 '\d LOAD $0\_s*' ..
1055 '\d 2BOOL (!!val)\_s*' ..
1056 '\d STORE $2\_s*',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001057 instr)
Bram Moolenaaree2e52a2020-02-19 14:17:18 +01001058 call assert_equal(true, InvertBool())
1059enddef
1060
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001061def Test_disassemble_compare()
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001062 let cases = [
Bram Moolenaara5565e42020-05-09 15:44:01 +02001063 ['true == isFalse', 'COMPAREBOOL =='],
1064 ['true != isFalse', 'COMPAREBOOL !='],
1065 ['v:none == isNull', 'COMPARESPECIAL =='],
1066 ['v:none != isNull', 'COMPARESPECIAL !='],
Bram Moolenaar675f7162020-04-12 22:53:54 +02001067
Bram Moolenaara5565e42020-05-09 15:44:01 +02001068 ['111 == aNumber', 'COMPARENR =='],
1069 ['111 != aNumber', 'COMPARENR !='],
1070 ['111 > aNumber', 'COMPARENR >'],
1071 ['111 < aNumber', 'COMPARENR <'],
1072 ['111 >= aNumber', 'COMPARENR >='],
1073 ['111 <= aNumber', 'COMPARENR <='],
1074 ['111 =~ aNumber', 'COMPARENR =\~'],
1075 ['111 !~ aNumber', 'COMPARENR !\~'],
Bram Moolenaar675f7162020-04-12 22:53:54 +02001076
Bram Moolenaara5565e42020-05-09 15:44:01 +02001077 ['"xx" != aString', 'COMPARESTRING !='],
1078 ['"xx" > aString', 'COMPARESTRING >'],
1079 ['"xx" < aString', 'COMPARESTRING <'],
1080 ['"xx" >= aString', 'COMPARESTRING >='],
1081 ['"xx" <= aString', 'COMPARESTRING <='],
1082 ['"xx" =~ aString', 'COMPARESTRING =\~'],
1083 ['"xx" !~ aString', 'COMPARESTRING !\~'],
1084 ['"xx" is aString', 'COMPARESTRING is'],
1085 ['"xx" isnot aString', 'COMPARESTRING isnot'],
Bram Moolenaar675f7162020-04-12 22:53:54 +02001086
Bram Moolenaara5565e42020-05-09 15:44:01 +02001087 ['0z11 == aBlob', 'COMPAREBLOB =='],
1088 ['0z11 != aBlob', 'COMPAREBLOB !='],
1089 ['0z11 is aBlob', 'COMPAREBLOB is'],
1090 ['0z11 isnot aBlob', 'COMPAREBLOB isnot'],
Bram Moolenaar675f7162020-04-12 22:53:54 +02001091
Bram Moolenaara5565e42020-05-09 15:44:01 +02001092 ['[1, 2] == aList', 'COMPARELIST =='],
1093 ['[1, 2] != aList', 'COMPARELIST !='],
1094 ['[1, 2] is aList', 'COMPARELIST is'],
1095 ['[1, 2] isnot aList', 'COMPARELIST isnot'],
Bram Moolenaar675f7162020-04-12 22:53:54 +02001096
Bram Moolenaara5565e42020-05-09 15:44:01 +02001097 ['#{a: 1} == aDict', 'COMPAREDICT =='],
1098 ['#{a: 1} != aDict', 'COMPAREDICT !='],
1099 ['#{a: 1} is aDict', 'COMPAREDICT is'],
1100 ['#{a: 1} isnot aDict', 'COMPAREDICT isnot'],
Bram Moolenaar675f7162020-04-12 22:53:54 +02001101
1102 ['{->33} == {->44}', 'COMPAREFUNC =='],
1103 ['{->33} != {->44}', 'COMPAREFUNC !='],
1104 ['{->33} is {->44}', 'COMPAREFUNC is'],
1105 ['{->33} isnot {->44}', 'COMPAREFUNC isnot'],
1106
1107 ['77 == g:xx', 'COMPAREANY =='],
1108 ['77 != g:xx', 'COMPAREANY !='],
1109 ['77 > g:xx', 'COMPAREANY >'],
1110 ['77 < g:xx', 'COMPAREANY <'],
1111 ['77 >= g:xx', 'COMPAREANY >='],
1112 ['77 <= g:xx', 'COMPAREANY <='],
1113 ['77 =~ g:xx', 'COMPAREANY =\~'],
1114 ['77 !~ g:xx', 'COMPAREANY !\~'],
1115 ['77 is g:xx', 'COMPAREANY is'],
1116 ['77 isnot g:xx', 'COMPAREANY isnot'],
1117 ]
Bram Moolenaara5565e42020-05-09 15:44:01 +02001118 let floatDecl = ''
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001119 if has('float')
1120 cases->extend([
Bram Moolenaara5565e42020-05-09 15:44:01 +02001121 ['1.1 == aFloat', 'COMPAREFLOAT =='],
1122 ['1.1 != aFloat', 'COMPAREFLOAT !='],
1123 ['1.1 > aFloat', 'COMPAREFLOAT >'],
1124 ['1.1 < aFloat', 'COMPAREFLOAT <'],
1125 ['1.1 >= aFloat', 'COMPAREFLOAT >='],
1126 ['1.1 <= aFloat', 'COMPAREFLOAT <='],
1127 ['1.1 =~ aFloat', 'COMPAREFLOAT =\~'],
1128 ['1.1 !~ aFloat', 'COMPAREFLOAT !\~'],
Bram Moolenaar675f7162020-04-12 22:53:54 +02001129 ])
Bram Moolenaara5565e42020-05-09 15:44:01 +02001130 floatDecl = 'let aFloat = 2.2'
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001131 endif
1132
1133 let nr = 1
1134 for case in cases
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001135 # declare local variables to get a non-constant with the right type
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001136 writefile(['def TestCase' .. nr .. '()',
Bram Moolenaara5565e42020-05-09 15:44:01 +02001137 ' let isFalse = false',
1138 ' let isNull = v:null',
1139 ' let aNumber = 222',
1140 ' let aString = "yy"',
1141 ' let aBlob = 0z22',
1142 ' let aList = [3, 4]',
1143 ' let aDict = #{x: 2}',
1144 floatDecl,
Bram Moolenaar675f7162020-04-12 22:53:54 +02001145 ' if ' .. case[0],
1146 ' echo 42'
1147 ' endif',
1148 'enddef'], 'Xdisassemble')
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001149 source Xdisassemble
1150 let instr = execute('disassemble TestCase' .. nr)
Bram Moolenaar675f7162020-04-12 22:53:54 +02001151 assert_match('TestCase' .. nr .. '.*' ..
1152 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*' ..
1153 '\d \(PUSH\|FUNCREF\).*' ..
Bram Moolenaara5565e42020-05-09 15:44:01 +02001154 '\d \(PUSH\|FUNCREF\|LOAD\).*' ..
Bram Moolenaar675f7162020-04-12 22:53:54 +02001155 '\d ' .. case[1] .. '.*' ..
1156 '\d JUMP_IF_FALSE -> \d\+.*',
1157 instr)
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001158
1159 nr += 1
1160 endfor
1161
Bram Moolenaar22da5592020-03-19 14:52:20 +01001162 delete('Xdisassemble')
Bram Moolenaarf2460a32020-02-07 22:09:54 +01001163enddef
1164
Bram Moolenaara4d4cf42020-04-02 13:50:27 +02001165def Test_disassemble_compare_const()
1166 let cases = [
Bram Moolenaar675f7162020-04-12 22:53:54 +02001167 ['"xx" == "yy"', false],
1168 ['"aa" == "aa"', true],
1169 ['has("eval") ? true : false', true],
1170 ['has("asdf") ? true : false', false],
1171 ]
Bram Moolenaara4d4cf42020-04-02 13:50:27 +02001172
1173 let nr = 1
1174 for case in cases
1175 writefile(['def TestCase' .. nr .. '()',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001176 ' if ' .. case[0],
1177 ' echo 42'
1178 ' endif',
1179 'enddef'], 'Xdisassemble')
Bram Moolenaara4d4cf42020-04-02 13:50:27 +02001180 source Xdisassemble
1181 let instr = execute('disassemble TestCase' .. nr)
1182 if case[1]
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001183 # condition true, "echo 42" executed
Bram Moolenaar675f7162020-04-12 22:53:54 +02001184 assert_match('TestCase' .. nr .. '.*' ..
1185 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*' ..
1186 '\d PUSHNR 42.*' ..
1187 '\d ECHO 1.*' ..
1188 '\d PUSHNR 0.*' ..
1189 '\d RETURN.*',
1190 instr)
Bram Moolenaara4d4cf42020-04-02 13:50:27 +02001191 else
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001192 # condition false, function just returns
Bram Moolenaar675f7162020-04-12 22:53:54 +02001193 assert_match('TestCase' .. nr .. '.*' ..
1194 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '[ \n]*' ..
1195 'echo 42[ \n]*' ..
1196 'endif[ \n]*' ..
1197 '\s*\d PUSHNR 0.*' ..
1198 '\d RETURN.*',
1199 instr)
Bram Moolenaara4d4cf42020-04-02 13:50:27 +02001200 endif
1201
1202 nr += 1
1203 endfor
1204
1205 delete('Xdisassemble')
1206enddef
1207
Bram Moolenaarad39c092020-02-26 18:23:43 +01001208def s:Execute()
1209 execute 'help vim9.txt'
1210 let cmd = 'help vim9.txt'
1211 execute cmd
1212 let tag = 'vim9.txt'
1213 execute 'help ' .. tag
1214enddef
1215
1216def Test_disassemble_execute()
1217 let res = execute('disass s:Execute')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001218 assert_match('\<SNR>\d*_Execute\_s*' ..
1219 "execute 'help vim9.txt'\\_s*" ..
1220 '\d PUSHS "help vim9.txt"\_s*' ..
1221 '\d EXECUTE 1\_s*' ..
1222 "let cmd = 'help vim9.txt'\\_s*" ..
1223 '\d PUSHS "help vim9.txt"\_s*' ..
1224 '\d STORE $0\_s*' ..
1225 'execute cmd\_s*' ..
1226 '\d LOAD $0\_s*' ..
1227 '\d EXECUTE 1\_s*' ..
1228 "let tag = 'vim9.txt'\\_s*" ..
1229 '\d PUSHS "vim9.txt"\_s*' ..
1230 '\d STORE $1\_s*' ..
1231 "execute 'help ' .. tag\\_s*" ..
1232 '\d\+ PUSHS "help "\_s*' ..
1233 '\d\+ LOAD $1\_s*' ..
1234 '\d\+ CONCAT\_s*' ..
1235 '\d\+ EXECUTE 1\_s*' ..
1236 '\d\+ PUSHNR 0\_s*' ..
1237 '\d\+ RETURN',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001238 res)
Bram Moolenaarad39c092020-02-26 18:23:43 +01001239enddef
1240
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001241def s:Echomsg()
1242 echomsg 'some' 'message'
1243 echoerr 'went' .. 'wrong'
1244enddef
1245
1246def Test_disassemble_echomsg()
1247 let res = execute('disass s:Echomsg')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001248 assert_match('\<SNR>\d*_Echomsg\_s*' ..
1249 "echomsg 'some' 'message'\\_s*" ..
1250 '\d PUSHS "some"\_s*' ..
1251 '\d PUSHS "message"\_s*' ..
1252 '\d ECHOMSG 2\_s*' ..
1253 "echoerr 'went' .. 'wrong'\\_s*" ..
1254 '\d PUSHS "wentwrong"\_s*' ..
1255 '\d ECHOERR 1\_s*' ..
1256 '\d PUSHNR 0\_s*' ..
Bram Moolenaarf93c7fe2020-04-23 22:16:53 +02001257 '\d RETURN',
1258 res)
1259enddef
1260
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001261def SomeStringArg(arg: string)
1262 echo arg
1263enddef
1264
1265def SomeAnyArg(arg: any)
1266 echo arg
1267enddef
1268
1269def SomeStringArgAndReturn(arg: string): string
1270 return arg
1271enddef
1272
1273def Test_display_func()
1274 let res1 = execute('function SomeStringArg')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001275 assert_match('.* def SomeStringArg(arg: string)\_s*' ..
1276 '\d *echo arg.*' ..
1277 ' *enddef',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001278 res1)
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001279
1280 let res2 = execute('function SomeAnyArg')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001281 assert_match('.* def SomeAnyArg(arg: any)\_s*' ..
1282 '\d *echo arg\_s*' ..
1283 ' *enddef',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001284 res2)
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001285
1286 let res3 = execute('function SomeStringArgAndReturn')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001287 assert_match('.* def SomeStringArgAndReturn(arg: string): string\_s*' ..
1288 '\d *return arg\_s*' ..
1289 ' *enddef',
Bram Moolenaar675f7162020-04-12 22:53:54 +02001290 res3)
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +01001291enddef
1292
Bram Moolenaar09689a02020-05-09 22:50:08 +02001293def Test_vim9script_forward_func()
1294 let lines =<< trim END
1295 vim9script
1296 def FuncOne(): string
1297 return FuncTwo()
1298 enddef
1299 def FuncTwo(): string
1300 return 'two'
1301 enddef
Bram Moolenaar67979662020-06-20 22:50:47 +02001302 g:res_FuncOne = execute('disass FuncOne')
Bram Moolenaar09689a02020-05-09 22:50:08 +02001303 END
1304 writefile(lines, 'Xdisassemble')
1305 source Xdisassemble
1306
Bram Moolenaarf5be8cd2020-07-17 20:36:00 +02001307 # check that the first function calls the second with DCALL
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001308 assert_match('\<SNR>\d*_FuncOne\_s*' ..
1309 'return FuncTwo()\_s*' ..
1310 '\d DCALL <SNR>\d\+_FuncTwo(argc 0)\_s*' ..
Bram Moolenaar09689a02020-05-09 22:50:08 +02001311 '\d RETURN',
1312 g:res_FuncOne)
1313
1314 delete('Xdisassemble')
1315 unlet g:res_FuncOne
1316enddef
1317
Bram Moolenaar61a89812020-05-07 16:58:17 +02001318def s:ConcatStrings(): string
1319 return 'one' .. 'two' .. 'three'
1320enddef
1321
Bram Moolenaar7d131b02020-05-08 19:10:34 +02001322def s:ComputeConst(): number
1323 return 2 + 3 * 4 / 6 + 7
1324enddef
1325
Bram Moolenaar1c747212020-05-09 18:28:34 +02001326def s:ComputeConstParen(): number
1327 return ((2 + 4) * (8 / 2)) / (3 + 4)
1328enddef
1329
Bram Moolenaar61a89812020-05-07 16:58:17 +02001330def Test_simplify_const_expr()
1331 let res = execute('disass s:ConcatStrings')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001332 assert_match('<SNR>\d*_ConcatStrings\_s*' ..
1333 "return 'one' .. 'two' .. 'three'\\_s*" ..
1334 '\d PUSHS "onetwothree"\_s*' ..
Bram Moolenaar61a89812020-05-07 16:58:17 +02001335 '\d RETURN',
1336 res)
Bram Moolenaar7d131b02020-05-08 19:10:34 +02001337
1338 res = execute('disass s:ComputeConst')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001339 assert_match('<SNR>\d*_ComputeConst\_s*' ..
1340 'return 2 + 3 \* 4 / 6 + 7\_s*' ..
1341 '\d PUSHNR 11\_s*' ..
Bram Moolenaar7d131b02020-05-08 19:10:34 +02001342 '\d RETURN',
1343 res)
Bram Moolenaar1c747212020-05-09 18:28:34 +02001344
1345 res = execute('disass s:ComputeConstParen')
Bram Moolenaar4902ab12020-05-15 19:21:31 +02001346 assert_match('<SNR>\d*_ComputeConstParen\_s*' ..
1347 'return ((2 + 4) \* (8 / 2)) / (3 + 4)\_s*' ..
1348 '\d PUSHNR 3\>\_s*' ..
Bram Moolenaar1c747212020-05-09 18:28:34 +02001349 '\d RETURN',
1350 res)
Bram Moolenaar61a89812020-05-07 16:58:17 +02001351enddef
1352
Bram Moolenaar389df252020-07-09 21:20:47 +02001353def s:CallAppend()
1354 eval "some text"->append(2)
1355enddef
1356
1357def Test_shuffle()
1358 let res = execute('disass s:CallAppend')
1359 assert_match('<SNR>\d*_CallAppend\_s*' ..
1360 'eval "some text"->append(2)\_s*' ..
1361 '\d PUSHS "some text"\_s*' ..
1362 '\d PUSHNR 2\_s*' ..
1363 '\d SHUFFLE 2 up 1\_s*' ..
1364 '\d BCALL append(argc 2)\_s*' ..
1365 '\d DROP\_s*' ..
1366 '\d PUSHNR 0\_s*' ..
1367 '\d RETURN',
1368 res)
1369enddef
1370
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001371" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker