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
| class Prototype { | |
| has $.HOW; | |
| has $.Str; | |
| method WHAT() { self } | |
| method defined() { False } | |
| } | |
| class PrototypeHOW { | |
| has $!name; | |
| # Attributes, methods, parents and roles directly added. | |
| has %!attributes; | |
| has %!methods; | |
| has @!parents; | |
| has @!roles; | |
| has $.ver is readonly; | |
| has $.auth is readonly; | |
| # Full list of roles that we do. | |
| has @!done; | |
| ## | |
| ## Declarative. | |
| ## | |
| # Creates a new instance of this meta-class. | |
| method new($name) { | |
| return Prototype.new( | |
| HOW => self.bless(*), | |
| Str => $name ~ "()" | |
| ); | |
| } | |
| method add_method($name, $code_obj) { | |
| if %!methods{$name} { | |
| die("This class already has a method named " ~ $name); | |
| } | |
| %!methods{$name} := $code_obj; | |
| } | |
| method add_attribute($obj, $meta_attr) { | |
| my $name = $meta_attr.name; | |
| if %!attributes{$name} { | |
| die("This class already has an attribute named " ~ $name); | |
| } | |
| %!attributes{$name} := $meta_attr; | |
| } | |
| method add_parent($parent) { | |
| @!parents.push($parent); | |
| } | |
| method compose($obj) { | |
| $obj | |
| } | |
| ## | |
| ## Introspecty | |
| ## | |
| method parents($obj, :$local!) { | |
| @!parents | |
| } | |
| method roles($obj, :$local!) { | |
| @!roles | |
| } | |
| method methods($obj, :$local!) { | |
| my @meths; | |
| for %!methods { | |
| @meths.push($_.value); | |
| } | |
| @meths | |
| } | |
| method attributes($obj, :$local!) { | |
| my @attrs; | |
| for %!attributes { | |
| @attrs.push($_.value); | |
| } | |
| @attrs | |
| } | |
| ## | |
| ## Checky | |
| ## | |
| method isa($obj, $check) { | |
| my $check-class := $check.WHAT; | |
| my $i = +@!mro; | |
| while $i > 0 { | |
| $i--; | |
| if @!mro[$i] =:= $check-class { | |
| return 1; | |
| } | |
| } | |
| return 0; | |
| } | |
| method does($obj, $check) { | |
| my $i = +@!done; | |
| while $i > 0 { | |
| $i--; | |
| if @!done[$i] =:= $check { | |
| return 1; | |
| } | |
| } | |
| return 0; | |
| } | |
| method can($obj, $name) { | |
| for @!mro { | |
| my %meths := $obj.HOW.method_table($obj); | |
| my $can := %meths{$name}; | |
| if $can { | |
| return $can; | |
| } | |
| } | |
| return 0; | |
| } | |
| method method($name) { | |
| return %!methods{$name} if %!methods{$name}; | |
| die("method not found"); | |
| } | |
| } | |
| say 'protohow'; | |
| # protoclass A { | |
| # has $x = 5; | |
| # } | |
| # | |
| # protoclass B is A { | |
| # has $x = 1; | |
| # } | |
| say 1; | |
| my $A = PrototypeHOW.proto('A'); | |
| # # my $attr_x = Attribute.new(:name("$x"), :has_accessor, :type(Mu)); | |
| # # $A.^add_attribute("$.x", $attr_x); | |
| # | |
| # my $a = $A.new; | |
| # $a.^add_method('foo', method { | |
| # say 'foo called'; | |
| # }); | |
| # | |
| # $A.^add_method('bar', method { | |
| # say 'bar called'; | |
| # }); | |
| # | |
| # $a.foo; | |
| # $A.foo; # fail | |
| # $a.bar; | |
| # $A.bar; | |
| # | |
| # say 'done'; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment