use Any::Moose;
+=head1 ATTRIBUTES
+
+=head2 C<mods>
+
+=cut
+
has '_mods' => (
is => 'ro',
isa => 'Maybe[ArrayRef[LaTeX::TikZ::Mod::Formatted]]',
default => sub { +{ } },
);
+=head2 C<body>
+
+=cut
+
has '_body' => (
is => 'rw',
isa => 'LaTeX::TikZ::Scope|ArrayRef[Str]',
my $_body_tc = __PACKAGE__->meta->find_attribute_by_name('_body')
->type_constraint;
+=head1 METHODS
+
+=head2 C<mod>
+
+=cut
+
sub mod {
my $scope = shift;
my $cache = $scope->_mods_cache;
for (@_) {
- my $mod = $ltmf_tc->check($_) ? $_ : $ltmf_tc->coerce($_);
+ my $mod = $ltmf_tc->coerce($_);
+ $ltmf_tc->assert_valid($mod);
my $tag = $mod->tag;
next if exists $cache->{$tag};
$cache->{$tag} = $mod;
$scope;
}
+=head2 C<body>
+
+=cut
+
sub body {
my $scope = shift;
}
use overload (
- '.' => \&concat,
+ '@{}' => 'dereference',
);
+=head2 C<flatten>
+
+=cut
+
sub flatten {
my ($scope) = @_;
return \@left, \@common, \@right;
});
+=head2 C<instantiate>
+
+=cut
+
sub instantiate {
my ($scope) = @_;
return @body;
}
-sub concat {
- my ($left, $right, $rev) = @_;
+=head2 C<dereference>
+
+=cut
+
+sub dereference { [ $_[0]->instantiate ] }
+
+=head2 C<fold>
- $_body_tc->assert_valid($right);
+=cut
- $left = $left->flatten;
+sub fold {
+ my ($left, $right, $rev) = @_;
my (@left, @right);
- if ($my_tc->check($right)) {
- $right = $right->flatten;
-
- my ($only_left, $common, $only_right) = $inter->(
- $left->_mods_cache,
- $right->_mods_cache,
- );
-
- if (@$common) {
- my $x = $left->new
- ->mod(@$only_left)
- ->body($left->_body);
- my $y = $left->new
- ->mod(@$only_right)
- ->body($right->_body);
- ($x, $y) = ($y, $x) if $rev;
- return $left->new
- ->mod(@$common)
- ->body($x . $y);
+ if ($my_tc->check($left)) {
+ $left = $left->flatten;
+
+ if ($my_tc->check($right)) {
+ $right = $right->flatten;
+
+ my ($only_left, $common, $only_right) = $inter->(
+ $left->_mods_cache,
+ $right->_mods_cache,
+ );
+
+ my $has_different_layers;
+ for (@$only_left) {
+ if ($_->type eq 'layer') {
+ $has_different_layers = 1;
+ last;
+ }
+ }
+ unless ($has_different_layers) {
+ for (@$only_right) {
+ if ($_->type eq 'layer') {
+ $has_different_layers = 1;
+ last;
+ }
+ }
+ }
+
+ if (!$has_different_layers and @$common) {
+ my $x = $left->new
+ ->mod(@$only_left)
+ ->body($left->_body);
+ my $y = $left->new
+ ->mod(@$only_right)
+ ->body($right->_body);
+ return $left->new
+ ->mod(@$common)
+ ->body(fold($x, $y, $rev));
+ } else {
+ @right = $right->instantiate;
+ }
} else {
- @right = $right->instantiate;
+ $_body_tc->assert_valid($right);
+ @right = @$right;
}
+
+ @left = $left->instantiate;
} else {
- @right = @$right;
+ if ($my_tc->check($right)) {
+ return fold($right, $left, 1);
+ } else {
+ $_body_tc->assert_valid($_) for $left, $right;
+ @left = @$left;
+ @right = @$right;
+ }
}
- @left = $left->instantiate;
-
- $left->new
- ->body($rev ? [ @right, @left ] : [ @left, @right ]);
+ $rev ? [ @right, @left ] : [ @left, @right ];
}
__PACKAGE__->meta->make_immutable;
+=head1 SEE ALSO
+
+L<LaTeX::TikZ>.
+
=head1 AUTHOR
Vincent Pit, C<< <perl at profvince.com> >>, L<http://www.profvince.com>.