diff --git a/src/Raku/ast/begintime.rakumod b/src/Raku/ast/begintime.rakumod index 225d7108183..d267d109a28 100644 --- a/src/Raku/ast/begintime.rakumod +++ b/src/Raku/ast/begintime.rakumod @@ -18,25 +18,9 @@ class RakuAST::BeginTime # Ensure the begin-time effects are performed. 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); - } + unless $!begin-performed { + self.PERFORM-BEGIN($resolver, $context); + nqp::bindattr_i(self, RakuAST::BeginTime, '$!begin-performed', 3); } Nil } diff --git a/src/Raku/ast/code.rakumod b/src/Raku/ast/code.rakumod index af25d7ff4c6..7d70e2fb27d 100644 --- a/src/Raku/ast/code.rakumod +++ b/src/Raku/ast/code.rakumod @@ -1323,6 +1323,7 @@ class RakuAST::Routine is RakuAST::AttachTarget is RakuAST::PlaceholderParameterOwner is RakuAST::ImplicitLookups + is RakuAST::ParseTime is RakuAST::BeginTime is RakuAST::TraitTarget is RakuAST::ScopePhaser @@ -1405,10 +1406,7 @@ class RakuAST::Routine $routine } - 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) { + method PERFORM-PARSE(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { my $placeholder-signature := self.placeholder-signature; if $placeholder-signature { $placeholder-signature.IMPL-ENSURE-IMPLICITS; @@ -1418,7 +1416,7 @@ class RakuAST::Routine } } - method PERFORM-BEGIN-AFTER-CHILDREN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { + method PERFORM-BEGIN(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 { @@ -1769,10 +1767,7 @@ class RakuAST::Methodish nqp::bindattr(self, RakuAST::Code, '$!resolver', $resolver.clone); } - 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) { + method PERFORM-PARSE(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { my $placeholder-signature := self.placeholder-signature; if $placeholder-signature { $placeholder-signature.set-is-on-method(True); @@ -1797,7 +1792,7 @@ class RakuAST::Methodish } } - method PERFORM-BEGIN-AFTER-CHILDREN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { + method PERFORM-BEGIN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { if nqp::getattr(self, RakuAST::Routine, '$!package') { nqp::getattr(self, RakuAST::Routine, '$!package').ATTACH-METHOD(self); } diff --git a/src/Raku/ast/package.rakumod b/src/Raku/ast/package.rakumod index f227fbfeff1..0a49300ec0d 100644 --- a/src/Raku/ast/package.rakumod +++ b/src/Raku/ast/package.rakumod @@ -5,7 +5,7 @@ class RakuAST::Package is RakuAST::IMPL::ImmediateBlockUser is RakuAST::Declaration is RakuAST::AttachTarget - is RakuAST::BeginTime + is RakuAST::ParseTime is RakuAST::TraitTarget is RakuAST::ImplicitBlockSemanticsProvider is RakuAST::LexicalScope @@ -170,9 +170,6 @@ class RakuAST::Package Nil } - # We install the name before parsing the class body. - method is-begin-performed-before-children() { True } - method IMPL-GENERATE-LEXICAL-DECLARATION(RakuAST::Name $name, Mu $type-object) { RakuAST::Declaration::LexicalPackage.new: :lexical-name($name), @@ -180,7 +177,7 @@ class RakuAST::Package :package(self); } - method PERFORM-BEGIN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { + method PERFORM-PARSE(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { # Note that this early return is actually not effective as the begin handler will # already be run when the parser enters the package and we only know that it's a # stub when we are done parsing the body. diff --git a/src/Raku/ast/parsetime.rakumod b/src/Raku/ast/parsetime.rakumod index e3dd39079fd..5e107dadf3f 100644 --- a/src/Raku/ast/parsetime.rakumod +++ b/src/Raku/ast/parsetime.rakumod @@ -21,4 +21,43 @@ class RakuAST::ParseTime nqp::bindattr_i(self, RakuAST::ParseTime, '$!parse-performed', 1); } } + + # Called when a BEGIN-time construct needs to evaluate code. Tries to + # interpret simple things to avoid the cost of compilation. + method IMPL-BEGIN-TIME-EVALUATE(RakuAST::Node $code, RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { + $code.IMPL-CHECK($resolver, $context, False); + if $code.IMPL-CAN-INTERPRET { + $code.IMPL-INTERPRET(RakuAST::IMPL::InterpContext.new) + } + elsif nqp::istype($code, RakuAST::Code) { + $code.meta-object; + } + elsif nqp::istype($code, RakuAST::Expression) { + my $thunk := RakuAST::ExpressionThunk.new; + $code.wrap-with-thunk($thunk); + $thunk.IMPL-STUB-CODE($resolver, $context); + $thunk.IMPL-QAST-BLOCK($context, :expression($code)); + $thunk.meta-object()() + } + else { + nqp::die('BEGIN time evaluation only supported for simple constructs so far') + } + } + + # Called when a BEGIN-time construct wants to evaluate a resolved code + # with a set of arguments. + method IMPL-BEGIN-TIME-CALL(RakuAST::Node $callee, RakuAST::ArgList $args, + RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { + if $callee.is-resolved && nqp::istype($callee.resolution, RakuAST::CompileTimeValue) && + $args.IMPL-CAN-INTERPRET { + my $resolved := $callee.resolution.compile-time-value; + my @args := $args.IMPL-INTERPRET(RakuAST::IMPL::InterpContext.new); + my @pos := @args[0]; + my %named := @args[1]; + return $resolved(|@pos, |%named); + } + else { + nqp::die('BEGIN time calls only supported for simple constructs so far') + } + } } diff --git a/src/Raku/ast/type.rakumod b/src/Raku/ast/type.rakumod index 22ebec9d8b6..893e137d75f 100644 --- a/src/Raku/ast/type.rakumod +++ b/src/Raku/ast/type.rakumod @@ -673,9 +673,7 @@ class RakuAST::Type::Subset :scope(self.scope); } - method is-begin-performed-after-children() { True } - - method PERFORM-BEGIN-AFTER-CHILDREN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { + method PERFORM-BEGIN(RakuAST::Resolver $resolver, RakuAST::IMPL::QASTContext $context) { self.apply-traits($resolver, $context, self); my $block := $!block;