source: to-imperative/trunk/runtime/rf_expr.hh @ 288

Last change on this file since 288 was 288, checked in by orlov, 18 years ago

* empty log message *

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.2 KB
Line 
1// $Source$
2// $Revision: 288 $
3// $Date: 2002-12-19 12:11:29 +0000 (Thu, 19 Dec 2002) $
4
5#ifndef __rf_expr_hh__
6#define __rf_expr_hh__
7
8#include "rf_common.hh"
9#include "rf_term.hh"
10#include "pxx_memory_chunk.hh"
11
12#include <new>
13#include <string.h>
14
15namespace rfrt
16{
17
18//
19// expression splitting directions
20enum Direction
21{
22  d_lt,         // split from left
23  d_rt          // split from right
24};
25
26//
27// Refal+ expression class
28class Expr
29{
30
31//
32// iterator is our friend
33template <Direction D = d_lt>
34friend class SplitIterator ;
35
36//
37// term is our friend
38friend class Term ;
39
40private:
41
42  //
43  // pointer to the first term
44  Term* first;
45  //
46  // pointer beyond the last term
47  Term* last;
48  //
49  // pointer to expression's holder in memory
50  M_Chunk* mem_chunk;
51  //
52  // flag pointing that expression has bracket terms
53  uintptr_t flags;
54
55private:
56
57  //
58  // private constructor reserving for expression with specified len
59  inline Expr (size_t const _len, int _d)
60  {
61    init(_len, _d);
62    flags = 0;
63    D( printf("+ %p(%p,%p,%p) of size %d\n", this, first, last, mem_chunk, _len); )
64  }
65
66public:
67
68  //
69  // constructor from character string
70  inline Expr (char const* _s = null)
71  {
72    //
73    // initialize expression
74    init(_s != null ? strlen(_s) : 0, 0);
75    //
76    // in a loop...
77    for (Term* p = first; p < last; p++, _s++) {
78      //
79      // ...create a symbol in place
80      new(p) Term(*_s);
81    }
82    //
83    // mark expression as flat
84    flags = 0;
85    D( printf("+ %p(%p,%p,%p) from %s\n", this, first, last, mem_chunk, _s); )
86  }
87
88  //
89  // constructor from expression holder
90  inline Expr( Term const* _cp )
91  {
92    //
93    // if we really have a reference to expression...
94    if( _cp->is_ref() ) {
95      //
96      // ...get its first term...
97      first = _cp->get_first();
98      //
99      // ...and last term
100      last = _cp->get_last();
101      //
102      // obtain a pointer to expression's memory chunk
103      mem_chunk = _cp->get_mem_chunk();
104      //
105      // increment reference counter
106      mem_chunk->inc_ref_count();
107      //
108      // check whether reference expression is flat and set a flag otherwise
109      flags = _cp->data1 & REF_BIT;
110      D( printf("+ %p(%p,%p,%p) from %p()\n", this, first, last, mem_chunk, _cp); )
111    }
112    //
113    // no, we have a symbol...
114    else {
115      //
116      // ...and this is the error
117      FATAL( "Unable to construct expression from symbol" );
118    }
119  }
120
121  //
122  //! Dereference constructor. Should be called only with valid
123  //  position.
124  inline Expr (Expr const& _expr, uintptr_t _pos)
125  {
126    new(this) Expr(_expr.first + _pos);
127  }
128 
129  //
130  //! Subexpression constructor
131  inline Expr (Expr const& _expr, uintptr_t _pos, uintptr_t _length)
132  {
133    new(this) Expr(
134      _expr.first + _pos, _expr.first + _pos + _length,
135      _expr.mem_chunk,
136      _expr.flags
137    );
138  }
139
140  //
141  // constructor from term
142  inline Expr (Term const& _cp)
143  {
144    init(1, 0);
145    *first = _cp;
146    flags |= REF_BIT;
147//    ref_childs();
148    D( printf("+ %p(%p,%p,%p) by copy from term %p\n",
149          this, first, last, mem_chunk, &_cp); )
150  }
151
152  //
153  // copy constructor
154  inline Expr (Expr const& _expr) :
155    first (_expr.first),
156    last (_expr.last),
157    mem_chunk (_expr.mem_chunk),
158    flags (_expr.flags)
159  {
160    //
161    // increment a reference counter to allocated block
162    mem_chunk->inc_ref_count();
163    D( printf("+ %p(%p,%p,%p) by copy from %p\n", this, first, last, mem_chunk, &_expr); )
164  }
165
166  //
167  // generic constructor - should not be called directly
168  inline Expr (
169    Term* const _first, Term* const _last,
170    M_Chunk* const _mem_chunk, uintptr_t const _flags
171  ) :
172    first (_first),
173    last (_last),
174    mem_chunk (_mem_chunk),
175    flags (_flags)
176  {
177    //
178    // increment a reference counter to allocated block
179    mem_chunk->inc_ref_count();
180    D( printf("+ %p(%p,%p,%p) by generic constructor",
181          this, first, last, mem_chunk); )
182  }
183
184  inline Expr (Expr const* _expr) :
185    first (_expr->first),
186    last (_expr->last),
187    mem_chunk (_expr->mem_chunk),
188    flags (_expr->flags)
189  {
190    //
191    // increment a reference counter to allocated block
192//    inc_ref_count();
193    D( printf("+ %p(%p,%p,%p) from *%p\n",
194          this, first, last, mem_chunk, _expr); )
195  }
196
197  //
198  // destructor
199  inline ~Expr ()
200  {
201    D( printf("- %p(%p,%p,%p)\n", this, first, last, mem_chunk); )
202    drop();
203  }
204
205  //
206  //! Drop an expression
207  inline void drop()
208  {
209    //
210    // decrement reference counter and destroy an object if it is zero
211    if( mem_chunk != null && !mem_chunk->dec_ref_count() ) {
212      //
213      // walk through and decrement reference counters on childs
214      deref_childs();
215      //
216      // destruct expression holder in memory
217      mem_chunk->destruct( &allocator );
218      D( printf("-- %p\n", mem_chunk); )
219    }
220//    first = last = null;
221    mem_chunk = null;
222//    flags = 0;
223  }
224
225  //
226  // assignment operator
227  inline const Expr &operator=( const Expr &_expr )
228  {
229    D( printf("%p(%p,%p,%p) = %p(%p,%p,%p)\n",
230          this, first, last, mem_chunk,
231          &_expr, _expr.first, _expr.last, _expr.mem_chunk); )
232    //
233    // if we are not assigning to self
234    if( this != &_expr ) {
235      //
236      // destroy old expression
237      drop();
238      //
239      // and build a copy in place
240      // new(this) Expr(_expr);     // not very good idea indeed
241      first     = _expr.first;
242      last      = _expr.last;
243      mem_chunk = _expr.mem_chunk;
244      flags     = _expr.flags;
245      //
246      //
247      mem_chunk->inc_ref_count();
248    }
249    //
250    // return reference to self
251    return *this;
252  }
253
254private:
255
256  //
257  // init an expression
258  inline void init( size_t _len, int _d )
259  {
260    D( printf("init is called for %p\n", this); )
261    //
262    // construct new memory chunk with a help from allocator
263    mem_chunk = pxx::construct_mem_chunk( &allocator, _len * sizeof(Term) );
264    //
265    // get pointers to the first and beyond the last terms in allocated block
266    Term *start = static_cast<Term*>( mem_chunk->get_first() );
267    Term *end   = static_cast<Term*>( mem_chunk->get_last () );
268    //
269    // if we place expression at the left side of allocated block...
270    if( _d > 0 ) {
271      first = start;
272      last  = first + _len;
273    }
274    //
275    // ...or at the right side of allocated block...
276    else if( _d < 0 ) {
277      last  = end;
278      first = last - _len;
279    }
280    //
281    // ...or in the middle of allocated block
282    else {
283      first = start + (mem_chunk->get_size() / sizeof(Term) - _len) / 2;
284      last  = first + _len;
285    }
286    Term* prev = first - 1;
287    //
288    // if we have at least one term to the left of the first term
289    if( prev >= start ) {
290      //
291      // setup border symbol
292      prev ->data1 = SYM_BORDER;
293      start->data1 = SYM_EMPTY;
294      start->data2 = first - start;
295    }
296    //
297    // if we have at least one term to the right of the last term
298    if( last < end ) {
299      //
300      // setup border symbol
301      last->data1 = SYM_BORDER;
302    }
303  }
304
305  inline void ref_childs() const
306  {
307    for( Term *p = first; p < last; p++ )
308    {
309      if( p->is_ref() )
310        p->get_mem_chunk()->inc_ref_count();
311    }
312  }
313/*
314    Term* p = first;
315    while (p < last) {
316      if (p->is_ref()) {
317        Expr e(p);
318        e.inc_ref_count();
319       
320      }
321      p++;
322    }
323  }
324*/
325
326  inline void deref_childs () const
327  {
328    Term *p = static_cast<Term*>( mem_chunk->get_first() );
329    Term *q = static_cast<Term*>( mem_chunk->get_last() );
330    if (p->data1 == SYM_EMPTY) p += p->data2;
331    // ОК, сейчас попали на первый терм выражения, под которое выделялся
332    // chunk. Так как deref_childs вызывается только из деструктора, то это
333    // выражение всегда совпадает с *this. Или это неправда???
334    //
335    // Между прочим, SYM_EMPTY нужен только для этого - находить
336    // первоначальное выражение в chunk'е.
337    //
338    // Итого:
339    //    Едем по куску chunk'а, который был отдан под изначальное выражение
340    //    (для которого он выделялся).
341    //   
342    //    Для каждого встретившегося скобочного терма, уменьшаем кол-во ссылок
343    //    на него.
344    //
345    //    Если встретили this выражение, и оно flat, то пропускаем его
346    //    полностью, что разумно.
347    //
348    while ((p < q) && !p->is_border()) {
349      if (p == first && is_flat()) { p = last; continue; }
350      if (p->is_ref()) {
351        p->get_mem_chunk()->dec_ref_count();
352      }
353      p++;
354    }
355  }
356
357public:
358
359  inline void write (FILE* _fp) const
360  {
361    bool chars_flag = false;
362    for (Term* p = first; p < last; p++) {
363      if (p->is_sym()) {
364        if (p->is_char()) {
365          if (!chars_flag) {
366            if (p != first) fputc(' ', _fp);
367            fputc('\'', _fp);
368            chars_flag = true;
369          }
370          fputc(p->get_char(), _fp);
371        } else {
372          FATAL("Not supported yet");
373        }
374      } else {
375        if (chars_flag) {
376          fputc('\'', _fp);
377          chars_flag = false;
378        }
379        if (p != first) fputc(' ', _fp);
380        fputc('(', _fp);
381        Expr e(p);
382        e.write(_fp);
383        fputc(')', _fp);
384      }
385    }
386    if (chars_flag) {
387      fputc('\'', _fp);
388    }
389  }
390
391  inline void writeln (FILE* _fp) const
392  {
393    write (_fp);
394    fputc('\n', _fp);
395  }
396
397private:
398
399  inline bool rt_alloc( uintptr_t _len ) const
400  {
401    Term *p = static_cast<Term*>( mem_chunk->get_last() );
402    //
403    // Если на наш chunk есть только одна ссылка (значит с нашего выражения),
404    // то убираем по ссылке со всех скобочных термов, которые лежат правее
405    // нашего выражения.
406    //
407    // Если справа от нашего выражения есть пространство, то выставляем
408    // границу после последнего терма нашего выражения. А почему её там не
409    // стояло????? !!!!!
410    //
411    if( mem_chunk->no_extern_refs() )
412    {
413      for( Term* q = last; (q < p) && (q->data1 != SYM_BORDER); q++ )
414      {
415        if( q->is_ref() )
416          q->get_mem_chunk()->dec_ref_count();
417      }
418      if( last < p )
419        last->data1 = SYM_BORDER;
420    }
421    //
422    // Если справа от нашего выражения есть достаточно места (_len) и
423    // выставлена граница после последнего терма (БЛИН!!! КАК она может быть
424    // НЕ выставлена????? Если _len == 0 ???), то выставить новую границу,
425    // если ещё остаётся место и вернуть true.
426    //
427    // Иначе вернуть false.
428    //
429    if( (last + _len <= p) && (last->data1 == SYM_BORDER) )
430    {
431      if( last + _len < p )
432      {
433        (last + _len)->data1 = SYM_BORDER;
434      }
435      return true;
436    }
437    else
438      return false;
439  }
440
441  inline bool lt_alloc( uintptr_t _len ) const
442  {
443    Term *p = static_cast<Term*>( mem_chunk->get_first() );
444    if( mem_chunk->no_extern_refs() )
445    {
446      for( Term* q = first - 1; (q >= p) && (q->data1 != SYM_BORDER); q-- )
447      {
448        if( q->is_ref() )
449          q->get_mem_chunk()->dec_ref_count();
450      }
451      if( first > p )
452      {
453        (first - 1)->data1 = SYM_BORDER;
454        p->data2 = first - p;
455      }
456    }
457    if( (first - _len >= p) && ((first - 1)->data1 == SYM_BORDER) )
458    {
459      if( first - _len > p )
460      {
461        (first - (_len + 1))->data1 = SYM_BORDER;
462        p->data2 = (first - _len) - p;
463      }
464      return true;
465    }
466    else
467      return false;
468  }
469  //
470  // Гм. Чтобы это могло лежать справа и слева от выражения,
471  // если ref_count == 1 ??? !!!!!
472  //
473
474public:
475
476  inline Expr operator + (Expr const& _expr) const
477  {
478    D( printf("Adding %p to %p\n", &_expr, this); )
479    uintptr_t len1 = last - first;
480    uintptr_t len2 = _expr.last - _expr.first;
481    uintptr_t len = len1 + len2;
482    if (len2 == 0) {
483      #if DEBUG
484      empty_copy++;
485      #endif
486      return *this;
487    } else if (len1 == 0) {
488      #if DEBUG
489      empty_copy++;
490      #endif
491      return _expr;
492    } else if (rt_alloc(len2)) {
493      //
494      // Copy second arg
495      #if DEBUG
496      rt_copy++;
497      #endif
498      if (!_expr.is_flat()) _expr.ref_childs();
499      Expr e(*this);
500      e.flags |= _expr.flags;
501      memcpy(e.last, _expr.first, len2 * sizeof(Term));
502      e.last += len2;
503      return e;
504    } else if (_expr.lt_alloc(len1)) {
505      //
506      // Copy first arg
507      #if DEBUG
508      lt_copy++;
509      #endif
510      if (!is_flat()) ref_childs();
511      Expr e(_expr);
512      e.flags |= flags;
513      e.first -= len1;
514      memcpy(e.first, first, len1 * sizeof(Term));
515      return e;
516    } else {
517      //
518      // Copy both args
519      #if DEBUG
520      both_copy++;
521      #endif
522      Expr e(len, len1 >= len2 ? 1 : -1);
523      e.flags = flags | _expr.flags;
524      memcpy(e.first, first, len1 * sizeof(Term));
525      memcpy(e.first + len1, _expr.first, len2 * sizeof(Term));
526      if (!e.is_flat()) e.ref_childs();
527      return e;
528    }
529  }
530
531  inline Term operator () () const
532//  inline Expr operator () () const
533  {
534    return Term(*this);
535//    return Expr(Term(self));
536  }
537
538  inline Expr operator * () const
539  {
540    if (last - first == 1) {
541      return Expr(first);
542    } else {
543      FATAL("Expression length not equal to 1");
544    }
545  }
546
547  inline Expr operator + (Term const& _term) const
548  {
549    uintptr_t len1 = last - first;
550    uintptr_t len = len1 + 1;
551    if (rt_alloc(1)) {
552      //
553      // Copy second arg
554      #if DEBUG
555      rt_copy++;
556      #endif
557      Expr e(*this);
558      if (_term.is_ref()) e.flags |= REF_BIT;
559      *e.last = _term;
560      e.last++;
561      return e;
562    } else {
563      //
564      // Copy both args
565      #if DEBUG
566      both_copy++;
567      #endif
568      Expr e(len, 1);
569      if (!is_flat()) {
570        e.flags = REF_BIT;
571        ref_childs();
572      }
573      if (_term.is_ref()) e.flags |= REF_BIT;
574      memcpy(e.first, first, len1 * sizeof(Term));
575      *(e.first + len1) = _term;
576      return e;
577    }
578  }
579
580  friend
581  inline Expr operator + (Term const& _term, Expr const& _expr)
582  {
583    uintptr_t len1 = _expr.last - _expr.first;
584    uintptr_t len = len1 + 1;
585    if (_expr.lt_alloc(1)) {
586      //
587      // Copy first arg
588      #if DEBUG
589      lt_copy++;
590      #endif
591      Expr e(_expr);
592      if (_term.is_ref()) e.flags |= REF_BIT;
593      e.first--;
594      *e.first = _term;
595      return e;
596    } else {
597      //
598      // Copy both args
599      #if DEBUG
600      both_copy++;
601      #endif
602      Expr e(len, -1);
603      if (!_expr.is_flat()) {
604        e.flags = REF_BIT;
605        _expr.ref_childs();
606      }
607      if (_term.is_ref()) e.flags |= REF_BIT;
608      memcpy(e.first + 1, _expr.first, len1 * sizeof(Term));
609      *(e.first) = _term;
610      return e;
611    }
612  }
613
614  friend
615  inline Expr operator + (Term const& _term1, Term const& _term2)
616  {
617    //
618    // Copy both args
619    #if DEBUG
620    both_copy++;
621    #endif
622    Expr e(2, 0);
623    if (_term1.is_ref() || _term2.is_ref()) {
624      e.flags |= REF_BIT;
625    }
626    *(e.first) = _term1;
627    *(e.first + 1) = _term2;
628    return e;
629  }
630
631  inline bool symbol_at (uintptr_t _pos) const
632  {
633    return (first + _pos)->is_sym();
634  }
635
636  inline bool is_flat () const
637  {
638    return flags == 0;
639  }
640
641  inline bool is_empty () const
642  {
643    return first == last;
644  }
645
646  inline Term* get_first () const
647  {
648    return first;
649  }
650
651  inline Term* get_last () const
652  {
653    return last;
654  }
655
656  inline uintptr_t get_len () const
657  {
658    return last - first;
659  }
660
661  inline uintptr_t get_flags () const
662  {
663    return flags;
664  }
665
666  inline void dump () const
667  {
668    Term* p;
669    printf ("%p, %p, %u: ", first, last, last - first);
670    for (p = first; p < last; p++) {
671      printf ("[%08x %08x]", p->data1, p->data2);
672    }
673    printf ("\n");
674  }
675
676  friend
677  inline bool eq (
678    Term const* _f1, Term const* _l1, Term const* _f2, Term const* _l2
679  )
680  {
681    if ((_l1 - _f1) == (_l2 - _f2)) {
682      for (; _f1 < _l1; _f1++, _f2++) {
683        if (*_f1 != *_f2) return false;
684      }
685      return true;
686    }
687    return false;
688  }
689
690friend
691inline bool eq_expr (
692  const Expr &_e1, uintptr_t _pos1, uintptr_t _len1,
693  const Expr &_e2, uintptr_t _pos2, uintptr_t _len2
694)
695{
696  if (_len1 == _len2) {
697    Term *p1 = _e1.get_first() + _pos1;
698    Term *p2 = _e2.get_first() + _pos2;
699    Term *l1 = p1  + _len1;
700    for (; p1 < l1; p1++, p2++) {
701      if (*p1 != *p2) return false;
702    }
703    return true;
704  }
705  return false;
706}
707
708
709friend
710inline bool flat_eq (
711  const Expr &_e1, uintptr_t _pos1,
712  const Expr &_e2, uintptr_t _pos2, uintptr_t _len
713)
714{
715  Term *p1 = _e1.get_first() + _pos1;
716  Term *p2 = _e2.get_first() + _pos2;
717  Term *l1 = p1  + _len;
718  for (; p1 < l1; p1++, p2++) {
719    if (p1->get_type() != p2->get_type() || p1->data2 != p2->data2)
720      return false;
721  }
722  return true;
723}
724
725  friend
726  inline bool operator == (Term const& _t1, Term const& _t2)
727  {
728    if (_t1.is_sym() && _t2.is_sym()) {
729      if (_t1.get_type() == _t2.get_type()) {
730        if (_t1.data2 == _t2.data2) {
731          return true;
732        }
733      }
734    } else if (_t1.is_ref() && _t2.is_ref()) {
735      return
736        eq(_t1.get_first(), _t1.get_last(), _t2.get_first(), _t2.get_last());
737    }
738    return false;
739  }
740
741// _t1.is_sym() && _t2.is_sym()
742// have_same_type(_t1, _t2)
743// _t1.data2 == _t2.data2 || (_t1.is_compound() && _t1->data2 == _t2->data2)
744// В принципе, компилятор мог бы знать с каким типом мы имеем дело. Тогда можно
745// было бы избежать лишней проверки is_compound().
746// _t1.is_ref() && _t2.is_ref()
747
748  friend
749  inline bool operator != (Term const& _t1, Term const& _t2)
750  {
751    return !(_t1 == _t2);
752  }
753
754  inline bool operator == (Expr const& _expr) const
755  {
756    return eq(first, last, _expr.first, _expr.last);
757  }
758
759  inline bool operator != (Expr const& _expr) const
760  {
761    return !eq(first, last, _expr.first, _expr.last);
762  }
763
764  inline M_Chunk *get_mem_chunk()
765  {
766    return mem_chunk;
767  }
768
769  inline void set_mem_chunk( M_Chunk *_ptr )
770  {
771    mem_chunk = _ptr;
772  }
773
774  class Iterator
775  {
776
777  private:
778
779    Expr& expr ;
780    Term* ptr ;
781
782  public:
783
784    inline Iterator (Expr& _expr) :
785      expr (_expr),
786      ptr (_expr.first)
787    {}
788
789    inline ~Iterator ()
790    {}
791
792    inline operator bool () const
793    {
794      return (ptr < expr.last) && (ptr >= expr.first);
795    }
796
797    inline Term* operator -> () const
798    {
799      #ifdef PARANOIA
800      if (!*this) FATAL("Attempt to obtain pointer to invalid term");
801      #endif
802      return ptr;
803    }
804
805    inline Iterator& operator ++ ()
806    {
807      ptr++;
808      return *this;
809    }
810
811    inline Iterator& operator ++ (int)
812    {
813      return operator++();
814    }
815
816    inline Iterator& operator -- ()
817    {
818      ptr--;
819      return *this;
820    }
821
822    inline Iterator& operator -- (int)
823    {
824      return operator--();
825    }
826
827    inline Iterator& operator += (int _offset)
828    {
829      ptr +=_offset;
830      return *this;
831    }
832
833    inline Iterator& operator -= (int _offset)
834    {
835      ptr -=_offset;
836      return *this;
837    }
838
839  };
840
841};
842
843//
844// is needed for () operation
845inline Term::Term (Expr const& _expr) :
846  data1 ((uintptr_t)_expr.first | ORDER1(_expr.mem_chunk->get_order())),
847  data2 ((uintptr_t)_expr.last | ORDER2(_expr.mem_chunk->get_order()))
848{
849  D( printf("+ term %p from expression %p(%p,%p,%p)\n",
850        this, &_expr, _expr.first, _expr.last, _expr.mem_chunk); )
851  data1 |= (_expr.flags & REF_BIT);
852  _expr.mem_chunk->inc_ref_count();
853}
854
855template <Direction D>
856class SplitIterator
857{
858
859  Expr lt ;
860  Expr rt ;
861  bool state ;
862
863public:
864
865  inline SplitIterator (Expr const& _expr, uintptr_t _min_len = 0)
866  {
867    FATAL("Not supported yet");
868  }
869
870  ~SplitIterator ()
871  {}
872
873  inline SplitIterator& operator ++ () {
874    if (lt.last < rt.last) {
875      if (lt.last->is_ref()) lt.flags |= REF_BIT;
876      lt.last++;
877      rt.first++;
878    } else {
879      state = false;
880    }
881    return *this;
882  }
883
884  inline SplitIterator& operator -- () {
885    if (lt.first < rt.first) {
886      lt.last--;
887      rt.first--;
888      if (rt.first->is_ref()) rt.flags |= REF_BIT;
889    } else {
890      state = false;
891    }
892    return *this;
893  }
894
895  inline SplitIterator& operator ++ (int) {
896    return operator++();
897  }
898
899  inline SplitIterator& operator -- (int) {
900    return operator--();
901  }
902
903  inline operator bool ()
904  {
905    return state;
906  }
907
908  inline Expr const& get_left () const
909  {
910    return lt;
911  }
912
913  inline Expr const& get_right () const
914  {
915    return rt;
916  }
917
918};
919
920template <>
921inline SplitIterator<d_lt>::SplitIterator (
922  Expr const& _expr, uintptr_t _min_len
923) :
924  lt (_expr.get_first(), _expr.get_first() + _min_len,
925      _expr.mem_chunk, 0),
926  rt (_expr.get_first() + _min_len, _expr.get_last(),
927      _expr.mem_chunk, 0),
928  state (true)
929{}
930
931#define iter(e) e##_iter
932
933#define lsplit(e, minlen, le, re) \
934  SplitIterator<d_lt> iter(e)(e, minlen); \
935  Expr const& le = iter(e).get_left(); \
936  Expr const& re = iter(e).get_right()
937
938#if 0
939#define lsplit_e(e, le, re) \
940  SplitIterator<d_lt> iter(e)(e, 0); \
941  Expr const& le = iter(e).get_left(); \
942  Expr const& re = iter(e).get_right()
943
944#define lsplit_v(e, le, re) \
945  SplitIterator<d_lt> iter(e)(e, 1); \
946  Expr const& le = iter(e).get_left(); \
947  Expr const& re = iter(e).get_right()
948
949#define can_lsplit_s(e) \
950  (e.get_len() >= 1 && e.get_first()->is_sym())
951
952#define lsplit_s(e, le, re) \
953  Expr le(e.get_first(), e.get_first() + 1, e.get_ref_count(), 0); \
954  Expr re(e.get_first() + 1, e.get_last(), e.get_ref_count(), e.get_flags()); \
955
956#define can_lsplit_t(e) \
957  (e.get_len() >= 1)
958
959#define lsplit_t(e, le, re) \
960  Expr le( \
961    e.get_first(), e.get_first() + 1, \
962    e.get_ref_count(), e.get_first()->is_sym() ? 0 : REF_BIT \
963  ); \
964  Expr re(e.get_first() + 1, e.get_last(), e.get_ref_count(), e.get_flags()); \
965
966#define can_lsplit_h(e, he) ( \
967  e.get_len() >= he.get_len() && \
968  eq( \
969    e.get_first(), e.get_first() + he.get_len(), \
970    he.get_first(), he.get_last() \
971  ) \
972)
973
974#define lsplit_h(e, le, re) \
975  Expr re( \
976    e.get_first() + le.get_len(), e.get_last(), \
977    e.get_ref_count(), e.get_flags() \
978  );
979#endif
980
981}
982
983#endif // __rf_expr_hh__
Note: See TracBrowser for help on using the repository browser.