blob: a873c86571569502840cdd7eb64b24f12dde3ef0 [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:')
Bram Moolenaar21456cd2020-02-13 21:29:32 +010026 assert_fails('disass', 'E471:')
27 assert_fails('disass [', 'E475:')
28 assert_fails('disass 234', 'E475:')
29 assert_fails('disass <XX>foo', 'E475:')
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010030
31 let res = execute('disass s:ScriptFuncLoad')
32 assert_match('<SNR>\d*_ScriptFuncLoad.*'
33 \ .. 'buffers.*'
34 \ .. ' EXEC \+buffers.*'
35 \ .. ' LOAD arg\[-1\].*'
36 \ .. ' LOAD $0.*'
37 \ .. ' LOADV v:version.*'
38 \ .. ' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*'
39 \ .. ' LOADG g:globalvar.*'
40 \ .. ' LOADENV $ENVVAR.*'
41 \ .. ' LOADREG @z.*'
42 \, res)
43enddef
44
45def s:ScriptFuncPush()
46 let localbool = true
47 let localspec = v:none
48 let localblob = 0z1234
49 if has('float')
50 let localfloat = 1.234
51 endif
52enddef
53
Bram Moolenaarf2460a32020-02-07 22:09:54 +010054def Test_disassemble_push()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010055 let res = execute('disass s:ScriptFuncPush')
56 assert_match('<SNR>\d*_ScriptFuncPush.*'
57 \ .. 'localbool = true.*'
58 \ .. ' PUSH v:true.*'
59 \ .. 'localspec = v:none.*'
60 \ .. ' PUSH v:none.*'
61 \ .. 'localblob = 0z1234.*'
62 \ .. ' PUSHBLOB 0z1234.*'
63 \, res)
64 if has('float')
65 assert_match('<SNR>\d*_ScriptFuncPush.*'
66 \ .. 'localfloat = 1.234.*'
67 \ .. ' PUSHF 1.234.*'
68 \, res)
69 endif
70enddef
71
72def s:ScriptFuncStore()
73 let localnr = 1
74 localnr = 2
75 let localstr = 'abc'
76 localstr = 'xyz'
77 v:char = 'abc'
78 s:scriptvar = 'sv'
79 g:globalvar = 'gv'
80 &tabstop = 8
81 $ENVVAR = 'ev'
82 @z = 'rv'
83enddef
84
Bram Moolenaarf2460a32020-02-07 22:09:54 +010085def Test_disassemble_store()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +010086 let res = execute('disass s:ScriptFuncStore')
87 assert_match('<SNR>\d*_ScriptFuncStore.*'
88 \ .. 'localnr = 2.*'
89 \ .. ' STORE 2 in $0.*'
90 \ .. 'localstr = ''xyz''.*'
91 \ .. ' STORE $1.*'
92 \ .. 'v:char = ''abc''.*'
93 \ .. 'STOREV v:char.*'
94 \ .. 's:scriptvar = ''sv''.*'
95 \ .. ' STORES s:scriptvar in .*test_vim9_disassemble.vim.*'
96 \ .. 'g:globalvar = ''gv''.*'
97 \ .. ' STOREG g:globalvar.*'
98 \ .. '&tabstop = 8.*'
99 \ .. ' STOREOPT &tabstop.*'
100 \ .. '$ENVVAR = ''ev''.*'
101 \ .. ' STOREENV $ENVVAR.*'
102 \ .. '@z = ''rv''.*'
103 \ .. ' STOREREG @z.*'
104 \, res)
105enddef
106
107def s:ScriptFuncTry()
108 try
109 echo 'yes'
110 catch /fail/
111 echo 'no'
112 finally
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100113 throw 'end'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100114 endtry
115enddef
116
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100117def Test_disassemble_try()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100118 let res = execute('disass s:ScriptFuncTry')
119 assert_match('<SNR>\d*_ScriptFuncTry.*'
120 \ .. 'try.*'
121 \ .. 'TRY catch -> \d\+, finally -> \d\+.*'
122 \ .. 'catch /fail/.*'
123 \ .. ' JUMP -> \d\+.*'
124 \ .. ' PUSH v:exception.*'
125 \ .. ' PUSHS "fail".*'
126 \ .. ' COMPARESTRING =\~.*'
127 \ .. ' JUMP_IF_FALSE -> \d\+.*'
128 \ .. ' CATCH.*'
129 \ .. 'finally.*'
130 \ .. ' PUSHS "end".*'
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100131 \ .. ' THROW.*'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100132 \ .. 'endtry.*'
133 \ .. ' ENDTRY.*'
134 \, res)
135enddef
136
137def s:ScriptFuncNew()
138 let ll = [1, "two", 333]
139 let dd = #{one: 1, two: "val"}
140enddef
141
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100142def Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100143 let res = execute('disass s:ScriptFuncNew')
144 assert_match('<SNR>\d*_ScriptFuncNew.*'
145 \ .. 'let ll = \[1, "two", 333].*'
146 \ .. 'PUSHNR 1.*'
147 \ .. 'PUSHS "two".*'
148 \ .. 'PUSHNR 333.*'
149 \ .. 'NEWLIST size 3.*'
150 \ .. 'let dd = #{one: 1, two: "val"}.*'
151 \ .. 'PUSHS "one".*'
152 \ .. 'PUSHNR 1.*'
153 \ .. 'PUSHS "two".*'
154 \ .. 'PUSHS "val".*'
155 \ .. 'NEWDICT size 2.*'
156 \, res)
157enddef
158
159def FuncWithArg(arg)
160 echo arg
161enddef
162
163func UserFunc()
164 echo 'nothing'
165endfunc
166
167func UserFuncWithArg(arg)
168 echo a:arg
169endfunc
170
171def s:ScriptFuncCall(): string
172 changenr()
173 char2nr("abc")
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100174 Test_disassemble_new()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100175 FuncWithArg(343)
176 ScriptFuncNew()
177 s:ScriptFuncNew()
178 UserFunc()
179 UserFuncWithArg("foo")
180 let FuncRef = function("UserFunc")
181 FuncRef()
182 let FuncRefWithArg = function("UserFuncWithArg")
183 FuncRefWithArg("bar")
184 return "yes"
185enddef
186
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100187def Test_disassemble_call()
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100188 let res = execute('disass s:ScriptFuncCall')
189 assert_match('<SNR>\d\+_ScriptFuncCall.*'
190 \ .. 'changenr().*'
191 \ .. ' BCALL changenr(argc 0).*'
192 \ .. 'char2nr("abc").*'
193 \ .. ' PUSHS "abc".*'
194 \ .. ' BCALL char2nr(argc 1).*'
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100195 \ .. 'Test_disassemble_new().*'
196 \ .. ' DCALL Test_disassemble_new(argc 0).*'
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100197 \ .. 'FuncWithArg(343).*'
198 \ .. ' PUSHNR 343.*'
199 \ .. ' DCALL FuncWithArg(argc 1).*'
200 \ .. 'ScriptFuncNew().*'
201 \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
202 \ .. 's:ScriptFuncNew().*'
203 \ .. ' DCALL <SNR>\d\+_ScriptFuncNew(argc 0).*'
204 \ .. 'UserFunc().*'
205 \ .. ' UCALL UserFunc(argc 0).*'
206 \ .. 'UserFuncWithArg("foo").*'
207 \ .. ' PUSHS "foo".*'
208 \ .. ' UCALL UserFuncWithArg(argc 1).*'
209 \ .. 'let FuncRef = function("UserFunc").*'
210 \ .. 'FuncRef().*'
211 \ .. ' LOAD $\d.*'
212 \ .. ' PCALL (argc 0).*'
213 \ .. 'let FuncRefWithArg = function("UserFuncWithArg").*'
214 \ .. 'FuncRefWithArg("bar").*'
215 \ .. ' PUSHS "bar".*'
216 \ .. ' LOAD $\d.*'
217 \ .. ' PCALL (argc 1).*'
218 \ .. 'return "yes".*'
219 \ .. ' PUSHS "yes".*'
220 \ .. ' RETURN.*'
221 \, res)
222enddef
223
Bram Moolenaar158906c2020-02-06 20:39:45 +0100224def HasEval()
225 if has("eval")
226 echo "yes"
227 else
228 echo "no"
229 endif
230enddef
231
232def HasNothing()
233 if has("nothing")
234 echo "yes"
235 else
236 echo "no"
237 endif
238enddef
239
240def HasSomething()
241 if has("nothing")
242 echo "nothing"
243 elseif has("something")
244 echo "something"
245 elseif has("eval")
246 echo "eval"
247 elseif has("less")
248 echo "less"
249 endif
250enddef
251
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100252def Test_disassemble_const_expr()
Bram Moolenaar158906c2020-02-06 20:39:45 +0100253 assert_equal("\nyes", execute('call HasEval()'))
254 let instr = execute('disassemble HasEval')
255 assert_match('HasEval.*'
256 \ .. 'if has("eval").*'
257 \ .. ' PUSHS "yes".*'
258 \, instr)
259 assert_notmatch('JUMP', instr)
260
261 assert_equal("\nno", execute('call HasNothing()'))
262 instr = execute('disassemble HasNothing')
263 assert_match('HasNothing.*'
264 \ .. 'if has("nothing").*'
265 \ .. 'else.*'
266 \ .. ' PUSHS "no".*'
267 \, instr)
268 assert_notmatch('PUSHS "yes"', instr)
269 assert_notmatch('JUMP', instr)
270
271 assert_equal("\neval", execute('call HasSomething()'))
272 instr = execute('disassemble HasSomething')
273 assert_match('HasSomething.*'
274 \ .. 'if has("nothing").*'
275 \ .. 'elseif has("something").*'
276 \ .. 'elseif has("eval").*'
277 \ .. ' PUSHS "eval".*'
278 \ .. 'elseif has("less").*'
279 \, instr)
280 assert_notmatch('PUSHS "nothing"', instr)
281 assert_notmatch('PUSHS "something"', instr)
282 assert_notmatch('PUSHS "less"', instr)
283 assert_notmatch('JUMP', instr)
284enddef
285
Bram Moolenaar777770f2020-02-06 21:27:08 +0100286def WithLambda(): string
287 let F = {a -> "X" .. a .. "X"}
288 return F("x")
289enddef
290
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100291def Test_disassemble_lambda()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100292 assert_equal("XxX", WithLambda())
293 let instr = execute('disassemble WithLambda')
294 assert_match('WithLambda.*'
295 \ .. 'let F = {a -> "X" .. a .. "X"}.*'
296 \ .. ' FUNCREF <lambda>\d\+.*'
297 \ .. 'PUSHS "x".*'
298 \ .. ' LOAD $0.*'
299 \ .. ' PCALL (argc 1).*'
300 \ .. ' CHECKTYPE string stack\[-1].*'
301 \, instr)
302enddef
303
304def AndOr(arg): string
305 if arg == 1 && arg != 2 || arg == 4
306 return 'yes'
307 endif
308 return 'no'
309enddef
310
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100311def Test_disassemble_and_or()
Bram Moolenaar777770f2020-02-06 21:27:08 +0100312 assert_equal("yes", AndOr(1))
313 assert_equal("no", AndOr(2))
314 assert_equal("yes", AndOr(4))
315 let instr = execute('disassemble AndOr')
316 assert_match('AndOr.*'
317 \ .. 'if arg == 1 && arg != 2 || arg == 4.*'
318 \ .. '\d LOAD arg\[-1].*'
319 \ .. '\d PUSHNR 1.*'
320 \ .. '\d COMPAREANY ==.*'
321 \ .. '\d JUMP_AND_KEEP_IF_FALSE -> \d\+.*'
322 \ .. '\d LOAD arg\[-1].*'
323 \ .. '\d PUSHNR 2.*'
324 \ .. '\d COMPAREANY !=.*'
325 \ .. '\d JUMP_AND_KEEP_IF_TRUE -> \d\+.*'
326 \ .. '\d LOAD arg\[-1].*'
327 \ .. '\d PUSHNR 4.*'
328 \ .. '\d COMPAREANY ==.*'
329 \ .. '\d JUMP_IF_FALSE -> \d\+.*'
330 \, instr)
331enddef
332
Bram Moolenaar04d05222020-02-06 22:06:54 +0100333def ForLoop(): list<number>
334 let res: list<number>
335 for i in range(3)
336 res->add(i)
337 endfor
338 return res
339enddef
340
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100341def Test_disassemble_for_loop()
Bram Moolenaar04d05222020-02-06 22:06:54 +0100342 assert_equal([0, 1, 2], ForLoop())
343 let instr = execute('disassemble ForLoop')
344 assert_match('ForLoop.*'
345 \ .. 'let res: list<number>.*'
346 \ .. ' NEWLIST size 0.*'
347 \ .. '\d STORE $0.*'
348 \ .. 'for i in range(3).*'
349 \ .. '\d STORE -1 in $1.*'
350 \ .. '\d PUSHNR 3.*'
351 \ .. '\d BCALL range(argc 1).*'
352 \ .. '\d FOR $1 -> \d\+.*'
353 \ .. '\d STORE $2.*'
354 \ .. 'res->add(i).*'
355 \ .. '\d LOAD $0.*'
356 \ .. '\d LOAD $2.*'
357 \ .. '\d BCALL add(argc 2).*'
358 \ .. '\d DROP.*'
359 \ .. 'endfor.*'
360 \ .. '\d JUMP -> \d\+.*'
361 \ .. '\d DROP.*'
362 \, instr)
363enddef
364
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100365let g:number = 42
366
367def Computing()
368 let nr = 3
369 let nrres = nr + 7
370 nrres = nr - 7
371 nrres = nr * 7
372 nrres = nr / 7
373 nrres = nr % 7
374
375 let anyres = g:number + 7
376 anyres = g:number - 7
377 anyres = g:number * 7
378 anyres = g:number / 7
379 anyres = g:number % 7
380
381 if has('float')
382 let fl = 3.0
383 let flres = fl + 7.0
384 flres = fl - 7.0
385 flres = fl * 7.0
386 flres = fl / 7.0
387 endif
388enddef
389
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100390def Test_disassemble_computing()
Bram Moolenaarc2a4b352020-02-06 22:41:16 +0100391 let instr = execute('disassemble Computing')
392 assert_match('Computing.*'
393 \ .. 'let nr = 3.*'
394 \ .. '\d STORE 3 in $0.*'
395 \ .. 'let nrres = nr + 7.*'
396 \ .. '\d LOAD $0.*'
397 \ .. '\d PUSHNR 7.*'
398 \ .. '\d OPNR +.*'
399 \ .. '\d STORE $1.*'
400 \ .. 'nrres = nr - 7.*'
401 \ .. '\d OPNR -.*'
402 \ .. 'nrres = nr \* 7.*'
403 \ .. '\d OPNR \*.*'
404 \ .. 'nrres = nr / 7.*'
405 \ .. '\d OPNR /.*'
406 \ .. 'nrres = nr % 7.*'
407 \ .. '\d OPNR %.*'
408 \ .. 'let anyres = g:number + 7.*'
409 \ .. '\d LOADG g:number.*'
410 \ .. '\d PUSHNR 7.*'
411 \ .. '\d OPANY +.*'
412 \ .. '\d STORE $2.*'
413 \ .. 'anyres = g:number - 7.*'
414 \ .. '\d OPANY -.*'
415 \ .. 'anyres = g:number \* 7.*'
416 \ .. '\d OPANY \*.*'
417 \ .. 'anyres = g:number / 7.*'
418 \ .. '\d OPANY /.*'
419 \ .. 'anyres = g:number % 7.*'
420 \ .. '\d OPANY %.*'
421 \, instr)
422 if has('float')
423 assert_match('Computing.*'
424 \ .. 'let fl = 3.0.*'
425 \ .. '\d PUSHF 3.0.*'
426 \ .. '\d STORE $3.*'
427 \ .. 'let flres = fl + 7.0.*'
428 \ .. '\d LOAD $3.*'
429 \ .. '\d PUSHF 7.0.*'
430 \ .. '\d OPFLOAT +.*'
431 \ .. '\d STORE $4.*'
432 \ .. 'flres = fl - 7.0.*'
433 \ .. '\d OPFLOAT -.*'
434 \ .. 'flres = fl \* 7.0.*'
435 \ .. '\d OPFLOAT \*.*'
436 \ .. 'flres = fl / 7.0.*'
437 \ .. '\d OPFLOAT /.*'
438 \, instr)
439 endif
440enddef
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100441
Bram Moolenaarf2460a32020-02-07 22:09:54 +0100442def Test_disassemble_compare()
443 " TODO: COMPAREFUNC
444 let cases = [
445 \ ['true == false', 'COMPAREBOOL =='],
446 \ ['true != false', 'COMPAREBOOL !='],
447 \ ['v:none == v:null', 'COMPARESPECIAL =='],
448 \ ['v:none != v:null', 'COMPARESPECIAL !='],
449 \
450 \ ['111 == 222', 'COMPARENR =='],
451 \ ['111 != 222', 'COMPARENR !='],
452 \ ['111 > 222', 'COMPARENR >'],
453 \ ['111 < 222', 'COMPARENR <'],
454 \ ['111 >= 222', 'COMPARENR >='],
455 \ ['111 <= 222', 'COMPARENR <='],
456 \ ['111 =~ 222', 'COMPARENR =\~'],
457 \ ['111 !~ 222', 'COMPARENR !\~'],
458 \
459 \ ['"xx" == "yy"', 'COMPARESTRING =='],
460 \ ['"xx" != "yy"', 'COMPARESTRING !='],
461 \ ['"xx" > "yy"', 'COMPARESTRING >'],
462 \ ['"xx" < "yy"', 'COMPARESTRING <'],
463 \ ['"xx" >= "yy"', 'COMPARESTRING >='],
464 \ ['"xx" <= "yy"', 'COMPARESTRING <='],
465 \ ['"xx" =~ "yy"', 'COMPARESTRING =\~'],
466 \ ['"xx" !~ "yy"', 'COMPARESTRING !\~'],
467 \ ['"xx" is "yy"', 'COMPARESTRING is'],
468 \ ['"xx" isnot "yy"', 'COMPARESTRING isnot'],
469 \
470 \ ['0z11 == 0z22', 'COMPAREBLOB =='],
471 \ ['0z11 != 0z22', 'COMPAREBLOB !='],
472 \ ['0z11 is 0z22', 'COMPAREBLOB is'],
473 \ ['0z11 isnot 0z22', 'COMPAREBLOB isnot'],
474 \
475 \ ['[1,2] == [3,4]', 'COMPARELIST =='],
476 \ ['[1,2] != [3,4]', 'COMPARELIST !='],
477 \ ['[1,2] is [3,4]', 'COMPARELIST is'],
478 \ ['[1,2] isnot [3,4]', 'COMPARELIST isnot'],
479 \
480 \ ['#{a:1} == #{x:2}', 'COMPAREDICT =='],
481 \ ['#{a:1} != #{x:2}', 'COMPAREDICT !='],
482 \ ['#{a:1} is #{x:2}', 'COMPAREDICT is'],
483 \ ['#{a:1} isnot #{x:2}', 'COMPAREDICT isnot'],
484 \
485 \ ['{->33} == {->44}', 'COMPAREPARTIAL =='],
486 \ ['{->33} != {->44}', 'COMPAREPARTIAL !='],
487 \ ['{->33} is {->44}', 'COMPAREPARTIAL is'],
488 \ ['{->33} isnot {->44}', 'COMPAREPARTIAL isnot'],
489 \
490 \ ['77 == g:xx', 'COMPAREANY =='],
491 \ ['77 != g:xx', 'COMPAREANY !='],
492 \ ['77 > g:xx', 'COMPAREANY >'],
493 \ ['77 < g:xx', 'COMPAREANY <'],
494 \ ['77 >= g:xx', 'COMPAREANY >='],
495 \ ['77 <= g:xx', 'COMPAREANY <='],
496 \ ['77 =~ g:xx', 'COMPAREANY =\~'],
497 \ ['77 !~ g:xx', 'COMPAREANY !\~'],
498 \ ['77 is g:xx', 'COMPAREANY is'],
499 \ ['77 isnot g:xx', 'COMPAREANY isnot'],
500 \ ]
501 if has('float')
502 cases->extend([
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 \ ['1.1 >= 2.2', 'COMPAREFLOAT >='],
508 \ ['1.1 <= 2.2', 'COMPAREFLOAT <='],
509 \ ['1.1 =~ 2.2', 'COMPAREFLOAT =\~'],
510 \ ['1.1 !~ 2.2', 'COMPAREFLOAT !\~'],
511 \ ])
512 endif
513
514 let nr = 1
515 for case in cases
516 writefile(['def TestCase' .. nr .. '()',
517 \ ' if ' .. case[0],
518 \ ' echo 42'
519 \ ' endif',
520 \ 'enddef'], 'Xdisassemble')
521 source Xdisassemble
522 let instr = execute('disassemble TestCase' .. nr)
523 assert_match('TestCase' .. nr .. '.*'
524 \ .. 'if ' .. substitute(case[0], '[[~]', '\\\0', 'g') .. '.*'
525 \ .. '\d \(PUSH\|FUNCREF\).*'
526 \ .. '\d \(PUSH\|FUNCREF\|LOADG\).*'
527 \ .. '\d ' .. case[1] .. '.*'
528 \ .. '\d JUMP_IF_FALSE -> \d\+.*'
529 \, instr)
530
531 nr += 1
532 endfor
533
534 " delete('Xdisassemble')
535enddef
536
Bram Moolenaar5cab73f2020-02-06 19:25:19 +0100537" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker