Sync with 5.1.0
[deliverable/titan.core.git] / compiler2 / subtypestuff.cc
CommitLineData
970ed795
EL
1///////////////////////////////////////////////////////////////////////////////
2// Copyright (c) 2000-2014 Ericsson Telecom AB
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
454////////////////////////////////////////////////////////////////////////////////
455
456string BooleanListConstraint::to_string() const
457{
458 string ret_val;
459 ret_val += '(';
460 if (values&BC_FALSE) ret_val += "false";
461 if (values==BC_ALL) ret_val += ',';
462 if (values&BC_TRUE) ret_val += "true";
463 ret_val += ')';
464 return ret_val;
465}
466
467////////////////////////////////////////////////////////////////////////////////
468
469string VerdicttypeListConstraint::to_string() const
470{
471 static const size_t verdict_count = 5;
472 static const char* verdict_names[verdict_count] = { "none", "pass", "inconc", "fail", "error" };
473 string ret_val;
474 ret_val += '(';
475 bool has_value = false;
476 for (size_t i=VC_NONE,idx=0; (i<VC_ALL)&&(idx<verdict_count); i<<=1,idx++)
477 {
478 if (values&i) {
479 if (has_value) ret_val += ',';
480 ret_val += verdict_names[idx];
481 has_value = true;
482 }
483 }
484 ret_val += ')';
485 return ret_val;
486}
487
488////////////////////////////////////////////////////////////////////////////////
489
490tribool StringPatternConstraint::match(const string& str) const
491{
492 string patt = pattern->get_full_str();
493 if (patt.size()==0) return TRIBOOL(str.size()==0);
494 string *result = regexp(str, string('(')+patt+string(')'), 0);
495 bool rv = (result->size()!=0);
496 delete result;
497 return TRIBOOL(rv);
498}
499
500string StringPatternConstraint::to_string() const
501{
502 string ret_val;
503 ret_val += "pattern(";
504 ret_val += pattern->get_full_str();
505 ret_val += ')';
506 return ret_val;
507}
508
509////////////////////////////////////////////////////////////////////////////////
510// constraint classes for structured types
511
512void ValueList::clean_up()
513{
514 values.clear();
515}
516
517void ValueList::copy_content(const ValueList& other)
518{
519 for (size_t j=0; j<other.values.size(); j++) values.add(other.values[j]);
520}
521
522tribool ValueList::is_equal(const ValueList& other) const
523{
524 if (values.size()!=other.values.size()) return TFALSE;
525 dynamic_array<bool> found(other.values.size()); // helper to skip unnecessary comparisons
526 for (size_t j=0; j<other.values.size(); j++) found[j] = false;
527 for (size_t i=0; i<values.size(); i++) {
528 bool found_i = false;
529 for (size_t j=0; j<other.values.size(); j++) {
530 if (found[j]) continue; // skip already found equal elements
531 if ( (values[i]==other.values[j]) || (*(values[i])==*(other.values[j])) ) {
532 found[j] = true;
533 found_i = true;
534 break;
535 }
536 }
537 if (!found_i) return TFALSE;
538 }
539 return TTRUE;
540}
541
542bool ValueList::is_element(Value* v) const
543{
544 for (size_t i=0; i<values.size(); i++) {
545 if ( (values[i]==v) || (*(values[i])==*v) ) return true;
546 }
547 return false;
548}
549
550ValueList ValueList::set_operation(const ValueList& other, bool is_union) const
551{
552 ValueList ret_val;
553 if (is_union) {
554 for (size_t i=0; i<values.size(); i++) ret_val.values.add(values[i]);
555 for (size_t i=0; i<other.values.size(); i++) {
556 if (!is_element(other.values[i])) ret_val.values.add(other.values[i]);
557 }
558 } else {
559 for (size_t i=0; i<values.size(); i++) {
560 if (other.is_element(values[i])) ret_val.values.add(values[i]);
561 }
562 }
563 return ret_val;
564}
565
566ValueList ValueList::operator-(const ValueList& other) const
567{
568 ValueList ret_val;
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 return ret_val;
573}
574
575void ValueList::remove(const SizeRangeListConstraint& size_constraint, bool if_element)
576{
577 for (size_t i=0; i<values.size(); i++) {
578 if (size_constraint.is_element(size_limit_t(values[i]->get_nof_comps()))==if_element) {
579 values.replace(i,1);
580 i--;
581 }
582 }
583}
584
585string ValueList::to_string() const
586{
587 string ret_val;
588 ret_val += '(';
589 for (size_t i=0; i<values.size(); i++) {
590 if (i>0) ret_val += ',';
591 ret_val += values[i]->create_stringRepr();
592 }
593 ret_val += ')';
594 return ret_val;
595}
596
597////////////////////////////////////////////////////////////////////////////////
598
599tribool ValueListConstraint::is_empty() const
600{
601 return complemented ? values.is_full() : values.is_empty();
602}
603
604
605tribool ValueListConstraint::is_full() const
606{
607 return complemented ? values.is_empty() : values.is_full();
608}
609
610
611tribool ValueListConstraint::is_equal(const ValueListConstraint& other) const
612{
613 return (complemented==other.complemented) ? values.is_equal(other.values) : TUNKNOWN;
614}
615
616
617bool ValueListConstraint::is_element(Value* v) const
618{
619 return complemented ^ values.is_element(v);
620}
621
622ValueListConstraint ValueListConstraint::operator+(const ValueListConstraint& other) const
623{
624 ValueListConstraint ret_val;
625 if (complemented) {
626 if (other.complemented) {
627 ret_val.complemented = true;
628 ret_val.values = values * other.values;
629 } else {
630 ret_val.complemented = true;
631 ret_val.values = values - other.values;
632 }
633 } else {
634 if (other.complemented) {
635 ret_val.complemented = true;
636 ret_val.values = other.values - values;
637 } else {
638 ret_val.complemented = false;
639 ret_val.values = values + other.values;
640 }
641 }
642 return ret_val;
643}
644
645ValueListConstraint ValueListConstraint::operator*(const ValueListConstraint& other) const
646{
647 ValueListConstraint ret_val;
648 if (complemented) {
649 if (other.complemented) {
650 ret_val.complemented = true;
651 ret_val.values = values + other.values;
652 } else {
653 ret_val.complemented = false;
654 ret_val.values = other.values - values;
655 }
656 } else {
657 if (other.complemented) {
658 ret_val.complemented = false;
659 ret_val.values = values - other.values;
660 } else {
661 ret_val.complemented = false;
662 ret_val.values = values * other.values;
663 }
664 }
665 return ret_val;
666}
667
668ValueListConstraint ValueListConstraint::operator~() const
669{
670 ValueListConstraint ret_val;
671 ret_val.complemented = !complemented;
672 ret_val.values = values;
673 return ret_val;
674}
675
676string ValueListConstraint::to_string() const
677{
678 if (complemented) {
679 string ret_val;
680 ret_val += "(ALL except ";
681 ret_val += values.to_string();
682 ret_val += ')';
683 return ret_val;
684 }
685 return values.to_string();
686}
687
688////////////////////////////////////////////////////////////////////////////////
689
690tribool RecofConstraint::is_empty() const
691{
692 if ( (size_constraint.is_empty()==TTRUE) && (has_values.is_empty()==TTRUE) ) return TTRUE;
693 if (has_values.is_empty()==TFALSE) return TFALSE;
694 if (not_values.is_empty()==TTRUE) return TFALSE;
695 return TUNKNOWN; // the set of not_values may possibly cancel the size constraint set
696}
697
698tribool RecofConstraint::is_full() const
699{
700 if ( (size_constraint.is_full()==TTRUE) && (not_values.is_empty()==TTRUE) ) return TTRUE;
701 if (not_values.is_empty()==TFALSE) return TFALSE;
702 return TUNKNOWN;
703}
704
705tribool RecofConstraint::is_equal(const RecofConstraint& other) const
706{
707 if ( (size_constraint.is_equal(other.size_constraint)==TTRUE) &&
708 (has_values.is_equal(other.has_values)==TTRUE) && (not_values.is_equal(other.not_values)==TTRUE) )
709 return TTRUE;
710 return TUNKNOWN; // unknown because there's no canonical form
711}
712
713bool RecofConstraint::is_element(Value* v) const
714{
715 if (size_constraint.is_element(size_limit_t(v->get_nof_comps()))) return !not_values.is_element(v);
716 return has_values.is_element(v);
717}
718
719// representation of two sets: [Si+Vi-Ni] where Si=size_constraint, Vi=has_values, Ni=not_values
720// UNION: [S1+V1-N1] + [S2+V2-N2] = ... = [(S1+S2)+(V1+V2)-((~S1*N2)+(N1*~S2)+(N1*N2))]
721// INTERSECTION: [S1+V1-N1] * [S2+V2-N2] = ... = [(S1*S2)+((S1*V2-N1)+(S2*V1-N2)+(V1*V2))-(N1+N2)]
722RecofConstraint RecofConstraint::set_operation(const RecofConstraint& other, bool is_union) const
723{
724 RecofConstraint ret_val;
725 ret_val.size_constraint = size_constraint.set_operation(other.size_constraint, is_union);
726 if (is_union) {
727 // V1+V2
728 ret_val.has_values = has_values + other.has_values;
729 // ~S1*N2
730 ValueList vlc1 = other.not_values;
731 vlc1.remove(size_constraint, true);
732 // N1*~S2
733 ValueList vlc2 = not_values;
734 vlc2.remove(other.size_constraint, true);
735 // ((~S1*N2)+(N1*~S2)+(N1*N2))
736 ret_val.not_values = vlc1 + vlc2 + (not_values * other.not_values);
737 } else { // intersection
738 // S2*V1-N2
739 ValueList vlc1 = has_values;
740 vlc1.remove(other.size_constraint, false);
741 vlc1 = vlc1 - other.not_values;
742 // S1*V2-N1
743 ValueList vlc2 = other.has_values;
744 vlc2.remove(size_constraint, false);
745 vlc2 = vlc2 - not_values;
746 // (S1*V2-N1)+(S2*V1-N2)+(V1*V2)
747 ret_val.has_values = (has_values * other.has_values) + vlc1 + vlc2;
748 // union of not_values
749 ret_val.not_values = not_values + other.not_values;
750 }
751 // drop the intersection, holes and points cancel each other
752 ValueList vlc = ret_val.has_values * ret_val.not_values;
753 ret_val.has_values = ret_val.has_values - vlc;
754 ret_val.not_values = ret_val.not_values - vlc;
755 // drop ret_val.has_values elements that are elements of the ret_val.size_constraint set
756 ret_val.has_values.remove(ret_val.size_constraint, true);
757 // drop ret_val.not_values elements that are not elements of the ret_val.size_constraint set
758 ret_val.not_values.remove(ret_val.size_constraint, false);
759 return ret_val;
760}
761
762RecofConstraint RecofConstraint::operator~() const
763{
764 RecofConstraint ret_val;
765 ret_val.size_constraint = ~size_constraint;
766 ret_val.has_values = not_values;
767 ret_val.not_values = has_values;
768 return ret_val;
769}
770
771tribool RecofConstraint::get_size_limit(bool is_upper, size_limit_t& limit) const
772{
773 if (size_constraint.is_empty()==TTRUE) return TFALSE;
774 limit = is_upper ? size_constraint.get_maximal() : size_constraint.get_minimal();
775 return TTRUE;
776}
777
778string RecofConstraint::to_string() const
779{
780 string ret_val;
781 if (has_values.is_empty()!=TTRUE) ret_val += has_values.to_string();
782 if (size_constraint.is_empty()!=TTRUE) {
783 if (has_values.is_empty()!=TTRUE) ret_val += " union ";
784 ret_val += "length";
785 ret_val += size_constraint.to_string();
786 }
787 // except not_values
788 if (not_values.is_empty()!=TTRUE) {
789 ret_val += " except ";
790 ret_val += not_values.to_string();
791 }
792 return ret_val;
793}
794
795
796} // namespace Common
This page took 0.051787 seconds and 5 git commands to generate.