Skip to content

Instantly share code, notes, and snippets.

@lizmat
Created December 22, 2019 21:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lizmat/31a39891dce0d8ed07bd4739846fa047 to your computer and use it in GitHub Desktop.
Save lizmat/31a39891dce0d8ed07bd4739846fa047 to your computer and use it in GitHub Desktop.
Attempting to make handles trait a method on Attribute
diff --git a/src/core.c/Attribute.pm6 b/src/core.c/Attribute.pm6
index 1de2f2074..c544307e3 100644
--- a/src/core.c/Attribute.pm6
+++ b/src/core.c/Attribute.pm6
@@ -218,6 +218,89 @@ my class Attribute { # declared in BOOTSTRAP
method set_why($why) {
$!why := $why;
}
+
+ role Handles {
+ has $.handles;
+
+ method set_handles($expr) {
+ $!handles := $expr;
+ }
+
+ method add_delegator_method($attr: $pkg, $meth_name, $call_name) {
+ my $meth := method (|c) is rw {
+ $attr.get_value(self)."$call_name"(|c)
+ };
+ $meth.set_name($meth_name);
+ $pkg.^add_method($meth_name, $meth);
+ }
+
+ method apply_handles($attr: Mu $pkg) {
+ sub applier($expr) {
+ if $expr.defined() {
+ if nqp::istype($expr,Str) {
+ self.add_delegator_method($pkg, $expr, $expr);
+ }
+ elsif nqp::istype($expr,Pair) {
+ self.add_delegator_method($pkg, $expr.key, $expr.value);
+ }
+ elsif nqp::istype($expr,Positional) {
+ for $expr.list {
+ applier($_);
+ }
+ 0;
+ }
+ elsif nqp::istype($expr, Whatever) {
+ $pkg.^add_fallback(
+ -> $obj, $name {
+ so $attr.get_value($obj).can($name);
+ },
+ -> $obj, $name {
+ -> $self, |c {
+ $attr.get_value($self)."$name"(|c)
+ }
+ });
+ }
+ elsif nqp::istype($expr, HyperWhatever) {
+ $pkg.^add_fallback(
+ -> $, $ --> True { },
+ -> $obj, $name {
+ -> $self, |c {
+ $attr.get_value($self)."$name"(|c)
+ }
+ });
+ }
+ else {
+ $pkg.^add_fallback(
+ -> $obj, $name {
+ ?($name ~~ $expr)
+ },
+ -> $obj, $name {
+ -> $self, |c {
+ $attr.get_value($self)."$name"(|c)
+ }
+ });
+ }
+ }
+ else {
+ $pkg.^add_fallback(
+ -> $obj, $name {
+ ?$expr.can($name)
+ },
+ -> $obj, $name {
+ -> $self, |c {
+ $attr.get_value($self)."$name"(|c)
+ }
+ });
+ }
+ }
+ applier($!handles);
+ }
+ }
+
+ method add-delegator(\delegatees --> Nil) {
+ self does Handles;
+ self.set_handles(delegatees)
+ }
}
# does trait
@@ -238,4 +321,7 @@ multi sub trait_mod:<does>(Attribute:D $a, Mu:U $role) {
}
}
+multi sub trait_mod:<handles>(Attribute:D $target, $thunk) {
+}
+
# vim: ft=perl6 expandtab sw=4
diff --git a/src/core.c/traits.pm6 b/src/core.c/traits.pm6
index 7a72f41da..bc4e63d9f 100644
--- a/src/core.c/traits.pm6
+++ b/src/core.c/traits.pm6
@@ -418,84 +418,7 @@ multi sub trait_mod:<returns>(Routine:D $target, Mu:U $type) {
proto sub trait_mod:<handles>($, $, *%) {*}
multi sub trait_mod:<handles>(Attribute:D $target, $thunk) {
- $target does role {
- has $.handles;
-
- method set_handles($expr) {
- $!handles := $expr;
- }
-
- method add_delegator_method($attr: $pkg, $meth_name, $call_name) {
- my $meth := method (|c) is rw {
- $attr.get_value(self)."$call_name"(|c)
- };
- $meth.set_name($meth_name);
- $pkg.^add_method($meth_name, $meth);
- }
-
- method apply_handles($attr: Mu $pkg) {
- sub applier($expr) {
- if $expr.defined() {
- if nqp::istype($expr,Str) {
- self.add_delegator_method($pkg, $expr, $expr);
- }
- elsif nqp::istype($expr,Pair) {
- self.add_delegator_method($pkg, $expr.key, $expr.value);
- }
- elsif nqp::istype($expr,Positional) {
- for $expr.list {
- applier($_);
- }
- 0;
- }
- elsif nqp::istype($expr, Whatever) {
- $pkg.^add_fallback(
- -> $obj, $name {
- so $attr.get_value($obj).can($name);
- },
- -> $obj, $name {
- -> $self, |c {
- $attr.get_value($self)."$name"(|c)
- }
- });
- }
- elsif nqp::istype($expr, HyperWhatever) {
- $pkg.^add_fallback(
- -> $, $ --> True { },
- -> $obj, $name {
- -> $self, |c {
- $attr.get_value($self)."$name"(|c)
- }
- });
- }
- else {
- $pkg.^add_fallback(
- -> $obj, $name {
- ?($name ~~ $expr)
- },
- -> $obj, $name {
- -> $self, |c {
- $attr.get_value($self)."$name"(|c)
- }
- });
- }
- }
- else {
- $pkg.^add_fallback(
- -> $obj, $name {
- ?$expr.can($name)
- },
- -> $obj, $name {
- -> $self, |c {
- $attr.get_value($self)."$name"(|c)
- }
- });
- }
- }
- applier($!handles);
- }
- };
- $target.set_handles($thunk());
+ $target.add-delegator($thunk());
}
multi sub trait_mod:<handles>(Method:D $m, &thunk) {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment