Skip to content

Instantly share code, notes, and snippets.

@ashgti
Created October 5, 2010 15:31
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ashgti/611732 to your computer and use it in GitHub Desktop.
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