blob: d10e74148db500546206b3dfc379649079c4373b [file] [log] [blame]
Bram Moolenaar5cab73f2020-02-06 19:25:19 +01001" Test the :disassemble command, and compilation as a side effect
2
3func NotCompiled()
4 echo "not"
5endfunc
6
7let s:scriptvar = 4
8let g:globalvar = 'g'
9
10def s:ScriptFuncLoad(arg: string)
11 let local = 1
12 buffers
13 echo arg
14 echo local
15 echo v:version
16 echo s:scriptvar
17 echo g:globalvar
18 echo &tabstop
19 echo $ENVVAR
20 echo @z
21enddef
22
Bram Moolenaarf2460a32020-02-07 22:09:54 +010023def Test_disassemble_load()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010024 assert_fails('disass NoFunc', 'E1061:')
25 assert_fails('disass NotCompiled', 'E1062:')
26
27 let res = execute('disass s:ScriptFuncLoad')
28 assert_match('<SNR>\d*_ScriptFuncLoad.*'
29 \ .. 'buffers.*'
30 \ .. ' EXEC \+buffers.*'
31 \ .. ' LOAD arg\[-1\].*'
32 \ .. ' LOAD $0.*'
33 \ .. ' LOADV v:version.*'
34 \ .. ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*'
35 \ .. ' LOADG g:globalvar.*'
36 \ .. ' LOADENV $ENVVAR.*'
37 \ .. ' LOADREG @z.*'
38 \, res)
39enddef
40
41def s:ScriptFuncPush()
42 let localbool = true
43 let localspec = v:none
44 let localblob = 0z1234
45 if has('float')
46 let localfloat = 1.234
47 endif
48enddef
49
Bram Moolenaarf2460a32020-02-07 22:09:54 +010050def Test_disassemble_push()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010051 let res = execute('disass s:ScriptFuncPush')
52 assert_match('<SNR>\d*_ScriptFuncPush.*'
53 \ .. 'localbool = true.*'
54 \ .. ' PUSH v:true.*'
55 \ .. 'localspec = v:none.*'
56 \ .. ' PUSH v:none.*'
57 \ .. 'localblob = 0z1234.*'
58 \ .. ' PUSHBLOB 0z1234.*'
59 \, res)
60 if has('float')
61 assert_match('<SNR>\d*_ScriptFuncPush.*'
62 \ .. 'localfloat = 1.234.*'
63 \ .. ' PUSHF 1.234.*'
64 \, res)
65 endif
66enddef
67
68def s:ScriptFuncStore()
69 let localnr = 1
70 localnr = 2
71 let localstr = 'abc'
72 localstr = 'xyz'
73 v:char = 'abc'
74 s:scriptvar = 'sv'
75 g:globalvar = 'gv'
76 &tabstop = 8
77 $ENVVAR = 'ev'
78 @z = 'rv'
79enddef
80
Bram Moolenaarf2460a32020-02-07 22:09:54 +010081def Test_disassemble_store()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010082 let res = execute('disass s:ScriptFuncStore')
83 assert_match('<SNR>\d*_ScriptFuncStore.*'
84 \ .. 'localnr = 2.*'
85 \ .. ' STORE 2 in $0.*'
86 \ .. 'localstr = ''xyz''.*'
87 \ .. ' STORE $1.*'
88 \ .. 'v:char = ''abc''.*'
89 \ .. 'STOREV v:char.*'
90 \ .. 's:scriptvar = ''sv''.*'
91 \ .. ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*'
92 \ .. 'g:globalvar = ''gv''.*'
93 \ .. ' STOREG g:globalvar.*'
94 \ .. '&tabstop = 8.*'
95 \ .. ' STOREOPT &tabstop.*'
96 \ .. '$ENVVAR = ''ev''.*'
97 \ .. ' STOREENV $ENVVAR.*'
98 \ .. '@z = ''rv''.*'
99 \ .. ' STOREREG @z.*'
100 \, res)
101enddef
102
103def s:ScriptFuncTry()
104 try
105 echo 'yes'
106 catch /fail/
107 echo 'no'
108 finally
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100109 throw 'end'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100110 endtry
111enddef
112
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100113def Test_disassemble_try()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100114 let res = execute('disass s:ScriptFuncTry')
115 assert_match('<SNR>\d*_ScriptFuncTry.*'
116 \ .. 'try.*'
117 \ .. 'TRY catch -> \d\+, finally -> \d\+.*'
118 \ .. 'catch /fail/.*'
119 \ .. ' JUMP -> \d\+.*'
120 \ .. ' PUSH v:exception.*'
121 \ .. ' PUSHS "fail".*'
122 \ .. ' COMPARESTRING =\~.*'
123 \ .. ' JUMP_IF_FALSE -> \d\+.*'
124 \ .. ' CATCH.*'
125 \ .. 'finally.*'
126 \ .. ' PUSHS "end".*'
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100127 \ .. ' THROW.*'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100128 \ .. 'endtry.*'
129 \ .. ' ENDTRY.*'
130 \, res)
131enddef
132
133def s:ScriptFuncNew()
134 let ll = [1, "two", 333]
135 let dd = #{one: 1, two: "val"}
136enddef
137
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100138def Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100139 let res = execute('disass s:ScriptFuncNew')
140 assert_match('<SNR>\d*_ScriptFuncNew.*'
141 \ .. 'let ll = \[1, "two", 333].*'
142 \ .. 'PUSHNR 1.*'
143 \ .. 'PUSHS "two".*'
144 \ .. 'PUSHNR 333.*'
145 \ .. 'NEWLIST size 3.*'
146 \ .. 'let dd = #{one: 1, two: "val"}.*'
147 \ .. 'PUSHS "one".*'
148 \ .. 'PUSHNR 1.*'
149 \ .. 'PUSHS "two".*'
150 \ .. 'PUSHS "val".*'
151 \ .. 'NEWDICT size 2.*'
152 \, res)
153enddef
154
155def FuncWithArg(arg)
156 echo arg
157enddef
158
159func UserFunc()
160 echo 'nothing'
161endfunc
162
163func UserFuncWithArg(arg)
164 echo a:arg
165endfunc
166
167def s:ScriptFuncCall(): string
168 changenr()
169 char2nr("abc")
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100170 Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100171 FuncWithArg(343)
172 ScriptFuncNew()
173 s:ScriptFuncNew()
174 UserFunc()
175 UserFuncWithArg("foo")
176 let FuncRef = function("UserFunc")
177 FuncRef()
178 let FuncRefWithArg = function("UserFuncWithArg")
179 FuncRefWithArg("bar")
180 return "yes"
181enddef
182
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100183def Test_disassemble_call()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100184 let res = execute('disass s:ScriptFuncCall')
185 assert_match('<SNR>\d\+_ScriptFuncCall.*'
186 \ .. 'changenr().*'
187 \ .. ' BCALL changenr(argc 0).*'
188 \ .. 'char2nr("abc").*'
189 \ .. ' PUSHS "abc".*'
190 \ .. ' BCALL char2nr(argc 1).*'
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100191 \ .. 'Test_disassemble_new().*'
192 \ .. ' DCALL Test_disassemble_new(argc 0).*'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100193 \ .. 'FuncWithArg(343).*'
194 \ .. ' PUSHNR 343.*'
195 \ .. ' DCALL FuncWithArg(argc 1).*'
196 \ .. 'ScriptFuncNew().*'
197 \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
198 \ .. 's:ScriptFuncNew().*'
199 \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
200 \ .. 'UserFunc().*'
201 \ .. ' UCALL UserFunc(argc 0).*'
202 \ .. 'UserFuncWithArg("foo").*'
203 \ .. ' PUSHS "foo".*'
204 \ .. ' UCALL UserFuncWithArg(argc 1).*'
205 \ .. 'let FuncRef = function("UserFunc").*'
206 \ .. 'FuncRef().*'
207 \ .. ' LOAD $\d.*'
208 \ .. ' PCALL (argc 0).*'
209 \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*'
210 \ .. 'FuncRefWithArg("bar").*'
211 \ .. ' PUSHS "bar".*'
212 \ .. ' LOAD $\d.*'
213 \ .. ' PCALL (argc 1).*'
214 \ .. 'return "yes".*'
215 \ .. ' PUSHS "yes".*'
216 \ .. ' RETURN.*'
217 \, res)
218enddef
219
Bram Moolenaar158906c2020-02-06 20:39:45 +0100220def HasEval()
221 if has("eval")
222 echo "yes"
223 else
224 echo "no"
225 endif
226enddef
227
228def HasNothing()
229 if has("nothing")
230 echo "yes"
231 else
232 echo "no"
233 endif
234enddef
235
236def HasSomething()
237 if has("nothing")
238 echo "nothing"
239 elseif has("something")
240 echo "something"
241 elseif has("eval")
242 echo "eval"
243 elseif has("less")
244 echo "less"
245 endif
246enddef
247
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100248def Test_disassemble_const_expr()
Bram Moolenaar158906c2020-02-06 20:39:45 +0100249 assert_equal("\nyes", execute('call HasEval()'))
250 let instr = execute('disassemble HasEval')
251 assert_match('HasEval.*'
252 \ .. 'if has("eval").*'
253 \ .. ' PUSHS "yes".*'
254 \, instr)
255 assert_notmatch('JUMP', instr)
256
257 assert_equal("\nno", execute('call HasNothing()'))
258 instr = execute('disassemble HasNothing')
259 assert_match('HasNothing.*'
260 \ .. 'if has("nothing").*'
261 \ .. 'else.*'
262 \ .. ' PUSHS "no".*'
263 \, instr)
264 assert_notmatch('PUSHS "yes"', instr)
265 assert_notmatch('JUMP', instr)
266
267 assert_equal("\neval", execute('call HasSomething()'))
268 instr = execute('disassemble HasSomething')
269 assert_match('HasSomething.*'
270 \ .. 'if has("nothing").*'
271 \ .. 'elseif has("something").*'
272 \ .. 'elseif has("eval").*'
273 \ .. ' PUSHS "eval".*'
274 \ .. 'elseif has("less").*'
275 \, instr)
276 assert_notmatch('PUSHS "nothing"', instr)
277 assert_notmatch('PUSHS "something"', instr)
278 assert_notmatch('PUSHS "less"', instr)
279 assert_notmatch('JUMP', instr)
280enddef
281
Bram Moolenaar777770f2020-02-06 21:27:08 +0100282def WithLambda(): string
283 let F = {a -> "X" .. a .. "X"}
284 return F("x")
285enddef
286
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100287def Test_disassemble_lambda()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100288 assert_equal("XxX", WithLambda())
289 let instr = execute('disassemble WithLambda')
290 assert_match('WithLambda.*'
291 \ .. 'let F = {a -> "X" .. a .. "X"}.*'
292 \ .. ' FUNCREF <lambda>\d\+.*'
293 \ .. 'PUSHS "x".*'
294 \ .. ' LOAD $0.*'
295 \ .. ' PCALL (argc 1).*'
296 \ .. ' CHECKTYPE string stack\[-1].*'
297 \, instr)
298enddef
299
300def AndOr(arg): string
301 if arg == 1 && arg != 2 || arg == 4
302 return 'yes'
303 endif
304 return 'no'
305enddef
306
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100307def Test_disassemble_and_or()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100308 assert_equal("yes", AndOr(1))
309 assert_equal("no", AndOr(2))
310 assert_equal("yes", AndOr(4))
311 let instr = execute('disassemble AndOr')
312 assert_match('AndOr.*'
313 \ .. 'if arg == 1 && arg != 2 || arg == 4.*'
314 \ .. '\d LOAD arg\[-1].*'
315 \ .. '\d PUSHNR 1.*'
316 \ .. '\d COMPAREANY ==.*'
317 \ .. '\d JUMP_AND_KEEP_IF_FALSE -> \d\+.*'
318 \ .. '\d LOAD arg\[-1].*'
319 \ .. '\d PUSHNR 2.*'
320 \ .. '\d COMPAREANY !=.*'
321 \ .. '\d JUMP_AND_KEEP_IF_TRUE -> \d\+.*'
322 \ .. '\d LOAD arg\[-1].*'
323 \ .. '\d PUSHNR 4.*'
324 \ .. '\d COMPAREANY ==.*'
325 \ .. '\d JUMP_IF_FALSE -> \d\+.*'
326 \, instr)
327enddef
328
Bram Moolenaar04d05222020-02-06 22:06:54 +0100329def ForLoop(): list<number>
330 let res: list<number>
331 for i in range(3)
332 res->add(i)
333 endfor
334 return res
335enddef
336
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100337def Test_disassemble_for_loop()
Bram Moolenaar04d05222020-02-06 22:06:54 +0100338 assert_equal([0, 1, 2], ForLoop())
339 let instr = execute('disassemble ForLoop')
340 assert_match('ForLoop.*'
341 \ .. 'let res: list<number>.*'
342 \ .. ' NEWLIST size 0.*'
343 \ .. '\d STORE $0.*'
344 \ .. 'for i in range(3).*'
345 \ .. '\d STORE -1 in $1.*'
346 \ .. '\d PUSHNR 3.*'
347 \ .. '\d BCALL range(argc 1).*'
348 \ .. '\d FOR $1 -> \d\+.*'
349 \ .. '\d STORE $2.*'
350 \ .. 'res->add(i).*'
351 \ .. '\d LOAD $0.*'
352 \ .. '\d LOAD $2.*'
353 \ .. '\d BCALL add(argc 2).*'
354 \ .. '\d DROP.*'
355 \ .. 'endfor.*'
356 \ .. '\d JUMP -> \d\+.*'
357 \ .. '\d DROP.*'
358 \, instr)
359enddef
360
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100361let g:number = 42
362
363def Computing()
364 let nr = 3
365 let nrres = nr + 7
366 nrres = nr - 7
367 nrres = nr * 7
368 nrres = nr / 7
369 nrres = nr % 7
370
371 let anyres = g:number + 7
372 anyres = g:number - 7
373 anyres = g:number * 7
374 anyres = g:number / 7
375 anyres = g:number % 7
376
377 if has('float')
378 let fl = 3.0
379 let flres = fl + 7.0
380 flres = fl - 7.0
381 flres = fl * 7.0
382 flres = fl / 7.0
383 endif
384enddef
385
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100386def Test_disassemble_computing()
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100387 let instr = execute('disassemble Computing')
388 assert_match('Computing.*'
389 \ .. 'let nr = 3.*'
390 \ .. '\d STORE 3 in $0.*'
391 \ .. 'let nrres = nr + 7.*'
392 \ .. '\d LOAD $0.*'
393 \ .. '\d PUSHNR 7.*'
394 \ .. '\d OPNR +.*'
395 \ .. '\d STORE $1.*'
396 \ .. 'nrres = nr - 7.*'
397 \ .. '\d OPNR -.*'
398 \ .. 'nrres = nr \* 7.*'
399 \ .. '\d OPNR \*.*'
400 \ .. 'nrres = nr / 7.*'
401 \ .. '\d OPNR /.*'
402 \ .. 'nrres = nr % 7.*'
403 \ .. '\d OPNR %.*'
404 \ .. 'let anyres = g:number + 7.*'
405 \ .. '\d LOADG g:number.*'
406 \ .. '\d PUSHNR 7.*'
407 \ .. '\d OPANY +.*'
408 \ .. '\d STORE $2.*'
409 \ .. 'anyres = g:number - 7.*'
410 \ .. '\d OPANY -.*'
411 \ .. 'anyres = g:number \* 7.*'
412 \ .. '\d OPANY \*.*'
413 \ .. 'anyres = g:number / 7.*'
414 \ .. '\d OPANY /.*'
415 \ .. 'anyres = g:number % 7.*'
416 \ .. '\d OPANY %.*'
417 \, instr)
418 if has('float')
419 assert_match('Computing.*'
420 \ .. 'let fl = 3.0.*'
421 \ .. '\d PUSHF 3.0.*'
422 \ .. '\d STORE $3.*'
423 \ .. 'let flres = fl + 7.0.*'
424 \ .. '\d LOAD $3.*'
425 \ .. '\d PUSHF 7.0.*'
426 \ .. '\d OPFLOAT +.*'
427 \ .. '\d STORE $4.*'
428 \ .. 'flres = fl - 7.0.*'
429 \ .. '\d OPFLOAT -.*'
430 \ .. 'flres = fl \* 7.0.*'
431 \ .. '\d OPFLOAT \*.*'
432 \ .. 'flres = fl / 7.0.*'
433 \ .. '\d OPFLOAT /.*'
434 \, instr)
435 endif
436enddef
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100437
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100438def Test_disassemble_compare()
439 " TODO: COMPAREFUNC
440 let cases = [
441 \ ['true == false', 'COMPAREBOOL =='],
442 \ ['true != false', 'COMPAREBOOL !='],
443 \ ['v:none == v:null', 'COMPARESPECIAL =='],
444 \ ['v:none != v:null', 'COMPARESPECIAL !='],
445 \
446 \ ['111 == 222', 'COMPARENR =='],
447 \ ['111 != 222', 'COMPARENR !='],
448 \ ['111 > 222', 'COMPARENR >'],
449 \ ['111 < 222', 'COMPARENR <'],
450 \ ['111 >= 222', 'COMPARENR >='],
451 \ ['111 <= 222', 'COMPARENR <='],
452 \ ['111 =~ 222', 'COMPARENR =\~'],
453 \ ['111 !~ 222', 'COMPARENR !\~'],
454 \
455 \ ['"xx" == "yy"', 'COMPARESTRING =='],
456 \ ['"xx" != "yy"', 'COMPARESTRING !='],
457 \ ['"xx" > "yy"', 'COMPARESTRING >'],
458 \ ['"xx" < "yy"', 'COMPARESTRING <'],
459 \ ['"xx" >= "yy"', 'COMPARESTRING >='],
460 \ ['"xx" <= "yy"', 'COMPARESTRING <='],
461 \ ['"xx" =~ "yy"', 'COMPARESTRING =\~'],
462 \ ['"xx" !~ "yy"', 'COMPARESTRING !\~'],
463 \ ['"xx" is "yy"', 'COMPARESTRING is'],
464 \ ['"xx" isnot "yy"', 'COMPARESTRING isnot'],
465 \
466 \ ['0z11 == 0z22', 'COMPAREBLOB =='],
467 \ ['0z11 != 0z22', 'COMPAREBLOB !='],
468 \ ['0z11 is 0z22', 'COMPAREBLOB is'],
469 \ ['0z11 isnot 0z22', 'COMPAREBLOB isnot'],
470 \
471 \ ['[1,2] == [3,4]', 'COMPARELIST =='],
472 \ ['[1,2] != [3,4]', 'COMPARELIST !='],
473 \ ['[1,2] is [3,4]', 'COMPARELIST is'],
474 \ ['[1,2] isnot [3,4]', 'COMPARELIST isnot'],
475 \
476 \ ['#{a:1} == #{x:2}', 'COMPAREDICT =='],
477 \ ['#{a:1} != #{x:2}', 'COMPAREDICT !='],
478 \ ['#{a:1} is #{x:2}', 'COMPAREDICT is'],
479 \ ['#{a:1} isnot #{x:2}', 'COMPAREDICT isnot'],
480 \
481 \ ['{->33} == {->44}', 'COMPAREPARTIAL =='],
482 \ ['{->33} != {->44}', 'COMPAREPARTIAL !='],
483 \ ['{->33} is {->44}', 'COMPAREPARTIAL is'],
484 \ ['{->33} isnot {->44}', 'COMPAREPARTIAL isnot'],
485 \
486 \ ['77 == g:xx', 'COMPAREANY =='],
487 \ ['77 != g:xx', 'COMPAREANY !='],
488 \ ['77 > g:xx', 'COMPAREANY >'],
489 \ ['77 < g:xx', 'COMPAREANY <'],
490 \ ['77 >= g:xx', 'COMPAREANY >='],
491 \ ['77 <= g:xx', 'COMPAREANY <='],
492 \ ['77 =~ g:xx', 'COMPAREANY =\~'],
493 \ ['77 !~ g:xx', 'COMPAREANY !\~'],
494 \ ['77 is g:xx', 'COMPAREANY is'],
495 \ ['77 isnot g:xx', 'COMPAREANY isnot'],
496 \ ]
497 if has('float')
498 cases->extend([
499 \ ['1.1 == 2.2', 'COMPAREFLOAT =='],
500 \ ['1.1 != 2.2', 'COMPAREFLOAT !='],
501 \ ['1.1 > 2.2', 'COMPAREFLOAT >'],
502 \ ['1.1 < 2.2', 'COMPAREFLOAT <'],
503 \ ['1.1 >= 2.2', 'COMPAREFLOAT >='],
504 \ ['1.1 <= 2.2', 'COMPAREFLOAT <='],
505 \ ['1.1 =~ 2.2', 'COMPAREFLOAT =\~'],
506 \ ['1.1 !~ 2.2', 'COMPAREFLOAT !\~'],
507 \ ])
508 endif
509
510 let nr = 1
511 for case in cases
512 writefile(['def TestCase' .. nr .. '()',
513 \ ' if ' .. case[0],
514 \ ' echo 42'
515 \ ' endif',
516 \ 'enddef'], 'Xdisassemble')
517 source Xdisassemble
518 let instr = execute('disassemble TestCase' .. nr)
519 assert_match('TestCase' .. nr .. '.*'
520 \ .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*'
521 \ .. '\d \(PUSH\|FUNCREF\).*'
522 \ .. '\d \(PUSH\|FUNCREF\|LOADG\).*'
523 \ .. '\d ' .. case[1] .. '.*'
524 \ .. '\d JUMP_IF_FALSE -> \d\+.*'
525 \, instr)
526
527 nr += 1
528 endfor
529
530 " delete('Xdisassemble')
531enddef
532
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100533" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker