Sync with 5.4.0
[deliverable/titan.core.git] / compiler2 / subtypestuff.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
3// All rights reserved. This program and the accompanying materials
4// are made available under the terms of the Eclipse Public License v1.0
5// which accompanies this distribution, and is available at
6// http://www.eclipse.org/legal/epl-v10.html
7///////////////////////////////////////////////////////////////////////////////
8#include "subtypestuff.hh"
9#include "../common/dbgnew.hh"
10#include "Identifier.hh"
11#include "Value.hh"
12#include "Setting.hh"
13#include "Type.hh"
14#include "CompilerError.hh"
15#include "Valuestuff.hh"
16#include "ttcn3/TtcnTemplate.hh"
17#include "ttcn3/Templatestuff.hh"
18#include "ttcn3/PatternString.hh"
19#include "PredefFunc.hh"
20
21#include <limits.h>
22
23namespace Common {
24
25
26tribool operator||(tribool a, tribool b)
27{
28 static tribool truth_table[3][3] = { {TFALSE, TUNKNOWN, TTRUE}, {TUNKNOWN, TUNKNOWN, TTRUE}, {TTRUE, TTRUE, TTRUE} };
29 return truth_table[a][b];
30}
31
32tribool operator&&(tribool a, tribool b)
33{
34 static tribool truth_table[3][3] = { {TFALSE, TFALSE, TFALSE}, {TFALSE, TUNKNOWN, TUNKNOWN}, {TFALSE, TUNKNOWN, TTRUE} };
35 return truth_table[a][b];
36}
37
38tribool operator!(tribool tb)
39{
40 static tribool truth_table[3] = { TTRUE, TUNKNOWN, TFALSE };
41 return truth_table[tb];
42}
43
44tribool TRIBOOL(bool b) { return ( b ? TTRUE : TFALSE ); }
45
46string to_string(const tribool& tb)
47{
48 switch (tb) {
49 case TFALSE:
50 return string("false");
51 case TTRUE:
52 return string("true");
53 case TUNKNOWN:
54 return string("unknown");
55 default:
56 FATAL_ERROR("print(tribool)");
57 }
58 return string();
59}
60
61////////////////////////////////////////////////////////////////////////////////
62
63const int_limit_t int_limit_t::minimum(int_limit_t::MINUS_INFINITY);
64
65const int_limit_t int_limit_t::maximum(int_limit_t::PLUS_INFINITY);
66
67int_limit_t::int_limit_t(int_limit_type_t p_type):
68 type(p_type)
69{
70 switch (p_type) {
71 case MINUS_INFINITY:
72 case PLUS_INFINITY:
73 break;
74 default:
75 FATAL_ERROR("int_limit_t::int_limit_t(int_limit_type_t)");
76 }
77}
78
79bool int_limit_t::operator<(const int_limit_t& right) const
80{
81 switch (type) {
82 case MINUS_INFINITY:
83 return (right.type!=MINUS_INFINITY);
84 case NUMBER:
85 return ( (right.type==PLUS_INFINITY) || ( (right.type==NUMBER) && (value<right.value) ) );
86 case PLUS_INFINITY:
87 return false;
88 default:
89 FATAL_ERROR("int_limit_t::operator<()");
90 }
91}
92
93bool int_limit_t::operator==(const int_limit_t& right) const
94{
95 if (type==NUMBER) return ( (right.type==NUMBER) && (value==right.value) );
96 else return (type==right.type);
97}
98
99bool int_limit_t::is_adjacent(const int_limit_t& other) const
100{
101 return ( (type==NUMBER) && (other.type==NUMBER) && ((value+1)==other.value) );
102}
103
104int_val_t int_limit_t::get_value() const
105{
106 if (type!=NUMBER) FATAL_ERROR("int_limit_t::get_value()");
107 return value;
108}
109
110int_limit_t int_limit_t::next() const
111{
112 return ( (type==NUMBER) ? int_limit_t(value+1) : *this );
113}
114
115int_limit_t int_limit_t::previous() const
116{
117 return ( (type==NUMBER) ? int_limit_t(value-1) : *this );
118}
119
120void int_limit_t::check_single_value() const
121{
122 if (type!=NUMBER) FATAL_ERROR("int_limit_t::check_single_value()");
123}
124
125void int_limit_t::check_interval_start() const
126{
127 if (type==PLUS_INFINITY) FATAL_ERROR("int_limit_t::check_interval_start()");
128}
129
130void int_limit_t::check_interval_end() const
131{
132 if (type==MINUS_INFINITY) FATAL_ERROR("int_limit_t::check_interval_end()");
133}
134
135string int_limit_t::to_string() const
136{
137 switch (type) {
138 case int_limit_t::MINUS_INFINITY:
139 return string("-infinity");
140 case int_limit_t::NUMBER:
141 return value.t_str();
142 case int_limit_t::PLUS_INFINITY:
143 return string("infinity");
144 default:
145 FATAL_ERROR("int_limit_t::print()");
146 }
147 return string();
148}
149
150////////////////////////////////////////////////////////////////////////////////
151
152const size_limit_t size_limit_t::minimum(0);
153
154const size_limit_t size_limit_t::maximum(INFINITE_SIZE);
155
156bool size_limit_t::operator<(const size_limit_t& right) const
157{
158 return ( !infinity && ( right.infinity || (size<right.size) ) );
159}
160
161bool size_limit_t::operator==(const size_limit_t& right) const
162{
163 return ( (infinity==right.infinity) && (infinity || (size==right.size)) );
164}
165
166bool size_limit_t::is_adjacent(const size_limit_t& other) const
167{
168 return ( !infinity && !other.infinity && (size+1==other.size) );
169}
170
171size_t size_limit_t::get_size() const
172{
173 if (infinity) FATAL_ERROR("size_limit_t::get_size()");
174 return size;
175}
176
177size_limit_t size_limit_t::next() const
178{
179 return ( infinity ? *this : size_limit_t(size+1) );
180}
181
182size_limit_t size_limit_t::previous() const
183{
184 if (size==0) FATAL_ERROR("size_limit_t::previous()");
185 return ( infinity ? *this : size_limit_t(size-1) );
186}
187
188void size_limit_t::check_single_value() const
189{
190 if (infinity) FATAL_ERROR("size_limit_t::check_single_value()");
191}
192
193void size_limit_t::check_interval_start() const
194{
195 if (infinity) FATAL_ERROR("size_limit_t::check_interval_start()");
196}
197
198string size_limit_t::to_string() const
199{
200 if (infinity) return string("infinity");
201 return Int2string((Int)size);
202}
203
204int_limit_t size_limit_t::to_int_limit() const
205{
206 if (infinity) return int_limit_t(int_limit_t::PLUS_INFINITY);
207 return int_limit_t(int_val_t((Int)size)); // FIXME: size_t -> Int
208}
209
210////////////////////////////////////////////////////////////////////////////////
211
212const short int char_limit_t::max_char = 127;
213
214const char_limit_t char_limit_t::minimum(0);
215
216const char_limit_t char_limit_t::maximum(max_char);
217
218bool char_limit_t::is_valid_value(short int p_chr)
219{
220 return ( (p_chr>=0) && (p_chr<=max_char) );
221}
222
223char_limit_t::char_limit_t(short int p_chr): chr(p_chr)
224{
225 if ( (chr<0) || (chr>max_char) ) FATAL_ERROR("char_limit_t::char_limit_t()");
226}
227
228char_limit_t char_limit_t::next() const
229{
230 if (chr>=max_char) FATAL_ERROR("char_limit_t::next()");
231 return char_limit_t(chr+1);
232}
233
234char_limit_t char_limit_t::previous() const
235{
236 if (chr<=0) FATAL_ERROR("char_limit_t::previous()");
237 return char_limit_t(chr-1);
238}
239
240string char_limit_t::to_string() const
241{
242 return string((char)chr).get_stringRepr();
243}
244
245////////////////////////////////////////////////////////////////////////////////
246
247void universal_char_limit_t::check_value() const
248{
249 if (code_point>max_code_point) FATAL_ERROR("universal_char_limit_t::check_value()");
250}
251
252unsigned int universal_char_limit_t::uchar2codepoint(const ustring::universal_char& uchr)
253{
254 return ( (((unsigned int)uchr.group)<<24) + (((unsigned int)uchr.plane)<<16) + (((unsigned int)uchr.row)<<8) + ((unsigned int)uchr.cell) );
255}
256
257ustring::universal_char universal_char_limit_t::codepoint2uchar(unsigned int cp)
258{
259 ustring::universal_char uchr;
260 uchr.cell = (unsigned char)(cp & 0xFF);
261 uchr.row = (unsigned char)((cp>>8) & 0xFF);
262 uchr.plane = (unsigned char)((cp>>16) & 0xFF);
263 uchr.group = (unsigned char)((cp>>24) & 0xFF);
264 return uchr;
265}
266
267const unsigned int universal_char_limit_t::max_code_point = 0x7FFFFFFF;
268
269const universal_char_limit_t universal_char_limit_t::minimum(0);
270
271const universal_char_limit_t universal_char_limit_t::maximum(max_code_point);
272
273bool universal_char_limit_t::is_valid_value(const ustring::universal_char& p_uchr)
274{
275 return (uchar2codepoint(p_uchr)<=max_code_point);
276}
277
278universal_char_limit_t universal_char_limit_t::next() const
279{
280 if (code_point>=max_code_point) FATAL_ERROR("universal_char_limit_t::next()");
281 return universal_char_limit_t(code_point+1);
282}
283
284universal_char_limit_t universal_char_limit_t::previous() const
285{
286 if (code_point<=0) FATAL_ERROR("universal_char_limit_t::previous()");
287 return universal_char_limit_t(code_point-1);
288}
289
290string universal_char_limit_t::to_string() const
291{
292 ustring::universal_char uc = codepoint2uchar(code_point);
293 return ustring(1,&uc).get_stringRepr();
294}
295
296////////////////////////////////////////////////////////////////////////////////
297
298const real_limit_t real_limit_t::minimum(make_ttcn3float(-REAL_INFINITY));
299
300const real_limit_t real_limit_t::maximum(make_ttcn3float(REAL_INFINITY));
301
302void real_limit_t::check_value() const
303{
304 if (value!=value) FATAL_ERROR("real_limit_t::check_value(): cannot be NaN");
305 if ( (value==-REAL_INFINITY) && (type==LOWER) ) FATAL_ERROR("real_limit_t::check_value(): cannot be -infinity.lower");
306 if ( (value==REAL_INFINITY) && (type==UPPER) ) FATAL_ERROR("real_limit_t::check_value(): cannot be infinity.upper");
307}
308
309bool real_limit_t::operator<(const real_limit_t& right) const
310{
311 ttcn3float v1,v2;
312 v1 = value;
313 v2 = right.value;
314 return ( (v1<v2) || ((v1==v2)&&(type<right.type)) );
315}
316
317bool real_limit_t::operator==(const real_limit_t& right) const
318{
319 ttcn3float v1,v2;
320 v1 = value;
321 v2 = right.value;
322 return ( (v1==v2) && (type==right.type) );
323}
324
325bool real_limit_t::is_adjacent(const real_limit_t& other) const
326{
327 ttcn3float v1,v2;
328 v1 = value;
329 v2 = other.value;
330 return ( (v1==v2) && (((type==LOWER)&&(other.type==EXACT)) || ((type==EXACT)&&(other.type==UPPER))) );
331}
332
333real_limit_t real_limit_t::next() const
334{
335 switch (type) {
336 case LOWER:
337 return real_limit_t(value);
338 case EXACT:
339 case UPPER:
340 return real_limit_t(value, UPPER);
341 default:
342 FATAL_ERROR("real_limit_t::next()");
343 }
344}
345
346real_limit_t real_limit_t::previous() const
347{
348 switch (type) {
349 case LOWER:
350 case EXACT:
351 return real_limit_t(value, LOWER);
352 case UPPER:
353 return real_limit_t(value);
354 default:
355 FATAL_ERROR("real_limit_t::previous()");
356 }
357}
358
359void real_limit_t::check_single_value() const
360{
361 if (type!=EXACT) FATAL_ERROR("real_limit_t::check_single_value()");
362}
363
364void real_limit_t::check_interval_start() const
365{
366 if (type==LOWER) FATAL_ERROR("real_limit_t::check_interval_start()");
367}
368
369void real_limit_t::check_interval_end() const
370{
371 if (type==UPPER) FATAL_ERROR("real_limit_t::check_interval_end()");
372}
373
374string real_limit_t::to_string() const
375{
376 string ret_val;
377 if (type!=EXACT) ret_val += '!';
378 ret_val += Real2string(value);
379 return ret_val;
380}
381
382////////////////////////////////////////////////////////////////////////////////
383
384bool convert_int_to_size(const RangeListConstraint<int_limit_t>& int_range, RangeListConstraint<size_limit_t>& size_range)
385{
386 size_range = RangeListConstraint<size_limit_t>();
387 size_range.intervals = int_range.intervals;
388 size_range.values = dynamic_array<size_limit_t>(int_range.values.size());
389 for (size_t i=0; i<int_range.values.size(); i++) {
390 const int_limit_t& il = int_range.values[i];
391 size_limit_t sl;
392 switch (il.get_type()) {
393 case int_limit_t::MINUS_INFINITY:
394 size_range = RangeListConstraint<size_limit_t>(size_limit_t::minimum, size_limit_t::maximum);
395 return false;
396 case int_limit_t::NUMBER: {
397 int_val_t number = il.get_value();
398 if ((number<0) || !number.is_native_fit()) {
399 size_range = RangeListConstraint<size_limit_t>(size_limit_t::minimum, size_limit_t::maximum);
400 return false;
401 }
402 sl = size_limit_t((size_t)number.get_val());
403 } break;
404 case int_limit_t::PLUS_INFINITY:
405 sl = size_limit_t::maximum;
406 break;
407 default:
408 FATAL_ERROR("RangeListConstraint::convert_int_to_size()");
409 }
410 size_range.values.add(sl);
411 }
412 return true;
413}
414
415////////////////////////////////////////////////////////////////////////////////
416
417bool RealRangeListConstraint::is_element(const ttcn3float& r) const
418{
419 if (r!=r) // this is a NaN value
420 return has_nan;
421 else
422 return rlc.is_element(real_limit_t(r));
423}
424
425RealRangeListConstraint RealRangeListConstraint::set_operation(const RealRangeListConstraint& other, bool is_union) const
426{
427 RealRangeListConstraint ret_val;
428 ret_val.rlc = rlc.set_operation(other.rlc, is_union);
429 ret_val.has_nan = is_union ? (has_nan || other.has_nan) : (has_nan && other.has_nan);
430 return ret_val;
431}
432
433RealRangeListConstraint RealRangeListConstraint::operator~() const
434{
435 RealRangeListConstraint ret_val;
436 ret_val.rlc = ~rlc;
437 ret_val.has_nan = !has_nan;
438 return ret_val;
439}
440
441string RealRangeListConstraint::to_string() const
442{
443 string ret_val;
444 ret_val += '(';
445 ret_val += rlc.to_string(false);
446 if (has_nan) {
447 if (rlc.is_empty()!=TTRUE) ret_val += ',';
448 ret_val += "NaN";
449 }
450 ret_val += ')';
451 return ret_val;
452}
453
af710487 454bool RealRangeListConstraint::is_upper_limit_infinity () const
455{
456 return rlc.is_upper_limit_infinity();
457}
458
459bool RealRangeListConstraint::is_lower_limit_infinity () const
460{
461 return rlc.is_lower_limit_infinity();
462}
463
970ed795
EL
464////////////////////////////////////////////////////////////////////////////////
465
466string BooleanListConstraint::to_string() const
467{
468 string ret_val;
469 ret_val += '(';
470 if (values&BC_FALSE) ret_val += "false";
471 if (values==BC_ALL) ret_val += ',';
472 if (values&BC_TRUE) ret_val += "true";
473 ret_val += ')';
474 return ret_val;
475}
476
477////////////////////////////////////////////////////////////////////////////////
478
479string VerdicttypeListConstraint::to_string() const
480{
481 static const size_t verdict_count = 5;
482 static const char* verdict_names[verdict_count] = { "none", "pass", "inconc", "fail", "error" };
483 string ret_val;
484 ret_val += '(';
485 bool has_value = false;
486 for (size_t i=VC_NONE,idx=0; (i<VC_ALL)&&(idx<verdict_count); i<<=1,idx++)
487 {
488 if (values&i) {
489 if (has_value) ret_val += ',';
490 ret_val += verdict_names[idx];
491 has_value = true;
492 }
493 }
494 ret_val += ')';
495 return ret_val;
496}
497
498////////////////////////////////////////////////////////////////////////////////
499
500tribool StringPatternConstraint::match(const string& str) const
501{
502 string patt = pattern->get_full_str();
503 if (patt.size()==0) return TRIBOOL(str.size()==0);
504 string *result = regexp(str, string('(')+patt+string(')'), 0);
505 bool rv = (result->size()!=0);
506 delete result;
507 return TRIBOOL(rv);
508}
509
510string StringPatternConstraint::to_string() const
511{
512 string ret_val;
513 ret_val += "pattern(";
514 ret_val += pattern->get_full_str();
515 ret_val += ')';
516 return ret_val;
517}
518
519////////////////////////////////////////////////////////////////////////////////
520// constraint classes for structured types
521
522void ValueList::clean_up()
523{
524 values.clear();
525}
526
527void ValueList::copy_content(const ValueList& other)
528{
529 for (size_t j=0; j<other.values.size(); j++) values.add(other.values[j]);
530}
531
532tribool ValueList::is_equal(const ValueList& other) const
533{
534 if (values.size()!=other.values.size()) return TFALSE;
535 dynamic_array<bool> found(other.values.size()); // helper to skip unnecessary comparisons
536 for (size_t j=0; j<other.values.size(); j++) found[j] = false;
537 for (size_t i=0; i<values.size(); i++) {
538 bool found_i = false;
539 for (size_t j=0; j<other.values.size(); j++) {
540 if (found[j]) continue; // skip already found equal elements
541 if ( (values[i]==other.values[j]) || (*(values[i])==*(other.values[j])) ) {
542 found[j] = true;
543 found_i = true;
544 break;
545 }
546 }
547 if (!found_i) return TFALSE;
548 }
549 return TTRUE;
550}
551
552bool ValueList::is_element(Value* v) const
553{
554 for (size_t i=0; i<values.size(); i++) {
555 if ( (values[i]==v) || (*(values[i])==*v) ) return true;
556 }
557 return false;
558}
559
560ValueList ValueList::set_operation(const ValueList& other, bool is_union) const
561{
562 ValueList ret_val;
563 if (is_union) {
564 for (size_t i=0; i<values.size(); i++) ret_val.values.add(values[i]);
565 for (size_t i=0; i<other.values.size(); i++) {
566 if (!is_element(other.values[i])) ret_val.values.add(other.values[i]);
567 }
568 } else {
569 for (size_t i=0; i<values.size(); i++) {
570 if (other.is_element(values[i])) ret_val.values.add(values[i]);
571 }
572 }
573 return ret_val;
574}
575
576ValueList ValueList::operator-(const ValueList& other) const
577{
578 ValueList ret_val;
579 for (size_t i=0; i<values.size(); i++) {
580 if (!other.is_element(values[i])) ret_val.values.add(values[i]);
581 }
582 return ret_val;
583}
584
585void ValueList::remove(const SizeRangeListConstraint& size_constraint, bool if_element)
586{
587 for (size_t i=0; i<values.size(); i++) {
588 if (size_constraint.is_element(size_limit_t(values[i]->get_nof_comps()))==if_element) {
589 values.replace(i,1);
590 i--;
591 }
592 }
593}
594
595string ValueList::to_string() const
596{
597 string ret_val;
598 ret_val += '(';
599 for (size_t i=0; i<values.size(); i++) {
600 if (i>0) ret_val += ',';
601 ret_val += values[i]->create_stringRepr();
602 }
603 ret_val += ')';
604 return ret_val;
605}
606
607////////////////////////////////////////////////////////////////////////////////
608
609tribool ValueListConstraint::is_empty() const
610{
611 return complemented ? values.is_full() : values.is_empty();
612}
613
614
615tribool ValueListConstraint::is_full() const
616{
617 return complemented ? values.is_empty() : values.is_full();
618}
619
620
621tribool ValueListConstraint::is_equal(const ValueListConstraint& other) const
622{
623 return (complemented==other.complemented) ? values.is_equal(other.values) : TUNKNOWN;
624}
625
626
627bool ValueListConstraint::is_element(Value* v) const
628{
629 return complemented ^ values.is_element(v);
630}
631
632ValueListConstraint ValueListConstraint::operator+(const ValueListConstraint& other) const
633{
634 ValueListConstraint ret_val;
635 if (complemented) {
636 if (other.complemented) {
637 ret_val.complemented = true;
638 ret_val.values = values * other.values;
639 } else {
640 ret_val.complemented = true;
641 ret_val.values = values - other.values;
642 }
643 } else {
644 if (other.complemented) {
645 ret_val.complemented = true;
646 ret_val.values = other.values - values;
647 } else {
648 ret_val.complemented = false;
649 ret_val.values = values + other.values;
650 }
651 }
652 return ret_val;
653}
654
655ValueListConstraint ValueListConstraint::operator*(const ValueListConstraint& other) const
656{
657 ValueListConstraint ret_val;
658 if (complemented) {
659 if (other.complemented) {
660 ret_val.complemented = true;
661 ret_val.values = values + other.values;
662 } else {
663 ret_val.complemented = false;
664 ret_val.values = other.values - values;
665 }
666 } else {
667 if (other.complemented) {
668 ret_val.complemented = false;
669 ret_val.values = values - other.values;
670 } else {
671 ret_val.complemented = false;
672 ret_val.values = values * other.values;
673 }
674 }
675 return ret_val;
676}
677
678ValueListConstraint ValueListConstraint::operator~() const
679{
680 ValueListConstraint ret_val;
681 ret_val.complemented = !complemented;
682 ret_val.values = values;
683 return ret_val;
684}
685
686string ValueListConstraint::to_string() const
687{
688 if (complemented) {
689 string ret_val;
690 ret_val += "(ALL except ";
691 ret_val += values.to_string();
692 ret_val += ')';
693 return ret_val;
694 }
695 return values.to_string();
696}
697
698////////////////////////////////////////////////////////////////////////////////
699
700tribool RecofConstraint::is_empty() const
701{
702 if ( (size_constraint.is_empty()==TTRUE) && (has_values.is_empty()==TTRUE) ) return TTRUE;
703 if (has_values.is_empty()==TFALSE) return TFALSE;
704 if (not_values.is_empty()==TTRUE) return TFALSE;
705 return TUNKNOWN; // the set of not_values may possibly cancel the size constraint set
706}
707
708tribool RecofConstraint::is_full() const
709{
710 if ( (size_constraint.is_full()==TTRUE) && (not_values.is_empty()==TTRUE) ) return TTRUE;
711 if (not_values.is_empty()==TFALSE) return TFALSE;
712 return TUNKNOWN;
713}
714
715tribool RecofConstraint::is_equal(const RecofConstraint& other) const
716{
717 if ( (size_constraint.is_equal(other.size_constraint)==TTRUE) &&
718 (has_values.is_equal(other.has_values)==TTRUE) && (not_values.is_equal(other.not_values)==TTRUE) )
719 return TTRUE;
720 return TUNKNOWN; // unknown because there's no canonical form
721}
722
723bool RecofConstraint::is_element(Value* v) const
724{
725 if (size_constraint.is_element(size_limit_t(v->get_nof_comps()))) return !not_values.is_element(v);
726 return has_values.is_element(v);
727}
728
729// representation of two sets: [Si+Vi-Ni] where Si=size_constraint, Vi=has_values, Ni=not_values
730// UNION: [S1+V1-N1] + [S2+V2-N2] = ... = [(S1+S2)+(V1+V2)-((~S1*N2)+(N1*~S2)+(N1*N2))]
731// INTERSECTION: [S1+V1-N1] * [S2+V2-N2] = ... = [(S1*S2)+((S1*V2-N1)+(S2*V1-N2)+(V1*V2))-(N1+N2)]
732RecofConstraint RecofConstraint::set_operation(const RecofConstraint& other, bool is_union) const
733{
734 RecofConstraint ret_val;
735 ret_val.size_constraint = size_constraint.set_operation(other.size_constraint, is_union);
736 if (is_union) {
737 // V1+V2
738 ret_val.has_values = has_values + other.has_values;
739 // ~S1*N2
740 ValueList vlc1 = other.not_values;
741 vlc1.remove(size_constraint, true);
742 // N1*~S2
743 ValueList vlc2 = not_values;
744 vlc2.remove(other.size_constraint, true);
745 // ((~S1*N2)+(N1*~S2)+(N1*N2))
746 ret_val.not_values = vlc1 + vlc2 + (not_values * other.not_values);
747 } else { // intersection
748 // S2*V1-N2
749 ValueList vlc1 = has_values;
750 vlc1.remove(other.size_constraint, false);
751 vlc1 = vlc1 - other.not_values;
752 // S1*V2-N1
753 ValueList vlc2 = other.has_values;
754 vlc2.remove(size_constraint, false);
755 vlc2 = vlc2 - not_values;
756 // (S1*V2-N1)+(S2*V1-N2)+(V1*V2)
757 ret_val.has_values = (has_values * other.has_values) + vlc1 + vlc2;
758 // union of not_values
759 ret_val.not_values = not_values + other.not_values;
760 }
761 // drop the intersection, holes and points cancel each other
762 ValueList vlc = ret_val.has_values * ret_val.not_values;
763 ret_val.has_values = ret_val.has_values - vlc;
764 ret_val.not_values = ret_val.not_values - vlc;
765 // drop ret_val.has_values elements that are elements of the ret_val.size_constraint set
766 ret_val.has_values.remove(ret_val.size_constraint, true);
767 // drop ret_val.not_values elements that are not elements of the ret_val.size_constraint set
768 ret_val.not_values.remove(ret_val.size_constraint, false);
769 return ret_val;
770}
771
772RecofConstraint RecofConstraint::operator~() const
773{
774 RecofConstraint ret_val;
775 ret_val.size_constraint = ~size_constraint;
776 ret_val.has_values = not_values;
777 ret_val.not_values = has_values;
778 return ret_val;
779}
780
781tribool RecofConstraint::get_size_limit(bool is_upper, size_limit_t& limit) const
782{
783 if (size_constraint.is_empty()==TTRUE) return TFALSE;
784 limit = is_upper ? size_constraint.get_maximal() : size_constraint.get_minimal();
785 return TTRUE;
786}
787
788string RecofConstraint::to_string() const
789{
790 string ret_val;
791 if (has_values.is_empty()!=TTRUE) ret_val += has_values.to_string();
792 if (size_constraint.is_empty()!=TTRUE) {
793 if (has_values.is_empty()!=TTRUE) ret_val += " union ";
794 ret_val += "length";
795 ret_val += size_constraint.to_string();
796 }
797 // except not_values
798 if (not_values.is_empty()!=TTRUE) {
799 ret_val += " except ";
800 ret_val += not_values.to_string();
801 }
802 return ret_val;
803}
804
805
806} // namespace Common
This page took 0.054999 seconds and 5 git commands to generate.