2 # Copyright (C) 2001-2008, The Perl Foundation.
7 use lib qw( . lib ../lib ../../lib );
10 use Parrot::Test tests => 65;
15 t/pmc/sub.t - Subroutine PMCs
23 Tests the creation and invocation of C<Sub>, C<Closure> and
28 my $temp = "temp.pasm";
31 unlink( $temp, 'temp.pbc', 'temp.pasm' );
34 pasm_output_is( <<'CODE', <<'OUTPUT', "PASM subs - invokecc" );
35 .const .Sub P0 = "func"
52 .include "interpinfo.pasm"
53 interpinfo P0, .INTERPINFO_CURRENT_SUB
55 invokecc P0 # recursive invoke
67 pasm_output_is( <<'CODE', <<'OUTPUT', "Continuation" );
71 new P1, 'Continuation'
81 print "going to cont\n"
99 pasm_output_is( <<'CODE', <<'OUTPUT', "definedness of Continuation" );
100 new P1, 'Continuation'
111 print "I'm a very boring continuation"
119 pasm_output_is( <<'CODE', <<'OUTPUT', "pcc sub" );
120 get_global P0, "_the_sub"
138 pasm_output_is( <<'CODE', <<'OUTPUT', "pcc sub, tail call" );
139 get_global P0, "_the_sub"
151 get_global P0, "_next_sub"
157 print "in next sub\n"
168 pasm_output_is( <<'CODE', <<'OUTPUT', "pcc sub perl::syn::tax" );
169 get_global P0, "_the::sub::some::where"
178 .pcc_sub _the::sub::some::where:
187 open my $S, '>', "$temp" or die "Can't write $temp";
195 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode call sub" );
198 load_bytecode "temp.pasm"
200 get_global P0, "_sub1"
216 open $S, '>', "$temp" or die "Can't write $temp";
224 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode call sub, ret" );
227 load_bytecode "temp.pasm"
229 get_global P0, "_sub1"
246 open $S, '>', "$temp" or die "Can't write $temp";
257 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode call different subs, ret" );
260 load_bytecode "temp.pasm"
262 get_global P0, "_sub1"
271 get_global P0, "_sub2"
296 system(".$PConfig{slash}parrot$PConfig{exe} -o temp.pbc $temp");
298 pir_output_is( <<'CODE', <<'OUTPUT', "load_bytecode Sx" );
312 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode PBC call different subs, ret" );
315 load_bytecode "temp.pbc"
317 get_global P0, "_sub1"
326 get_global P0, "_sub2"
351 pasm_output_is( <<'CODE', <<'OUTPUT', "equality of closures" );
353 .const .Sub P3 = "f1"
360 .const .Sub P4 = "f2"
368 .pcc_sub :outer(main) f1:
372 .pcc_sub :outer(main) f2:
380 pasm_output_is( <<'CODE', <<'OUTPUT', "equality of subs" );
381 .const .Sub P0 = "f1"
387 .const .Sub P2 = "f2"
407 pasm_output_is( <<'CODE', <<'OUT', "MAIN pragma, syntax only" );
408 .pcc_sub :main _main:
415 open $S, '>', "$temp" or die "Can't write $temp";
417 .pcc_sub :load _sub1:
423 pasm_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode :load' );
426 load_bytecode "temp.pasm"
435 open $S, '>', "$temp" or die "Can't write $temp";
439 .pcc_sub :load _sub1:
445 pasm_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode :load second sub' );
448 load_bytecode "temp.pasm"
457 system(".$PConfig{slash}parrot$PConfig{exe} -o temp.pbc $temp");
459 pasm_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode :load in pbc' );
462 load_bytecode "temp.pbc"
471 open $S, '>', "$temp" or die "Can't write $temp";
473 .pcc_sub :load _sub1:
482 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode autorun first" );
485 load_bytecode "temp.pasm"
487 get_global P0, "_sub2"
499 system(".$PConfig{slash}parrot$PConfig{exe} -o temp.pbc $temp");
501 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode autorun first in pbc" );
504 load_bytecode "temp.pbc"
506 get_global P0, "_sub2"
518 open $S, '>', "$temp" or die "Can't write $temp";
523 .pcc_sub :load _sub2:
529 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode autorun second" );
532 load_bytecode "temp.pasm"
534 get_global P0, "_sub1"
546 system(".$PConfig{slash}parrot$PConfig{exe} -o temp.pbc $temp");
548 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode autorun second in pbc" );
551 load_bytecode "temp.pbc"
553 get_global P0, "_sub1"
565 open $S, '>', "$temp" or die "Can't write $temp";
567 .pcc_sub :load _sub1:
570 .pcc_sub :load _sub2:
576 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode autorun both" );
579 load_bytecode "temp.pasm"
581 get_global P0, "_sub1"
594 system(".$PConfig{slash}parrot$PConfig{exe} -o temp.pbc $temp");
596 pasm_output_is( <<'CODE', <<'OUTPUT', "load_bytecode autorun both in pbc" );
599 load_bytecode "temp.pbc"
601 get_global P0, "_sub1"
614 pasm_output_is( <<'CODE', <<'OUTPUT', ':main pragma' );
618 .pcc_sub :main _main:
625 pasm_output_is( <<'CODE', <<'OUTPUT', 'two :main pragmas' );
629 .pcc_sub :main _main:
632 .pcc_sub :main _second:
639 pasm_output_is( <<'CODE', <<'OUTPUT', ':main pragma call subs' );
646 .pcc_sub :main _main:
648 get_global P0, "_first"
650 get_global P0, "_second"
659 pir_error_output_like( <<'CODE', <<'OUTPUT', "implicit :main with wrong # args." );
665 /too few arguments passed \(1\) - 2 params expected/
668 pir_error_output_like( <<'CODE', <<'OUTPUT', "explicit :main with wrong # args." );
674 /too few arguments passed \(1\) - 2 params expected/
678 open $S, '>', "$temp" or die "Can't write $temp";
687 pasm_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode :load first sub - pir' );
690 load_bytecode "temp.pir"
699 open $S, '>', "$temp" or die "Can't write $temp";
705 # :load or other pragmas are only evaluated on the first
706 # instruction of a compilation unit
714 pasm_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode :load second sub - pir' );
717 load_bytecode "temp.pir"
726 open $S, '>', "$temp" or die "Can't write $temp";
738 pasm_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode no :load - pir' );
741 load_bytecode "temp.pir"
749 # This is the behavior of Parrot 0.4.3
750 # RT#46817 Should there be a warning ?
751 pir_output_is( <<'CODE', '', 'warn on in main' );
753 .include "warnings.pasm"
754 warningson .PARROT_WARNINGS_UNDEF_FLAG
763 pir_output_is( <<'CODE', <<'OUTPUT', "warn on in sub" );
765 .include "warnings.pasm"
772 warningson .PARROT_WARNINGS_UNDEF_FLAG
778 # RT#46819 This is the behavior of Parrot 0.4.3
779 # It looks like core PMCs never emit warning.
780 # Look in perlundef.t for a more sane test of 'warningson' in subs
781 pir_output_is( <<'CODE', <<'OUTPUT', "warn on in sub, turn off in f2" );
783 .include "warnings.pasm"
791 warningson .PARROT_WARNINGS_UNDEF_FLAG
797 warningsoff .PARROT_WARNINGS_UNDEF_FLAG
804 pasm_output_is( <<'CODE', <<'OUTPUT', "sub names" );
806 .include "interpinfo.pasm"
807 interpinfo P20, .INTERPINFO_CURRENT_SUB
810 get_global P0, "the_sub"
812 interpinfo P20, .INTERPINFO_CURRENT_SUB
817 interpinfo P20, .INTERPINFO_CURRENT_SUB
820 interpinfo P1, .INTERPINFO_CURRENT_CONT
828 pasm_output_is( <<'CODE', <<'OUTPUT', "sub names w MAIN" );
833 .include "interpinfo.pasm"
834 interpinfo P20, .INTERPINFO_CURRENT_SUB
837 get_global P0, "the_sub"
839 interpinfo P20, .INTERPINFO_CURRENT_SUB
844 interpinfo P20, .INTERPINFO_CURRENT_SUB
847 interpinfo P1, .INTERPINFO_CURRENT_CONT
855 pir_output_is( <<'CODE', <<'OUTPUT', "caller introspection via interp" );
857 .include "interpinfo.pasm"
858 # this test will fail when run with -Oc
859 # as the call chain is cut down with tail calls
862 $P0 = get_hll_global ["Bar"], "foo"
868 $P0 = get_hll_global ["Bar"], "bar"
887 $P0 = $P1["sub"; $I0]
914 # the test has different output when run with --run-pbc (make testr)
915 # actually not - compiling creates 2 'initial'
916 # running emts 'main'
919 .sub optc :immediate :postcomp
926 my $descr = ':immediate :postcomp';
927 if ( exists $ENV{TEST_PROG_ARGS} and $ENV{TEST_PROG_ARGS} =~ m/-r/ ) {
928 pir_output_is( $code, <<'OUT', $descr );
935 pir_output_is( $code, <<'OUT', $descr );
943 pir_output_like( <<'CODE', <<'OUTPUT', ':anon' );
952 unless null $P0 goto foo
973 open $S, '>', "test_l1.pir" or die "Can't write test_l1.pir";
985 open $S, '>', "test_l2.pir" or die "Can't write test_l2.pir";
997 system(".$PConfig{slash}parrot$PConfig{exe} -o test_l1.pbc test_l1.pir");
998 system(".$PConfig{slash}parrot$PConfig{exe} -o test_l2.pbc test_l2.pir");
1000 END { unlink(qw/ test_l1.pir test_l2.pir test_l1.pbc test_l2.pbc /); }
1002 pir_output_is( <<'CODE', <<'OUTPUT', 'multiple :load' );
1005 load_bytecode "test_l1.pir"
1006 load_bytecode "test_l2.pir"
1008 load_bytecode "test_l1.pbc" # these have to be ignored
1009 load_bytecode "test_l2.pbc"
1022 pir_output_is( <<'CODE', <<'OUTPUT', "immediate code as const" );
1023 .sub make_pi :immediate :anon
1032 .const .Sub pi = "make_pi"
1040 pir_output_is( <<'CODE', <<'OUTPUT', "immediate code as const - obj" );
1041 .sub make_obj :immediate :anon
1044 addattribute cl, 'x'
1048 setattribute o, 'x', $P0
1053 .const .Sub o = "make_obj"
1054 $P0 = getattribute o, 'x'
1062 pir_output_is( <<'CODE', <<'OUTPUT', "__get_regs_used 1" );
1065 .include "interpinfo.pasm"
1066 m = interpinfo .INTERPINFO_CURRENT_SUB
1067 $I0 = m."__get_regs_used"('N')
1069 $I0 = m."__get_regs_used"('I')
1071 $I0 = m."__get_regs_used"('S')
1073 $I0 = m."__get_regs_used"('P')
1082 pir_output_is( <<'CODE', <<'OUTPUT', "__get_regs_used 2" );
1088 .include "interpinfo.pasm"
1089 m = interpinfo .INTERPINFO_CURRENT_SUB
1095 $I0 = m."__get_regs_used"('N')
1097 $I0 = m."__get_regs_used"('I')
1099 $I0 = m."__get_regs_used"('S')
1101 $I0 = m."__get_regs_used"('P')
1112 <<"CODE", <<'OUTPUT', 'warn on in main', todo => "RT#46819 core undef doesn't warn here. Should it?" );
1114 .include "warnings.pasm"
1115 warningson .PARROT_WARNINGS_UNDEF_FLAG
1126 pir_output_is( <<"CODE", <<'OUTPUT', 'warn on in sub' );
1128 .include "warnings.pasm"
1135 warningson .PARROT_WARNINGS_UNDEF_FLAG
1142 <<"CODE", <<'OUTPUT', 'warn on in sub, turn off in f2', todo => "RT#46819 core undef doesn't warn here. Should it?" );
1144 .include "warnings.pasm"
1152 warningson .PARROT_WARNINGS_UNDEF_FLAG
1158 warningsoff .PARROT_WARNINGS_UNDEF_FLAG
1161 /uninit.*\n.*\nback\nok/
1164 pir_output_is( <<'CODE', <<'OUTPUT', ':postcomp' );
1189 pir_output_is( <<'CODE', <<'OUTPUT', 'unicode sub names, compilation' );
1190 .sub unicode:"\u7777"
1197 pir_output_is( <<'CODE', <<'OUTPUT', 'unicode sub names, invocation' );
1198 .sub unicode:"\u7777"
1209 pir_output_is( <<'CODE', <<'OUTPUT', 'unicode sub names, dynamic' );
1210 .sub unicode:"\u7777"
1215 $P1 = find_name unicode:"\u7777"
1222 pir_output_is( <<'CODE', <<'OUTPUT', 'unicode sub names' );
1223 .sub unicode:"\u7777"
1228 # unicode:"\u7777" ends up as a string nicode:"\u7777
1229 # (or it did, in r12860)
1230 $P1 = find_name 'nicode:"\u7777'
1231 unless null $P1 goto bad
1239 pir_output_is( <<'CODE', <<'OUTPUT', 'unicode sub constant' );
1241 .const .Sub s = unicode:"\u7777"
1245 .sub unicode:"\u7777"
1252 pir_output_is( <<'CODE', <<'OUTPUT', 'literal \u in sub name (not unicode)' );
1260 pir_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode with .pir (RT #39807)' );
1262 load_bytecode 'PGE.pbc'
1263 load_bytecode 'dumper.pir'
1264 load_bytecode 'PGE/Dumper.pir'
1266 $P0 = compreg 'PGE::P5Regex'
1268 $P2 = $P1('fooaabbbar')
1273 "VAR1" => PMC 'PGE::Match' => "aabbb" @ 3
1276 pir_output_is( <<'CODE', <<'OUTPUT', 'load_bytecode with .pbc (RT #39807)' );
1278 load_bytecode 'PGE.pbc'
1279 load_bytecode 'dumper.pbc'
1280 load_bytecode 'PGE/Dumper.pbc'
1282 $P0 = compreg 'PGE::P5Regex'
1284 $P2 = $P1('fooaabbbar')
1289 "VAR1" => PMC 'PGE::Match' => "aabbb" @ 3
1292 pir_error_output_like( <<'CODE', qr/Null PMC access in invoke()/, 'invoking null pmc' );
1299 pir_output_is( <<'CODE', <<'OUTPUT', ":init" );
1312 pir_output_is( <<'CODE', <<'OUTPUT', 'assign' );
1314 $P0 = get_global 'ok'
1329 pir_output_is( <<'CODE', <<'OUTPUT', 'assign w/:outer' );
1331 $P0 = get_global 'ok'
1339 .sub ok :outer('main')
1346 pir_output_is( <<'CODE', <<'OUTPUT', 'get_namespace()' );
1348 $P0 = get_global 'main'
1349 $P0 = $P0.'get_namespace'()
1350 $P0 = $P0.'get_name'()
1354 $P0 = get_global ['Foo'; 'Bar'], 'foo'
1355 $P0 = $P0.'get_namespace'()
1356 $P0 = $P0.'get_name'()
1361 .namespace ['Foo'; 'Bar']
1370 pir_output_is( <<'CODE', <<'OUTPUT', 'arity()' );
1372 $P0 = get_global 'none'
1376 $P0 = get_global 'one'
1380 $P0 = get_global 'four'
1384 $P0 = get_global 'all_slurpy'
1388 $P0 = get_global 'some_optional'
1392 $P0 = get_global 'some_named'
1396 $P0 = get_global 'allsorts'
1416 .param pmc s :slurpy
1421 .param int b :optional
1422 .param int bo :opt_flag
1434 .param int b :optional
1435 .param int bo :opt_flag
1437 .param pmc s :slurpy
1449 pir_output_is( <<'CODE', <<'OUTPUT', 'set_outer' );
1451 $P0 = find_global "example_outer"
1452 $P1 = find_global "example_inner"
1461 $P0 = 'I can has outer?'
1465 $P0 = find_lex "Foo"
1472 pir_output_is( <<'CODE', <<'OUTPUT', ':outer with identical sub names' );
1474 $P0 = get_hll_global ['ABC'], 'outer'
1477 $P0 = get_hll_global ['DEF'], 'outer'
1482 .sub 'outer' :lexid('abc_outer')
1489 .sub 'inner' :outer('abc_outer')
1491 $P0 = find_lex '$abc'
1496 .sub 'outer' :lexid('def_outer')
1503 .sub 'inner' :outer('def_outer')
1505 $P0 = find_lex '$def'
1517 pir_output_is( <<'CODE', <<'OUTPUT', ':lexid and identical string constants' );
1529 .sub 'bar' :lexid("abc")
1541 # cperl-indent-level: 4
1544 # vim: expandtab shiftwidth=4: