Created
November 14, 2013 20:11
-
-
Save japhb/7473529 to your computer and use it in GitHub Desktop.
Using the Perl 6 metamodel to serialize class *definitions*.
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; | |
#= Composed into an Attribute subclass that can serialize attribute definitions to Perl source | |
role PerlableAttribute { | |
method traits_perl() { | |
my $traits = ''; | |
$traits ~= ' is rw' if self.rw; | |
$traits ~= ' is box_target' if self.box_target; | |
$traits; | |
} | |
multi method perl(PerlableAttribute:) { | |
my $type = self.type.^name; | |
my $name = self.name; | |
$name .= subst('!', '.') if self.has_accessor; | |
my $traits = self.traits_perl; | |
"has $type $name$traits"; | |
} | |
} | |
#= Composed into a ClassHOW subclass that can serialize class definitions to Perl source | |
role PerlableClass { | |
multi method perl(Mu $class) { | |
my $perl = "class $class.^name()"; | |
$perl ~= " is $_.^name()" for $class.^parents; | |
$perl ~= " does $_.^name()" for $class.^roles; | |
$perl ~= " \{\n"; | |
for $class.^attributes -> $attr { | |
my $attr_perl = $attr.perl; | |
if $class.defined { | |
my $value = $class."$attr.name.substr(2)"(); | |
$attr_perl ~= " = $value.perl()"; | |
} | |
$perl ~= " $attr_perl;\n"; | |
} | |
$perl ~= "}\n"; | |
$perl; | |
} | |
} | |
#= A metaclass for classes whose definition can be serialized into Perl source | |
class PerlableClassHOW is Metamodel::ClassHOW does PerlableClass { } | |
#= An extended Attribute type for Test::Message attributes | |
class Test::Metamodel::Attribute is Attribute does PerlableAttribute { | |
has Bool $.frobulated is rw; | |
method traits_perl() { | |
my $traits = callsame; | |
$traits ~= ' is frobulated' if $.frobulated; | |
} | |
} | |
# A test message | |
class Test::Message { } | |
my $name := 'FooBar::Test::BazQuux'; | |
my $class := PerlableClassHOW.new_type(:$name); | |
$class.HOW.add_parent($class, Test::Message); | |
my $attr := Test::Metamodel::Attribute.new(:name<$!foo>, :type(Str), :package($class), :has_accessor); | |
$attr.set_rw; | |
$attr.frobulated = True; | |
$class.^add_attribute($attr); | |
$class.^compose; | |
say $class.^perl; | |
my $o = $class.new(foo => 'bar'); | |
say $o.^perl; |
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
$ perl6 metamodel-test.pl | |
class FooBar::Test::BazQuux is Test::Message { | |
has Str $.foo is frobulated; | |
} | |
class FooBar::Test::BazQuux is Test::Message { | |
has Str $.foo is frobulated = "bar"; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment