#!perl
# Copyright (C) 2001-2007, The Perl Foundation.
# $Id: stacks.t 22984 2007-11-23 17:49:26Z kjs $
use strict;
use warnings;
use lib qw( . lib ../lib ../../lib );
use Test::More;
use Parrot::Test tests => 24;
=head1 NAME
t/op/stacks.t - Stacks
=head1 SYNOPSIS
% prove t/op/stacks.t
=head1 DESCRIPTION
Tests for stack operations.
Currently only the ops C<save>, C<restore> and C<rotate_up> are tested.
=cut
# This defines two macros:
# fp_eq N, N, LABEL
# fp_ne N, N, LABEL
# which will conditionally branch
# to LABEL if abs(n,n) < epsilon
my $fp_equality_macro = <<'ENDOFMACRO';
.macro fp_eq(J,K,L)
save N0
save N1
save N2
set N0, .J
set N1, .K
sub N2, N1,N0
abs N2, N2
gt N2, 0.000001, .$FPEQNOK
restore N2
restore N1
restore N0
branch .L
.label $FPEQNOK:
restore N2
restore N1
restore N0
.endm
.macro fp_ne(J,K,L)
save N0
save N1
save N2
set N0, .J
set N1, .K
sub N2, N1,N0
abs N2, N2
lt N2, 0.000001, .$FPNENOK
restore N2
restore N1
restore N0
branch .L
.label $FPNENOK:
restore N2
restore N1
restore N0
.endm
ENDOFMACRO
############### Tests ##################
# Test proper stack chunk handling
pasm_output_is( <<CODE, <<'OUTPUT', 'save_i & restore_i' );
set I3, 1
testloop:
set I0, 0
set I1, I3
saveloop:
inc I0
save I0
ne I0, I1, saveloop
restoreloop:
restore I0
ne I0, I1, error
dec I1
ne I1, 0, restoreloop
add I3, I3, 1
ne I3, 769, testloop # At least 3 stack chunks
print "OK\\n"
error: end
CODE
OK
OUTPUT
# Rotate
pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 0' );
set I0, 1
save I0
set I0, 2
save I0
rotate_up 0
restore I0
print I0
print "\\n"
end
CODE
2
OUTPUT
pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 1' );
set I0, 1
save I0
set I0, 2
save I0
rotate_up 1
restore I0
print I0
print "\\n"
end
CODE
2
OUTPUT
pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 2' );
set I0, 1
save I0
set I0, 2
save I0
rotate_up 2
restore I0
print I0
print "\\n"
end
CODE
1
OUTPUT
pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate 3' );
set I0, 1
save I0
set I0, 2
save I0
set I0, 3
save I0
rotate_up 3
restore I0
print I0
restore I0
print I0
restore I0
print I0
print "\\n"
end
CODE
213
OUTPUT
pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate -1' );
set I0, 1
save I0
set I0, 2
save I0
set I0, 3
save I0
rotate_up -1
restore I0
print I0
restore I0
print I0
restore I0
print I0
print "\\n"
end
CODE
321
OUTPUT
pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate -2' );
set I0, 1
save I0
set I0, 2
save I0
set I0, 3
save I0
rotate_up -2
restore I0
print I0
restore I0
print I0
restore I0
print I0
print "\\n"
end
CODE
231
OUTPUT
pasm_output_is( <<"CODE", <<'OUTPUT', 'rotate -3' );
set I0, 1
save I0
set I0, 2
save I0
set I0, 3
save I0
rotate_up -3
restore I0
print I0
restore I0
print I0
restore I0
print I0
print "\\n"
end
CODE
132
OUTPUT
pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate with a full stack chunk' );
set I0, 0
FOO: save I0
inc I0
lt I0, 256, FOO
rotate_up 2
restore I1
print I1
print "\n"
end
CODE
254
OUTPUT
pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate across stack chunk boundary' );
set I0, 0
FOO: save I0
inc I0
lt I0, 257, FOO
rotate_up 2
restore I1
print I1
print "\n"
end
CODE
255
OUTPUT
pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate by stack chunk size' );
set I0, 0
FOO: save I0
inc I0
lt I0, 300, FOO
rotate_up -256
restore I1
print I1
print "\n"
end
CODE
44
OUTPUT
pasm_output_is( <<'CODE', <<'OUTPUT', 'rotate by more than stack chunk size' );
set I0, 0
FOO: save I0
inc I0
lt I0, 300, FOO
rotate_up -257
restore I1
print I1
print "\n"
end
CODE
43
OUTPUT
pasm_error_output_like( <<"CODE", <<'OUTPUT', 'rotate up by more than stack size' );
set I0, 1
save I0
set I0, 2
save I0
rotate_up 3
end
CODE
/Stack too shallow!/
OUTPUT
pasm_error_output_like( <<"CODE", <<'OUTPUT', 'rotate down by more than stack size' );
set I0, 1
save I0
set I0, 2
save I0
rotate_up -3
end
CODE
/Stack too shallow!/
OUTPUT
pasm_output_is( <<'CODE', <<'OUTPUT', 'save/savec for strings' );
set S0, "Foobar"
savec S0
chopn S0, 3
print S0
print "\n"
restore S2
print S2
print "\n"
set S1, "Foobar"
save S1
chopn S1, 3
print S1
print "\n"
restore S3
print S3
print "\n"
end
CODE
Foo
Foobar
Foo
Foo
OUTPUT
pasm_output_is( <<CODE, <<OUTPUT, "save, restore" );
@{[ $fp_equality_macro ]}
set I0, 1
save I0
set I0, 2
print I0
print "\\n"
restore I0
print I0
print "\\n"
set N0, 1.0
save N0
set N0, 2.0
.fp_eq (N0, 2.0, EQ1)
print "not "
EQ1: print "equal to 2.0\\n"
restore N0
.fp_eq (N0, 1.0, EQ2)
print "not "
EQ2: print "equal to 1.0\\n"
set S0, "HONK\\n"
save S0
set S0, "HONK HONK\\n"
print S0
restore S0
print S0
save 123
restore I0
print I0
print "\\n"
save 3.14159
restore N0
.fp_eq (N0, 3.14159, EQ3)
print "<kansas> not "
EQ3: print "equal to PI\\n"
save "All the world's people\\n"
restore S0
print S0
new P0, 'String'
set P0, "never to escape\\n"
save P0
new P0, 'String'
set P0, "find themselves caught in a loop\\n"
print P0
restore P0
print P0
end
CODE
2
1
equal to 2.0
equal to 1.0
HONK HONK
HONK
123
equal to PI
All the world's people
find themselves caught in a loop
never to escape
OUTPUT
pasm_output_is( <<CODE, <<OUTPUT, "entrytype" );
set I0, 12
set N0, 0.1
set S0, "Difference Engine #2"
new P0, 'String'
set P0, "Shalmaneser"
save P0
save S0
save "Wintermute"
save N0
save 1.23
save I0
save 12
print "starting\\n"
set I1, 0
LOOP: entrytype I0, I1
print I0
print "\\n"
inc I1
lt I1, 7, LOOP
print "done\\n"
end
CODE
starting
1
1
2
2
3
3
4
done
OUTPUT
pasm_error_output_like( <<CODE, <<OUTPUT, "entrytype, beyond stack depth" );
save 12
print "ready\\n"
entrytype I0, 1
print "done\\n"
end
CODE
/ready\nStack Depth wrong/
OUTPUT
pasm_output_is( <<'CODE', <<'OUTPUT', "depth op" );
depth I0
print I0
print "\n"
save "Foo"
depth I0
print I0
print "\n"
restore S0
set I1, 0
LOOP: save I1
inc I1
lt I1, 1024, LOOP
depth I0
print I0
print "\n"
end
CODE
0
1
1024
OUTPUT
pasm_output_is( <<'CODE', <<'OUTPUT', "saveall/restoreall" );
set S0,"test ok"
set N0,4.3
set I0,6
saveall
set S0,"test not ok"
set N0,4.1
set I0,8
restoreall
print I0
print "\n"
print N0
print "\n"
print S0
print "\n"
end
CODE
6
4.300000
test ok
OUTPUT
pasm_output_is( <<CODE, <<'OUTPUT', "lookback" );
@{[ $fp_equality_macro ]}
save 1
save 1.0
save "Foo"
new P12, 'Hash'
set P12["Apple"], "Banana"
save P12
lookback P0, 0
lookback S0, 1
lookback N0, 2
lookback I0, 3
set S2, P0["Apple"]
eq S2, "Banana", OK1
print "not "
OK1: print "ok 1\\n"
eq I0, 1, OK2
print "not "
OK2: print "ok 2\\n"
.fp_eq (N0, 1.0, OK3)
print "not "
OK3: print "ok 3\\n"
eq S0, "Foo", OK4
print "not "
OK4: print "ok 4\\n"
lookback I1, -1
lookback N1, -2
lookback S1, -3
lookback P1, -4
eq I0, 1, OK5
print "not "
OK5: print "ok 5\\n"
.fp_eq (N0, 1.0, OK6)
print "not "
OK6: print "ok 6\\n"
eq S0, "Foo", OK7
print "not "
OK7: print "ok 7\\n"
set S3, P1["Apple"]
eq S3, "Banana", OK8
print "not "
OK8: print "ok 8\\n"
end
CODE
ok 1
ok 2
ok 3
ok 4
ok 5
ok 6
ok 7
ok 8
OUTPUT
SKIP: {
skip( "no stack limit currently", 3 );
pasm_output_is( <<CODE, <<'OUTPUT', "check limit - User" );
lp:
save I0
branch lp
end
CODE
Stack 'User' too deep
OUTPUT
pasm_output_is( <<CODE, <<'OUTPUT', "check limit - Pad" );
lp:
new_pad 0
branch lp
end
CODE
Stack 'Pad' too deep
OUTPUT
pasm_output_is( <<CODE, <<'OUTPUT', "check limit - Control" );
lp:
bsr lp
end
CODE
Stack 'Control' too deep
OUTPUT
}
##############################
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4:
syntax highlighted by Code2HTML, v. 0.9.1