2 # Copyright (C) 2001-2009, Parrot Foundation.
7 use lib qw( . lib ../lib ../../lib );
10 use Parrot::Test tests => 99;
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
50 get_params "0, 0", P0, I0
64 pasm_output_is( <<'CODE', <<'OUTPUT', "call - i, ic" );
67 set_args "0, 0", 42, I16
73 get_params "0, 0", I16, I17
85 pasm_output_is( <<'CODE', <<'OUTPUT', "call - i, ic, return i, ic" );
88 set_args "0, 0", 42, I16
91 get_results "0, 0", I16, I17
98 get_params "0, 0", I16, I17
104 set_returns "0, 0", 99, I16
114 pasm_output_is( <<'CODE', <<'OUTPUT', "call - i, ic, return i, ic - adjust sig" );
117 set_args "0, 0", 42, I16
120 get_results "0, 0", I16, I17
127 get_params "0, 0", I16, I17
133 set_returns "0, 0", 99, I16
143 pasm_output_is( <<'CODE', <<'OUTPUT', "all together now" );
150 set_args "0, 0, 0, 0, 0, 0, 0", 42, I16, 4.5, N16, S16, "ok 2\n", P16
153 get_results "0, 0, 0, 0", I16, N16, S16, P16
162 get_params "0, 0, 0, 0, 0, 0, 0", I16, I17, N16, N17, S16, S17, P16
180 set_returns "0, 0, 0, 0", I16, N16, S16, P16
196 pasm_output_is( <<'CODE', <<'OUTPUT', "flatten arg" );
200 new P17, 'ResizablePMCArray'
206 set_args "0, 0x20, 0", P16, P17, P18
212 get_params "0, 0, 0, 0, 0", P1, P2, P3, P4, P5
228 pasm_output_is( <<'CODE', <<'OUTPUT', "slurpy param" );
236 set_args "0, 0, 0", P16, P17, P18
242 get_params "0, 0x20", P1, P2
260 pir_output_is( <<'CODE', <<'OUTPUT', "use it in PIR" );
265 # set_args and invoke must be adjacent
277 pasm_output_is( <<'CODE', <<'OUTPUT', "flatten + slurpy param" );
281 new P19, 'ResizablePMCArray'
288 new P20, 'ResizablePMCArray'
297 set_args "0, 0x20, 0x20, 0", P16, P19, P20, P21
303 get_params "0, 0x20", P1, P2
334 pir_output_is( <<'CODE', <<'OUTPUT', "use it in PIR" );
339 # set_args and invoke must be adjacent
351 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - autobox" );
356 # set_args and invoke must be adjacent
357 set_args "0,0,0", $P0, 42, "bar"
361 get_params "0x20", $P0
376 pir_output_is( <<'CODE', <<'OUTPUT', "more autobox" );
378 foo( 101, 0.77, 'seven and seven is' )
383 .param pmc some_float
384 .param pmc some_string
386 $S0 = typeof some_int
390 $S0 = typeof some_float
394 $S0 = typeof some_string
406 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - fetch" );
416 find_name $P10, "foo"
417 # set_args and invoke must be adjacent
418 set_args "0,0,0,0", $P0, $P1, $P2, $P3
422 get_params "0,0,0,0", $P0, $I0, $S0, $N0
437 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too few" );
439 .include "errors.pasm"
440 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
448 get_params "0,0", $P0, $P1
452 /too few positional arguments/
456 <<'CODE', <<'OUTPUT', "argc mismatch, too many - no getparams", todo => 'no get_params at all' );
458 .include "errors.pasm"
459 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
466 /too many arguments passed/
469 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too many - force get_params" );
474 .include "errors.pasm"
475 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
483 /too many positional arguments/
486 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too many" );
488 .include "errors.pasm"
489 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
493 set_args "0,0", $P0, 77
501 /too many positional arguments/
504 pir_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, too many - catch exception" );
506 .include "errors.pasm"
507 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
511 set_args "0,0", $P0, 77
525 # print "\nexception type: "
529 /^caught: too many positional arguments/
532 pir_output_is( <<'CODE', <<'OUTPUT', "argc mismatch, optional" );
534 .include "errors.pasm"
535 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
543 get_params "0,0x80,0x100", $P0, $P1, $I0
555 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, optional" );
557 .include "errors.pasm"
558 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
560 ar = new 'ResizableIntegerArray'
570 .param int j :optional
571 .param int got_j :opt_flag
572 .param int k :optional
573 .param int got_k :opt_flag
576 /too many positional arguments/
579 pasm_output_is( <<'CODE', <<'OUTPUT', "get_param later" );
582 set_args "0, 0", 42, I16
585 get_results "0, 0", I16, I17
593 get_params "0, 0", I16, I17
599 set_returns "4, 0", 99, I16
609 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 1" );
611 .const 'Sub' f = "foo"
618 .const 'Sub' b = "bar"
624 set_returns "0", "bar_ret\n"
634 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 2 - pass arg" );
636 .const 'Sub' f = "foo"
643 .const 'Sub' b = "bar"
645 set_args "0", "from_foo\n"
652 set_returns "0", "bar_ret\n"
663 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 3 - pass arg" );
665 .const 'Sub' f = "foo"
672 .const 'Sub' b = "bar"
674 set_args "0", "from_foo\n"
681 set_returns "0", "bar_ret\n"
692 pir_output_is( <<'CODE', <<'OUTPUT', "empty args" );
701 get_params "0x80, 0x100", $P1, $I0
711 pir_output_is( <<'CODE', <<'OUTPUT', "optional args" );
720 get_params "0x80, 0x100", $P1, $I0
730 pir_output_is( <<'CODE', <<'OUTPUT', "pir uses no ops" );
738 get_params "0, 0", $I16, $I17
752 pir_output_is( <<'CODE', <<'OUTPUT', "pir call evaled code" );
756 s .= ".param int i\n"
757 s .= ".param int j\n"
761 s .= "print \"\\n\"\n"
778 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 4 - pir calls" );
780 .const 'Sub' f = "foo"
786 .const 'Sub' b = "bar"
788 .tailcall b("from_foo\n")
794 .return ("bar_ret\n")
804 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - native" );
806 foo_int(42, "42", 42.20)
807 foo_float(42, "42", 42.20)
808 foo_string(42, "42", 42.20)
811 get_params "0,0,0", $I0, $I1, $I2
820 get_params "0,0,0", $N0, $N1, $N2
829 get_params "0,0,0", $S0, $S1, $S2
843 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - PIR const" );
844 .const int MYCONST = -2
850 .param string str1 :optional
851 .param int has_s :opt_flag
859 pir_output_is( <<'CODE', <<'OUTPUT', "optional args, :opt_flag" );
867 .param pmc p1 :optional
868 .param int i1 :opt_flag
882 pir_output_is( <<'CODE', <<'OUTPUT', "optional multiple :opt_flag" );
886 foo($P0, "ok 2\n", "ok 3\n")
889 .param pmc p1 :optional
890 .param int i1 :opt_flag
891 .param pmc p2 :optional
892 .param int i2 :opt_flag
893 .param pmc p3 :optional
894 .param int i3 :opt_flag
895 .param pmc p4 :optional
896 .param int i4 :opt_flag
924 pir_output_is( <<'CODE', <<'OUTPUT', "optional returns, void ret" );
931 .get_result $P0 :optional
932 .get_result $I0 :opt_flag
945 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 5 - arg/param conflict" );
969 .tailcall bar($P0, a, b)
983 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing" );
989 f = get_global ["Foo"], "bar"
992 f = get_global ["Foo"], "baz"
996 .sub bar :method :nsentry('bar')
1002 .sub baz :method :nsentry('baz')
1008 .sub get_string :vtable :method
1019 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing - 2" );
1031 .sub get_string :vtable :method
1037 .sub get_string_keyed_int :vtable :method
1051 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing - 3" );
1061 .return (arg) # force conversion to string
1064 .sub get_string :vtable :method
1075 # see also tcl in leo-ctx5 by Coke; Date 28.08.2005
1076 pir_output_is( <<'CODE', <<'OUTPUT', "bug - :slurpy promotes to :flatten" );
1086 .param pmc p :slurpy
1102 pir_output_is( <<'CODE', <<'OUTPUT', "call :slurpy with :flat" );
1104 .param pmc rest_arg :slurpy
1110 $P34 = new 'ResizablePMCArray'
1112 ## normal flattening direct call, non-slurpy returns
1113 $P35 = _fn1($P34 :flat)
1120 pir_output_is( <<'CODE', <<'OUTPUT', "call with :flat in the middle" );
1136 $P30 = new 'Integer'
1138 $P31 = new 'Integer'
1140 $P34 = new 'ResizablePMCArray'
1145 $P35 = _fn1(1, $P34 :flat, $I4)
1151 pir_output_is( <<'CODE', <<'OUTPUT', "right number of args via :flat" );
1167 .include "errors.pasm"
1168 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1169 $P30 = new 'Integer'
1171 $P31 = new 'Integer'
1173 $P34 = new 'ResizablePMCArray'
1178 $P35 = _fn1(1, $P34 :flat)
1184 pir_error_output_like( <<'CODE', <<'OUTPUT', "too many args via :flat" );
1200 .include "errors.pasm"
1201 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1202 $P30 = new 'Integer'
1204 $P31 = new 'Integer'
1206 $P34 = new 'ResizablePMCArray'
1212 $P35 = _fn1(1, $P34 :flat)
1215 /too many positional arguments: 5 passed, 4 expected/
1218 pir_error_output_like( <<'CODE', <<'OUTPUT', "too few args via :flat" );
1234 .include "errors.pasm"
1235 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1236 $P30 = new 'Integer'
1238 $P31 = new 'Integer'
1240 $P34 = new 'ResizablePMCArray'
1244 $P35 = _fn1(1, $P34 :flat)
1247 /too few positional arguments: 3 passed, 4 \(or more\) expected/
1250 pir_output_is( <<'CODE', <<'OUTPUT', "faux tailcall to NCI" );
1254 $I0 = s."is_integer"(22)
1261 $I0 = s."is_integer"(22)
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 pir_output_is( <<'CODE', <<'OUTPUT', "clone_key_arg" );
1417 cl = newclass "MyClass"
1424 .namespace ["MyClass"]
1426 # key arguments in register have to be expanded into their
1427 # values because in the called sub frame the original refered
1428 # registers just don't exist #' for vim
1430 .sub set_integer_keyed :vtable :method
1433 print key # print first key
1435 key = shift key # get next key
1448 pir_output_is( <<'CODE', <<'OUTPUT', "result_info op" );
1451 $P0 = new 'FixedIntegerArray'
1455 $P0 = new 'FixedIntegerArray'
1458 ($I1, $I2, $I3) = test()
1474 pir_output_is( <<'CODE', <<'OUTPUT', "result_info op with eval" );
1486 $P0 = new 'FixedIntegerArray'
1490 $P0 = new 'FixedIntegerArray'
1495 $P0 = new 'FixedIntegerArray'
1498 ($I1, $I2, $I3) = test()
1506 pir_output_is( <<'CODE', <<'OUTPUT', ":slurpy result" );
1508 ($P0 :slurpy) = foo()
1515 .return("ok 1\n", "ok 2\n")
1522 pir_output_is( <<'CODE', <<'OUTPUT', ":optional result" );
1524 ($S0 :optional, $I1 :opt_flag) = foo()
1525 unless $I1 goto no_ret
1540 pir_output_is( <<'CODE', <<'OUTPUT', ":optional result" );
1542 ($S0 :optional, $I1 :opt_flag) = foo()
1556 pir_output_is( <<'CODE', <<'OUTPUT', "set_args via continuation -> results" );
1558 .local string result
1559 result = foo("ok 1\n")
1566 .include 'interpinfo.pasm'
1567 cc = interpinfo .INTERPINFO_CURRENT_CONT
1582 pir_output_is( <<'CODE', <<'OUTPUT', "set_args via explicit continuation" );
1584 .local string result
1585 result = "not ok 2\n"
1587 cont = new 'Continuation'
1588 set_addr cont, cont_dest
1592 .get_results (result)
1607 # this is a regression test for a bug in which tail-calling without set_args
1608 # used the args of the sub.
1609 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall explicit continuation, no args" );
1611 .local string result
1612 result = "not ok 2\n"
1614 cont = new 'Continuation'
1615 set_addr cont, cont_dest
1633 pir_output_is( <<'CODE', <<'OUTPUT', "newclosure followed by tailcall" );
1634 ## regression test for newclosure followed by tailcall, which used to recycle
1635 ## the context too soon. it looks awful because (a) the original version was
1636 ## produced by a compiler, and (b) in order to detect regression, we must force
1637 ## parrot to reuse the context, which seems to requires having other calls that
1638 ## use particular numbers of registers (and probably a fair amount of luck).
1641 .lex "MAIN-CONT", $P41
1643 $P41 = new 'Continuation'
1647 get_results '0', $P45
1653 .const 'Sub' $P49 = "___internal_main_test_"
1654 newclosure $P48, $P49
1655 .tailcall _try_it($I42, $P48)
1658 .sub ___internal_main_test_ :outer('_main')
1661 find_lex $P41, "MAIN-CONT"
1663 if arg1 != 3 goto L3
1666 $P57 = mul $P58, $P59
1667 set_args '(0)', $P57
1699 pir_output_is( <<'CODE', <<'OUTPUT', "call evaled vtable code" );
1706 .sub get_integer_keyed_int :vtable :method
1713 comp = compreg "PIR"
1724 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 1" );
1726 set_args "0x200, 0, 0x200, 0", "b", 10, "a", 20
1733 get_params "0x200, 0, 0x200, 0", "a", I0, "b", I1
1744 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 2 flatten" );
1749 set_args "0x220", P0 # :flatten :named
1756 get_params "0x200, 0, 0x200, 0", "a", I0, "b", I1
1767 pir_output_is( <<'CODE', <<'OUTPUT', "named - 3 slurpy hash PIR" );
1769 foo('a' => 10 , 'b' => 20, 'c' => 30)
1774 .param int a :named('a')
1775 .param pmc bar :slurpy :named
1797 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 3 slurpy hash" );
1799 set_args "0x200, 0, 0x200, 0,0x200, 0", "a", 10, "b", 20, 'c', 30
1806 get_params "0x200, 0, 0x220", "a", I0, P0
1828 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 4 positional -> named" );
1830 set_args "0, 0, 0", 10, 20, 30
1837 get_params "0x200, 0, 0x200, 0, 0x200, 0", "a", I0, "b", I1, 'c', I2
1850 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 5 slurpy array -> named" );
1852 set_args "0, 0, 0, 0x200, 0, 0x200, 0", 10, 20, 30, 'a', 40, 'b', 50
1859 get_params "0, 0x20, 0x200, 0, 0x200, 0", I0, P0, "b", I1, "a", I2
1878 pir_output_is( <<'CODE', <<'OUTPUT', ":optional followed by :slurpy (empty)" );
1883 .param pmc arg1 :optional
1884 .param pmc rest_arg :slurpy
1894 pir_output_is( <<'CODE', <<'OUTPUT', ":optional followed by :slurpy (used)" );
1896 _write_thing(3, 4, 5)
1899 .param pmc arg1 :optional
1900 .param pmc rest_arg :slurpy
1911 pir_output_is( <<'CODE', <<'OUTPUT', ":named(\"...\") syntax for .param and sub call" );
1913 foo( 10 :named("b"), 20 :named("a"))
1919 .param int c :named("a")
1920 .param int d :named("b")
1934 pir_output_is( <<'CODE', <<'OUTPUT', ":named(\"...\") syntax for the 4 kind" );
1936 ($I0 :named("b"), $I1 :named("a")) = foo( 10 :named("b"), 20 :named("a"))
1947 .param int c :named("a")
1948 .param int d :named("b")
1955 .return ( 10 :named("a"), 20 :named("b"))
1964 pir_output_is( <<'CODE', <<'OUTPUT', " 'foo' => 10 syntax for function call" );
1966 foo ('a'=>20,'b'=>10)
1973 .param int c :named("a")
1974 .param int d :named("b")
1988 pir_error_output_like( <<'CODE', <<'OUTPUT', "named => pos passing" );
1990 foo( "b" => 10 , "a" => 20)
2000 /too few positional/
2003 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - set" );
2005 foo ('a'=>20,'b'=>10)
2010 .param int d :named('b')
2011 .param int c :named('a') :optional
2022 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - set, :opt_flag" );
2024 foo ('a'=>20,'b'=>10)
2029 .param int d :named('b') :optional
2030 .param int has_d :opt_flag
2031 .param int c :named('a') :optional
2032 .param int has_c :opt_flag
2047 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - mix" );
2049 foo ('a'=>20,'b'=>10)
2057 .param int d :named('b') :optional
2058 .param int has_d :opt_flag
2059 .param int c :named('a') :optional
2060 .param int has_c :opt_flag
2078 pir_output_is( <<'CODE', <<'OUTPUT', "named flat/slurpy" );
2084 foo( h :named :flat )
2090 .param pmc h :named :slurpy
2103 pir_error_output_like( <<'CODE', <<'OUTPUT', "param .. 'a' => v :named('foo')" );
2105 foo( "b" => 10, "a" => 20)
2111 .param int c :named("foo") :named("bar")
2115 /Named parameter with more than one name/
2118 pir_output_is( <<'CODE', <<'OUTPUT', "default value for an unused :optional" );
2127 .param int var :optional
2134 pir_error_output_like( <<'CODE', qr/too few named arguments/, "argc mismatch - missing named" );
2136 .include "errors.pasm"
2137 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2143 .param int d :named('b')
2144 .param int c :named('a')
2152 pir_error_output_like( <<'CODE', qr/too few named arguments/, "argc mismatch - missing named" );
2154 .include "errors.pasm"
2155 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2161 .param int d :named('b')
2162 .param int c :named('a')
2170 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - too many named" );
2172 .include "errors.pasm"
2173 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2174 foo ('a'=>10, 'b'=>20, 'c'=>30)
2179 .param int d :named('b')
2180 .param int c :named('a')
2190 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - duplicate named" );
2192 .include "errors.pasm"
2193 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2194 foo ('a'=>10, 'b'=>20, 'a'=>30)
2199 .param int d :named('b')
2200 .param int c :named('a')
2210 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named after slurpy array" );
2214 $P0 = new 'ResizablePMCArray'
2216 foo($P0 :flat, 'abc' => 3)
2217 $P0 = new 'ResizablePMCArray'
2218 foo($P0 :flat, 'abc' => 4)
2222 .param pmc array :slurpy
2223 .param pmc hash :slurpy :named
2236 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named loses :flat arg (#39044)" );
2242 foo(0, 1, $P0 :flat :named)
2246 .param pmc array :slurpy
2247 .param pmc hash :slurpy :named
2248 $I0 = elements array
2265 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named loses :flat arg" );
2271 foo(0, 1, 'z'=>2626, $P0 :flat :named)
2275 .param pmc array :slurpy
2276 .param pmc hash :slurpy :named
2293 pir_error_output_like( <<'CODE', <<'OUTPUT', "unexpected positional arg" );
2295 'foo'('abc', 'def', 'ghi'=>1)
2300 .param pmc args :slurpy :named
2303 /too many positional arguments/
2306 pir_error_output_like( <<'CODE', <<'OUTPUT', "unexpected positional arg" );
2308 'foo'('abc', 'def'=>1, 'ghi', 'jkl'=>1)
2313 .param pmc args :slurpy :named
2316 /named arguments must follow all positional arguments/
2319 pir_output_is( <<'CODE', <<'OUTPUT', "flat/slurpy named arguments" );
2326 bar_only( args :flat :named )
2330 .param string bar :named( 'bar' )
2331 .param pmc args :named :slurpy
2342 <<'CODE', <<'OUTPUT', "Tail call without arguments should not free the context when a closure depends on it" );
2344 $P0 = create_closure_and_run_it()
2347 .sub create_closure_and_run_it
2351 $P2 = get_global "myclosure"
2352 $P1 = newclosure $P2
2353 # There is a closure depending on our current context, so this shouldn't
2358 .sub myclosure :outer(create_closure_and_run_it)
2359 $P1 = find_lex "val"
2362 $P1 = find_lex "val"
2370 # This creates a new binding that is not accessible by the
2371 # caller (myclosure)
2381 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named after :optional" );
2385 $P0 = new 'ResizablePMCArray'
2387 foo($P0 :flat, 'abc' => 3)
2388 $P0 = new 'ResizablePMCArray'
2389 foo($P0 :flat, 'abc' => 4)
2392 foo($P0 :named :flat)
2396 .param pmc val :optional
2397 .param int has_val :opt_flag
2398 .param pmc hash :slurpy :named
2412 pir_output_is( <<'CODE', <<'OUTPUT', "named optional after :optional" );
2418 'foo'($P0 :named('y'))
2422 .param pmc x :optional
2423 .param int has_x :opt_flag
2424 .param pmc y :optional :named('y')
2425 .param int has_y :opt_flag
2426 if has_y goto have_y
2438 pir_error_output_like( <<'CODE', <<'OUTPUT', "arg mismatch with no params", todo=> 'TT #1033' );
2446 /too many arguments passed\(1\) - 0 params expected/
2449 # See Rakudo queue http://rt.perl.org/rt3/Ticket/Display.html?id=62730
2450 pir_output_is( <<'CODE', <<'OUTPUT', "named from register, not constant" );
2453 example('foo' => 42) # normal named parameter
2454 example( $S0 => 42) # parameter named by non-const register
2455 just_a_string( $S0, 'foo' => 42 ) # nameyness should not stick on register
2459 .param pmc foo :named('foo')
2463 .sub 'just_a_string'
2465 .param int baz :named( 'foo' )
2476 # See Rakudo queue http://rt.perl.org/rt3/Ticket/Display.html?id=62730
2477 pir_output_is( <<'CODE', <<'OUTPUT', "Handling :flat of empty arguments" );
2486 .param pmc arg :slurpy
2496 pir_output_is( <<'CODE', <<'OUTPUT', "Tailcall from vtable" );
2499 $P1 = newclass "Foo"
2502 ## Should return 2, but doesn't.
2510 .sub elements :vtable
2513 .tailcall identity($I1)
2524 pir_output_is( <<'CODE', <<'OUTPUT', "methodtailcall 1 TT#133" );
2528 $P0 = foo() ## fails :-(
2537 .tailcall p."attributes"()
2544 $P0 = p."attributes"()
2555 pir_output_is( <<'CODE', <<'OUTPUT', "handling of slurpy after optional, TT #1733" );
2557 # Lua calling convention scheme
2559 # f() has 2 known parameters
2561 .param pmc p1 :optional
2562 .param int has_p1 :opt_flag
2563 .param pmc p2 :optional
2564 .param int has_p2 :opt_flag
2565 .param pmc extra :slurpy
2566 unless has_p1 goto L1
2568 unless has_p2 goto L1
2599 # cperl-indent-level: 4
2602 # vim: expandtab shiftwidth=4: