Back to index

texmacs  1.0.7.15
Classes | Defines | Functions
patch.hpp File Reference
#include "modification.hpp"
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  patch_rep
class  patch

Defines

#define PATCH_MODIFICATION   0
#define PATCH_COMPOUND   1
#define PATCH_BRANCH   2
#define PATCH_BIRTH   3
#define PATCH_AUTHOR   4

Functions

 ABSTRACT_NULL_CODE (patch)
int nr_children (patch p)
patch child (patch p, int i)
array< patchchildren (patch p)
array< patchchildren (patch p, int i, int j)
int nr_branches (patch p)
patch branch (patch p, int i)
array< patchbranches (patch p)
array< patchbranches (patch p, int i, int j)
double new_author ()
double new_marker ()
void set_author (double author)
double get_author ()
tm_ostreamoperator<< (tm_ostream &out, patch p)
patch copy (patch p)
patch compactify (patch p)
path cursor_hint (patch p, tree t)
int get_type (patch p)
int N (patch p)
modification get_modification (patch p)
modification get_inverse (patch p)
bool get_birth (patch p)
double get_author (patch p)
bool is_applicable (patch p, tree t)
tree clean_apply (patch p, tree t)
void apply (patch p, tree &t)
modification invert (modification m, tree t)
bool commute (modification m1, modification m2)
bool swap (modification &m1, modification &m2)
bool join (modification &m1, modification m2, tree t)
patch invert (patch p, tree t)
bool commute (patch p1, patch p2)
bool swap (patch &p1, patch &p2)
bool join (patch &p1, patch p2, tree t)
patch remove_set_cursor (patch p)
bool does_modify (patch p)

Define Documentation

#define PATCH_AUTHOR   4

Definition at line 20 of file patch.hpp.

#define PATCH_BIRTH   3

Definition at line 19 of file patch.hpp.

#define PATCH_BRANCH   2

Definition at line 18 of file patch.hpp.

#define PATCH_COMPOUND   1

Definition at line 17 of file patch.hpp.

#define PATCH_MODIFICATION   0

Definition at line 16 of file patch.hpp.


Function Documentation

void apply ( patch  p,
tree t 
)

Definition at line 303 of file patch.cpp.

                         {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    apply (t, get_modification (p));
    break;
  case PATCH_BRANCH:
    ASSERT (N(p) <= 1, "ambiguous application");
  case PATCH_COMPOUND:
  case PATCH_AUTHOR:
    for (int i=0; i<N(p); i++)
      apply (p[i], t);
    break;
  case PATCH_BIRTH:
    break;
  default:
    FAILED ("unsupported patch type");
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

patch branch ( patch  p,
int  i 
)

Definition at line 139 of file patch.cpp.

                        {
  ASSERT (0 <= i && i < nr_branches (p), "index out of range");
  if (get_type (p) != PATCH_BRANCH) return p;
  else return p[i];
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 146 of file patch.cpp.

                   {
  if (get_type (p) != PATCH_BRANCH) return singleton (p);
  else return get_array (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

array<patch> branches ( patch  p,
int  i,
int  j 
)

Definition at line 152 of file patch.cpp.

                                 {
  ASSERT (0 <= i && i <= nr_branches (p), "index out of range");
  ASSERT (i <= j && j <= nr_branches (p), "index out of range");
  return range (branches (p), i, j);
}

Here is the call graph for this function:

patch child ( patch  p,
int  i 
)

Definition at line 113 of file patch.cpp.

                       {
  ASSERT (0 <= i && i < nr_children (p), "index out of range");
  if (get_type (p) != PATCH_COMPOUND) return p;
  else return p[i];
}

Here is the call graph for this function:

Definition at line 120 of file patch.cpp.

                   {
  if (get_type (p) != PATCH_COMPOUND) return singleton (p);
  else return get_array (p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

array<patch> children ( patch  p,
int  i,
int  j 
)

Definition at line 126 of file patch.cpp.

                                 {
  ASSERT (0 <= i && i <= nr_children (p), "index out of range");
  ASSERT (i <= j && j <= nr_children (p), "index out of range");
  return range (children (p), i, j);
}

Here is the call graph for this function:

tree clean_apply ( patch  p,
tree  t 
)

Definition at line 283 of file patch.cpp.

                              {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    return clean_apply (t, get_modification (p));
  case PATCH_BRANCH:
    ASSERT (N(p) <= 1, "ambiguous application");
  case PATCH_COMPOUND:
  case PATCH_AUTHOR:
    for (int i=0; i<N(p); i++)
      t= clean_apply (p[i], t);
    return t;
  case PATCH_BIRTH:
    return t;
  default:
    FAILED ("unsupported patch type");
    return t;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool commute ( modification  m1,
modification  m2 
)

Definition at line 309 of file commute.cpp.

                                           {
  modification s1= m1;
  modification s2= m2;
  return swap (s1, s2);
}

Here is the call graph for this function:

bool commute ( patch  p1,
patch  p2 
)

Definition at line 475 of file patch.cpp.

                             {
  patch s1= p1;
  patch s2= p2;
  return swap (s1, s2);
}

Here is the call graph for this function:

Definition at line 562 of file patch.cpp.

                     {
  switch (get_type (p)) {
  case PATCH_COMPOUND:
    {
      double a= 0;
      for (int i=0; i<N(p); i++)
       if (get_type (p[i]) != PATCH_AUTHOR) a= -1;
       else if (a == 0) a= get_author (p[i]);
       else if (a != get_author (p[i])) a= -1;
      if (a <= 0) {
       array<patch> r;
       insert (r, p);
       if (N(r) == 1) return r[0];
       return patch (r);
      }
      else {
       array<patch> r;
       for (int i=0; i<N(p); i++) insert (r, p[i][0]);
       if (N(r) == 1) return patch (a, r[0]);
       return patch (a, patch (r));
      }
    }
  case PATCH_BRANCH:
    if (N(p) == 1) return p[0];
    else {
      int i, n= N(p);
      array<patch> r (n);
      for (i=0; i<n; i++) r[i]= compactify (p[i]);
      return patch (true, r);
    }
  case PATCH_AUTHOR:
    return patch (get_author (p), compactify (p[0]));
  }
  return p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

patch copy ( patch  p)

Definition at line 231 of file patch.cpp.

               {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    return patch (copy (get_modification (p)), copy (get_inverse (p)));
  case PATCH_COMPOUND:
  case PATCH_BRANCH:
    {
      int i, n= N(p);
      array<patch> r (n);
      for (i=0; i<N(p); i++) r[i]= copy (p[i]);
      return patch (get_type (p) == PATCH_BRANCH, r);
    }
  case PATCH_BIRTH:
    return p;
  case PATCH_AUTHOR:
    return patch (get_author (p), copy (p[0]));
  default:
    FAILED ("unsupported patch type");
  }
  return p;
}

Here is the call graph for this function:

path cursor_hint ( patch  p,
tree  t 
)

Definition at line 636 of file patch.cpp.

                              {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    return cursor_hint (get_modification (p), t);
  case PATCH_COMPOUND:
    for (int i=0; i<N(p); i++) {
      path r= cursor_hint (p[i], t);
      if (!is_nil (r)) return r;
    }
    return path ();
  case PATCH_BRANCH:
    if (N(p) == 0) return path ();
  case PATCH_AUTHOR:
    return cursor_hint (p[0], t);
  case PATCH_BIRTH:
    return path ();
  default:
    FAILED ("unsupported patch type");
  }
  return path ();
}

Here is the call graph for this function:

bool does_modify ( patch  p)

Definition at line 690 of file patch.cpp.

                      {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    return get_modification (p)->k != MOD_SET_CURSOR;
  case PATCH_COMPOUND:
  case PATCH_BRANCH:
    for (int i=0; i<N(p); i++)
      if (does_modify (p[i]))
        return true;
    return false;
  case PATCH_BIRTH:
  case PATCH_AUTHOR:
    return false;
  default:
    return true;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

double get_author ( )

Definition at line 184 of file patch.cpp.

              {
  return current_author;
}

Here is the caller graph for this function:

double get_author ( patch  p) [inline]

Definition at line 94 of file patch.hpp.

                                   {
  return p->get_author (); }
bool get_birth ( patch  p) [inline]

Definition at line 92 of file patch.hpp.

                                {
  return p->get_birth (); }

Here is the caller graph for this function:

modification get_inverse ( patch  p) [inline]

Definition at line 90 of file patch.hpp.

                                          {
  return p->get_inverse (); }

Here is the caller graph for this function:

Definition at line 88 of file patch.hpp.

                                               {
  return p->get_modification (); }

Here is the caller graph for this function:

int get_type ( patch  p) [inline]

Definition at line 84 of file patch.hpp.

                              {
  return p->get_type (); }

Here is the caller graph for this function:

Definition at line 40 of file commute.cpp.

                                {
  ASSERT (is_applicable (t, m), "modification not applicable");
  path rp= root (m);
  switch (m->k) {
  case MOD_ASSIGN:
    return mod_assign (rp, copy (subtree (t, rp)));
  case MOD_INSERT:
    return mod_remove (rp, index (m), insert_length (m->t));
  case MOD_REMOVE:
    {
      int i= index (m);
      int n= argument (m);
      return mod_insert (rp, i, copy (insert_range (subtree (t, rp), i, n)));
    }
  case MOD_SPLIT:
    return mod_join (rp, index (m));
  case MOD_JOIN:
    {
      int  i= index (m);
      return mod_split (rp, i, insert_length (subtree (t, rp * i)));
    }
  case MOD_ASSIGN_NODE:
    return mod_assign_node (rp, L (subtree (t, rp)));
  case MOD_INSERT_NODE:
    return mod_remove_node (rp, argument (m));
  case MOD_REMOVE_NODE:
    {
      tree u= subtree (t, rp);
      int  i= index (m);
      return mod_insert_node (rp, i, copy (u (0, i) * u (i+1, N(u))));
    }
  case MOD_SET_CURSOR:
    return m;
  default:
    FAILED ("unexpected situation");
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

patch invert ( patch  p,
tree  t 
)

Definition at line 327 of file patch.cpp.

                         {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    return patch (get_inverse (p), get_modification (p));
  case PATCH_BRANCH:
    ASSERT (N(p) <= 1, "ambiguous application");
  case PATCH_COMPOUND:
    {
      int i, n=N(p);
      array<patch> r(n);
      for (i=0; i<n; i++) {
       r[n-1-i]= invert (p[i], t);
       t= clean_apply (p[i], t);
      }
      return patch (get_type (p) == PATCH_BRANCH, r);
    }
  case PATCH_BIRTH:
    return patch (get_author (p), !get_birth (p));
  case PATCH_AUTHOR:
    return patch (get_author (p), invert (p[0], t));
  default:
    FAILED ("unsupported patch type");
    return patch ();
  }
}

Here is the call graph for this function:

bool is_applicable ( patch  p,
tree  t 
)

Definition at line 258 of file patch.cpp.

                                {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    return is_applicable (t, get_modification (p));
  case PATCH_COMPOUND:
    for (int i=0; i<N(p); i++) {
      if (!is_applicable (p[i], t)) return false;
      t= clean_apply (p[i], t);
    }
    return true;
  case PATCH_BRANCH:
  case PATCH_AUTHOR:
    for (int i=0; i<N(p); i++)
      if (!is_applicable (p[i], t))
       return false;
    return true;
  case PATCH_BIRTH:
    return true;
  default:
    FAILED ("unsupported patch type");
    return false;
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool join ( modification m1,
modification  m2,
tree  t 
)

Definition at line 320 of file commute.cpp.

                                                 {
  if (m1->k == MOD_INSERT &&
      m2->k == MOD_INSERT &&
      is_atomic (m1->t) &&
      root (m1) == root (m2) &&
      (index (m2) == index (m1) ||
       index (m2) == index (m1) + N (m1->t->label)))
    {
      string s= m1->t->label * m2->t->label;
      if (index (m2) == index (m1))
       s= m2->t->label * m1->t->label;
      m1= mod_insert (root (m1), index (m1), tree (s));
      return true;
    }
  if (m1->k == MOD_REMOVE &&
      m2->k == MOD_REMOVE &&
      is_atomic (subtree (t, root (m1))) &&
      root (m1) == root (m2) &&
      (index (m1) == index (m2) ||
       index (m1) == index (m2) + argument (m2)))
    {
      m1= mod_remove (root (m2), index (m2),
                    argument (m1) + argument (m2));
      return true;
    }
  return false;
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool join ( patch p1,
patch  p2,
tree  t 
)

Definition at line 486 of file patch.cpp.

                                   {
  //cout << "Join " << p1 << LF << "with " << p2 << LF;
  if (get_type (p1) == PATCH_AUTHOR &&
      get_type (p2) == PATCH_AUTHOR &&
      get_author (p1) == get_author (p2))
    {
      double author= get_author (p1);
      patch q1= p1[0];
      patch q2= p2[0];
      bool r= join (q1, q2, t);
      if (r) p1= patch (author, q1);
      return r;
    }
  if (get_type (p1) == PATCH_MODIFICATION &&
      get_type (p2) == PATCH_MODIFICATION)
    {
      modification m1= get_modification (p1);
      modification m2= get_modification (p2);
      modification i2= get_inverse (p2);
      modification i1= get_inverse (p1);
      bool r= join (m1, m2, t);
      bool v= join (i2, i1, clean_apply (p2, clean_apply (p1, t)));
      if (r && v) p1= patch (m1, i2);
      return r && v;
    }
  if (get_type (p1) == PATCH_COMPOUND &&
      nr_children (p1) > 0 &&
      nr_children (remove_set_cursor (p1)) == 1 &&
      nr_children (p1[0]) == 1)
    {
      patch q= p1[0];
      bool rf= join (q, p2, t);
      if (rf) p1= q;
      return rf;
    }
  if (get_type (p2) == PATCH_COMPOUND &&
      nr_children (p2) > 0 &&
      nr_children (remove_set_cursor (p2)) == 1 &&
      nr_children (p2[0]) == 1)
    {
      patch q= p2[0];
      bool rf= join (p1, q, t);
      if (rf) {
        array<patch> a= children (p1);
        array<patch> b= children (p2);
        p1= patch (append (a, range (b, 1, N(b))));
      }
      return rf;
    }
  return false;
}

Here is the call graph for this function:

int N ( patch  p) [inline]

Definition at line 86 of file patch.hpp.

                       {
  return p->get_arity (); }
double new_author ( )

Definition at line 165 of file patch.cpp.

              {
  static double next_author= 0.0;
  next_author += 1.0;
  return next_author;
}

Here is the caller graph for this function:

double new_marker ( )

Definition at line 172 of file patch.cpp.

              {
  static double next_marker= 0.5;
  next_marker += 1.0;
  return next_marker;
}

Here is the caller graph for this function:

int nr_branches ( patch  p)

Definition at line 133 of file patch.cpp.

                      {
  if (get_type (p) != PATCH_BRANCH) return 1;
  else return N(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int nr_children ( patch  p)

Definition at line 107 of file patch.cpp.

                      {
  if (get_type (p) != PATCH_COMPOUND) return 1;
  else return N(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

tm_ostream& operator<< ( tm_ostream out,
patch  p 
)

Definition at line 193 of file patch.cpp.

                                       {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    out << get_modification (p) << " -- " << get_inverse (p);
    break;
  case PATCH_COMPOUND:
    if (N(p) == 0) out << "No children";
    else {
      out << "Composite" << INDENT;
      for (int i=0; i<N(p); i++)
       out << LF << p[i];
      out << UNINDENT;
    }
    break;
  case PATCH_BRANCH:
    if (N(p) == 0) out << "No branches";
    else for (int i=0; i<N(p); i++) {
      if (i != 0) out << LF;
      out << "Branch " << i << INDENT << LF << p[i] << UNINDENT;
    }
    break;
  case PATCH_BIRTH:
    if (get_birth (p)) out << "Birth ";
    else out << "Death ";
    out << get_author (p);
    break;
  case PATCH_AUTHOR:
    out << "Author " << get_author (p) << INDENT << LF;
    out << p[0];
    out << UNINDENT;
    break;
  default:
    FAILED ("unsupported patch type");
  }
  return out;
}

Here is the call graph for this function:

Definition at line 659 of file patch.cpp.

                            {
  switch (get_type (p)) {
  case PATCH_MODIFICATION:
    if (get_modification (p)->k != MOD_SET_CURSOR) return copy (p);
    return patch (array<patch> ());
  case PATCH_COMPOUND:
    {
      array<patch> r;
      for (int i=0; i<N(p); i++) {
        patch q= remove_set_cursor (p[i]);
        r << children (q);
      }
      if (N(r) == 1) return r[0];
      return patch (r);
    }
  case PATCH_BRANCH:
  case PATCH_BIRTH:
    return copy (p);
  case PATCH_AUTHOR:
    {
      patch q= remove_set_cursor (p[0]);
      if (nr_children (q) == 0) return q;
      else return patch (get_author (p), q);
    }
  default:
    FAILED ("unsupported patch type");
  }
  return p;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void set_author ( double  author)

Definition at line 179 of file patch.cpp.

                      {
  current_author= a;
}

Here is the caller graph for this function:

bool swap ( modification m1,
modification m2 
)

Definition at line 151 of file commute.cpp.

                                          {
  path rp1= root (m1);
  path rp2= root (m2);
  if (is_nil (rp1))
    switch (m1->k) {
    case MOD_ASSIGN:
      {
       if (m1 == m2) return true;
       if (!is_nil (rp2) || m2->k != MOD_INSERT_NODE) return false;
       modification aux= m2;
       m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
       m1= aux;
       return true;
      }
    case MOD_INSERT:
      {
       if (is_nil (m2->p)) return false;
       int b= m1->p->item;
       int e= b + insert_length (m1->t);
       if (m2->p->item >= b && m2->p->item < e)
         if (!is_nil (root (m2)) || m2->p->item != b || m2->k != MOD_INSERT)
           if (!is_nil (root (m2)) || m2->k != MOD_INSERT_NODE)
             return false;
       return swap1 (m1, m2, b, e-b);
      }
    case MOD_REMOVE:
      {
       if (is_nil (m2->p)) return false;
       int i= m1->p->item;
       int d= m1->p->next->item;
       return swap1 (m1, m2, i, -d);
      }
    case MOD_SPLIT:
      {
       if (is_nil (m2->p)) return false;
       int i= m1->p->item;
       if (m2->p->item == i || m2->p->item == i+1)
         if (!is_nil (root (m2)) || m2->p->item != i || m2->k != MOD_INSERT)
           if (!is_nil (root (m2)) || m2->k != MOD_INSERT_NODE)
             return false;
       return swap1 (m1, m2, i, 1);
      }
    case MOD_JOIN:
      {
       if (is_nil (m2->p)) return false;
       int i= m1->p->item;
       if (m2->p->item == i)
         if (!is_nil (root (m2)) || m2->k != MOD_INSERT)
           return false;
       return swap1 (m1, m2, i, -1);
      }
    case MOD_ASSIGN_NODE:
      {
       if (!is_nil (root (m2))) return swap_basic (m1, m2);
       if (m1 == m2) return true;
       if (!is_nil (rp2) || m2->k != MOD_INSERT_NODE) return false;
       modification aux= m2;
       m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
       m1= aux;
       return true;
      }
    case MOD_INSERT_NODE:
      {
       if (is_nil (root (m2))) return false;
       if (m2->p->item != m1->p->item) return false;
       modification aux= m1;
       m1= modification (m2->k, m2->p->next, m2->t);
       if (m2->k != MOD_INSERT_NODE || !is_nil (root (m1))) m2= aux;
       else m2= modification (aux->k, path (m1->p->item, aux->p), aux->t);
       return true;
      }
    case MOD_REMOVE_NODE:
      {
       modification aux= m1;
       m1= modification (m2->k, path (m1->p->item, m2->p), m2->t);
       m2= aux;
       return true;
      }
    case MOD_SET_CURSOR:
      {
        if (!is_nil (rp2) ||
            m2->k == MOD_JOIN ||
            m2->k == MOD_SPLIT ||
            m2->k == MOD_ASSIGN_NODE)
          return swap_basic (m1, m2);
        return false;
      }
    }
  else if (is_nil (rp2))
    switch (m2->k) {
    case MOD_ASSIGN:
      return false;
    case MOD_INSERT:
      {
       int b= m2->p->item;
       int e= b + insert_length (m2->t);
       return swap2 (m1, m2, b, e-b);
      }
    case MOD_REMOVE:
      {
       int b= m2->p->item;
       int e= b + m2->p->next->item;
       if (m1->p->item >= b && m1->p->item < e) return false;
       return swap2 (m1, m2, b, b-e);
      }
    case MOD_SPLIT:
      {
       int i= m2->p->item;
       if (m1->p->item == i) return false;
       return swap2 (m1, m2, i, 1);
      }
    case MOD_JOIN:
      {
       int i= m2->p->item;
       if (m1->p->item == i || m1->p->item == i+1) return false;
       return swap2 (m1, m2, i, -1);
      }
    case MOD_ASSIGN_NODE:
      return swap_basic (m1, m2);
    case MOD_INSERT_NODE:
      {
       modification aux= m2;
       m2= modification (m1->k, path (m2->p->item, m1->p), m1->t);
       m1= aux;
       return true;
      }
    case MOD_REMOVE_NODE:
      {
       if (m1->p->item != m2->p->item) return false;
       modification aux= m2;
       m2= modification (m1->k, m1->p->next, m1->t);
       m1= aux;
       return true;
      }
    case MOD_SET_CURSOR:
      {
        if (!is_nil (rp1) ||
            m1->k == MOD_JOIN ||
            m1->k == MOD_SPLIT ||
            m1->k == MOD_ASSIGN_NODE)
          return swap_basic (m1, m2);
        return false;
      }
    }
  else if (rp1->item == rp2->item) {
    path h (rp1->item);
    modification s1= m1 / h;
    modification s2= m2 / h;
    bool r= swap (s1, s2);
    m1= h * s1;
    m2= h * s2;
    return r;
  }
  else return swap_basic (m1, m2);
  FAILED ("unexpected situation");
}

Here is the call graph for this function:

Here is the caller graph for this function:

bool swap ( patch p1,
patch p2 
)

Definition at line 470 of file patch.cpp.

                            {
  return swap (p1, p2, 0, 0);
}

Here is the call graph for this function: