Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for re-binding #800

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions S03-binding/rebinding.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use v6;
use Test;

=begin pod

Rebinding from L<S03> (with some guidance from L<S02/List assignment and binding>
and L<S06/Parameters and arguments>). See rakudo/rakudo#4536 for related discussion

=end pod

subtest "Sigiled variables can be rebound", {
plan 3;
my $scalar := 'old scalar';
$scalar := 'new';
is $scalar, 'new', '$-sigiled variable can be rebound';

my @positional := ['old'];
@positional := ['new'];
is @positional, ['new'], '@-sigiled variable can be rebound';

my %associative := {:old};
%associative := {:new};
is %associative, {:new}, '%-sigiled variable can be rebound';
}

subtest "Scalars in signatures be rebound if they are 'copy' or 'rw'", {
plan 4;
is-deeply do {
sub f($bound-scalar-copy is copy) { $bound-scalar-copy := 'new' }
f 'old-value' }, 'new',
"Scalars in function signatures can be rebound when they are 'is copy'";
is-deeply do {
sub f($bound-scalar-rw is rw) { $bound-scalar-rw := 'new' }
f my $ = 'old-value' }, 'new',
"Scalars in function signatures can be rebound when they are 'is rw' (and get a writable container)";
is-deeply do {
my ($bound-scalar-copy is copy) := ('old-value',);
$bound-scalar-copy := 'new' }, 'new',
"Scalars in bound signatures can be rebound when they are 'is copy'";
is-deeply do {
my ($bound-scalar-rw is rw) := (my $ = 'old-value',);
$bound-scalar-rw := 'new'}, 'new',
"Scalars in bound signatures can be rebound when they are 'is rw' (and get a writable container)";
}

subtest "Scalars in signatures that aren't 'copy' or 'rw' cannot be rebound", {
plan 4;
throws-like {
‘sub f($bound-scalar-in-sig) { $bound-scalar-in-sig := 'new' }’.EVAL },
X::Bind::Rebind, message => /'$bound-scalar-in-sig'/ & /'signature'/,
"Scalars in function signatures cannot be rebound";
throws-like {
'sub f(Mu $bound-scalar-with-type) { $bound-scalar-with-type := 0 }'.EVAL },
X::Bind::Rebind, message => /'$bound-scalar-with-type'/ & /'signature'/,
"Scalars in function signatures cannot be rebound even if they have a type constraint";
throws-like {
‘my ($bound-scalar,) := ('original',); $bound-scalar := 'new'’.EVAL },
X::Bind::Rebind, message => /'$bound-scalar'/ & /'signature'/,
"Scalars in bound signatures cannot be rebound";
throws-like {
‘my ($a, $b, Int $bound-scalar) := (0, 0, 0); $bound-scalar := 42’.EVAL },
X::Bind::Rebind, message => /'$bound-scalar'/ & /'signature'/,
"Scalars in more complex bound signatures cannot be rebound";
}

subtest "Positional and Associative variables in signatures can be rebound if they are 'copy'", {
plan 4;
is-deeply do {
sub f(@positional-copy is copy) { @positional-copy := ['new'] }
f ['old-value'] }, ['new'],
"Positional variables in function signatures can be rebound when they are 'is copy'";
is-deeply do {
my ($a, @positional-copy is copy) := (0, ['old']);
@positional-copy := ['new'] }, ['new'],
"Positional variables in bound signatures can be rebound when they are 'is copy'";
is-deeply do {
sub f(%associative-copy is copy) { %associative-copy := {:new} }
f {:old-value} }, %(:new),
"Associative variables in function signatures can be rebound when they are 'is copy'";
is-deeply do {
my ($a, %associative-copy is copy) := (0, {:old});
%associative-copy := {:new} }, %(:new),
"Associative variables bound in signatures can be rebound when they are 'is copy'";
}

subtest "Positional and Associative variables in signatures that aren't 'copy' cannot be rebound", {
plan 4;
throws-like {
‘sub f(@bound-positional-in-sig) { @bound-positional-in-sig := ['new'] }’.EVAL },
X::Bind::Rebind, message => /'@bound-positional-in-sig'/ & /'signature'/,
"Positional variables in function signatures cannot be rebound";
throws-like {
‘my ($a, @bound-positional) := (0, []); @bound-positional := ['new']’.EVAL },
X::Bind::Rebind, message => /'@bound-positional'/ & /'signature'/,
"Positional variables in bound signatures cannot be rebound";
throws-like {
'sub f(%bound-associative-in-sig) { %bound-associative-in-sig := {:new} }'.EVAL },
X::Bind::Rebind, message => /'%bound-associative-in-sig'/ & /'signature'/,
"Associative variables in function signatures cannot be rebound";
throws-like {
‘my ($a, %bound-associative) := (0, []); %bound-associative := {:new}’.EVAL },
X::Bind::Rebind, message => /'%bound-associative'/ & /'signature'/,
"Associative variables in bound signatures cannot be rebound";
}

subtest 'Sigilless "variables" can never be rebound', {
plan 4;
throws-like {
‘my \sigilless = 'old'; sigilless := 'new'’.EVAL },
X::Bind::Rebind, message => /'sigilless'/ & /'signature'/.none,
"Sigilless scalar terms cannot be rebound";
throws-like {
‘my \sigilless-array = ['old']; sigilless-array := ['new']’.EVAL },
X::Bind::Rebind, message => /'sigilless-array'/ & /'signature'/.none,
"Sigilless positional terms cannot be rebound";
throws-like {
‘my \sigilless-hash = {:old}; sigilless-hash := {:new}’.EVAL },
X::Bind::Rebind, message => /'sigilless-hash'/ & /'signature'/.none,
"Sigilless associative terms cannot be rebound";
throws-like {
‘constant con = 'old'; con := 'new'’.EVAL },
X::Bind::Rebind, message => /'con'/ & /'signature'/.none,
"Constants cannot be rebound";
}

subtest "Code items can never be rebound", {
plan 2;
throws-like {
'sub f() { }; &f := &say; }'.EVAL },
X::Bind::Rebind, message => /'&f'/ & /'signature'/.none,
"A sub cannot be rebound";
throws-like {
'my regex reg-exp { old }; &reg-exp := /new/; }'.EVAL },
X::Bind::Rebind, message => /'&reg-exp'/ & /'signature'/.none,
"A regex cannot be rebound";
}

subtest "Terms can never be rebound", {
plan 4;
throws-like {
'my class C { has $.old }; C := class { has $.new } }'.EVAL },
X::Bind::Rebind, message => /'C'/ & /'signature'/.none,
"A class cannot be rebound";
throws-like {
'my role R { has $.old }; R := role { has $.new } }'.EVAL },
X::Bind::Rebind, message => /'R'/ & /'signature'/.none,
"A role cannot be rebound";
throws-like {
'my grammar G { }; G := grammar { } }'.EVAL },
X::Bind::Rebind, message => /'G'/ & /'signature'/.none,
"A grammar cannot be rebound";
throws-like {
'int := str;'.EVAL },
X::Bind::Rebind, message => /'int'/ & /'signature'/.none,
"Native types cannot be rebound";
}

subtest "Items that were never bound don't throw *re*binding errors", {
plan 8;
given (try { ‘my int $var := 'new'’.EVAL }) {
cmp-ok $!, &[!~~], X::Bind::Rebind, ‘Binding to a native type doesn't throw X::Bind::Rebind’;
throws-like {$!.throw}, X::Bind::NativeType, 'Binding to a native type throws X::Bind::NativeType' }
given (try { ‘'literal string' := 'new'’.EVAL}) {
cmp-ok $!, &[!~~], X::Bind::Rebind, ‘Binding to a literal doesn't throw X::Bind::Rebind’;
throws-like {$!.throw}, X::Bind, 'Binding to a literal throws X::Bind' }
given (try { ‘sub f {}; f() := 'new'’.EVAL }) {
cmp-ok $!, &[!~~], X::Bind::Rebind, ‘Binding to a function call LHS doesn't throw X::Bind::Rebind’;
throws-like {$!.throw}, X::Bind, 'Binding to a function call LHS throws X::Bind' }
given (try { ‘::OUTER := 'new'’.EVAL }) {
cmp-ok $!, &[!~~], X::Bind::Rebind, ‘Binding to a pseudo-package LHS doesn't throw X::Bind::Rebind’;
throws-like {$!.throw}, X::Bind, 'Binding to a pseudo-package LHS throws X::Bind' }
}

done-testing;
3 changes: 2 additions & 1 deletion spectest.data
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ S03-binding/attributes.t
S03-binding/closure.t
S03-binding/hashes.t
S03-binding/nested.t
S03-binding/rebinding.t
S03-binding/ro.t
S03-binding/scalars.t
S03-buf/read-int.t # moar
Expand Down Expand Up @@ -845,7 +846,7 @@ S15-string-types/Uni.t # moar
S15-unicode-information/unimatch-general.t # moar
S15-unicode-information/uniname.t
S15-unicode-information/uniprop.t # moar
S15-unicode-information/unival.t # moar
S15-unicode-information/unival.t # moar
S16-filehandles/argfiles.t
S16-filehandles/chmod.t
S16-filehandles/filestat.t
Expand Down