diff --git a/src/Perl6/Actions.nqp b/src/Perl6/Actions.nqp index 5de9d9bee95..383bbc69e73 100644 --- a/src/Perl6/Actions.nqp +++ b/src/Perl6/Actions.nqp @@ -2496,7 +2496,8 @@ Compilation unit '$file' contained the following violations: } else { $*W.handle_OFTYPE_for_pragma($/,'parameters'); - my %cont_info := $*W.container_type_info($/, $_ || '$', $*OFTYPE ?? [$*OFTYPE.ast] !! []); + my %cont_info := $*W.container_type_info($/, $_ || '$', + $*OFTYPE ?? [$*OFTYPE.ast] !! [], []); $list.push($*W.build_container_past( %cont_info, $*W.create_container_descriptor( @@ -2625,6 +2626,9 @@ Compilation unit '$file' contained the following violations: my int $have_of_type; my $of_type; + my int $have_is_type; + my $is_type; + $*W.handle_OFTYPE_for_pragma($/, $*SCOPE eq 'has' ?? 'attributes' !! 'variables'); if $*OFTYPE { $have_of_type := 1; @@ -2653,6 +2657,14 @@ Compilation unit '$file' contained the following violations: $of_type := $type; next; } + if $mod eq '&trait_mod:' { + my @args := $trait.args; + if nqp::elems(@args) == 1 && !nqp::isconcrete(@args[0]) { + $have_is_type := 1; + $is_type := @args[0]; + next; + } + } nqp::push(@late_traits, $_); } } @@ -2676,7 +2688,9 @@ Compilation unit '$file' contained the following violations: } my $attrname := ~$sigil ~ '!' ~ $desigilname; my %cont_info := $*W.container_type_info($/, $sigil, - $have_of_type ?? [$of_type] !! [], $shape, :@post); + $have_of_type ?? [$of_type] !! [], + $have_is_type ?? [$is_type] !! [], + $shape, :@post); my $descriptor := $*W.create_container_descriptor( %cont_info, 1, $attrname, %cont_info); @@ -2744,7 +2758,9 @@ Compilation unit '$file' contained the following violations: # 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] !! [], $shape, :@post); + $have_of_type ?? [$of_type] !! [], + $have_is_type ?? [$is_type] !! [], + $shape, :@post); my $descriptor := $*W.create_container_descriptor( %cont_info, 1, $varname || $name, %cont_info); diff --git a/src/Perl6/World.nqp b/src/Perl6/World.nqp index 197d01dc765..0d5d0b54156 100644 --- a/src/Perl6/World.nqp +++ b/src/Perl6/World.nqp @@ -1257,14 +1257,7 @@ class Perl6::World is HLL::World { } # Build container. - my $cont := nqp::create(%cont_info); - if %cont_info.REPR eq 'P6opaque' { - nqp::bindattr($cont, %cont_info, '$!descriptor', $descriptor); - if nqp::existskey(%cont_info, 'scalar_value') { - nqp::bindattr($cont, %cont_info, '$!value', - %cont_info); - } - } + my $cont := self.build_container(%cont_info, $descriptor); self.add_object($cont); $block.symbol($name, :value($cont)); self.install_package_symbol_unchecked($package, $name, $cont) if $scope eq 'our'; @@ -1285,16 +1278,41 @@ class Perl6::World is HLL::World { $cd } + # Builds a container. + method build_container(%cont_info, $descriptor) { + my $cont; + my $cont_type := %cont_info; + if nqp::istype($cont_type, self.find_symbol(['Scalar'])) { + $cont := nqp::create($cont_type); + nqp::bindattr($cont, %cont_info, '$!descriptor', $descriptor); + if nqp::existskey(%cont_info, 'scalar_value') { + nqp::bindattr($cont, %cont_info, '$!value', + %cont_info); + } + } + elsif nqp::istype($cont_type, self.find_symbol(['Array'])) || + nqp::istype($cont_type, self.find_symbol(['Hash'])) { + $cont := nqp::create($cont_type); + nqp::bindattr($cont, %cont_info, '$!descriptor', $descriptor); + } + else { + $cont := $cont_type.new; + try nqp::bindattr($cont, %cont_info, '$!descriptor', $descriptor); + } + $cont + } + # Given a sigil and the value type specified, works out the # container type (what should we instantiate and bind into the # attribute/lexpad), bind constraint (what could we bind to this # slot later), and if specified a constraint on the inner value # and a default value. - method container_type_info($/, $sigil, @value_type, $shape?, :@post) { + method container_type_info($/, $sigil, @value_type, @cont_type, $shape?, :@post) { my %info; %info := $sigil; @value_type[0] := nqp::decont(@value_type[0]) if @value_type; + @cont_type[0] := nqp::decont(@cont_type[0]) if @cont_type; for @post -> $con { @value_type[0] := self.create_subset(self.resolve_mo($/, 'subset'), @@ -1302,11 +1320,17 @@ class Perl6::World is HLL::World { $con); } if $sigil eq '@' { - %info := self.find_symbol(['Positional']); + if @cont_type { + %info := @cont_type[0]; + %info := @cont_type[0]; + } + else { + %info := self.find_symbol(['Positional']); + my $base_type_name := nqp::objprimspec(@value_type[0]) ?? 'array' !! 'Array'; + %info := self.find_symbol([$base_type_name]); + } if @value_type { my $vtype := @value_type[0]; - my $base_type_name := nqp::objprimspec($vtype) ?? 'array' !! 'Array'; - %info := self.find_symbol([$base_type_name]); %info := self.parameterize_type_with_args($/, %info, [$vtype], nqp::hash()); %info := self.parameterize_type_with_args($/, @@ -1315,7 +1339,6 @@ class Perl6::World is HLL::World { %info := $vtype; } else { - %info := self.find_symbol(['Array']); %info := %info; %info := self.find_symbol(['Mu']); %info := self.find_symbol(['Any']); @@ -1325,8 +1348,14 @@ class Perl6::World is HLL::World { } } elsif $sigil eq '%' { - %info := self.find_symbol(['Hash']); - %info := self.find_symbol(['Associative']); + if @cont_type { + %info := @cont_type[0]; + %info := @cont_type[0]; + } + else { + %info := self.find_symbol(['Hash']); + %info := self.find_symbol(['Associative']); + } if $shape { @value_type[0] := self.find_symbol(['Any']) unless +@value_type; my $shape_ast := $shape[0].ast; @@ -1373,6 +1402,9 @@ class Perl6::World is HLL::World { } } elsif $sigil eq '&' { + if @cont_type { + self.throw($/, 'X::NYI', :feature('is trait on &-sigil variable')); + } %info := self.find_symbol(['Scalar']); %info := %info; %info := self.find_symbol(['Callable']); @@ -1385,6 +1417,9 @@ class Perl6::World is HLL::World { %info := self.find_symbol(['Callable']); } else { + if @cont_type { + self.throw($/, 'X::NYI', :feature('is trait on $-sigil variable')); + } %info := self.find_symbol(['Scalar']); %info := %info; if @value_type { @@ -1513,7 +1548,8 @@ class Perl6::World is HLL::World { my $name := $varast.name; my $BLOCK := self.cur_lexpad(); self.handle_OFTYPE_for_pragma($/,'variables'); - my %cont_info := self.container_type_info(NQPMu, $var, $*OFTYPE ?? [$*OFTYPE.ast] !! []); + my %cont_info := self.container_type_info(NQPMu, $var, + $*OFTYPE ?? [$*OFTYPE.ast] !! [], []); my $descriptor := self.create_container_descriptor(%cont_info, 1, $name); self.install_lexical_container($BLOCK, $name, %cont_info, $descriptor, @@ -2543,21 +2579,12 @@ class Perl6::World is HLL::World { # serialization context. The type would be passed in this way. method pkg_add_attribute($/, $obj, $meta_attr, %lit_args, %obj_args, %cont_info, $descriptor) { - # Build container. - my $cont := nqp::create(%cont_info); - nqp::bindattr($cont, %cont_info, '$!descriptor', $descriptor); - if nqp::existskey(%cont_info, 'scalar_value') { - nqp::bindattr($cont, %cont_info, '$!value', - %cont_info); - } - # Create meta-attribute instance and add right away. Also add # it to the SC. + my $cont := self.build_container(%cont_info, $descriptor); my $attr := $meta_attr.new(:auto_viv_container($cont), |%lit_args, |%obj_args); $obj.HOW.add_attribute($obj, $attr); self.add_object($attr); - - # Return attribute that was built. $attr } diff --git a/src/core/Variable.pm b/src/core/Variable.pm index e1a9a94d096..b4bc8a3ea1f 100644 --- a/src/core/Variable.pm +++ b/src/core/Variable.pm @@ -35,11 +35,6 @@ multi sub trait_mod:(Variable:D $v, |c ) { expected => , ); } -multi sub trait_mod:(Variable:D $v, Mu:U $is ) { - $v.throw( 'X::Comp::NYI', - feature => "Variable trait 'is TypeObject'", - ); -} multi sub trait_mod:(Variable:D $v, Mu :$default!) { my $var := $v.var; my $what := $var.VAR.WHAT;