summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordoy <doy@tozt.net>2009-04-13 23:16:14 -0500
committerdoy <doy@tozt.net>2009-04-13 23:16:14 -0500
commit4ea8fc9fe89dc29a9132cdf946714264550aee9b (patch)
tree4e93c9071c3573bde333d1a74ae132c08c8c1283 /lib
parentd8c86365f2648f6921dd6ebaefa87553088b2600 (diff)
downloadmoosex-nonmoose-4ea8fc9fe89dc29a9132cdf946714264550aee9b.tar.gz
moosex-nonmoose-4ea8fc9fe89dc29a9132cdf946714264550aee9b.zip
oh god what am i doing
Diffstat (limited to 'lib')
-rw-r--r--lib/MooseX/NonMoose.pm2
-rw-r--r--lib/MooseX/NonMoose/Meta/Role/Class.pm20
-rw-r--r--lib/MooseX/NonMoose/Meta/Role/Constructor.pm82
3 files changed, 104 insertions, 0 deletions
diff --git a/lib/MooseX/NonMoose.pm b/lib/MooseX/NonMoose.pm
index e01e837..7a6aec6 100644
--- a/lib/MooseX/NonMoose.pm
+++ b/lib/MooseX/NonMoose.pm
@@ -51,6 +51,7 @@ sub extends {
$moose_self->BUILDALL($params);
return $moose_self;
});
+ $caller_meta->replace_constructor(1);
}
sub init_meta {
@@ -59,6 +60,7 @@ sub init_meta {
Moose->init_meta(%options);
Moose::Util::MetaRole::apply_metaclass_roles(
for_class => $options{for_class},
+ metaclass_roles => ['MooseX::NonMoose::Meta::Role::Class'],
constructor_class_roles =>
['MooseX::NonMoose::Meta::Role::Constructor'],
);
diff --git a/lib/MooseX/NonMoose/Meta/Role/Class.pm b/lib/MooseX/NonMoose/Meta/Role/Class.pm
new file mode 100644
index 0000000..8195b4a
--- /dev/null
+++ b/lib/MooseX/NonMoose/Meta/Role/Class.pm
@@ -0,0 +1,20 @@
+package MooseX::NonMoose::Meta::Role::Class;
+use Moose::Role;
+
+has replace_constructor => (
+ is => 'rw',
+ isa => 'Bool',
+ default => 0,
+);
+
+around _make_immutable_transformer => sub {
+ my $orig = shift;
+ my $self = shift;
+ my @args = @_;
+ unshift @args, replace_constructor => 1 if $self->replace_constructor;
+ $self->$orig(@args);
+};
+
+no Moose::Role;
+
+1;
diff --git a/lib/MooseX/NonMoose/Meta/Role/Constructor.pm b/lib/MooseX/NonMoose/Meta/Role/Constructor.pm
index 81b59ab..23de2be 100644
--- a/lib/MooseX/NonMoose/Meta/Role/Constructor.pm
+++ b/lib/MooseX/NonMoose/Meta/Role/Constructor.pm
@@ -1,6 +1,88 @@
package MooseX::NonMoose::Meta::Role::Constructor;
use Moose::Role;
+around can_be_inlined => sub {
+ my $orig = shift;
+ my $self = shift;
+
+ my $meta = $self->associated_metaclass;
+ my $super_new = $meta->find_method_by_name($self->name);
+ if (!$super_new->associated_metaclass->isa($self->_expected_constructor_class)) {
+ # XXX: in the future, hopefully we'll be able to inline this?
+ #return $self->should_be_inlined;
+ return 1;
+ }
+
+ return $self->$orig(@_);
+};
+
+sub _initialize_body {
+ my $self = shift;
+ # TODO:
+ # the %options should also include a both
+ # a call 'initializer' and call 'SUPER::'
+ # options, which should cover approx 90%
+ # of the possible use cases (even if it
+ # requires some adaption on the part of
+ # the author, after all, nothing is free)
+ my $source = 'sub {';
+ $source .= "\n" . 'my $class = shift;';
+
+ $source .= "\n" . 'return $class->Moose::Object::new(@_)';
+ $source .= "\n if \$class ne '" . $self->associated_metaclass->name
+ . "';\n";
+
+ $source .= $self->_generate_params('$params', '$class');
+ $source .= $self->_generate_instance('$instance', '$class');
+ $source .= $self->_generate_slot_initializers;
+
+ $source .= $self->_generate_triggers();
+ $source .= ";\n" . $self->_generate_BUILDALL();
+
+ $source .= ";\nreturn \$instance";
+ $source .= ";\n" . '}';
+ warn $source if $self->options->{debug};
+
+ # We need to check if the attribute ->can('type_constraint')
+ # since we may be trying to immutabilize a Moose meta class,
+ # which in turn has attributes which are Class::MOP::Attribute
+ # objects, rather than Moose::Meta::Attribute. And
+ # Class::MOP::Attribute attributes have no type constraints.
+ # However we need to make sure we leave an undef value there
+ # because the inlined code is using the index of the attributes
+ # to determine where to find the type constraint
+
+ my $attrs = $self->_attributes;
+
+ my @type_constraints = map {
+ $_->can('type_constraint') ? $_->type_constraint : undef
+ } @$attrs;
+
+ my @type_constraint_bodies = map {
+ defined $_ ? $_->_compiled_type_constraint : undef;
+ } @type_constraints;
+
+ my $super_new = $self->associated_metaclass->find_next_method_by_name('new');
+ my $code = $self->_compile_code(
+ code => $source,
+ environment => {
+ '$meta' => \$self,
+ '$attrs' => \$attrs,
+ '@type_constraints' => \@type_constraints,
+ '@type_constraint_bodies' => \@type_constraint_bodies,
+ '$super_new' => \$super_new,
+ },
+ ) or $self->throw_error("Could not eval the constructor :\n\n$source\n\nbecause :\n\n$@", error => $@, data => $source );
+
+ $self->{'body'} = $code;
+}
+
+sub _generate_instance {
+ my $self = shift;
+ my ($var, $class_var) = @_;
+ "my $var = \$super_new->execute($class_var, \@_);\n";
+}
+
no Moose::Role;
1;