Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Ensure that when we mix in a role, its attributes are initialized app…
…ropriately (for example, any defaults are applied).
  • Loading branch information
jnthn committed Sep 19, 2011
1 parent d9b19d6 commit e97afdb
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
34 changes: 34 additions & 0 deletions src/core/Mu.pm
Expand Up @@ -86,6 +86,40 @@ my class Mu {
self
}

method BUILD_LEAST_DERIVED(%attrinit) {
# Get the build plan for just this class.
my $build_plan := pir::find_method__PPs(self.HOW, 'BUILDPLAN')(self.HOW, self);
my int $count = nqp::elems($build_plan);
my int $i = 0;
while nqp::islt_i($i, $count) {
my $task := nqp::atpos($build_plan, $i);
$i = nqp::add_i($i, 1);
if nqp::iseq_i(nqp::atpos($task, 0), 0) {
# Custom BUILD call.
nqp::atpos($task, 1)(self, |%attrinit);
}
elsif nqp::iseq_i(nqp::atpos($task, 0), 1) {
# See if we have a value to initialize this attr
# with.
my $key_name := nqp::p6box_s(nqp::atpos($task, 2));
if %attrinit.exists($key_name) {
nqp::getattr(self, nqp::atpos($task, 1),
nqp::atpos($task, 3)) = pir::nqp_decontainerize__PP(%attrinit{$key_name});
}
}
elsif nqp::iseq_i(nqp::atpos($task, 0), 2) {
unless nqp::attrinited(self, nqp::atpos($task, 1), nqp::atpos($task, 2)) {
my $attr := nqp::getattr(self, nqp::atpos($task, 1), nqp::atpos($task, 2));
$attr = nqp::atpos($task, 3)(self, $attr);
}
}
else {
die "Invalid BUILDALLPLAN";
}
}
self
}

proto method Numeric(|$) { * }
multi method Numeric(Mu:U:) {
note 'Use of uninitialized value in numeric context';
Expand Down
8 changes: 4 additions & 4 deletions src/core/operators.pm
Expand Up @@ -10,19 +10,19 @@ sub infix:<=>(Mu \$a, Mu \$b) is rw {
proto infix:<does>(|$) { * }
multi infix:<does>(Mu \$obj, Mu:U \$role) is rw {
# XXX Mutability check.
$obj.HOW.mixin($obj, $role);
$obj.HOW.mixin($obj, $role).BUILD_LEAST_DERIVED({});
}
multi infix:<does>(Mu \$obj, @roles) is rw {
# XXX Mutability check.
$obj.HOW.mixin($obj, |@roles);
$obj.HOW.mixin($obj, |@roles).BUILD_LEAST_DERIVED({});
}

proto infix:<but>(|$) { * }
multi infix:<but>(Mu \$obj, Mu:U \$role) {
$obj.HOW.mixin($obj.clone(), $role);
$obj.HOW.mixin($obj.clone(), $role).BUILD_LEAST_DERIVED({});
}
multi infix:<but>(Mu \$obj, @roles) {
$obj.HOW.mixin($obj.clone(), |@roles);
$obj.HOW.mixin($obj.clone(), |@roles).BUILD_LEAST_DERIVED({});
}

sub SEQUENCE($left, $right, :$exclude_end) {
Expand Down

0 comments on commit e97afdb

Please sign in to comment.