]> git.vpit.fr Git - perl/modules/LaTeX-TikZ.git/blobdiff - lib/LaTeX/TikZ/Scope.pm
First cut at the documentation
[perl/modules/LaTeX-TikZ.git] / lib / LaTeX / TikZ / Scope.pm
index 05308ddb07a067041770ff797aad66eedc28815b..e973adc20d6baa6af64b81c16fe6cc0b2b45b9f4 100644 (file)
@@ -21,6 +21,12 @@ use LaTeX::TikZ::Tools;
 
 use Any::Moose;
 
+=head1 ATTRIBUTES
+
+=head2 C<mods>
+
+=cut
+
 has '_mods' => (
  is       => 'ro',
  isa      => 'Maybe[ArrayRef[LaTeX::TikZ::Mod::Formatted]]',
@@ -37,6 +43,10 @@ has '_mods_cache' => (
  default  => sub { +{ } },
 );
 
+=head2 C<body>
+
+=cut
+
 has '_body' => (
  is       => 'rw',
  isa      => 'LaTeX::TikZ::Scope|ArrayRef[Str]',
@@ -48,13 +58,20 @@ my $ltmf_tc  = LaTeX::TikZ::Tools::type_constraint('LaTeX::TikZ::Mod::Formatted'
 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;
@@ -64,6 +81,10 @@ sub mod {
  $scope;
 }
 
+=head2 C<body>
+
+=cut
+
 sub body {
  my $scope = shift;
 
@@ -76,9 +97,13 @@ sub body {
 }
 
 use overload (
- '.' => \&concat,
+ '@{}' => 'dereference',
 );
 
+=head2 C<flatten>
+
+=cut
+
 sub flatten {
  my ($scope) = @_;
 
@@ -113,6 +138,10 @@ my $inter = Sub::Name::subname('inter' => sub {
  return \@left, \@common, \@right;
 });
 
+=head2 C<instantiate>
+
+=cut
+
 sub instantiate {
  my ($scope) = @_;
 
@@ -163,45 +192,78 @@ sub instantiate {
  return @body;
 }
 
-sub concat {
- my ($left, $right, $rev) = @_;
+=head2 C<dereference>
+
+=cut
 
- $_body_tc->assert_valid($right);
+sub dereference { [ $_[0]->instantiate ] }
 
- $left = $left->flatten;
+=head2 C<fold>
+
+=cut
+
+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;