blob: 95cd2894fe20ef80b6d0a39c3d7e027c22014750 [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'
11
12def s:ScriptFuncLoad(arg: string)
13 let local = 1
14 buffers
15 echo arg
16 echo local
17 echo v:version
18 echo s:scriptvar
19 echo g:globalvar
20 echo &tabstop
21 echo $ENVVAR
22 echo @z
23enddef
24
Bram Moolenaarf2460a32020-02-07 22:09:54 +010025def Test_disassemble_load()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010026 assert_fails('disass NoFunc', 'E1061:')
27 assert_fails('disass NotCompiled', 'E1062:')
Bram Moolenaar21456cd2020-02-13 21:29:32 +010028 assert_fails('disass', 'E471:')
29 assert_fails('disass [', 'E475:')
30 assert_fails('disass 234', 'E475:')
31 assert_fails('disass <XX>foo', 'E475:')
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010032
33 let res = execute('disass s:ScriptFuncLoad')
34 assert_match('<SNR>\d*_ScriptFuncLoad.*'
35 \ .. 'buffers.*'
36 \ .. ' EXEC \+buffers.*'
37 \ .. ' LOAD arg\[-1\].*'
38 \ .. ' LOAD $0.*'
39 \ .. ' LOADV v:version.*'
40 \ .. ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*'
41 \ .. ' LOADG g:globalvar.*'
42 \ .. ' LOADENV $ENVVAR.*'
43 \ .. ' LOADREG @z.*'
44 \, res)
45enddef
46
47def s:ScriptFuncPush()
48 let localbool = true
49 let localspec = v:none
50 let localblob = 0z1234
51 if has('float')
52 let localfloat = 1.234
53 endif
54enddef
55
Bram Moolenaarf2460a32020-02-07 22:09:54 +010056def Test_disassemble_push()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010057 let res = execute('disass s:ScriptFuncPush')
58 assert_match('<SNR>\d*_ScriptFuncPush.*'
59 \ .. 'localbool = true.*'
60 \ .. ' PUSH v:true.*'
61 \ .. 'localspec = v:none.*'
62 \ .. ' PUSH v:none.*'
63 \ .. 'localblob = 0z1234.*'
64 \ .. ' PUSHBLOB 0z1234.*'
65 \, res)
66 if has('float')
67 assert_match('<SNR>\d*_ScriptFuncPush.*'
68 \ .. 'localfloat = 1.234.*'
69 \ .. ' PUSHF 1.234.*'
70 \, res)
71 endif
72enddef
73
74def s:ScriptFuncStore()
75 let localnr = 1
76 localnr = 2
77 let localstr = 'abc'
78 localstr = 'xyz'
79 v:char = 'abc'
80 s:scriptvar = 'sv'
81 g:globalvar = 'gv'
82 &tabstop = 8
83 $ENVVAR = 'ev'
84 @z = 'rv'
85enddef
86
Bram Moolenaarf2460a32020-02-07 22:09:54 +010087def Test_disassemble_store()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010088 let res = execute('disass s:ScriptFuncStore')
89 assert_match('<SNR>\d*_ScriptFuncStore.*'
90 \ .. 'localnr = 2.*'
91 \ .. ' STORE 2 in $0.*'
92 \ .. 'localstr = ''xyz''.*'
93 \ .. ' STORE $1.*'
94 \ .. 'v:char = ''abc''.*'
95 \ .. 'STOREV v:char.*'
96 \ .. 's:scriptvar = ''sv''.*'
97 \ .. ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*'
98 \ .. 'g:globalvar = ''gv''.*'
99 \ .. ' STOREG g:globalvar.*'
100 \ .. '&tabstop = 8.*'
101 \ .. ' STOREOPT &tabstop.*'
102 \ .. '$ENVVAR = ''ev''.*'
103 \ .. ' STOREENV $ENVVAR.*'
104 \ .. '@z = ''rv''.*'
105 \ .. ' STOREREG @z.*'
106 \, res)
107enddef
108
109def s:ScriptFuncTry()
110 try
111 echo 'yes'
112 catch /fail/
113 echo 'no'
114 finally
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100115 throw 'end'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100116 endtry
117enddef
118
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100119def Test_disassemble_try()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100120 let res = execute('disass s:ScriptFuncTry')
121 assert_match('<SNR>\d*_ScriptFuncTry.*'
122 \ .. 'try.*'
123 \ .. 'TRY catch -> \d\+, finally -> \d\+.*'
124 \ .. 'catch /fail/.*'
125 \ .. ' JUMP -> \d\+.*'
126 \ .. ' PUSH v:exception.*'
127 \ .. ' PUSHS "fail".*'
128 \ .. ' COMPARESTRING =\~.*'
129 \ .. ' JUMP_IF_FALSE -> \d\+.*'
130 \ .. ' CATCH.*'
131 \ .. 'finally.*'
132 \ .. ' PUSHS "end".*'
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100133 \ .. ' THROW.*'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100134 \ .. 'endtry.*'
135 \ .. ' ENDTRY.*'
136 \, res)
137enddef
138
139def s:ScriptFuncNew()
140 let ll = [1, "two", 333]
141 let dd = #{one: 1, two: "val"}
142enddef
143
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100144def Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100145 let res = execute('disass s:ScriptFuncNew')
146 assert_match('<SNR>\d*_ScriptFuncNew.*'
147 \ .. 'let ll = \[1, "two", 333].*'
148 \ .. 'PUSHNR 1.*'
149 \ .. 'PUSHS "two".*'
150 \ .. 'PUSHNR 333.*'
151 \ .. 'NEWLIST size 3.*'
152 \ .. 'let dd = #{one: 1, two: "val"}.*'
153 \ .. 'PUSHS "one".*'
154 \ .. 'PUSHNR 1.*'
155 \ .. 'PUSHS "two".*'
156 \ .. 'PUSHS "val".*'
157 \ .. 'NEWDICT size 2.*'
158 \, res)
159enddef
160
161def FuncWithArg(arg)
162 echo arg
163enddef
164
165func UserFunc()
166 echo 'nothing'
167endfunc
168
169func UserFuncWithArg(arg)
170 echo a:arg
171endfunc
172
173def s:ScriptFuncCall(): string
174 changenr()
175 char2nr("abc")
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100176 Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100177 FuncWithArg(343)
178 ScriptFuncNew()
179 s:ScriptFuncNew()
180 UserFunc()
181 UserFuncWithArg("foo")
182 let FuncRef = function("UserFunc")
183 FuncRef()
184 let FuncRefWithArg = function("UserFuncWithArg")
185 FuncRefWithArg("bar")
186 return "yes"
187enddef
188
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100189def Test_disassemble_call()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100190 let res = execute('disass s:ScriptFuncCall')
191 assert_match('<SNR>\d\+_ScriptFuncCall.*'
192 \ .. 'changenr().*'
193 \ .. ' BCALL changenr(argc 0).*'
194 \ .. 'char2nr("abc").*'
195 \ .. ' PUSHS "abc".*'
196 \ .. ' BCALL char2nr(argc 1).*'
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100197 \ .. 'Test_disassemble_new().*'
198 \ .. ' DCALL Test_disassemble_new(argc 0).*'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100199 \ .. 'FuncWithArg(343).*'
200 \ .. ' PUSHNR 343.*'
201 \ .. ' DCALL FuncWithArg(argc 1).*'
202 \ .. 'ScriptFuncNew().*'
203 \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
204 \ .. 's:ScriptFuncNew().*'
205 \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
206 \ .. 'UserFunc().*'
207 \ .. ' UCALL UserFunc(argc 0).*'
208 \ .. 'UserFuncWithArg("foo").*'
209 \ .. ' PUSHS "foo".*'
210 \ .. ' UCALL UserFuncWithArg(argc 1).*'
211 \ .. 'let FuncRef = function("UserFunc").*'
212 \ .. 'FuncRef().*'
213 \ .. ' LOAD $\d.*'
214 \ .. ' PCALL (argc 0).*'
215 \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*'
216 \ .. 'FuncRefWithArg("bar").*'
217 \ .. ' PUSHS "bar".*'
218 \ .. ' LOAD $\d.*'
219 \ .. ' PCALL (argc 1).*'
220 \ .. 'return "yes".*'
221 \ .. ' PUSHS "yes".*'
222 \ .. ' RETURN.*'
223 \, res)
224enddef
225
Bram Moolenaar8ed04582020-02-22 19:07:28 +0100226
Bram Moolenaarbd5da372020-03-31 23:13:10 +0200227def EchoArg(arg: string): string
228 return arg
229enddef
230def RefThis(): func
231 return function('EchoArg')
232enddef
233def s:ScriptPCall()
234 RefThis()("text")
235enddef
236
237def Test_disassemble_pcall()
238 let res = execute('disass s:ScriptPCall')
239 assert_match('<SNR>\d\+_ScriptPCall.*'
240 \ .. 'RefThis()("text").*'
241 \ .. '\d DCALL RefThis(argc 0).*'
242 \ .. '\d PUSHS "text".*'
243 \ .. '\d PCALL top (argc 1).*'
244 \ .. '\d PCALL end.*'
245 \ .. '\d DROP.*'
246 \ .. '\d PUSHNR 0.*'
247 \ .. '\d RETURN.*'
248 \, res)
249enddef
250
251
Bram Moolenaar7eeefd42020-02-26 21:24:23 +0100252def FuncWithForwardCall(): string
253 return DefinedLater("yes")
254enddef
255
256def DefinedLater(arg: string): string
257 return arg
258enddef
259
260def Test_disassemble_update_instr()
261 let res = execute('disass FuncWithForwardCall')
262 assert_match('FuncWithForwardCall.*'
263 \ .. 'return DefinedLater("yes").*'
264 \ .. '\d PUSHS "yes".*'
265 \ .. '\d UCALL DefinedLater(argc 1).*'
266 \ .. '\d CHECKTYPE string stack\[-1].*'
267 \ .. '\d RETURN.*'
268 \, res)
269
270 " Calling the function will change UCALL into the faster DCALL
271 assert_equal('yes', FuncWithForwardCall())
272
273 res = execute('disass FuncWithForwardCall')
274 assert_match('FuncWithForwardCall.*'
275 \ .. 'return DefinedLater("yes").*'
276 \ .. '\d PUSHS "yes".*'
277 \ .. '\d DCALL DefinedLater(argc 1).*'
278 \ .. '\d CHECKTYPE string stack\[-1].*'
279 \ .. '\d RETURN.*'
280 \, res)
281enddef
282
283
Bram Moolenaar8ed04582020-02-22 19:07:28 +0100284def FuncWithDefault(arg: string = 'default'): string
285 return arg
286enddef
287
288def Test_disassemble_call_default()
289 let res = execute('disass FuncWithDefault')
290 assert_match('FuncWithDefault.*'
291 \ .. '\d PUSHS "default".*'
292 \ .. '\d STORE arg\[-1].*'
293 \ .. 'return arg.*'
294 \ .. '\d LOAD arg\[-1].*'
295 \ .. '\d RETURN.*'
296 \, res)
297enddef
298
299
Bram Moolenaar158906c2020-02-06 20:39:45 +0100300def HasEval()
301 if has("eval")
302 echo "yes"
303 else
304 echo "no"
305 endif
306enddef
307
308def HasNothing()
309 if has("nothing")
310 echo "yes"
311 else
312 echo "no"
313 endif
314enddef
315
316def HasSomething()
317 if has("nothing")
318 echo "nothing"
319 elseif has("something")
320 echo "something"
321 elseif has("eval")
322 echo "eval"
323 elseif has("less")
324 echo "less"
325 endif
326enddef
327
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100328def Test_disassemble_const_expr()
Bram Moolenaar158906c2020-02-06 20:39:45 +0100329 assert_equal("\nyes", execute('call HasEval()'))
330 let instr = execute('disassemble HasEval')
331 assert_match('HasEval.*'
332 \ .. 'if has("eval").*'
333 \ .. ' PUSHS "yes".*'
334 \, instr)
335 assert_notmatch('JUMP', instr)
336
337 assert_equal("\nno", execute('call HasNothing()'))
338 instr = execute('disassemble HasNothing')
339 assert_match('HasNothing.*'
340 \ .. 'if has("nothing").*'
341 \ .. 'else.*'
342 \ .. ' PUSHS "no".*'
343 \, instr)
344 assert_notmatch('PUSHS "yes"', instr)
345 assert_notmatch('JUMP', instr)
346
347 assert_equal("\neval", execute('call HasSomething()'))
348 instr = execute('disassemble HasSomething')
349 assert_match('HasSomething.*'
350 \ .. 'if has("nothing").*'
351 \ .. 'elseif has("something").*'
352 \ .. 'elseif has("eval").*'
353 \ .. ' PUSHS "eval".*'
354 \ .. 'elseif has("less").*'
355 \, instr)
356 assert_notmatch('PUSHS "nothing"', instr)
357 assert_notmatch('PUSHS "something"', instr)
358 assert_notmatch('PUSHS "less"', instr)
359 assert_notmatch('JUMP', instr)
360enddef
361
Bram Moolenaarf51cb4e2020-03-01 17:55:14 +0100362def WithFunc()
363 let funky1: func
364 let funky2: func = function("len")
365 let party1: partial
366 let party2: partial = funcref("UserFunc")
367enddef
368
369def Test_disassemble_function()
370 let instr = execute('disassemble WithFunc')
371 assert_match('WithFunc.*'
372 \ .. 'let funky1: func.*'
373 \ .. '0 PUSHFUNC "\[none]".*'
374 \ .. '1 STORE $0.*'
375 \ .. 'let funky2: func = function("len").*'
376 \ .. '2 PUSHS "len".*'
377 \ .. '3 BCALL function(argc 1).*'
378 \ .. '4 STORE $1.*'
379 \ .. 'let party1: partial.*'
380 \ .. '5 PUSHPARTIAL "\[none]".*'
381 \ .. '6 STORE $2.*'
382 \ .. 'let party2: partial = funcref("UserFunc").*'
383 \ .. '7 PUSHS "UserFunc".*'
384 \ .. '8 BCALL funcref(argc 1).*'
385 \ .. '9 STORE $3.*'
386 \ .. '10 PUSHNR 0.*'
387 \ .. '11 RETURN.*'
388 \, instr)
389enddef
390
391if has('channel')
392 def WithChannel()
393 let job1: job
394 let job2: job = job_start("donothing")
395 let chan1: channel
396 enddef
397endif
398
399def Test_disassemble_channel()
400 CheckFeature channel
401
402 let instr = execute('disassemble WithChannel')
403 assert_match('WithChannel.*'
404 \ .. 'let job1: job.*'
405 \ .. '\d PUSHJOB "no process".*'
406 \ .. '\d STORE $0.*'
407 \ .. 'let job2: job = job_start("donothing").*'
408 \ .. '\d PUSHS "donothing".*'
409 \ .. '\d BCALL job_start(argc 1).*'
410 \ .. '\d STORE $1.*'
411 \ .. 'let chan1: channel.*'
412 \ .. '\d PUSHCHANNEL 0.*'
413 \ .. '\d STORE $2.*'
414 \ .. '\d PUSHNR 0.*'
415 \ .. '\d RETURN.*'
416 \, instr)
417enddef
418
Bram Moolenaar777770f2020-02-06 21:27:08 +0100419def WithLambda(): string
420 let F = {a -> "X" .. a .. "X"}
421 return F("x")
422enddef
423
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100424def Test_disassemble_lambda()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100425 assert_equal("XxX", WithLambda())
426 let instr = execute('disassemble WithLambda')
427 assert_match('WithLambda.*'
428 \ .. 'let F = {a -> "X" .. a .. "X"}.*'
429 \ .. ' FUNCREF <lambda>\d\+.*'
430 \ .. 'PUSHS "x".*'
431 \ .. ' LOAD $0.*'
432 \ .. ' PCALL (argc 1).*'
433 \ .. ' CHECKTYPE string stack\[-1].*'
434 \, instr)
435enddef
436
437def AndOr(arg): string
438 if arg == 1 && arg != 2 || arg == 4
439 return 'yes'
440 endif
441 return 'no'
442enddef
443
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100444def Test_disassemble_and_or()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100445 assert_equal("yes", AndOr(1))
446 assert_equal("no", AndOr(2))
447 assert_equal("yes", AndOr(4))
448 let instr = execute('disassemble AndOr')
449 assert_match('AndOr.*'
450 \ .. 'if arg == 1 && arg != 2 || arg == 4.*'
451 \ .. '\d LOAD arg\[-1].*'
452 \ .. '\d PUSHNR 1.*'
453 \ .. '\d COMPAREANY ==.*'
454 \ .. '\d JUMP_AND_KEEP_IF_FALSE -> \d\+.*'
455 \ .. '\d LOAD arg\[-1].*'
456 \ .. '\d PUSHNR 2.*'
457 \ .. '\d COMPAREANY !=.*'
458 \ .. '\d JUMP_AND_KEEP_IF_TRUE -> \d\+.*'
459 \ .. '\d LOAD arg\[-1].*'
460 \ .. '\d PUSHNR 4.*'
461 \ .. '\d COMPAREANY ==.*'
462 \ .. '\d JUMP_IF_FALSE -> \d\+.*'
463 \, instr)
464enddef
465
Bram Moolenaar04d05222020-02-06 22:06:54 +0100466def ForLoop(): list<number>
467 let res: list<number>
468 for i in range(3)
469 res->add(i)
470 endfor
471 return res
472enddef
473
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100474def Test_disassemble_for_loop()
Bram Moolenaar04d05222020-02-06 22:06:54 +0100475 assert_equal([0, 1, 2], ForLoop())
476 let instr = execute('disassemble ForLoop')
477 assert_match('ForLoop.*'
478 \ .. 'let res: list<number>.*'
479 \ .. ' NEWLIST size 0.*'
480 \ .. '\d STORE $0.*'
481 \ .. 'for i in range(3).*'
482 \ .. '\d STORE -1 in $1.*'
483 \ .. '\d PUSHNR 3.*'
484 \ .. '\d BCALL range(argc 1).*'
485 \ .. '\d FOR $1 -> \d\+.*'
486 \ .. '\d STORE $2.*'
487 \ .. 'res->add(i).*'
488 \ .. '\d LOAD $0.*'
489 \ .. '\d LOAD $2.*'
490 \ .. '\d BCALL add(argc 2).*'
491 \ .. '\d DROP.*'
492 \ .. 'endfor.*'
493 \ .. '\d JUMP -> \d\+.*'
494 \ .. '\d DROP.*'
495 \, instr)
496enddef
497
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100498let g:number = 42
499
500def Computing()
501 let nr = 3
502 let nrres = nr + 7
503 nrres = nr - 7
504 nrres = nr * 7
505 nrres = nr / 7
506 nrres = nr % 7
507
508 let anyres = g:number + 7
509 anyres = g:number - 7
510 anyres = g:number * 7
511 anyres = g:number / 7
512 anyres = g:number % 7
513
514 if has('float')
515 let fl = 3.0
516 let flres = fl + 7.0
517 flres = fl - 7.0
518 flres = fl * 7.0
519 flres = fl / 7.0
520 endif
521enddef
522
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100523def Test_disassemble_computing()
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100524 let instr = execute('disassemble Computing')
525 assert_match('Computing.*'
526 \ .. 'let nr = 3.*'
527 \ .. '\d STORE 3 in $0.*'
528 \ .. 'let nrres = nr + 7.*'
529 \ .. '\d LOAD $0.*'
530 \ .. '\d PUSHNR 7.*'
531 \ .. '\d OPNR +.*'
532 \ .. '\d STORE $1.*'
533 \ .. 'nrres = nr - 7.*'
534 \ .. '\d OPNR -.*'
535 \ .. 'nrres = nr \* 7.*'
536 \ .. '\d OPNR \*.*'
537 \ .. 'nrres = nr / 7.*'
538 \ .. '\d OPNR /.*'
539 \ .. 'nrres = nr % 7.*'
540 \ .. '\d OPNR %.*'
541 \ .. 'let anyres = g:number + 7.*'
542 \ .. '\d LOADG g:number.*'
543 \ .. '\d PUSHNR 7.*'
544 \ .. '\d OPANY +.*'
545 \ .. '\d STORE $2.*'
546 \ .. 'anyres = g:number - 7.*'
547 \ .. '\d OPANY -.*'
548 \ .. 'anyres = g:number \* 7.*'
549 \ .. '\d OPANY \*.*'
550 \ .. 'anyres = g:number / 7.*'
551 \ .. '\d OPANY /.*'
552 \ .. 'anyres = g:number % 7.*'
553 \ .. '\d OPANY %.*'
554 \, instr)
555 if has('float')
556 assert_match('Computing.*'
557 \ .. 'let fl = 3.0.*'
558 \ .. '\d PUSHF 3.0.*'
559 \ .. '\d STORE $3.*'
560 \ .. 'let flres = fl + 7.0.*'
561 \ .. '\d LOAD $3.*'
562 \ .. '\d PUSHF 7.0.*'
563 \ .. '\d OPFLOAT +.*'
564 \ .. '\d STORE $4.*'
565 \ .. 'flres = fl - 7.0.*'
566 \ .. '\d OPFLOAT -.*'
567 \ .. 'flres = fl \* 7.0.*'
568 \ .. '\d OPFLOAT \*.*'
569 \ .. 'flres = fl / 7.0.*'
570 \ .. '\d OPFLOAT /.*'
571 \, instr)
572 endif
573enddef
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100574
Bram Moolenaaree2e52a2020-02-19 14:17:18 +0100575def AddListBlob()
576 let reslist = [1, 2] + [3, 4]
577 let resblob = 0z1122 + 0z3344
578enddef
579
580def Test_disassemble_add_list_blob()
581 let instr = execute('disassemble AddListBlob')
582 assert_match('AddListBlob.*'
583 \ .. 'let reslist = \[1, 2] + \[3, 4].*'
584 \ .. '\d PUSHNR 1.*'
585 \ .. '\d PUSHNR 2.*'
586 \ .. '\d NEWLIST size 2.*'
587 \ .. '\d PUSHNR 3.*'
588 \ .. '\d PUSHNR 4.*'
589 \ .. '\d NEWLIST size 2.*'
590 \ .. '\d ADDLIST.*'
591 \ .. '\d STORE $.*.*'
592 \ .. 'let resblob = 0z1122 + 0z3344.*'
593 \ .. '\d PUSHBLOB 0z1122.*'
594 \ .. '\d PUSHBLOB 0z3344.*'
595 \ .. '\d ADDBLOB.*'
596 \ .. '\d STORE $.*'
597 \, instr)
598enddef
599
600let g:aa = 'aa'
601def ConcatString(): string
602 let res = g:aa .. "bb"
603 return res
604enddef
605
606def Test_disassemble_concat()
607 let instr = execute('disassemble ConcatString')
608 assert_match('ConcatString.*'
609 \ .. 'let res = g:aa .. "bb".*'
610 \ .. '\d LOADG g:aa.*'
611 \ .. '\d PUSHS "bb".*'
612 \ .. '\d 2STRING stack\[-2].*'
613 \ .. '\d CONCAT.*'
614 \ .. '\d STORE $.*'
615 \, instr)
616 assert_equal('aabb', ConcatString())
617enddef
618
619def ListIndex(): number
620 let l = [1, 2, 3]
621 let res = l[1]
622 return res
623enddef
624
625def Test_disassemble_list_index()
626 let instr = execute('disassemble ListIndex')
627 assert_match('ListIndex.*'
628 \ .. 'let l = \[1, 2, 3].*'
629 \ .. '\d PUSHNR 1.*'
630 \ .. '\d PUSHNR 2.*'
631 \ .. '\d PUSHNR 3.*'
632 \ .. '\d NEWLIST size 3.*'
633 \ .. '\d STORE $0.*'
634 \ .. 'let res = l\[1].*'
635 \ .. '\d LOAD $0.*'
636 \ .. '\d PUSHNR 1.*'
637 \ .. '\d INDEX.*'
638 \ .. '\d STORE $1.*'
639 \, instr)
640 assert_equal(2, ListIndex())
641enddef
642
643def DictMember(): number
644 let d = #{item: 1}
645 let res = d.item
646 return res
647enddef
648
649def Test_disassemble_dict_member()
650 let instr = execute('disassemble DictMember')
651 assert_match('DictMember.*'
652 \ .. 'let d = #{item: 1}.*'
653 \ .. '\d PUSHS "item".*'
654 \ .. '\d PUSHNR 1.*'
655 \ .. '\d NEWDICT size 1.*'
656 \ .. '\d STORE $0.*'
657 \ .. 'let res = d.item.*'
658 \ .. '\d LOAD $0.*'
659 \ .. '\d MEMBER item.*'
660 \ .. '\d STORE $1.*'
661 \, instr)
662 call assert_equal(1, DictMember())
663enddef
664
665def NegateNumber(): number
666 let nr = 9
667 let plus = +nr
668 let res = -nr
669 return res
670enddef
671
672def Test_disassemble_negate_number()
673 let instr = execute('disassemble NegateNumber')
674 assert_match('NegateNumber.*'
675 \ .. 'let nr = 9.*'
676 \ .. '\d STORE 9 in $0.*'
677 \ .. 'let plus = +nr.*'
678 \ .. '\d LOAD $0.*'
679 \ .. '\d CHECKNR.*'
680 \ .. '\d STORE $1.*'
681 \ .. 'let res = -nr.*'
682 \ .. '\d LOAD $0.*'
683 \ .. '\d NEGATENR.*'
684 \ .. '\d STORE $2.*'
685 \, instr)
686 call assert_equal(-9, NegateNumber())
687enddef
688
689def InvertBool(): bool
690 let flag = true
691 let invert = !flag
692 let res = !!flag
693 return res
694enddef
695
696def Test_disassemble_invert_bool()
697 let instr = execute('disassemble InvertBool')
698 assert_match('InvertBool.*'
699 \ .. 'let flag = true.*'
700 \ .. '\d PUSH v:true.*'
701 \ .. '\d STORE $0.*'
702 \ .. 'let invert = !flag.*'
703 \ .. '\d LOAD $0.*'
704 \ .. '\d INVERT (!val).*'
705 \ .. '\d STORE $1.*'
706 \ .. 'let res = !!flag.*'
707 \ .. '\d LOAD $0.*'
708 \ .. '\d 2BOOL (!!val).*'
709 \ .. '\d STORE $2.*'
710 \, instr)
711 call assert_equal(true, InvertBool())
712enddef
713
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100714def Test_disassemble_compare()
715 " TODO: COMPAREFUNC
716 let cases = [
717 \ ['true == false', 'COMPAREBOOL =='],
718 \ ['true != false', 'COMPAREBOOL !='],
719 \ ['v:none == v:null', 'COMPARESPECIAL =='],
720 \ ['v:none != v:null', 'COMPARESPECIAL !='],
721 \
722 \ ['111 == 222', 'COMPARENR =='],
723 \ ['111 != 222', 'COMPARENR !='],
724 \ ['111 > 222', 'COMPARENR >'],
725 \ ['111 < 222', 'COMPARENR <'],
726 \ ['111 >= 222', 'COMPARENR >='],
727 \ ['111 <= 222', 'COMPARENR <='],
728 \ ['111 =~ 222', 'COMPARENR =\~'],
729 \ ['111 !~ 222', 'COMPARENR !\~'],
730 \
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100731 \ ['"xx" != "yy"', 'COMPARESTRING !='],
732 \ ['"xx" > "yy"', 'COMPARESTRING >'],
733 \ ['"xx" < "yy"', 'COMPARESTRING <'],
734 \ ['"xx" >= "yy"', 'COMPARESTRING >='],
735 \ ['"xx" <= "yy"', 'COMPARESTRING <='],
736 \ ['"xx" =~ "yy"', 'COMPARESTRING =\~'],
737 \ ['"xx" !~ "yy"', 'COMPARESTRING !\~'],
738 \ ['"xx" is "yy"', 'COMPARESTRING is'],
739 \ ['"xx" isnot "yy"', 'COMPARESTRING isnot'],
740 \
741 \ ['0z11 == 0z22', 'COMPAREBLOB =='],
742 \ ['0z11 != 0z22', 'COMPAREBLOB !='],
743 \ ['0z11 is 0z22', 'COMPAREBLOB is'],
744 \ ['0z11 isnot 0z22', 'COMPAREBLOB isnot'],
745 \
746 \ ['[1,2] == [3,4]', 'COMPARELIST =='],
747 \ ['[1,2] != [3,4]', 'COMPARELIST !='],
748 \ ['[1,2] is [3,4]', 'COMPARELIST is'],
749 \ ['[1,2] isnot [3,4]', 'COMPARELIST isnot'],
750 \
751 \ ['#{a:1} == #{x:2}', 'COMPAREDICT =='],
752 \ ['#{a:1} != #{x:2}', 'COMPAREDICT !='],
753 \ ['#{a:1} is #{x:2}', 'COMPAREDICT is'],
754 \ ['#{a:1} isnot #{x:2}', 'COMPAREDICT isnot'],
755 \
756 \ ['{->33} == {->44}', 'COMPAREPARTIAL =='],
757 \ ['{->33} != {->44}', 'COMPAREPARTIAL !='],
758 \ ['{->33} is {->44}', 'COMPAREPARTIAL is'],
759 \ ['{->33} isnot {->44}', 'COMPAREPARTIAL isnot'],
760 \
761 \ ['77 == g:xx', 'COMPAREANY =='],
762 \ ['77 != g:xx', 'COMPAREANY !='],
763 \ ['77 > g:xx', 'COMPAREANY >'],
764 \ ['77 < g:xx', 'COMPAREANY <'],
765 \ ['77 >= g:xx', 'COMPAREANY >='],
766 \ ['77 <= g:xx', 'COMPAREANY <='],
767 \ ['77 =~ g:xx', 'COMPAREANY =\~'],
768 \ ['77 !~ g:xx', 'COMPAREANY !\~'],
769 \ ['77 is g:xx', 'COMPAREANY is'],
770 \ ['77 isnot g:xx', 'COMPAREANY isnot'],
771 \ ]
772 if has('float')
773 cases->extend([
774 \ ['1.1 == 2.2', 'COMPAREFLOAT =='],
775 \ ['1.1 != 2.2', 'COMPAREFLOAT !='],
776 \ ['1.1 > 2.2', 'COMPAREFLOAT >'],
777 \ ['1.1 < 2.2', 'COMPAREFLOAT <'],
778 \ ['1.1 >= 2.2', 'COMPAREFLOAT >='],
779 \ ['1.1 <= 2.2', 'COMPAREFLOAT <='],
780 \ ['1.1 =~ 2.2', 'COMPAREFLOAT =\~'],
781 \ ['1.1 !~ 2.2', 'COMPAREFLOAT !\~'],
782 \ ])
783 endif
784
785 let nr = 1
786 for case in cases
787 writefile(['def TestCase' .. nr .. '()',
788 \ ' if ' .. case[0],
789 \ ' echo 42'
790 \ ' endif',
791 \ 'enddef'], 'Xdisassemble')
792 source Xdisassemble
793 let instr = execute('disassemble TestCase' .. nr)
794 assert_match('TestCase' .. nr .. '.*'
795 \ .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*'
796 \ .. '\d \(PUSH\|FUNCREF\).*'
797 \ .. '\d \(PUSH\|FUNCREF\|LOADG\).*'
798 \ .. '\d ' .. case[1] .. '.*'
799 \ .. '\d JUMP_IF_FALSE -> \d\+.*'
800 \, instr)
801
802 nr += 1
803 endfor
804
Bram Moolenaar22da5592020-03-19 14:52:20 +0100805 delete('Xdisassemble')
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100806enddef
807
Bram Moolenaara4d4cf42020-04-02 13:50:27 +0200808def Test_disassemble_compare_const()
809 let cases = [
810 \ ['"xx" == "yy"', false],
811 \ ['"aa" == "aa"', true],
812 \ ]
813
814 let nr = 1
815 for case in cases
816 writefile(['def TestCase' .. nr .. '()',
817 \ ' if ' .. case[0],
818 \ ' echo 42'
819 \ ' endif',
820 \ 'enddef'], 'Xdisassemble')
821 source Xdisassemble
822 let instr = execute('disassemble TestCase' .. nr)
823 if case[1]
824 " condition true, "echo 42" executed
825 assert_match('TestCase' .. nr .. '.*'
826 \ .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*'
827 \ .. '\d PUSHNR 42.*'
828 \ .. '\d ECHO 1.*'
829 \ .. '\d PUSHNR 0.*'
830 \ .. '\d RETURN.*'
831 \, instr)
832 else
833 " condition false, function just returns
834 assert_match('TestCase' .. nr .. '.*'
835 \ .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '[ \n]*'
836 \ .. 'echo 42[ \n]*'
837 \ .. 'endif[ \n]*'
838 \ .. '\s*\d PUSHNR 0.*'
839 \ .. '\d RETURN.*'
840 \, instr)
841 endif
842
843 nr += 1
844 endfor
845
846 delete('Xdisassemble')
847enddef
848
Bram Moolenaarad39c092020-02-26 18:23:43 +0100849def s:Execute()
850 execute 'help vim9.txt'
851 let cmd = 'help vim9.txt'
852 execute cmd
853 let tag = 'vim9.txt'
854 execute 'help ' .. tag
855enddef
856
857def Test_disassemble_execute()
858 let res = execute('disass s:Execute')
859 assert_match('\<SNR>\d*_Execute.*'
860 \ .. "execute 'help vim9.txt'.*"
861 \ .. '\d PUSHS "help vim9.txt".*'
862 \ .. '\d EXECUTE 1.*'
863 \ .. "let cmd = 'help vim9.txt'.*"
864 \ .. '\d PUSHS "help vim9.txt".*'
865 \ .. '\d STORE $0.*'
866 \ .. 'execute cmd.*'
867 \ .. '\d LOAD $0.*'
868 \ .. '\d EXECUTE 1.*'
869 \ .. "let tag = 'vim9.txt'.*"
870 \ .. '\d PUSHS "vim9.txt".*'
871 \ .. '\d STORE $1.*'
872 \ .. "execute 'help ' .. tag.*"
873 \ .. '\d PUSHS "help ".*'
874 \ .. '\d LOAD $1.*'
875 \ .. '\d CONCAT.*'
876 \ .. '\d EXECUTE 1.*'
877 \ .. '\d PUSHNR 0.*'
878 \ .. '\d RETURN'
879 \, res)
880enddef
881
Bram Moolenaar61a6d4e2020-03-01 23:32:25 +0100882def SomeStringArg(arg: string)
883 echo arg
884enddef
885
886def SomeAnyArg(arg: any)
887 echo arg
888enddef
889
890def SomeStringArgAndReturn(arg: string): string
891 return arg
892enddef
893
894def Test_display_func()
895 let res1 = execute('function SomeStringArg')
896 assert_match('.* def SomeStringArg(arg: string).*'
897 \ .. ' echo arg.*'
898 \ .. ' enddef'
899 \, res1)
900
901 let res2 = execute('function SomeAnyArg')
902 assert_match('.* def SomeAnyArg(arg: any).*'
903 \ .. ' echo arg.*'
904 \ .. ' enddef'
905 \, res2)
906
907 let res3 = execute('function SomeStringArgAndReturn')
908 assert_match('.* def SomeStringArgAndReturn(arg: string): string.*'
909 \ .. ' return arg.*'
910 \ .. ' enddef'
911 \, res3)
912enddef
913
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100914" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker