Skip to content

Instantly share code, notes, and snippets.

@peschwa
Created October 27, 2015 21:01
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 peschwa/cb8f5e954ba932e15c31 to your computer and use it in GitHub Desktop.
Save peschwa/cb8f5e954ba932e15c31 to your computer and use it in GitHub Desktop.
use nqp;
my class WriteOnceAttribute is Attribute {
has Mu $!type;
method compose(Mu $package) {
# Generate accessor method, if we're meant to have one.
if self.has_accessor {
my str $name = nqp::unbox_s(self.name);
my $meth_name := nqp::substr($name, 2);
unless $package.^declares_method($meth_name) {
my $dcpkg := nqp::decont($package);
my $meth;
my int $attr_type = nqp::objprimspec($!type);
if self.rw {
$meth := nqp::p6bool(nqp::iseq_i($attr_type, 0))
??
method (Mu:D \fles:) is raw {
state $written = False;
if !$written {
$written = True;
nqp::getattr(nqp::decont(fles), $dcpkg, $name)
}
else {
return nqp::getattr(nqp::decont(fles), $dcpkg, $name)
}
}
!!
nqp::p6bool(nqp::iseq_i($attr_type, 1))
??
method (Mu:D \fles:) is raw {
state $written = False;
if !$written {
$written = True;
nqp::getattrref_i(nqp::decont(fles), $dcpkg, $name)
}
else {
return nqp::getattr(nqp::decont(fles), $dcpkg, $name)
}
}
!!
nqp::p6bool(nqp::iseq_i($attr_type, 2))
??
method (Mu:D \fles:) is raw {
state $written = False;
if !$written {
$written = True;
nqp::getattrref_n(nqp::decont(fles), $dcpkg, $name)
}
else {
return nqp::getattr(nqp::decont(fles), $dcpkg, $name)
}
}
!!
method (Mu:D \fles:) is raw {
state $written = False;
if !$written {
$written = True;
nqp::getattrref_s(nqp::decont(fles), $dcpkg, $name)
}
else {
return nqp::getattr(nqp::decont(fles), $dcpkg, $name)
}
}
} else {
nextsame;
}
$meth.set_name($meth_name);
$package.^add_method($meth_name, $meth);
}
}
# Apply any handles trait we may have.
self.apply_handles($package);
}
}
my module EXPORTHOW { }
EXPORTHOW.WHO<class-attr> = WriteOnceAttribute;
######
$ cat test.pl
use WriteOnceAttribute;
class A {
has $.foo is rw;
}
my A $a .= new;
$a.foo = 5;
say $a.foo;
$a.foo = 10;
say $a.foo;
######
$ ./perl6-m -I. test.pl
5
Cannot assign to a readonly variable or a value
in block <unit> at test.pl:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment