Created
February 13, 2021 13:58
-
-
Save gfldex/09e8db29bdf1524d2da95414ae96443f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use v6.e.PREVIEW; | |
use MONKEY-TYPING; | |
# augment class Any { | |
# method chain { | |
# class Chainer { | |
# has $.the-object; | |
# method FALLBACK($name, *@a) { | |
# my $o = $.the-object; | |
# if @a { | |
# for @a -> $e { | |
# $o = $o."$name"($e, |%_); | |
# } | |
# } elsif %_ { | |
# for %_ -> %p { | |
# $o = $o."$name"(|%p); | |
# } | |
# } else { | |
# # XXX error handling | |
# } | |
# | |
# $o | |
# } | |
# } | |
# | |
# Chainer.new(the-object => self) | |
# } | |
# } | |
# IO::Path.HOW.compose(IO::Path); | |
# DateTime.HOW.compose(DateTime); | |
# sub chain($self) { | |
# class :: is Mu { | |
# has $.the-object; | |
# method FALLBACK($name, *@a) { | |
# my $o = $.the-object; | |
# my \m = $o.^lookup($name) orelse { | |
# my $bt = Backtrace.new; | |
# my $idx = $bt.next-interesting-index($bt.next-interesting-index + 1); | |
# (X::Method::NotFound.new(:method($name), :typename($o.^name)) but role :: { method vault-backtrace { False }}).throw(Backtrace.new($idx + 1)); | |
# } | |
# if @a { | |
# for @a -> $e { | |
# # $o = $o.^lookup($name).($o, $e, |%_); | |
# $o = $o."$name"($e, |%_); | |
# } | |
# } elsif %_ { | |
# for %_ -> %p { | |
# $o = $o."$name"(|%p); | |
# } | |
# } else { | |
# # XXX error handling | |
# } | |
# | |
# $o | |
# } | |
# }.new(the-object => $self) | |
# } | |
# | |
# constant no-argument-given = Mu.new; | |
# sub try($self, Mu $alternate-value = no-argument-given) { | |
# class :: is Mu { | |
# has $.the-object; | |
# method WHY { 'This is a wrapper for `sub defuse` around ' ~ $.the-object.WHAT.gist ~ '.' } | |
# method gist { self.WHY } | |
# method FALLBACK($name, |c) { | |
# my $o = $.the-object; | |
# my \m = $o.^lookup($name) orelse { | |
# my $bt = Backtrace.new; | |
# my $idx = $bt.next-interesting-index($bt.next-interesting-index + 1); | |
# (X::Method::NotFound.new(:method($name), :typename($o.^name)) but role :: { method vault-backtrace { False }}).throw(Backtrace.new($idx + 1)); | |
# } | |
# | |
# try { | |
# $o = $o."$name"(|c); | |
# } | |
# | |
# $! ~~ Exception | |
# ?? $alternate-value.WHICH eqv no-argument-given.WHICH | |
# ?? $o.WHAT | |
# !! $alternate-value | |
# !! $o | |
# } | |
# }.new(the-object => $self) | |
# } | |
# | |
# | |
# sub pry(Mu $the-object is raw) { | |
# class :: is Mu { | |
# has $.the-object; | |
# method WHY { 'This is a wrapper for `sub pry` around ' ~ $.the-object.WHAT.gist ~ '.' } | |
# method gist { self.WHY } | |
# method FALLBACK($name) is rw { | |
# use nqp; | |
# nqp::getattr($.the-object, $.the-object.WHAT, '$!' ~ $name) | |
# } | |
# }.new(:$the-object) | |
# } | |
# | |
# '/home/dex'.IO.&chain.add(<tmp foo.txt>).say; | |
# '/home/dex'.IO.&chain.add('tmp').add('foo.txt').say; | |
# | |
# { | |
# | |
# my $d = now.DateTime; | |
# say $d; | |
# say $d.later(:1hour).later(:30minutes); | |
# | |
# say $d.&chain.later(:1hour, :30minutes); | |
# | |
# my $h = '/home/dex/not-there.txt'.IO.&try($*IN).open(:r); | |
# my $o = '/home/dex/not-there.txt'.IO.&try; | |
# say $o; | |
# dd $h; | |
# | |
# my \j = (1|2|3); | |
# | |
# dd j.&pry.WHY; | |
# .say for j.&pry.eigenstates; | |
# | |
# } | |
# | |
# class InterceptHOW is Metamodel::ClassHOW { | |
# method publish_method_cache(|) { } | |
# } | |
# | |
# sub ipry(Mu $the-object is raw) { | |
# use InterceptAllMethods; | |
# | |
# my class Interceptor { | |
# has Mu $!the-object; | |
# method ^find_method(Mu \type, Str $name) { | |
# my method (Mu \SELF:) is raw { | |
# use nqp; | |
# my $the-object := nqp::getattr(SELF, Interceptor, '$!the-object'); | |
# nqp::getattr($the-object, $the-object.WHAT, '$!' ~ $name) | |
# } | |
# } | |
# } | |
# | |
# | |
# # my \Interceptor = InterceptHOW.new_type(:name<Interceptor>); | |
# # Interceptor.^add_attribute(Attribute.new(:name<$!the-object>, :type(Mu), :package(Interceptor))); | |
# # Interceptor.^add_meta_method('find_method', | |
# # my method (Mu \type, Str $name) { | |
# # my method (Mu \SELF:) is raw { | |
# # use nqp; | |
# # my $the-object := nqp::getattr(SELF, Interceptor, '$!the-object'); | |
# # nqp::getattr($the-object, $the-object.WHAT, '$!' ~ $name) | |
# # } | |
# # }); | |
# # Interceptor.^compose; | |
# | |
# use nqp; | |
# nqp::p6bindattrinvres(nqp::create(Interceptor), Interceptor, '$!the-object', $the-object); | |
# } | |
# | |
# { | |
# my \j = (1|2|3); | |
# .say for j.&ipry.eigenstates; | |
# } | |
# sub interceptor(Method $the-method){ | |
# use InterceptAllMethods; | |
# use nqp; | |
# | |
# sub (Mu $the-object is raw) { | |
# my class Interceptor { | |
# has Mu $!the-object; | |
# has Code $!the-method; | |
# | |
# method ^find_method(Mu \type, Mu:D $name) { | |
# my method (Mu \SELF: |c) is raw { | |
# $!the-method.($!the-object, $name, |c) | |
# } | |
# } | |
# method ^introspect(Mu \type, Mu \obj) { | |
# my method call-it() is raw { | |
# $!the-object | |
# } | |
# obj.&call-it; | |
# } | |
# } | |
# | |
# nqp::p6bindattrinvres( | |
# nqp::p6bindattrinvres(nqp::create(Interceptor), Interceptor, '$!the-object', $the-object), | |
# Interceptor, '$!the-method', $the-method); | |
# } | |
# } | |
# | |
# my &first-defined = interceptor( | |
# my method (Positional \SELF: $name) { | |
# for SELF -> $e { | |
# dd $e; | |
# with $e."$name"(|%_) { | |
# .return | |
# } | |
# } | |
# Nil | |
# } | |
# ); | |
# sub true-then($self) { | |
# | |
# } | |
# | |
# sub defined-then($self) { | |
# | |
# } | |
# | |
# my $file = <file1.txt file2.txt file3.txt nohup.out>».IO.&first-defined.open(:r); | |
# | |
# dd $file; | |
# | |
# my &poke = interceptor(my method (Mu \SELF: $name, |c) is rw { | |
# use nqp; | |
# Proxy.new( | |
# FETCH => method () { nqp::getattr_s(SELF, SELF.WHAT, '$!' ~ $name) }, | |
# STORE => method (\v) { nqp::bindattr_s(SELF, SELF.WHAT, '$!' ~ $name, v); v } | |
# ) | |
# }); | |
# | |
# { | |
# my \j = (1|2|3); | |
# dd j; | |
# j.&poke.type = 'all'; | |
# dd j; | |
# } | |
# | |
# multi sub methodify(%h) { | |
# role Undefined { method defined { False } } | |
# interceptor( | |
# my method (Mu \SELF: $name, |c) is rw { | |
# return-rw SELF.AT-KEY($name) | |
# } | |
# ).(%h) | |
# } | |
# | |
# my %h = :answer(42); | |
# my $o = methodify(%h); | |
# $o.answer.say; | |
# $o.awesome = <Raku Ruby Rust>; | |
# say $o.awesome; | |
# $o."WHAT"() = ‚LOL WUT‽‘; | |
# dd %h; | |
multi sub methodify(%h, :$deeply!) { | |
sub interceptor(%h, $parent = Nil){ | |
use InterceptAllMethods; | |
use nqp; | |
class Interceptor { | |
has Mu $!the-object; | |
has Mu @!stack; | |
method ^find_method(Mu \type, Mu:D $name) { | |
say "looking for $name"; | |
my method (Mu \SELF: |c) is raw { | |
my @new-stack = @!stack; | |
@new-stack.push: $name; | |
my $the-object = $!the-object; | |
my \nextlevel = SELF.^new($!the-object, @new-stack, $name); | |
Proxy.new: | |
FETCH => method FETCH (Mu \s:) { | |
nextlevel | |
}, | |
STORE => method STORE (Mu \s: \v) { | |
$the-object{||@new-stack} = v; | |
v | |
} | |
} | |
} | |
method ^introspect(Mu \type, Mu \obj) { | |
my method call-it() is raw { | |
$!the-object, @!stack | |
} | |
obj.&call-it; | |
} | |
method ^new(Mu \type, $the-object!, @new-stack?, $name?) { | |
$name | |
?? nqp::p6bindattrinvres( | |
nqp::p6bindattrinvres(nqp::create(Interceptor), Interceptor, '$!the-object', $the-object), | |
Interceptor, '@!stack', @new-stack) | |
!! nqp::p6bindattrinvres(nqp::create(Interceptor), Interceptor, '$!the-object', $the-object) | |
} | |
} | |
Interceptor.^new(%h) | |
} | |
interceptor(%h) | |
} | |
my %h2; | |
my $o2 = methodify(%h2, :deeply); | |
dd $o2.^introspect($o2); | |
$o2.a.b = 42; | |
my $b = $o2.a.b; | |
dd %h2; | |
$o2.a.b.c = <answer>; | |
dd %h2; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment