Skip to content

Commit

Permalink
Implement use experimental :rakuast
Browse files Browse the repository at this point in the history
This pretty hacky approach fetches the RakuAST type object at the
end of the core.c compilation, and stashes that with bindcurhllsym.
It then replaces the CORE::<RakuAST> entry with a subclass of Nil,
causing all lookups for RakuAST classes to fail from thereon with a
nice informative message.

It also lexically enables RakuAST again in the 6.e Formatter class
to keep that working and puts in provisions to let dd work with
RakuAST classes.

And it adds an entry in lib/experimental that basically makes the
original RakuAST type object visible again and make everything
work as if the interface was completely stable.

Also add comments on when to remove the code and fix the
RakuAST test files by adding 'use experimental :rakuast' to them.

This also moves src/core.c/RakuAST/Deparse.pm6 to
lib/RakuAST/Deparse.rakumod and allow for it to work with
late loading.
  • Loading branch information
lizmat committed Dec 13, 2022
1 parent a918629 commit 0f86d6f
Show file tree
Hide file tree
Showing 29 changed files with 88 additions and 8 deletions.
Expand Up @@ -6,6 +6,13 @@
# method expects an instance if a subclass of a RakuAST::Node as the first
# positional parameter.

# This code can be removed once RakuAST is stable and
# use experimental :rakuast;
# is no longer necessary to be able to access the RakuAST classes
# and their functionality.
use nqp;
my constant RakuAST = nqp::gethllsym('Raku','RakuAST');

class RakuAST::Deparse {
has str $.before-comma = ' ';
has str $.after-comma = ' ';
Expand Down
14 changes: 14 additions & 0 deletions lib/experimental.rakumod
@@ -1,5 +1,19 @@
use nqp;

package EXPORT::rakuast {
# This code can be removed once RakuAST is stable and
# use experimental :rakuast;
# is no longer necessary to be able to access the RakuAST classes
# and their functionality.
my \RakuAST := nqp::getcurhllsym('RakuAST');

require ::("RakuAST::Deparse");
use nqp;
nqp::bindcurhllsym('DEPARSE',::("RakuAST::Deparse"));

OUR::<RakuAST> := RakuAST;
}

package EXPORT::cached {
multi sub trait_mod:<is>(Routine $r, :$cached!) {
my %cache;
Expand Down
6 changes: 5 additions & 1 deletion src/core.c/Any.pm6
Expand Up @@ -592,10 +592,14 @@ sub dd(|c) { # is implementation-detail

my Mu $args := nqp::p6argvmarray();
if nqp::elems($args) {
# This code can be removed once RakuAST is stable and
# use experimental :rakuast;
# is no longer necessary to be able to access the RakuAST classes
# and their functionality.
while $args {
my $var := nqp::shift($args);
if nqp::istype($var,RakuAST::Node) {
note $var.DEPARSE.chomp;
Rakudo::Internals.DEPARSE($var);
}
else {
my $name := ! nqp::istype($var.VAR, Failure) && try $var.VAR.name;
Expand Down
9 changes: 8 additions & 1 deletion src/core.c/Stash.pm6
Expand Up @@ -24,6 +24,13 @@ my class Stash { # declared in BOOTSTRAP
ContainerDescriptor::BindHashKey.new(Mu, self, $key)
)
}

method !fail-not-found($key) {
(self.Str eq 'must-use-experimental-rakuast'
?? "Must do a 'use experimental :rakuast' to access RakuAST::$key.substr(1)"
!! "Could not find symbol '$key' in '{self}'"
).Failure
}
multi method AT-KEY(Stash:D: Str() $key, :$global_fallback!) is raw {
my \storage := nqp::getattr(self,Map,'$!storage');
nqp::if(
Expand All @@ -34,7 +41,7 @@ my class Stash { # declared in BOOTSTRAP
nqp::if(
nqp::existskey(GLOBAL.WHO,$key),
nqp::atkey(GLOBAL.WHO,$key),
"Could not find symbol '$key' in '{self}'".Failure
self!fail-not-found($key)
),
nqp::p6scalarfromdesc(
ContainerDescriptor::BindHashKey.new(Mu, self, $key)
Expand Down
27 changes: 27 additions & 0 deletions src/core.c/core_epilogue.pm6
Expand Up @@ -135,6 +135,33 @@ BEGIN .^compose for

BEGIN Metamodel::ClassHOW.exclude_parent(Mu);

# This code can be removed once RakuAST is stable and
# use experimental :rakuast;
# is no longer necessary to be able to access the RakuAST classes
# and their functionality.
{
my Mu $ctx := nqp::getattr(CORE::, PseudoStash, '$!ctx');
my class must-use-experimental-rakuast is Nil { }
until nqp::isnull($ctx) {
my $pad := nqp::ctxlexpad($ctx);
if nqp::existskey($pad, 'CORE-SETTING-REV') {
nqp::bindcurhllsym('RakuAST',RakuAST);
nqp::bindkey($pad,'RakuAST',must-use-experimental-rakuast);
last;
}
$ctx := nqp::ctxouterskipthunks($ctx);
}
}
augment class Rakudo::Internals {
# This code needs to live late, as at compilation time of
# "sub dd", the ::() lookup doesn't work yet
method DEPARSE($var) {
require ::("RakuAST::Deparse");
nqp::bindcurhllsym("DEPARSE",::("RakuAST::Deparse"));
note $var.DEPARSE.chomp;
}
}

{YOU_ARE_HERE}

# vim: expandtab shiftwidth=4
4 changes: 0 additions & 4 deletions src/core.c/core_prologue.pm6
Expand Up @@ -10,7 +10,6 @@ my class List { ... }
my class Map { ... }
my class Match { ... }
my class Failure { ... }
my class RakuAST::Deparse { ... }
my class Rakudo::Deprecations { ... }
my class Rakudo::Internals { ... }
my class Rakudo::Internals::JSON { ... }
Expand Down Expand Up @@ -44,9 +43,6 @@ BEGIN nqp::bindhllsym('Raku', 'Iterable', Iterable);
nqp::bindhllsym('Raku', 'Iterable', Iterable);
nqp::bindhllsym('Raku', 'Failure', Failure);

# Make deparsing possible with the .DEPARSE method from NQP
nqp::bindhllsym('Raku','DEPARSE',RakuAST::Deparse);

BEGIN {
# Ensure routines with traits using mixins applied to them typecheck as Callable.
Code.^add_role: Callable;
Expand Down
7 changes: 6 additions & 1 deletion src/core.e/Formatter.pm6
Expand Up @@ -99,6 +99,11 @@ grammar Formatter::Syntax {
}

class Formatter {
# This code can be removed once RakuAST is stable and
# use experimental :rakuast;
# is no longer necessary to be able to access the RakuAST classes
# and their functionality.
my constant RakuAST = nqp::getcurhllsym('RakuAST');

# class to be used with Grammar to turn format into array of pieces of code
class Actions {
Expand Down Expand Up @@ -446,7 +451,7 @@ class Formatter {

my $size = size($/);
my $ast = ast-call-sub("unsigned-int", parameter($/));

# handle zero padding / left / right justification
if $size {
$ast = ast-call-sub(
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/call.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 18;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/circumfix.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 7;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/code.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 11;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/contextualizer.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 4;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/errors.t
@@ -1,3 +1,4 @@
use experimental :rakuast;
use Test;

plan 1;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/literals.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 8;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/meta-operators.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 4;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/name.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 6;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/operators.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 23;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/package.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 11;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/pair.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 6;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/regex.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 41;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/signature.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 14;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/statement-mods.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 13;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/statementprefixes.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 15;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/statements.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 26; # Do not change this file to done-testing
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/strings.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 13;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/stubs.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 6;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/terms.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 11;
Expand Down
1 change: 1 addition & 0 deletions t/12-rakuast/var.t
@@ -1,4 +1,5 @@
use MONKEY-SEE-NO-EVAL;
use experimental :rakuast;
use Test;

plan 37;
Expand Down
1 change: 1 addition & 0 deletions tools/build/install-core-dist.raku
Expand Up @@ -14,6 +14,7 @@ my %provides =
"snapper" => "lib/snapper.rakumod",
"safe-snapper" => "lib/safe-snapper.rakumod",
"BUILDPLAN" => "lib/BUILDPLAN.rakumod",
"RakuAST::Deparse" => "lib/RakuAST/Deparse.rakumod",
;

%provides<NativeCall::Dispatcher> = "lib/NativeCall/Dispatcher.rakumod"
Expand Down
1 change: 0 additions & 1 deletion tools/templates/6.c/core_sources
Expand Up @@ -251,5 +251,4 @@ src/core.c/WrappedJSObject.pm6)@
src/core.c/Rakudo/Metaops.pm6
src/core.c/Rakudo/Internals/PostcircumfixAdverbs.pm6
src/core.c/unicodey.pm6
src/core.c/RakuAST/Deparse.pm6
src/core.c/core_epilogue.pm6

0 comments on commit 0f86d6f

Please sign in to comment.