2 # Copyright (C) 2001-2007, The Perl Foundation.
7 use lib qw( . lib ../lib ../../lib );
10 use Parrot::Test tests => 96;
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
432 hello 42 again 47.110000
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 arguments passed/
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 arguments passed/
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 arguments passed/
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
518 get_results "0,0", $P1, $S0
523 /^catched: too many arguments passed/
526 pir_output_is( <<'CODE', <<'OUTPUT', "argc mismatch, optional" );
528 .include "errors.pasm"
529 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
537 get_params "0,0x80,0x100", $P0, $P1, $I0
549 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch, optional" );
551 .include "errors.pasm"
552 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
554 ar = new 'ResizableIntegerArray'
564 .param int j :optional
565 .param int got_j :opt_flag
566 .param int k :optional
567 .param int got_k :opt_flag
570 /too many arguments passed/
573 pasm_output_is( <<'CODE', <<'OUTPUT', "get_param later" );
576 set_args "0, 0", 42, I16
577 get_results "0, 0", I16, I17
587 get_params "0, 0", I16, I17
593 set_returns "4, 0", 99, I16
603 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 1" );
605 .const .Sub f = "foo"
612 .const .Sub b = "bar"
618 set_returns "0", "bar_ret\n"
628 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 2 - pass arg" );
630 .const .Sub f = "foo"
637 .const .Sub b = "bar"
639 set_args "0", "from_foo\n"
646 set_returns "0", "bar_ret\n"
657 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 3 - pass arg" );
659 .const .Sub f = "foo"
666 .const .Sub b = "bar"
668 set_args "0", "from_foo\n"
675 set_returns "0", "bar_ret\n"
686 pir_output_is( <<'CODE', <<'OUTPUT', "empty args" );
695 get_params "0x80, 0x100", $P1, $I0
705 pir_output_is( <<'CODE', <<'OUTPUT', "optional args" );
714 get_params "0x80, 0x100", $P1, $I0
724 pir_output_is( <<'CODE', <<'OUTPUT', "pir uses no ops" );
732 get_params "0, 0", I16, I17
746 pir_output_is( <<'CODE', <<'OUTPUT', "pir call evaled code" );
750 s .= ".param int i\n"
751 s .= ".param int j\n"
755 s .= "print \"\\n\"\n"
772 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 4 - pir calls" );
774 .const .Sub f = "foo"
780 .const .Sub b = "bar"
782 .return b("from_foo\n")
788 .return ("bar_ret\n")
798 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - native" );
800 foo_int(42, "42", 42.20)
801 foo_float(42, "42", 42.20)
802 foo_string(42, "42", 42.20)
805 get_params "0,0,0", $I0, $I1, $I2
814 get_params "0,0,0", $N0, $N1, $N2
823 get_params "0,0,0", $S0, $S1, $S2
833 42.000000 42.000000 42.200000
837 pir_output_is( <<'CODE', <<'OUTPUT', "type conversion - PIR const" );
838 .const int MYCONST = -2
844 .param string str1 :optional
845 .param int has_s :opt_flag
853 pir_output_is( <<'CODE', <<'OUTPUT', "optional args, :opt_flag" );
861 .param pmc p1 :optional
862 .param int i1 :opt_flag
876 pir_output_is( <<'CODE', <<'OUTPUT', "optional multiple :opt_flag" );
880 foo($P0, "ok 2\n", "ok 3\n")
883 .param pmc p1 :optional
884 .param int i1 :opt_flag
885 .param pmc p2 :optional
886 .param int i2 :opt_flag
887 .param pmc p3 :optional
888 .param int i3 :opt_flag
889 .param pmc p4 :optional
890 .param int i4 :opt_flag
918 pir_output_is( <<'CODE', <<'OUTPUT', "optional returns, void ret" );
925 .result $P0 :optional
926 .result $I0 :opt_flag
939 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall 5 - arg/param conflict" );
963 .return bar($P0, a, b)
977 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing" );
983 f = get_global ["Foo"], "bar"
986 f = get_global ["Foo"], "baz"
1002 .sub get_string :vtable :method
1013 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing - 2" );
1025 .sub get_string :vtable :method
1031 .sub get_string_keyed_int :vtable :method
1045 pir_output_is( <<'CODE', <<'OUTPUT', "OO argument passing - 3" );
1055 .return (arg) # force conversion to string
1058 .sub get_string :vtable :method
1069 # see also tcl in leo-ctx5 by Coke; Date 28.08.2005
1070 pir_output_is( <<'CODE', <<'OUTPUT', "bug - :slurpy promotes to :flatten" );
1080 .param pmc p :slurpy
1096 pir_output_is( <<'CODE', <<'OUTPUT', "call :slurpy with :flat" );
1098 .param pmc rest_arg :slurpy
1106 ## normal flattening direct call, non-slurpy returns
1107 $P35 = _fn1($P34 :flat)
1114 pir_output_is( <<'CODE', <<'OUTPUT', "call with :flat in the middle" );
1130 $P30 = new 'Integer'
1132 $P31 = new 'Integer'
1139 $P35 = _fn1(1, $P34 :flat, $I4)
1145 pir_output_is( <<'CODE', <<'OUTPUT', "right number of args via :flat" );
1161 .include "errors.pasm"
1162 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1163 $P30 = new 'Integer'
1165 $P31 = new 'Integer'
1172 $P35 = _fn1(1, $P34 :flat)
1178 pir_error_output_like( <<'CODE', <<'OUTPUT', "too many args via :flat" );
1194 .include "errors.pasm"
1195 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1196 $P30 = new 'Integer'
1198 $P31 = new 'Integer'
1206 $P35 = _fn1(1, $P34 :flat)
1209 /too many arguments passed \(5\) - 4 params expected/
1212 pir_error_output_like( <<'CODE', <<'OUTPUT', "too few args via :flat" );
1228 .include "errors.pasm"
1229 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
1230 $P30 = new 'Integer'
1232 $P31 = new 'Integer'
1238 $P35 = _fn1(1, $P34 :flat)
1241 /too few arguments passed \(3\) - 4 params expected/
1244 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall to NCI" );
1265 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall to NCI - 2" );
1267 $P0 = eval("print \"Foo!\\n\"")
1274 code = ".sub main :main :anon\n" . code
1275 code = code . "\n.end\n"
1283 # bug - repeated calls to eval'd sub crashes (pmichaud, 2005.10.27)
1284 pir_output_is( <<'CODE', <<'OUTPUT', "repeated calls to eval'd sub" );
1288 s = ".namespace [ \"XYZ\" ]\n"
1290 s .= " .param int n\n"
1291 s .= " $I0 = n % 1000\n"
1292 s .= " if $I0 goto end\n"
1294 s .= " print \"\\n\"\n"
1299 outer = get_global ["XYZ"], "outer"
1303 if $I1 > 10000 goto end
1321 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall - overlapping Ix" );
1329 .const .Sub b = "bar"
1332 set_args "0,0", I1, I0
1336 get_params "0,0", I0, I1
1343 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall - optional not set" );
1349 .const .Sub b = "bar"
1355 .param int c :optional
1356 .param int has_c :opt_flag
1361 unless has_c goto no_c
1374 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall - optional set" );
1380 .const .Sub b = "bar"
1381 .return b(10, 20, 30)
1386 .param int c :optional
1387 .param int has_c :opt_flag
1392 unless has_c goto no_c
1405 pir_output_is( <<'CODE', <<'OUTPUT', "clone_key_arg" );
1413 cl = newclass "MyClass"
1420 .namespace ["MyClass"]
1422 # key arguments in register have to be expanded into their
1423 # values because in the called sub frame the original refered
1424 # registers just don't exist #' for vim
1426 .sub set_integer_keyed :vtable :method
1429 print key # print first key
1431 key = shift key # get next key
1444 pir_output_is( <<'CODE', <<'OUTPUT', "result_info op" );
1448 ($I1, $I2, $I3) = test()
1464 pir_output_is( <<'CODE', <<'OUTPUT', "result_info op with eval" );
1478 ($I1, $I2, $I3) = test()
1486 pir_output_is( <<'CODE', <<'OUTPUT', ":slurpy result" );
1488 ($P0 :slurpy) = foo()
1495 .return("ok 1\n", "ok 2\n")
1502 pir_output_is( <<'CODE', <<'OUTPUT', ":optional result" );
1504 ($S0 :optional, $I1 :opt_flag) = foo()
1505 unless $I1 goto no_ret
1520 pir_output_is( <<'CODE', <<'OUTPUT', ":optional result" );
1522 ($S0 :optional, $I1 :opt_flag) = foo()
1536 pir_output_is( <<'CODE', <<'OUTPUT', "set_args via continuation -> results" );
1538 .local string result
1539 result = foo("ok 1\n")
1546 .include 'interpinfo.pasm'
1547 cc = interpinfo .INTERPINFO_CURRENT_CONT
1562 pir_output_is( <<'CODE', <<'OUTPUT', "set_args via explicit continuation" );
1564 .local string result
1565 result = "not ok 2\n"
1567 cont = new 'Continuation'
1568 set_addr cont, cont_dest
1572 .get_results (result)
1587 # this is a regression test for a bug in which tail-calling without set_args
1588 # used the args of the sub.
1589 pir_output_is( <<'CODE', <<'OUTPUT', "tailcall explicit continuation, no args" );
1591 .local string result
1592 result = "not ok 2\n"
1594 cont = new 'Continuation'
1595 set_addr cont, cont_dest
1613 pir_output_is( <<'CODE', <<'OUTPUT', "newclosure followed by tailcall" );
1614 ## regression test for newclosure followed by tailcall, which used to recycle
1615 ## the context too soon. it looks awful because (a) the original version was
1616 ## produced by a compiler, and (b) in order to detect regression, we must force
1617 ## parrot to reuse the context, which seems to requires having other calls that
1618 ## use particular numbers of registers (and probably a fair amount of luck).
1621 .lex "MAIN-CONT", $P41
1623 $P41 = new 'Continuation'
1627 get_results '0', $P45
1633 .const .Sub $P49 = "___internal_main_test_"
1634 newclosure $P48, $P49
1635 .return _try_it($I42, $P48)
1638 .sub ___internal_main_test_ :outer('_main')
1641 find_lex $P41, "MAIN-CONT"
1643 if arg1 != 3 goto L3
1646 $P57 = n_mul $P58, $P59
1647 set_args '(0)', $P57
1679 pir_output_is( <<'CODE', <<'OUTPUT', "call evaled vtable code" );
1686 .sub get_integer_keyed_int :vtable :method
1693 comp = compreg "PIR"
1704 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 1" );
1706 set_args "0x200, 0, 0x200, 0", "b", 10, "a", 20
1713 get_params "0x200, 0, 0x200, 0", "a", I0, "b", I1
1724 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 2 flatten" );
1729 set_args "0x220", P0 # :flatten :named
1736 get_params "0x200, 0, 0x200, 0", "a", I0, "b", I1
1747 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 3 slurpy hash" );
1749 set_args "0x200, 0, 0x200, 0,0x200, 0", "a", 10, "b", 20, 'c', 30
1756 get_params "0x200, 0, 0x220", "a", I0, P0
1778 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 4 positional -> named" );
1780 set_args "0, 0, 0", 10, 20, 30
1787 get_params "0x200, 0, 0x200, 0, 0x200, 0", "a", I0, "b", I1, 'c', I2
1800 pasm_output_is( <<'CODE', <<'OUTPUT', "named - 5 slurpy array -> named" );
1802 set_args "0, 0, 0, 0x200, 0, 0x200, 0", 10, 20, 30, 'a', 40, 'b', 50
1809 get_params "0, 0x20, 0x200, 0, 0x200, 0", I0, P0, "b", I1, "a", I2
1828 pir_output_is( <<'CODE', <<'OUTPUT', ":optional followed by :slurpy (empty)" );
1833 .param pmc arg1 :optional
1834 .param pmc rest_arg :slurpy
1844 pir_output_is( <<'CODE', <<'OUTPUT', ":optional followed by :slurpy (used)" );
1846 _write_thing(3, 4, 5)
1849 .param pmc arg1 :optional
1850 .param pmc rest_arg :slurpy
1861 pir_output_is( <<'CODE', <<'OUTPUT', ":named(\"...\") syntax for .param and sub call" );
1863 foo( 10 :named("b"), 20 :named("a"))
1869 .param int c :named("a")
1870 .param int d :named("b")
1884 pir_output_is( <<'CODE', <<'OUTPUT', ":named(\"...\") syntax for the 4 kind" );
1886 ($I0 :named("b"), $I1 :named("a")) = foo( 10 :named("b"), 20 :named("a"))
1897 .param int c :named("a")
1898 .param int d :named("b")
1905 .return ( 10 :named("a"), 20 :named("b"))
1914 pir_output_is( <<'CODE', <<'OUTPUT', " 'foo' => 10 syntax for function call" );
1916 foo ('a'=>20,'b'=>10)
1923 .param int c :named("a")
1924 .param int d :named("b")
1939 pir_output_is( <<'CODE', <<'OUTPUT', " 'foo' => d syntax for parameters" );
1941 foo ('a'=>20,'b'=>10)
1964 pir_output_is( <<'CODE', <<'OUTPUT', " 'foo' => d syntax for target list" );
1966 ("b" => $I0 , "a" => $I1) = foo( "b" => 10 , "a" => 20)
1985 .return ( 10 :named("a"), 20 :named("b"))
1994 pir_output_is( <<'CODE', <<'OUTPUT', " 'foo' => d syntax for return" );
1996 ("b" => $I0 , "a" => $I1) = foo( "b" => 10 , "a" => 20)
2015 .return ( "a" => 10, "b" => 20 )
2023 pir_error_output_like( <<'CODE', <<'OUTPUT', "named => pos passing" );
2025 foo( "b" => 10 , "a" => 20)
2035 /many named arguments/
2038 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - set" );
2040 foo ('a'=>20,'b'=>10)
2045 .param int d :named('b')
2046 .param int c :named('a') :optional
2057 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - set" );
2059 foo ('a'=>20,'b'=>10)
2065 .param int 'a' => c :optional
2076 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - set, :opt_flag" );
2078 foo ('a'=>20,'b'=>10)
2083 .param int d :named('b') :optional
2084 .param int has_d :opt_flag
2085 .param int c :named('a') :optional
2086 .param int has_c :opt_flag
2101 pir_output_is( <<'CODE', <<'OUTPUT', "named optional - mix" );
2103 foo ('a'=>20,'b'=>10)
2111 .param int d :named('b') :optional
2112 .param int has_d :opt_flag
2113 .param int c :named('a') :optional
2114 .param int has_c :opt_flag
2132 pir_output_is( <<'CODE', <<'OUTPUT', "named flat/slurpy" );
2138 foo( h :named :flat )
2144 .param pmc h :named :slurpy
2157 pir_error_output_like( <<'CODE', <<'OUTPUT', "param .. 'a' => v :named('foo')" );
2159 foo( "b" => 10, "a" => 20)
2165 .param int "a" => c :named("foo")
2169 /Named parameter with more than one name/
2172 pir_error_output_like( <<'CODE', <<'OUTPUT', "param .. 'a' => v :named('foo')" );
2174 foo( "b" => 10, "a" => 20)
2180 .param int c :named("foo") :named("bar")
2184 /Named parameter with more than one name/
2187 pir_output_is( <<'CODE', <<'OUTPUT', "default value for an unused :optional" );
2196 .param int var :optional
2203 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - missing named" );
2205 .include "errors.pasm"
2206 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2212 .param int d :named('b')
2213 .param int c :named('a')
2223 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - missing named" );
2225 .include "errors.pasm"
2226 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2232 .param int d :named('b')
2233 .param int c :named('a')
2243 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - too many named" );
2245 .include "errors.pasm"
2246 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2247 foo ('a'=>10, 'b'=>20, 'c'=>30)
2252 .param int d :named('b')
2253 .param int c :named('a')
2263 pir_error_output_like( <<'CODE', <<'OUTPUT', "argc mismatch - duplicate named" );
2265 .include "errors.pasm"
2266 errorson .PARROT_ERRORS_PARAM_COUNT_FLAG
2267 foo ('a'=>10, 'b'=>20, 'a'=>30)
2272 .param int d :named('b')
2273 .param int c :named('a')
2283 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named after slurpy array" );
2287 $P0 = new 'ResizablePMCArray'
2289 foo($P0 :flat, 'abc' => 3)
2290 $P0 = new 'ResizablePMCArray'
2291 foo($P0 :flat, 'abc' => 4)
2295 .param pmc array :slurpy
2296 .param pmc hash :slurpy :named
2309 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named loses :flat arg (#39044)" );
2315 foo(0, 1, $P0 :flat :named)
2319 .param pmc array :slurpy
2320 .param pmc hash :slurpy :named
2321 $I0 = elements array
2338 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named loses :flat arg" );
2344 foo(0, 1, 'z'=>2626, $P0 :flat :named)
2348 .param pmc array :slurpy
2349 .param pmc hash :slurpy :named
2366 pir_error_output_like( <<'CODE', <<'OUTPUT', "unexpected positional arg" );
2368 'foo'('abc', 'def', 'ghi'=>1)
2373 .param pmc args :slurpy :named
2376 /positional inside named args at position 2/
2379 pir_error_output_like( <<'CODE', <<'OUTPUT', "unexpected positional arg" );
2381 'foo'('abc', 'def'=>1, 'ghi', 'jkl'=>1)
2386 .param pmc args :slurpy :named
2389 /positional inside named args at position 3/
2392 pir_output_is( <<'CODE', <<'OUTPUT', "RT #40490 - flat/slurpy named arguments" );
2399 bar_only( args :flat :named )
2403 .param string bar :named( 'bar' )
2404 .param pmc args :named :slurpy
2415 <<'CODE', <<'OUTPUT', "Tail call without arguments should not free the context when a closure depends on it" );
2417 $P0 = create_closure_and_run_it()
2420 .sub create_closure_and_run_it
2424 P2 = get_global "myclosure"
2426 # There is a closure depending on our current context, so this shouldn't
2431 .sub myclosure :outer(create_closure_and_run_it)
2443 # This creates a new binding that is not accessible by the
2444 # caller (myclosure)
2454 pir_output_is( <<'CODE', <<'OUTPUT', "slurpy named after :optional" );
2458 $P0 = new 'ResizablePMCArray'
2460 foo($P0 :flat, 'abc' => 3)
2461 $P0 = new 'ResizablePMCArray'
2462 foo($P0 :flat, 'abc' => 4)
2466 .param pmc val :optional
2467 .param int has_val :opt_flag
2468 .param pmc hash :slurpy :named
2483 # cperl-indent-level: 4
2486 # vim: expandtab shiftwidth=4: