Skip to content

Commit

Permalink
Streamline variable "is" / "of" handling
Browse files Browse the repository at this point in the history
- use nqp::null as a semaphore instead of an additional int
- add "check_type" sub to see if a type was specified before
- check for multiple "is" traits on a variable and sorry about that
  • Loading branch information
lizmat committed May 12, 2020
1 parent de43f19 commit 5561669
Showing 1 changed file with 25 additions and 24 deletions.
49 changes: 25 additions & 24 deletions src/Perl6/Actions.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -3668,21 +3668,28 @@ class Perl6::Actions is HLL::Actions does STDActions {
my $BLOCK := $*W.cur_lexpad();
my $package := $/.package;

my int $have_of_type;
my $of_type;
my int $have_is_type;
my $is_type;
my $of_type := nqp::null;
my $is_type := nqp::null;

$*W.handle_OFTYPE_for_pragma($/, $*SCOPE eq 'has' ?? 'attributes' !! 'variables');
if $*OFTYPE {
$have_of_type := 1;
$of_type := $*OFTYPE.ast;
my $archetypes := $of_type.HOW.archetypes;
unless $archetypes.nominal || $archetypes.nominalizable || $archetypes.generic || $archetypes.definite {
$*OFTYPE.typed_sorry('X::Syntax::Variable::BadType', type => $of_type);
}
}

sub check_type($thrower, $outer, $inner) {
unless nqp::isnull($outer) {
$thrower.typed_sorry(
'X::Syntax::Variable::ConflictingTypes',
outer => $outer, inner => $inner
);
}
$inner
}

# Process traits for `is Type` and `of Type`, which get special
# handling by the compiler.
my @late_traits;
Expand All @@ -3691,14 +3698,7 @@ class Perl6::Actions is HLL::Actions does STDActions {
if $trait {
my str $mod := $trait.mod;
if $mod eq '&trait_mod:<of>' {
my $type := $trait.args[0];
if $have_of_type {
$_.typed_sorry(
'X::Syntax::Variable::ConflictingTypes',
outer => $of_type, inner => $type)
}
$have_of_type := 1;
$of_type := $type;
$of_type := check_type($_, $of_type, $trait.args[0]);
next;
}

Expand All @@ -3712,19 +3712,20 @@ class Perl6::Actions is HLL::Actions does STDActions {

# is Foo
if $elems == 1 {
$have_is_type := 1;
$is_type := $type;
$is_type := check_type($_, $is_type, $type);
next; # handled the trait now
}

# is Foo[Bar]
elsif $elems == 2 && $trait.args[1] -> $params {
my $List := $*W.find_single_symbol('List');
if nqp::istype($params,$List) {
$have_is_type := 1;
$is_type := $type.HOW.parameterize(
$type,
|nqp::getattr($params,$List,'$!reified')
$is_type := check_type(
$_, $is_type,
$type.HOW.parameterize(
$type,
|nqp::getattr($params,$List,'$!reified')
)
);
next; # handled the trait now
}
Expand Down Expand Up @@ -3755,8 +3756,8 @@ class Perl6::Actions is HLL::Actions does STDActions {
}
my $attrname := ~$sigil ~ '!' ~ $desigilname;
my %cont_info := $*W.container_type_info($/, $sigil,
$have_of_type ?? [$of_type] !! [],
$have_is_type ?? [$is_type] !! [],
nqp::isnull($of_type) ?? [] !! [$of_type],
nqp::isnull($is_type) ?? [] !! [$is_type],
$shape, :@post);
my $descriptor := $*W.create_container_descriptor(
%cont_info<value_type>, $attrname, %cont_info<default_value>);
Expand Down Expand Up @@ -3801,7 +3802,7 @@ class Perl6::Actions is HLL::Actions does STDActions {
# Some things can't be done to our vars.
my $varname;
if $*SCOPE eq 'our' {
if $have_of_type || @post {
if !nqp::isnull($of_type) || @post {
$/.panic("Cannot put a type constraint on an 'our'-scoped variable");
}
elsif $shape {
Expand All @@ -3827,8 +3828,8 @@ class Perl6::Actions is HLL::Actions does STDActions {
# Create a container descriptor. Default to rw and set a
# type if we have one; a trait may twiddle with that later.
my %cont_info := $*W.container_type_info($/, $sigil,
$have_of_type ?? [$of_type] !! [],
$have_is_type ?? [$is_type] !! [],
nqp::isnull($of_type) ?? [] !! [$of_type],
nqp::isnull($is_type) ?? [] !! [$is_type],
$shape, :@post);
my $descriptor := $*W.create_container_descriptor(
%cont_info<value_type>, $varname || $name, %cont_info<default_value>);
Expand Down

0 comments on commit 5561669

Please sign in to comment.