2 # Copyright (C) 2001-2009, Parrot Foundation.
7 use lib qw( . lib ../lib ../../lib );
10 use Parrot::Test tests => 97;
14 t/op/calling.t - Parrot Calling Conventions
18 % prove t/op/calling.t
22 Tests Parrot calling conventions.
26 pasm_output_is( <<'CODE', <<'OUTPUT', "set_args - parsing" );
28 set_args "0, 0", P0, I0
38 pasm_output_is( <<'CODE', <<'OUTPUT', "var_args - parsing" );
41 set_args "0, 0", P0, I0
49 get_params "0, 0", P0, I0
62 pasm_output_is( <<'CODE', <<'OUTPUT', "call - i, ic" );
65 set_args "0, 0", 42, I16
71 get_params "0, 0", I16, I17
83 pasm_output_is( <<'CODE', <<'OUTPUT', "call - i, ic, return i, ic" );
86 set_args "0, 0", 42, I16
87 get_results "0, 0", I16, I17
96 get_params "0, 0", I16, I17
102 set_returns "0, 0", 99, I16
112 pasm_output_is( <<'CODE', <<'OUTPUT', "call - i, ic, return i, ic - adjust sig" );
115 set_args "0, 0", 42, I16
116 get_results "0, 0", I16, I17
125 get_params "0, 0", I16, I17
131 set_returns "0, 0", 99, I16
141 pasm_output_is( <<'CODE', <<'OUTPUT', "all together now" );
148 set_args "0, 0, 0, 0, 0, 0, 0", 42, I16, 4.5, N16, S16, "ok 2\n", P16
149 get_results "0, 0, 0, 0", I16, N16, S16, P16
160 get_params "0, 0, 0, 0, 0, 0, 0", I16, I17, N16, N17, S16, S17, P16
178 set_returns "0, 0, 0, 0", I16, N16, S16, P16
194 pasm_output_is( <<'CODE', <<'OUTPUT', "flatten arg" );
198 new P17, 'ResizablePMCArray'
204 set_args "0, 0x20, 0", P16, P17, P18
210 get_params "0, 0, 0, 0, 0", P1, P2, P3, P4, P5
226 pasm_output_is( <<'CODE', <<'OUTPUT', "slurpy param" );
234 set_args "0, 0, 0", P16, P17, P18
240 get_params "0, 0x20", P1, P2
258 pir_output_is( <<'CODE', <<'OUTPUT', "use it in PIR" );
263 # set_args and invoke must be adjacent
275 pasm_output_is( <<'CODE', <<'OUTPUT', "flatten + slurpy param" );
279 new P19, 'ResizablePMCArray'
286 new P20, 'ResizablePMCArray'
295 set_args "0, 0x20, 0x20, 0", P16, P19, P20, P21
301 get_params "0, 0x20", P1, P2
332 pir_output_is( <<'CODE', <<'OUTPUT', "use it in PIR" );
337 # set_args and invoke must be adjacent
349 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - autobox" );
354 # set_args and invoke must be adjacent
355 set_args "0,0,0", $P0, 42, "bar"
359 get_params "0x20", $P0
374 pir_output_is( <<'CODE', <<'OUTPUT', "more autobox" );
376 foo( 101, 0.77, 'seven and seven is' )
381 .param pmc some_float
382 .param pmc some_string
384 $S0 = typeof some_int
388 $S0 = typeof some_float
392 $S0 = typeof some_string
404 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - fetch" );
414 find_name $P10, "foo"
415 # set_args and invoke must be adjacent
416 set_args "0,0,0,0", $P0, $P1, $P2, $P3
420 get_params "0,0,0,0", $P0, $I0, $S0, $N0
435 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too few" );
437 .include "errors.pasm"
438 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
446 get_params "0,0", $P0, $P1
450 /too few positional arguments/
454 <<'CODE', <<'OUTPUT', "argc mismatch, too many - no getparams", todo => 'no get_params at all' );
456 .include "errors.pasm"
457 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
464 /too many arguments passed/
467 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too many - force get_params" );
472 .include "errors.pasm"
473 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
481 /too many positional arguments/
484 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too many" );
486 .include "errors.pasm"
487 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
491 set_args "0,0", $P0, 77
499 /too many positional arguments/
502 pir_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too many - catch exception" );
504 .include "errors.pasm"
505 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
509 set_args "0,0", $P0, 77
523 # print "\nexception type: "
527 /^caught: too many positional arguments/
530 pir_output_is( <<'CODE', <<'OUTPUT', "argc mismatch, optional" );
532 .include "errors.pasm"
533 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
541 get_params "0,0x80,0x100", $P0, $P1, $I0
553 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, optional" );
555 .include "errors.pasm"
556 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
558 ar = new 'ResizableIntegerArray'
568 .param int j :optional
569 .param int got_j :opt_flag
570 .param int k :optional
571 .param int got_k :opt_flag
574 /too many positional arguments/
577 pasm_output_is( <<'CODE', <<'OUTPUT', "get_param later" );
580 set_args "0, 0", 42, I16
581 get_results "0, 0", I16, I17
591 get_params "0, 0", I16, I17
597 set_returns "4, 0", 99, I16
607 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 1" );
609 .const 'Sub' f = "foo"
616 .const 'Sub' b = "bar"
622 set_returns "0", "bar_ret\n"
632 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 2 - pass arg" );
634 .const 'Sub' f = "foo"
641 .const 'Sub' b = "bar"
643 set_args "0", "from_foo\n"
650 set_returns "0", "bar_ret\n"
661 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 3 - pass arg" );
663 .const 'Sub' f = "foo"
670 .const 'Sub' b = "bar"
672 set_args "0", "from_foo\n"
679 set_returns "0", "bar_ret\n"
690 pir_output_is( <<'CODE', <<'OUTPUT', "empty args" );
699 get_params "0x80, 0x100", $P1, $I0
709 pir_output_is( <<'CODE', <<'OUTPUT', "optional args" );
718 get_params "0x80, 0x100", $P1, $I0
728 pir_output_is( <<'CODE', <<'OUTPUT', "pir uses no ops" );
736 get_params "0, 0", $I16, $I17
750 pir_output_is( <<'CODE', <<'OUTPUT', "pir call evaled code" );
754 s .= ".param int i\n"
755 s .= ".param int j\n"
759 s .= "print \"\\n\"\n"
776 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 4 - pir calls" );
778 .const 'Sub' f = "foo"
784 .const 'Sub' b = "bar"
786 .tailcall b("from_foo\n")
792 .return ("bar_ret\n")
802 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - native" );
804 foo_int(42, "42", 42.20)
805 foo_float(42, "42", 42.20)
806 foo_string(42, "42", 42.20)
809 get_params "0,0,0", $I0, $I1, $I2
818 get_params "0,0,0", $N0, $N1, $N2
827 get_params "0,0,0", $S0, $S1, $S2
841 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - PIR const" );
842 .const int MYCONST = -2
848 .param string str1 :optional
849 .param int has_s :opt_flag
857 pir_output_is( <<'CODE', <<'OUTPUT', "optional args, :opt_flag" );
865 .param pmc p1 :optional
866 .param int i1 :opt_flag
880 pir_output_is( <<'CODE', <<'OUTPUT', "optional multiple :opt_flag" );
884 foo($P0, "ok 2\n", "ok 3\n")
887 .param pmc p1 :optional
888 .param int i1 :opt_flag
889 .param pmc p2 :optional
890 .param int i2 :opt_flag
891 .param pmc p3 :optional
892 .param int i3 :opt_flag
893 .param pmc p4 :optional
894 .param int i4 :opt_flag
922 pir_output_is( <<'CODE', <<'OUTPUT', "optional returns, void ret" );
929 .get_result $P0 :optional
930 .get_result $I0 :opt_flag
943 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 5 - arg/param conflict" );
967 .tailcall bar($P0, a, b)
981 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing" );
987 f = get_global ["Foo"], "bar"
990 f = get_global ["Foo"], "baz"
1006 .sub get_string :vtable :method
1017 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing - 2" );
1029 .sub get_string :vtable :method
1035 .sub get_string_keyed_int :vtable :method
1049 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing - 3" );
1059 .return (arg) # force conversion to string
1062 .sub get_string :vtable :method
1073 # see also tcl in leo-ctx5 by Coke; Date 28.08.2005
1074 pir_output_is( <<'CODE', <<'OUTPUT', "bug - :slurpy promotes to :flatten" );
1084 .param pmc p :slurpy
1100 pir_output_is( <<'CODE', <<'OUTPUT', "call :slurpy with :flat" );
1102 .param pmc rest_arg :slurpy
1110 ## normal flattening direct call, non-slurpy returns
1111 $P35 = _fn1($P34 :flat)
1118 pir_output_is( <<'CODE', <<'OUTPUT', "call with :flat in the middle" );
1134 $P30 = new 'Integer'
1136 $P31 = new 'Integer'
1143 $P35 = _fn1(1, $P34 :flat, $I4)
1149 pir_output_is( <<'CODE', <<'OUTPUT', "right number of args via :flat" );
1165 .include "errors.pasm"
1166 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1167 $P30 = new 'Integer'
1169 $P31 = new 'Integer'
1176 $P35 = _fn1(1, $P34 :flat)
1182 pir_error_output_like( <<'CODE', <<'OUTPUT', "too many args via :flat" );
1198 .include "errors.pasm"
1199 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1200 $P30 = new 'Integer'
1202 $P31 = new 'Integer'
1210 $P35 = _fn1(1, $P34 :flat)
1213 /too many positional arguments: 5 passed, 4 expected/
1216 pir_error_output_like( <<'CODE', <<'OUTPUT', "too few args via :flat" );
1232 .include "errors.pasm"
1233 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1234 $P30 = new 'Integer'
1236 $P31 = new 'Integer'
1242 $P35 = _fn1(1, $P34 :flat)
1245 /too few positional arguments: 3 passed, 4 \(or more\) expected/
1248 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall to NCI" );
1269 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall to NCI - 2" );
1271 $P0 = eval("print \"Foo!\\n\"")
1278 code = ".sub main :main :anon\n" . code
1279 code = code . "\n.end\n"
1287 # bug - repeated calls to eval'd sub crashes (pmichaud, 2005.10.27)
1288 pir_output_is( <<'CODE', <<'OUTPUT', "repeated calls to eval'd sub" );
1292 s = ".namespace [ \"XYZ\" ]\n"
1294 s .= " .param int n\n"
1295 s .= " $I0 = n % 1000\n"
1296 s .= " if $I0 goto end\n"
1298 s .= " print \"\\n\"\n"
1303 outer = get_global ["XYZ"], "outer"
1307 if $I1 > 10000 goto end
1325 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall - overlapping Ix" );
1333 .const 'Sub' b = "bar"
1336 set_args "0,0", $I1, $I0
1340 get_params "0,0", $I0, $I1
1347 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall - optional not set" );
1353 .const 'Sub' b = "bar"
1359 .param int c :optional
1360 .param int has_c :opt_flag
1365 unless has_c goto no_c
1378 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall - optional set" );
1384 .const 'Sub' b = "bar"
1385 .tailcall b(10, 20, 30)
1390 .param int c :optional
1391 .param int has_c :opt_flag
1396 unless has_c goto no_c
1409 my @todo = ( todo => 'broken with JIT (TT #983)' )
1410 if ( defined $ENV{TEST_PROG_ARGS} and
1411 $ENV{TEST_PROG_ARGS} =~ /--runcore=jit/ );
1412 pir_output_is( <<'CODE', <<'OUTPUT', "clone_key_arg", @todo );
1420 cl = newclass "MyClass"
1427 .namespace ["MyClass"]
1429 # key arguments in register have to be expanded into their
1430 # values because in the called sub frame the original refered
1431 # registers just don't exist #' for vim
1433 .sub set_integer_keyed :vtable :method
1436 print key # print first key
1438 key = shift key # get next key
1451 pir_output_is( <<'CODE', <<'OUTPUT', "result_info op" );
1455 ($I1, $I2, $I3) = test()
1471 pir_output_is( <<'CODE', <<'OUTPUT', "result_info op with eval" );
1485 ($I1, $I2, $I3) = test()
1493 pir_output_is( <<'CODE', <<'OUTPUT', ":slurpy result" );
1495 ($P0 :slurpy) = foo()
1502 .return("ok 1\n", "ok 2\n")
1509 pir_output_is( <<'CODE', <<'OUTPUT', ":optional result" );
1511 ($S0 :optional, $I1 :opt_flag) = foo()
1512 unless $I1 goto no_ret
1527 pir_output_is( <<'CODE', <<'OUTPUT', ":optional result" );
1529 ($S0 :optional, $I1 :opt_flag) = foo()
1543 pir_output_is( <<'CODE', <<'OUTPUT', "set_args via continuation -> results" );
1545 .local string result
1546 result = foo("ok 1\n")
1553 .include 'interpinfo.pasm'
1554 cc = interpinfo .INTERPINFO_CURRENT_CONT
1569 pir_output_is( <<'CODE', <<'OUTPUT', "set_args via explicit continuation" );
1571 .local string result
1572 result = "not ok 2\n"
1574 cont = new 'Continuation'
1575 set_addr cont, cont_dest
1579 .get_results (result)
1594 # this is a regression test for a bug in which tail-calling without set_args
1595 # used the args of the sub.
1596 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall explicit continuation, no args" );
1598 .local string result
1599 result = "not ok 2\n"
1601 cont = new 'Continuation'
1602 set_addr cont, cont_dest
1620 pir_output_is( <<'CODE', <<'OUTPUT', "newclosure followed by tailcall" );
1621 ## regression test for newclosure followed by tailcall, which used to recycle
1622 ## the context too soon. it looks awful because (a) the original version was
1623 ## produced by a compiler, and (b) in order to detect regression, we must force
1624 ## parrot to reuse the context, which seems to requires having other calls that
1625 ## use particular numbers of registers (and probably a fair amount of luck).
1628 .lex "MAIN-CONT", $P41
1630 $P41 = new 'Continuation'
1634 get_results '0', $P45
1640 .const 'Sub' $P49 = "___internal_main_test_"
1641 newclosure $P48, $P49
1642 .tailcall _try_it($I42, $P48)
1645 .sub ___internal_main_test_ :outer('_main')
1648 find_lex $P41, "MAIN-CONT"
1650 if arg1 != 3 goto L3
1653 $P57 = mul $P58, $P59
1654 set_args '(0)', $P57
1686 pir_output_is( <<'CODE', <<'OUTPUT', "call evaled vtable code" );
1693 .sub get_integer_keyed_int :vtable :method
1700 comp = compreg "PIR"
1711 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 1" );
1713 set_args "0x200, 0, 0x200, 0", "b", 10, "a", 20
1720 get_params "0x200, 0, 0x200, 0", "a", I0, "b", I1
1731 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 2 flatten" );
1736 set_args "0x220", P0 # :flatten :named
1743 get_params "0x200, 0, 0x200, 0", "a", I0, "b", I1
1754 pir_output_is( <<'CODE', <<'OUTPUT', "named - 3 slurpy hash PIR" );
1756 foo('a' => 10 , 'b' => 20, 'c' => 30)
1761 .param int a :named('a')
1762 .param pmc bar :slurpy :named
1784 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 3 slurpy hash" );
1786 set_args "0x200, 0, 0x200, 0,0x200, 0", "a", 10, "b", 20, 'c', 30
1793 get_params "0x200, 0, 0x220", "a", I0, P0
1815 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 4 positional -> named" );
1817 set_args "0, 0, 0", 10, 20, 30
1824 get_params "0x200, 0, 0x200, 0, 0x200, 0", "a", I0, "b", I1, 'c', I2
1837 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 5 slurpy array -> named" );
1839 set_args "0, 0, 0, 0x200, 0, 0x200, 0", 10, 20, 30, 'a', 40, 'b', 50
1846 get_params "0, 0x20, 0x200, 0, 0x200, 0", I0, P0, "b", I1, "a", I2
1865 pir_output_is( <<'CODE', <<'OUTPUT', ":optional followed by :slurpy (empty)" );
1870 .param pmc arg1 :optional
1871 .param pmc rest_arg :slurpy
1881 pir_output_is( <<'CODE', <<'OUTPUT', ":optional followed by :slurpy (used)" );
1883 _write_thing(3, 4, 5)
1886 .param pmc arg1 :optional
1887 .param pmc rest_arg :slurpy
1898 pir_output_is( <<'CODE', <<'OUTPUT', ":named(\"...\") syntax for .param and sub call" );
1900 foo( 10 :named("b"), 20 :named("a"))
1906 .param int c :named("a")
1907 .param int d :named("b")
1921 pir_output_is( <<'CODE', <<'OUTPUT', ":named(\"...\") syntax for the 4 kind" );
1923 ($I0 :named("b"), $I1 :named("a")) = foo( 10 :named("b"), 20 :named("a"))
1934 .param int c :named("a")
1935 .param int d :named("b")
1942 .return ( 10 :named("a"), 20 :named("b"))
1951 pir_output_is( <<'CODE', <<'OUTPUT', " 'foo' => 10 syntax for function call" );
1953 foo ('a'=>20,'b'=>10)
1960 .param int c :named("a")
1961 .param int d :named("b")
1975 pir_error_output_like( <<'CODE', <<'OUTPUT', "named => pos passing" );
1977 foo( "b" => 10 , "a" => 20)
1987 /too few positional/
1990 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - set" );
1992 foo ('a'=>20,'b'=>10)
1997 .param int d :named('b')
1998 .param int c :named('a') :optional
2009 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - set, :opt_flag" );
2011 foo ('a'=>20,'b'=>10)
2016 .param int d :named('b') :optional
2017 .param int has_d :opt_flag
2018 .param int c :named('a') :optional
2019 .param int has_c :opt_flag
2034 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - mix" );
2036 foo ('a'=>20,'b'=>10)
2044 .param int d :named('b') :optional
2045 .param int has_d :opt_flag
2046 .param int c :named('a') :optional
2047 .param int has_c :opt_flag
2065 pir_output_is( <<'CODE', <<'OUTPUT', "named flat/slurpy" );
2071 foo( h :named :flat )
2077 .param pmc h :named :slurpy
2090 pir_error_output_like( <<'CODE', <<'OUTPUT', "param .. 'a' => v :named('foo')" );
2092 foo( "b" => 10, "a" => 20)
2098 .param int c :named("foo") :named("bar")
2102 /Named parameter with more than one name/
2105 pir_output_is( <<'CODE', <<'OUTPUT', "default value for an unused :optional" );
2114 .param int var :optional
2121 pir_error_output_like( <<'CODE', qr/too few named arguments/, "argc mismatch - missing named" );
2123 .include "errors.pasm"
2124 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2130 .param int d :named('b')
2131 .param int c :named('a')
2139 pir_error_output_like( <<'CODE', qr/too few named arguments/, "argc mismatch - missing named" );
2141 .include "errors.pasm"
2142 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2148 .param int d :named('b')
2149 .param int c :named('a')
2157 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - too many named" );
2159 .include "errors.pasm"
2160 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2161 foo ('a'=>10, 'b'=>20, 'c'=>30)
2166 .param int d :named('b')
2167 .param int c :named('a')
2177 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - duplicate named" );
2179 .include "errors.pasm"
2180 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2181 foo ('a'=>10, 'b'=>20, 'a'=>30)
2186 .param int d :named('b')
2187 .param int c :named('a')
2197 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named after slurpy array" );
2201 $P0 = new 'ResizablePMCArray'
2203 foo($P0 :flat, 'abc' => 3)
2204 $P0 = new 'ResizablePMCArray'
2205 foo($P0 :flat, 'abc' => 4)
2209 .param pmc array :slurpy
2210 .param pmc hash :slurpy :named
2223 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named loses :flat arg (#39044)" );
2229 foo(0, 1, $P0 :flat :named)
2233 .param pmc array :slurpy
2234 .param pmc hash :slurpy :named
2235 $I0 = elements array
2252 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named loses :flat arg" );
2258 foo(0, 1, 'z'=>2626, $P0 :flat :named)
2262 .param pmc array :slurpy
2263 .param pmc hash :slurpy :named
2280 pir_error_output_like( <<'CODE', <<'OUTPUT', "unexpected positional arg" );
2282 'foo'('abc', 'def', 'ghi'=>1)
2287 .param pmc args :slurpy :named
2290 /too many positional arguments/
2293 pir_error_output_like( <<'CODE', <<'OUTPUT', "unexpected positional arg" );
2295 'foo'('abc', 'def'=>1, 'ghi', 'jkl'=>1)
2300 .param pmc args :slurpy :named
2303 /named arguments must follow all positional arguments/
2306 pir_output_is( <<'CODE', <<'OUTPUT', "flat/slurpy named arguments" );
2313 bar_only( args :flat :named )
2317 .param string bar :named( 'bar' )
2318 .param pmc args :named :slurpy
2329 <<'CODE', <<'OUTPUT', "Tail call without arguments should not free the context when a closure depends on it" );
2331 $P0 = create_closure_and_run_it()
2334 .sub create_closure_and_run_it
2338 $P2 = get_global "myclosure"
2339 $P1 = newclosure $P2
2340 # There is a closure depending on our current context, so this shouldn't
2345 .sub myclosure :outer(create_closure_and_run_it)
2346 $P1 = find_lex "val"
2349 $P1 = find_lex "val"
2357 # This creates a new binding that is not accessible by the
2358 # caller (myclosure)
2368 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named after :optional" );
2372 $P0 = new 'ResizablePMCArray'
2374 foo($P0 :flat, 'abc' => 3)
2375 $P0 = new 'ResizablePMCArray'
2376 foo($P0 :flat, 'abc' => 4)
2379 foo($P0 :named :flat)
2383 .param pmc val :optional
2384 .param int has_val :opt_flag
2385 .param pmc hash :slurpy :named
2399 pir_output_is( <<'CODE', <<'OUTPUT', "named optional after :optional" );
2405 'foo'($P0 :named('y'))
2409 .param pmc x :optional
2410 .param int has_x :opt_flag
2411 .param pmc y :optional :named('y')
2412 .param int has_y :opt_flag
2413 if has_y goto have_y
2425 pir_error_output_like( <<'CODE', <<'OUTPUT', "arg mismatch with no params", todo=> 'TT #1033' );
2433 /too many arguments passed\(1\) - 0 params expected/
2436 # See Rakudo queue http://rt.perl.org/rt3/Ticket/Display.html?id=62730
2437 pir_output_is( <<'CODE', <<'OUTPUT', "named from register, not constant" );
2440 example('foo' => 42) # normal named parameter
2441 example( $S0 => 42) # parameter named by non-const register
2442 just_a_string( $S0, 'foo' => 42 ) # nameyness should not stick on register
2446 .param pmc foo :named('foo')
2450 .sub 'just_a_string'
2452 .param int baz :named( 'foo' )
2463 # See Rakudo queue http://rt.perl.org/rt3/Ticket/Display.html?id=62730
2464 pir_output_is( <<'CODE', <<'OUTPUT', "Handling :flat of emtpy arguments" );
2473 .param pmc arg :slurpy
2483 pir_output_is( <<'CODE', <<'OUTPUT', "Tailcall from vtable" );
2486 $P1 = newclass "Foo"
2489 ## Should return 2, but doesn't.
2497 .sub elements :vtable
2500 .tailcall identity($I1)
2513 # cperl-indent-level: 4
2516 # vim: expandtab shiftwidth=4: