Skip to content

Commit

Permalink
RakuAST: split BEGIN time into pre-children and post-children
Browse files Browse the repository at this point in the history
Routines have BEGIN time effects that need to be applied before its
children try to resolve names as well as effects that need the body to
be processed. Augment PERFORM-BEGIN by adding support for
PERFORM-BEGIN-BEFORE-CHILDREN and PERFORM-BEGIN-AFTER-CHILDREN.
  • Loading branch information
niner committed Jan 28, 2023
1 parent 9cfaff1 commit 85240f0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 33 deletions.
1 change: 0 additions & 1 deletion src/Raku/Actions.nqp
Expand Up @@ -1593,7 +1593,6 @@ class Raku::Actions is HLL::Actions does Raku::CommonActions {
}
}
$routine.replace-body($<onlystar> ?? $<onlystar>.ast !! $<blockoid>.ast);
$routine.IMPL-ENSURE-IMPLICITS($*R);
$routine.IMPL-CHECK($*R, $*CU.context, 1);
$routine.ensure-begin-performed($*R, $*CU.context);
self.attach: $/, $routine;
Expand Down
13 changes: 4 additions & 9 deletions src/Raku/ast/base.rakumod
Expand Up @@ -103,13 +103,8 @@ class RakuAST::Node {
# Apply any pre-children BEGIN-time effects that were not yet
# performed (and figure out if we have to do the later).
my int $needs-begin-after;
if nqp::istype(self, RakuAST::BeginTime) {
if self.is-begin-performed-before-children() {
self.ensure-begin-performed($resolver, $context);
}
else {
$needs-begin-after := 1;
}
if nqp::istype(self, RakuAST::BeginTime) && self.is-begin-performed-before-children() {
self.ensure-begin-performed($resolver, $context, :phase(1));
}

# Visit children.
Expand All @@ -122,8 +117,8 @@ class RakuAST::Node {
$resolver.pop-package() if $is-package;

# Perform any after-children BEGIN-time effects.
if $needs-begin-after {
self.ensure-begin-performed($resolver, $context);
if nqp::istype(self, RakuAST::BeginTime) && self.is-begin-performed-after-children() {
self.ensure-begin-performed($resolver, $context, :phase(2));
}

# Unless in resolve-only mode, do other check-time activities.
Expand Down
27 changes: 22 additions & 5 deletions src/Raku/ast/begintime.rakumod
Expand Up @@ -10,14 +10,31 @@ class RakuAST::BeginTime is RakuAST::Node {
}

# Should the BEGIN-time effects be performed before or after the parse of
# this node?
# this node or both?
method is-begin-performed-before-children() { False }
method is-begin-performed-after-children() { !self.is-begin-performed-before-children }

# Ensure the begin-time effects are performed.
method ensure-begin-performed(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) {
unless $!begin-performed {
self.PERFORM-BEGIN($resolver, $context);
nqp::bindattr_i(self, RakuAST::BeginTime, '$!begin-performed', 1);
method ensure-begin-performed(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context, int :$phase) {
if nqp::can(self, 'PERFORM-BEGIN-BEFORE-CHILDREN') || nqp::can(self, 'PERFORM-BEGIN-AFTER-CHILDREN') {
if $phase == 0 && self.is-begin-performed-before-children || $phase == 1 {
unless $!begin-performed +& 1 {
self.PERFORM-BEGIN-BEFORE-CHILDREN($resolver, $context);
nqp::bindattr_i(self, RakuAST::BeginTime, '$!begin-performed', $!begin-performed +| 1);
}
}
if $phase == 0 && self.is-begin-performed-after-children || $phase == 2 {
unless $!begin-performed +& 2 {
self.PERFORM-BEGIN-AFTER-CHILDREN($resolver, $context);
nqp::bindattr_i(self, RakuAST::BeginTime, '$!begin-performed', $!begin-performed +| 2);
}
}
}
else {
unless $!begin-performed {
self.PERFORM-BEGIN($resolver, $context);
nqp::bindattr_i(self, RakuAST::BeginTime, '$!begin-performed', 3);
}
}
Nil
}
Expand Down
27 changes: 9 additions & 18 deletions src/Raku/ast/code.rakumod
Expand Up @@ -1226,9 +1226,10 @@ class RakuAST::Routine
$routine
}

method is-begin-performed-before-children() { False }
method is-begin-performed-before-children() { True }
method is-begin-performed-after-children() { True }

method IMPL-ENSURE-IMPLICITS() {
method PERFORM-BEGIN-BEFORE-CHILDREN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) {
my $placeholder-signature := self.placeholder-signature;
if $placeholder-signature {
$placeholder-signature.IMPL-ENSURE-IMPLICITS;
Expand All @@ -1238,7 +1239,7 @@ class RakuAST::Routine
}
}

method PERFORM-BEGIN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) {
method PERFORM-BEGIN-AFTER-CHILDREN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) {
# Make sure that our placeholder signature has resolutions performed.
my $placeholder-signature := self.placeholder-signature;
if $placeholder-signature {
Expand Down Expand Up @@ -1562,7 +1563,10 @@ class RakuAST::Methodish
}
}

method IMPL-ENSURE-IMPLICITS(RakuAST::Resolver $resolver) {
method is-begin-performed-before-children() { True }
method is-begin-performed-after-children() { True }

method PERFORM-BEGIN-BEFORE-CHILDREN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) {
my $placeholder-signature := self.placeholder-signature;
if $placeholder-signature {
$placeholder-signature.set-is-on-method(True);
Expand All @@ -1587,7 +1591,7 @@ class RakuAST::Methodish
}
}

method PERFORM-BEGIN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) {
method PERFORM-BEGIN-AFTER-CHILDREN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) {
if nqp::getattr(self, RakuAST::Routine, '$!package') {
nqp::getattr(self, RakuAST::Routine, '$!package').ATTACH-METHOD(self);
}
Expand All @@ -1598,24 +1602,11 @@ class RakuAST::Methodish
# Make sure that our placeholder signature has resolutions performed.
my $placeholder-signature := self.placeholder-signature;
if $placeholder-signature {
$placeholder-signature.set-is-on-method(True);
$placeholder-signature.set-is-on-named-method(True) if self.name;
$placeholder-signature.set-is-on-meta-method(True) if nqp::can(self, 'meta') && self.meta;
$placeholder-signature.IMPL-ENSURE-IMPLICITS;
$placeholder-signature.IMPL-CHECK($resolver, $context, True);
}
# Make sure that our signature has resolutions performed.
my $signature := self.signature;
if $signature {
$signature.set-default-type(
RakuAST::Type::Simple.new(
RakuAST::Name.from-identifier('Any'),
),
);
$signature.set-is-on-method(True);
$signature.set-is-on-named-method(True) if self.name;
$signature.set-is-on-meta-method(True) if nqp::can(self, 'meta') && self.meta;
$signature.IMPL-ENSURE-IMPLICITS;
$signature.IMPL-CHECK($resolver, $context, True);
}

Expand Down

0 comments on commit 85240f0

Please sign in to comment.