source: to-imperative/trunk/runtime/rf_expr.ih @ 1138

Last change on this file since 1138 was 1138, checked in by orlov, 17 years ago
  • Write for Integers.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1//-----------------------------------------------------------------------------
2/// @file rf_expr.ih
3///
4/// Refal+ expression inline method implementation
5//
6//  $Source$
7//  $Revision: 1138 $
8//  $Date: 2003-08-09 00:43:04 +0000 (Sat, 09 Aug 2003) $
9//-----------------------------------------------------------------------------
10
11#ifndef __rf_expr_ih__
12#define __rf_expr_ih__
13
14#include "rf_expr.hh"
15#include "rf_term.ih"
16#include "rf_object_ref.ih"
17#include "rf_integer.ih"
18#include "rf_short_int.ih"
19#include "pxx_heap_allocator.ih"
20#include "pxx_common.ih"
21
22#include <wchar.h>
23#include <wctype.h>
24
25namespace rfrt
26{
27
28using namespace rftype ;
29
30inline Expr::Expr (
31  Term* const _first, Term* const _last,
32  MemoryChunk* const _mem_chunk, uintptr_t const _flags
33) :
34  first (_first),
35  last (_last),
36  mem_chunk (_mem_chunk),
37  flags (_flags)
38{
39  //
40  // Increment a reference counter to memory block containing an expression
41  mem_chunk->inc_ref_count();
42  D(printf("+ %p(%p,%p,%p) by generic constructor",
43           this, first, last, mem_chunk);)
44}
45
46inline Expr::Expr (Expr const* _expr) :
47  first (_expr->first),
48  last (_expr->last),
49  mem_chunk (_expr->mem_chunk),
50  flags (_expr->flags)
51{
52  //
53  // This is a special kind of copy constructor used to get arguments and
54  // results from stack. Do not increment a reference counter to memory block!
55//    inc_ref_count();
56  D(printf("+ %p(%p,%p,%p) from *%p\n",
57           this, first, last, mem_chunk, _expr);)
58}
59
60inline Expr::Expr (size_t _len, int _align)
61{
62  //
63  // Initialize an expression with requested length
64  init(_len, _align);
65  D(printf("+ %p(%p,%p,%p) of size %d\n", this, first, last, mem_chunk, _len);)
66}
67
68inline Expr::Expr (Object* _obj)
69{
70  init(1, 0);
71  new(first) ObjectRef(_obj);
72}
73
74#if 0
75inline Expr::Expr (char const* _string /* = null */)
76{
77  //
78  // Initialize an expression with necessary length
79  init(_string != null ? strlen(_string) : 0, 0);
80  //
81  // In a loop...
82  for (Term* p = first; p < last; p++, _string++) {
83    //
84    // ...create a symbol in place
85    new(p) Term(*_string);
86  }
87  //
88  // Mark expression as flat
89  flags = FLAT_BIT;
90  D(printf("+ %p(%p,%p,%p) from %s\n", this, first, last, mem_chunk, _string);)
91}
92#endif
93
94inline Expr::Expr ()
95{
96  init(0, 0);
97}
98
99inline Expr::Expr (Term const* _cp)
100{
101  //
102  // If we really have a reference term...
103  if (_cp->is_ref()) {
104    //
105    // ...get a first term of referenced expression...
106    first = _cp->get_first();
107    //
108    // ...and its right margin
109    last = _cp->get_last();
110    //
111    // Obtain a pointer to a memory block containing an expression
112    mem_chunk = _cp->get_mem_chunk();
113    //
114    // Increment reference counter to this memory block
115    mem_chunk->inc_ref_count();
116    //
117    // Check whether reference expression is flat and set a flag appropriately
118    flags = _cp->data1 & FLAT_BIT;
119    D(printf("+ %p(%p,%p,%p) from %p()\n", this, first, last, mem_chunk, _cp);)
120  }
121  //
122  // Oh, no, we have a symbol...
123  else {
124    //
125    // ...and this is the error
126    FATAL("Attempt to dereference a symbol" );
127  }
128}
129
130inline Expr::Expr (Expr const& _expr, uintptr_t _index)
131{
132  new(this) Expr(_expr.first + _index);
133}
134
135inline Expr::Expr (Expr const& _expr, uintptr_t _index, uintptr_t _length)
136{
137  //
138  // Call a generic constructor
139  new(this) Expr(
140    _expr.first + _index, _expr.first + _index + _length,
141    _expr.mem_chunk, _expr.flags
142  );
143}
144
145inline Expr::Expr (Expr const& _expr) :
146  first (_expr.first),
147  last (_expr.last),
148  mem_chunk (_expr.mem_chunk),
149  flags (_expr.flags)
150{
151  //
152  // Increment a reference counter to memory block
153  mem_chunk->inc_ref_count();
154  D(printf("+ %p(%p,%p,%p) by copy from %p\n",
155           this, first, last, mem_chunk, &_expr);)
156}
157
158inline Expr::~Expr ()
159{
160  D(printf("- %p(%p,%p,%p)\n", this, first, last, mem_chunk);)
161  //
162  // Destructor only calls a drop() method
163  drop();
164}
165
166inline Expr& Expr::operator = (Expr const& _expr)
167{
168  D(printf("%p(%p,%p,%p) = %p(%p,%p,%p)\n",
169           this, first, last, mem_chunk,
170           &_expr, _expr.first, _expr.last, _expr.mem_chunk);)
171  //
172  // If we are not assigning to self
173  if( this != &_expr ) {
174    //
175    // Destroy old expression
176    drop();
177    //
178    // Build a copy in place
179    new(this) Expr(_expr);
180  }
181  //
182  // Return reference to self
183  return *this;
184}
185
186inline Expr Expr::operator () () const
187{
188//  return Expr(Term(self));
189  Expr res(1, 0);
190  new(res.first) Term(self);
191  res.flags = 0;
192  return res;
193}
194
195inline Expr Expr::operator * () const
196{
197  if (last - first == 1) {
198    return Expr(first);
199  } else {
200    FATAL("Expression length not equal to 1");
201  }
202}
203
204inline bool Expr::symbol_at (uintptr_t _index) const
205{
206  return (first + _index)->is_sym();
207}
208
209inline bool Expr::is_flat () const
210{
211  return flags & FLAT_BIT;
212}
213
214inline bool Expr::is_empty () const
215{
216  return first == last;
217}
218
219inline Term* Expr::get_first () const
220{
221  return first;
222}
223
224inline Term* Expr::get_last () const
225{
226  return last;
227}
228
229inline uintptr_t Expr::get_len () const
230{
231  return last - first;
232}
233
234inline uintptr_t Expr::get_flags () const
235{
236  return flags;
237}
238
239inline void Expr::dump () const
240{
241  Term* p;
242  printf("%p, %p, %"PRIuPTR": ", first, last, last - first);
243  for (p = first; p < last; p++) {
244    printf("[%08"PRIxPTR" %08"PRIxPTR"]", p->data1, p->uint_data2);
245  }
246  printf("\n");
247}
248
249inline void Expr::drop ()
250{
251  //
252  // Decrement reference counter and destroy an object if it is zero
253  if (mem_chunk != null && mem_chunk->dec_ref_count() == 0) {
254    //
255    // Walk through and decrement reference counters on childs
256//    deref_childs();
257    deref_childs(first, is_flat() ? last : first, mem_chunk);
258    //
259    // Deallocate expression holder in memory
260    MemoryChunk::destroy_instance(mem_chunk);
261    D(printf("-- %p\n", mem_chunk);)
262  }
263  mem_chunk = null;
264}
265
266#if 0
267inline void Expr::ref_childs () const
268{
269  for (Term* p = first; p < last; p++) {
270    if (p->is_ref()) p->get_mem_chunk()->inc_ref_count();
271  }
272}
273#endif
274
275inline bool Expr::writeln (FILE* _fp) const
276{
277  if (!write (_fp)) return false;
278  if (fputc('\n', _fp) == EOF) return false;
279  return true;
280}
281
282inline bool Expr::println (FILE* _fp) const
283{
284  if (!print (_fp)) return false;
285  if (fputc('\n', _fp) == EOF) return false;
286  return true;
287}
288
289//
290// We prefer to have inline functions instead of macros, but changing macros
291// below to inline functions gives worse execution times
292
293///
294/// Check whether a term pointer is not a right margin of used area in
295/// a memory block
296#define is_not_right_margin(_p, _last) \
297  (((_p) < (_last)) && ((_p)->data1 != SYM_BORDER))
298
299///
300/// Check whether a term pointer is not a left margin of used area in
301/// a memory block
302#define is_not_left_margin(_p, _first) \
303  (((_p) >= (_first)) && ((_p)->data1 != SYM_BORDER))
304
305inline bool Expr::rt_alloc (uintptr_t _len) const
306{
307  //
308  // Get a pointer beyond the term area in our memory block
309  Term *p = static_cast<Term*>(mem_chunk->get_last());
310  //
311  // If our expression is the only one referencing a memory block than we can
312  // go to the right and destroy all terms there, because they are not a part
313  // of any expression
314  if (mem_chunk->no_extern_refs()) {
315    for (Term* q = last; is_not_right_margin(q, p); q++ ) {
316      q->~Term();
317    }
318    //
319    // Set correct right margin of used area in a memory block
320    if (last < p) last->data1 = SYM_BORDER;
321  } else {
322    //
323    // If there are other references to our memory block than if last is not
324    // a right margin of used area, we cannot allocate some space.
325    if (is_not_right_margin(last, p)) return false;
326  }
327  //
328  // Ok, here last is a a right margin of used area. Check whether we have
329  // enough space.
330  if (last + _len > p) return false;
331  //
332  // Set right margin if needed.
333  if (last + _len < p) (last + _len)->data1 = SYM_BORDER;
334  return true;
335}
336
337inline bool Expr::lt_alloc (uintptr_t _len) const
338{
339  Term* p = static_cast<Term*>(mem_chunk->get_first());
340  Term* f = first - 1;
341  if (mem_chunk->no_extern_refs()) {
342    for (Term* q = f; is_not_left_margin(q, p); q--) {
343      q->~Term();
344    }
345    if (f >= p) f->data1 = SYM_BORDER;
346  } else {
347    if (is_not_left_margin(f, p)) return false;
348  }
349  --p;
350  if (f - _len < p) return false;
351  if (f - _len > p) (f - _len)->data1 = SYM_BORDER;
352  return true;
353}
354
355//
356// FIXME: should be a real hash computation
357inline uint32_t Expr::hash () const
358{
359  return 0;
360}
361
362inline bool Expr::term_eq (Expr const& _expr, uintptr_t _index) const
363{
364  return *first == *(_expr.first + _index);
365}
366
367inline bool Expr::eq (Expr const& _expr, uintptr_t _index) const
368{
369  Term *f = _expr.first + _index;
370  if (first == f) {
371    #if DEBUG
372    identical++;
373    #endif
374    return true;
375  }
376  return Term::eq(first, f, get_len());
377}
378
379inline bool Expr::eq (Expr const& _expr, uintptr_t _index)
380{
381  Term *f = _expr.first + _index;
382  if (first == f) {
383    #if DEBUG
384    identical++;
385    #endif
386    return true;
387  }
388  bool res = Term::eq(first, f, get_len());
389  if (res) {
390    #if DEBUG
391    unifications++;
392    #endif
393    uintptr_t new_flags = flags | _expr.flags;
394    drop();
395    new(this) Expr(f, f + get_len(), _expr.mem_chunk, new_flags);
396  }
397  return res;
398}
399
400inline bool Expr::operator == (Expr const& _expr) const
401{
402  if (get_len() != _expr.get_len()) return false;
403  return eq(_expr, 0);
404}
405
406inline bool Expr::operator != (Expr const& _expr) const
407{
408  if (get_len() != _expr.get_len()) return true;
409  return !eq(_expr, 0);
410}
411
412inline bool Expr::operator == (Expr& _expr)
413{
414  if (first == _expr.first && last == _expr.last) {
415    #if DEBUG
416    identical++;
417    #endif
418    return true;
419  } else {
420    bool res = Term::eq(first, last, _expr.first, _expr.last);
421    if (res) {
422      #if DEBUG
423      unifications++;
424      #endif
425      if (mem_chunk->get_ref_count() >= _expr.mem_chunk->get_ref_count()) {
426        flags |= _expr.flags;
427        _expr = self;
428      } else {
429        _expr.flags |= flags;
430        self = _expr;
431      }
432    }
433    return res;
434  }
435}
436
437inline bool Expr::operator != (Expr& _expr)
438{
439  return !(self == _expr);
440}
441
442inline int Expr::compare (Expr const& _expr1, Expr const& _expr2)
443{
444  return Term::compare(_expr1.get_first(), _expr1.get_last(),
445                       _expr2.get_first(), _expr2.get_last());
446}
447
448inline MemoryChunk* Expr::get_mem_chunk () const
449{
450  return mem_chunk;
451}
452
453inline void Expr::set_mem_chunk (MemoryChunk* _ptr)
454{
455  mem_chunk = _ptr;
456}
457
458//
459// explicit specialization for SplitIterator constructor with left splitting
460template <>
461inline SplitIterator<d_lt>::SplitIterator (
462  Expr const& _expr, uintptr_t _min_len
463) :
464  lt (_expr.get_first(), _expr.get_first() + _min_len,
465      _expr.get_mem_chunk(), _expr.get_flags()),
466  rt (_expr.get_first() + _min_len, _expr.get_last(),
467      _expr.get_mem_chunk(), _expr.get_flags()),
468  state (true)
469{
470//  if (_min_len == 0) lt.flags = FLAT_BIT;
471}
472
473template <Direction D>
474SplitIterator<D>::~SplitIterator ()
475{}
476
477template <Direction D>
478inline SplitIterator<D>& SplitIterator<D>::operator ++ ()
479{
480  if (lt.last < rt.last) {
481    //
482    // FIXME: correctly we only should clear FLAT_BIT
483//    if (lt.last->is_ref()) lt.flags = 0;
484    lt.last++;
485    rt.first++;
486  } else {
487    state = false;
488  }
489  return *this;
490}
491
492template <Direction D>
493inline SplitIterator<D>& SplitIterator<D>::operator ++ (int)
494{
495  return operator++();
496}
497
498template <Direction D>
499inline SplitIterator<D>& SplitIterator<D>::operator -- ()
500{
501  if (lt.first < rt.first) {
502    lt.last--;
503    rt.first--;
504    //
505    // FIXME: correctly we only should clear FLAT_BIT
506//    if (rt.first->is_ref()) rt.flags = 0;
507  } else {
508    state = false;
509  }
510  return *this;
511}
512
513template <Direction D>
514inline SplitIterator<D>& SplitIterator<D>::operator -- (int)
515{
516  return operator--();
517}
518
519template <Direction D>
520inline SplitIterator<D>::operator bool ()
521{
522  return state;
523}
524
525template <Direction D>
526inline Expr const& SplitIterator<D>::get_left () const
527{
528  return lt;
529}
530
531template <Direction D>
532inline Expr const& SplitIterator<D>::get_right () const
533{
534  return rt;
535}
536
537#if defined(ALL_INLINE) || defined(INSTANTIATE_INLINE)
538
539INLINE Expr Expr::operator + (Expr const& _expr) const
540{
541  D(printf("Adding %p to %p\n", &_expr, this);)
542  if (last == _expr.first) {
543    #if DEBUG
544    empty_copy++;
545    #endif
546    //
547    // Call a generic constructor
548    return Expr (first, _expr.last, mem_chunk, flags & _expr.flags);
549  }
550  //
551  // Get lentgths of both arguments
552  uintptr_t len1 = last - first;
553  uintptr_t len2 = _expr.last - _expr.first;
554  //
555  // If a length of a second argument is zero do nothing and return a copy of
556  // a first argument
557  if (len2 == 0) {
558    #if DEBUG
559    empty_copy++;
560    #endif
561    return *this;
562  //
563  // If a length of a first argument is zero do nothing and return a copy of
564  // a second argument
565  } else if (len1 == 0) {
566    #if DEBUG
567    empty_copy++;
568    #endif
569    return _expr;
570  //
571  // Try to get a memory to the right of the first argument that able to
572  // contain a second argument
573  } else if (rt_alloc(len2)) {
574    //
575    // On success copy a contents of a second argument
576    #if DEBUG
577    rt_copy++;
578    #endif
579    //
580    // A legal method of copying expression contents is by perform per-term
581    // assignment. But in a case of a flat expression we need not that
582    // overhead. So we simply do memcpy() and advance child references only if
583    // needed.
584    //
585    // In a case of not flat expression advance reference counters for child
586    // memory blocks
587//    if (!_expr.is_flat()) _expr.ref_childs();
588    //
589    // Initialize expression by a copy of a first argument
590    Expr e(*this);
591//    memcpy(e.last, _expr.first, len2 * sizeof(Term));
592    if (_expr.is_flat())
593      memcpy(e.last, _expr.first, len2 * sizeof(Term));
594    else {
595      Term* to = e.last;
596      Term const* from = _expr.first;
597      while (from != _expr.last) {
598        new(to) Term(*from);
599        from++; to++;
600      }
601    }
602    //
603    // Adjust flags
604    e.flags &= _expr.flags;
605    //
606    // Adjust expression length
607    e.last += len2;
608    return e;
609  //
610  // Try to get a memory to the left of the second argument that able to
611  // contain a first argument
612  } else if (_expr.lt_alloc(len1)) {
613    //
614    // On success copy a contents of a first argument. This is almost the
615    // same as described above.
616    #if DEBUG
617    lt_copy++;
618    #endif
619//    if (!is_flat()) ref_childs();
620    Expr e(_expr);
621    e.first -= len1;
622//    memcpy(e.first, first, len1 * sizeof(Term));
623    if (is_flat()) memcpy(e.first, first, len1 * sizeof(Term));
624    else {
625      Term* to = e.first;
626      Term const* from = first;
627      while (from != last) {
628        new(to) Term(*from);
629        from++; to++;
630      }
631    }
632    e.flags &= flags;
633    return e;
634  //
635  // If all optimized copy methods fail, copy both arguments
636  } else {
637    #if DEBUG
638    both_copy++;
639    #endif
640    //
641    // Create a new expression with specified length. Use simple euristic to
642    // define appropriate alignment
643    Expr e(len1 + len2, len1 >= len2 ? 1 : -1);
644    //
645    // Child references are incremented separately for two arguments rather
646    // then for the resulting expression. This advances our chances to avoid
647    // some work in a case if at least one of two expressions is flat.
648    if (is_flat()) memcpy(e.first, first, len1 * sizeof(Term));
649    else {
650      Term* to = e.first;
651      Term const* from = first;
652      while (from != last) {
653        new(to) Term(*from);
654        from++; to++;
655      }
656    }
657    if (_expr.is_flat())
658      memcpy(e.first + len1, _expr.first, len2 * sizeof(Term));
659    else {
660      Term* to = e.first + len1;
661      Term const* from = _expr.first;
662      while (from != _expr.last) {
663        new(to) Term(*from);
664        from++; to++;
665      }
666    }
667    //
668    // Adjust flags
669    e.flags = flags & _expr.flags;
670//    if (!e.is_flat()) e.ref_childs();
671    return e;
672  }
673}
674
675INLINE void Expr::init (size_t _len, int _align)
676{
677  D(printf("init is called for %p\n", this);)
678  //
679  // Create a new memory block via allocator
680  mem_chunk = MemoryChunk::create_instance(_len * sizeof(Term));
681  //
682  // Get pointers to the first and beyond the last terms in allocated block
683  Term *start = static_cast<Term*>(mem_chunk->get_first());
684  Term *end   = static_cast<Term*>(mem_chunk->get_last());
685  //
686  // Compute expression margins depending on alignment inside memory block
687  if( _align > 0 ) {
688    //
689    // Left aligned expression
690    first = start;
691    last  = first + _len;
692  } else if( _align < 0 ) {
693    //
694    // Right aligned expression
695    last  = end;
696    first = last - _len;
697  } else {
698    //
699    // Center aligned expression
700    first = start + (mem_chunk->get_size() / sizeof(Term) - _len) / 2;
701    last  = first + _len;
702  }
703  //
704  // Setup border symbols if necessary
705  // FIXME: it is possible to slightly optimize this by moving a code below
706  // into appropriate parts of conditional operator above (for example, in a
707  // case of left aligned expression we never need to setup left border
708  // symbol).
709  if (first > start) {
710    (first - 1)->data1 = SYM_BORDER;
711  }
712  if (last < end) {
713    last->data1 = SYM_BORDER;
714  }
715  //
716  // Expression with zero length is always "flat"
717  if (_len == 0) flags = FLAT_BIT;
718  else flags = 0;
719}
720
721INLINE void Expr::deref_childs (
722  Term* _first, Term* _last, MemoryChunk* _mem
723)
724{
725  //
726  // First go to the left, and deal with all reference terms there.
727  _first--;
728  Term* p = _mem->get_first();
729  while (is_not_left_margin(_first, p)) {
730    _first->~Term();
731    _first--;
732  }
733  //
734  // Go to the right, and deal with all reference terms there.
735  p = _mem->get_last();
736  while (is_not_right_margin(_last, p)) {
737    _last->~Term();
738    _last++;
739  }
740}
741
742INLINE void Expr::deref_childs () const
743{
744  //
745  // First go to the left, and deal with all reference terms there.
746  Term* r = first - 1;
747  Term* p = mem_chunk->get_first();
748  while (is_not_left_margin(r, p)) {
749    r->~Term();
750    r--;
751  }
752  //
753  // If our expression is flat we may skip its body
754  r = is_flat() ? last : first;
755  //
756  // Go to the right, and deal with all reference terms there.
757  p = mem_chunk->get_last();
758  while (is_not_right_margin(r, p)) {
759    r->~Term();
760    r++;
761  }
762}
763
764static INLINE bool is_good_wstr (WString const& _ws)
765{
766  wchar_t const* p = _ws.get_data();
767  wchar_t wc;
768  bool first = true;
769  if (*p == null) return false;
770  while ((wc = *p++) != null) {
771    if (!iswalnum(wc) && wc != L'!' && wc != L'?' && wc != L'-') return false;
772    if (first && !iswupper(wc)) return false;
773    first = false;
774  }
775  return true;
776}
777
778static INLINE bool write_wstr (FILE* _fp, WString const& _ws)
779{
780  wchar_t const* p = _ws.get_data();
781  wchar_t wc;
782  char buf[MB_CUR_MAX + 1];
783  while ((wc = *p++) != null) {
784    switch (wc) {
785    case L'\t':
786      if (fputs("\\t", _fp) == EOF) return false; break;
787    case L'\r':
788      if (fputs("\\r", _fp) == EOF) return false; break;
789    case L'\n':
790      if (fputs("\\n", _fp) == EOF) return false; break;
791    case L'\v':
792      if (fputs("\\v", _fp) == EOF) return false; break;
793    case L'\\':
794      if (fputs("\\\\", _fp) == EOF) return false; break;
795    case L'\'':
796      if (fputs("\\\'", _fp) == EOF) return false; break;
797    case L'\"':
798      if (fputs("\\\"", _fp) == EOF) return false; break;
799    default:
800      if (iswprint(wc)) {
801        size_t n = wctomb(buf, wc);
802        if (n != (size_t)(-1)) {
803          buf[n] = 0;
804          if (fputs(buf, _fp) == EOF) return false;
805        } else {
806          if (fprintf(_fp, "\\%04x", wc) == -1) return false;
807        }
808      } else {
809        if (fprintf(_fp, "\\%04x", wc) == -1) return false;
810      }
811    }
812  }
813  return true;
814}
815
816INLINE bool Expr::write (FILE* _fp) const
817{
818  bool chars_flag = false;
819  for (Term* p = first; p < last; p++) {
820    if (p->get_type() == type_char) {
821      if (!chars_flag) {
822        if (p != first) {
823          if (fputc(' ', _fp) == EOF) return false;
824        }
825        if (fputc('\'', _fp) == EOF) return false;
826        chars_flag = true;
827      }
828      if (!write_wstr(_fp, (WString)(*p))) return false;
829    } else {
830      if (chars_flag) {
831        if (fputc('\'', _fp) == EOF) return false;
832        chars_flag = false;
833      }
834      if (p != first) fputc(' ', _fp);
835      if (p->get_type() == type_ref) {
836        if (fputs("( ", _fp) == EOF) return false;
837        Expr e(p);
838        if (!e.write(_fp)) return false;
839        if (fputs(" )", _fp) == EOF) return false;
840      } else if (p->get_type() == type_word) {
841        WString ws = (WString)(*p);
842        bool f = is_good_wstr(ws);
843        if (!f) fputc('\"', _fp);
844        if (!write_wstr(_fp, ws)) return false;
845        if (!f) fputc('\"', _fp);
846      } else if (p->get_type() == type_int32) {
847        if (fprintf(_fp, "%" PRIdPTR, ((Int32 const&)(*p)).to_int()) == -1)
848          return false;
849      } else if (p->get_type() == type_int) {
850        mpz_t* z = static_cast<Integer*>(p)->get_mpz_ptr();
851        if (!mpz_out_str(_fp, 10, *z)) return false;
852//        if (!write_wstr(_fp, (WString)(*p))) return false;
853      } else {
854        FATAL("Not supported yet");
855      }
856    }
857  }
858  if (chars_flag) {
859    if (fputc('\'', _fp) == EOF) return false;
860  }
861  return true;
862}
863
864INLINE bool Expr::print (FILE* _fp) const
865{
866  for (Term* p = first; p < last; p++) {
867    if (p->is_sym()) {
868      WString s = (WString)(*p);
869      size_t len = s.get_length();
870      char buf[MB_CUR_MAX + 1];
871      for (size_t i = 0; i < len; i++) {
872        size_t n = wctomb(buf, s[i]);
873        if (n != (size_t)(-1)) {
874          buf[n] = 0;
875          if (fputs(buf, _fp) == EOF) return false;
876        } else {
877          if (fputc('?', _fp) == EOF) return false;
878        }
879      }
880    } else if (p->is_ref()) {
881      if (fputc('(', _fp) == EOF) return false;
882      Expr e(p);
883      if (!e.print(_fp)) return false;
884      if (fputc(')', _fp) == EOF) return false;
885    } else {
886      FATAL("Not supported yet");
887    }
888  }
889  return true;
890}
891
892INLINE Expr::operator WString () const
893{
894  WString res;
895  for (Term* p = first; p < last; p++) {
896    if (p->is_sym()) {
897      res = res + (WString)(*p);
898    } else if (p->is_ref()) {
899      res = res + WString(L"(") + (WString)(Expr(p)) + WString(L")");
900    } else {
901      FATAL("Not supported yet");
902    }
903  }
904  return res;
905}
906
907#endif // ALL_INLINE
908
909#undef is_not_right_margin
910#undef is_not_left_margin
911
912}
913
914#endif // __rf_expr_ih__
Note: See TracBrowser for help on using the repository browser.