diff --git a/compiler2/Setting.hh b/compiler2/Setting.hh index 3eef9120a04a3604b7c173e7e497079c5dd05672..a105bbe173d4f7964fdbbe347ae4dc6f22e9d109 100644 --- a/compiler2/Setting.hh +++ b/compiler2/Setting.hh @@ -745,9 +745,10 @@ public: class Ref_simple : public Reference { public: enum reftype_t { - REF_BASIC, // basic reference (not class related to any class scope) + REF_BASIC, // basic reference (not related to a class scope or a dynamic template) REF_SUPER, // reference to the superclass - REF_THIS // reference to the current class object + REF_THIS, // reference to the current class object + REF_VALUE // reference to the value being matched in a dynamic template }; protected: // Derived classes need access /** Points to the referred assignment. Used for caching. */ diff --git a/compiler2/Value.cc b/compiler2/Value.cc index 355c5a9c2a1acc48b1aa0b31cf97ac5e05b0d69f..54af76a944f7aa0fa052626c6679db7804490a04 100644 --- a/compiler2/Value.cc +++ b/compiler2/Value.cc @@ -4587,7 +4587,7 @@ namespace Common { case Assignment::A_PAR_TEMPL_IN: case Assignment::A_PAR_TEMPL_OUT: case Assignment::A_PAR_TEMPL_INOUT: - u.expr.t1=new Template(tmpref); // TEMPLATE_REFD constructor + u.expr.t1=new Template(Template::TEMPLATE_REFD, tmpref); // TEMPLATE_REFD constructor u.expr.t1->set_location(*tmpref); u.expr.t1->set_my_scope(get_my_scope()); u.expr.t1->set_fullname(get_fullname()+".<operand>"); @@ -6704,7 +6704,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case Assignment::A_PAR_TEMPL_IN: case Assignment::A_PAR_TEMPL_OUT: case Assignment::A_PAR_TEMPL_INOUT: { - Template* t = new Template(ref->clone()); + Template* t = new Template(Template::TEMPLATE_REFD, ref->clone()); t->set_location(*ref); t->set_my_scope(get_my_scope()); t->set_fullname(get_fullname()+".<operand>"); @@ -12043,7 +12043,7 @@ void Value::chk_expr_operand_execute_refd(Value *v1, case Assignment::A_PAR_TEMPL_IN: case Assignment::A_PAR_TEMPL_OUT: case Assignment::A_PAR_TEMPL_INOUT: { - Template* t = new Template(ref->clone()); + Template* t = new Template(Template::TEMPLATE_REFD, ref->clone()); t->set_location(*ref); t->set_my_scope(get_my_scope()); t->set_fullname(get_fullname()+".<operand>"); diff --git a/compiler2/ttcn3/AST_ttcn3.cc b/compiler2/ttcn3/AST_ttcn3.cc index 58529e1eddf3302af88e9374db9bf987d06d25d0..ba77515f579e3f05c0770ae3ef1fff1d605edab0 100644 --- a/compiler2/ttcn3/AST_ttcn3.cc +++ b/compiler2/ttcn3/AST_ttcn3.cc @@ -746,7 +746,7 @@ namespace Ttcn { : Ref_base(), reftype(p_reftype), parlist(NULL), params(NULL), gen_const_prefix(false), expr_cache(NULL) { - if (reftype != REF_THIS) { + if (reftype != REF_THIS && reftype != REF_VALUE) { FATAL_ERROR("Ttcn::Reference(): basic or 'super' reference with no ID"); } } diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index 07c90a698eb60b7ae8c269a9a21e33a6b0fe6a13..e04463c3c96ef85e50f34443de49d81ca0c0af86 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -396,16 +396,26 @@ namespace Ttcn { } } - Template::Template(Reference *p_ref) + Template::Template(templatetype_t tt, Reference *p_ref) : GovernedSimple(S_TEMPLATE), - templatetype(TEMPLATE_REFD), my_governor(0), length_restriction(0), + templatetype(tt), my_governor(0), length_restriction(0), is_ifpresent(false), specific_value_checked(false), has_permutation(false), base_template(0) { if(!p_ref) FATAL_ERROR("Template::Template()"); - u.ref.ref=p_ref; - u.ref.refd=0; - u.ref.refd_last=0; + switch (tt) { + case TEMPLATE_REFD: + u.ref.ref=p_ref; + u.ref.refd=0; + u.ref.refd_last=0; + break; + case DYNAMIC_MATCH: + delete p_ref; + // todo + break; + default: + FATAL_ERROR("Template::Template()"); + } } Template::Template(templatetype_t tt, Templates *ts) @@ -421,6 +431,7 @@ namespace Ttcn { case SUPERSET_MATCH: case SUBSET_MATCH: case PERMUTATION_MATCH: + case CONJUNCTION_MATCH: break; default: FATAL_ERROR("Template::Template()"); @@ -529,6 +540,33 @@ namespace Ttcn { u.dec_match.str_enc = v; u.dec_match.target = ti; } + + Template::Template(Template* prec, TemplateInstance* imp_t) + : GovernedSimple(S_TEMPLATE), + templatetype(IMPLICATION_MATCH), my_governor(0), length_restriction(0), + is_ifpresent(false), specific_value_checked(false), + has_permutation(false), flattened(true), base_template(0) + { + if (prec == NULL || imp_t == NULL) { + FATAL_ERROR("Template::Template()"); + } + delete prec; + delete imp_t; + // todo + } + + Template::Template(StatementBlock* block) + : GovernedSimple(S_TEMPLATE), + templatetype(DYNAMIC_MATCH), my_governor(0), length_restriction(0), + is_ifpresent(false), specific_value_checked(false), + has_permutation(false), flattened(true), base_template(0) + { + if (block == NULL) { + FATAL_ERROR("Template::Template()"); + } + delete block; + // todo + } Template::~Template() { @@ -5813,7 +5851,7 @@ compile_time: // check, remove and delete after checked if (template_body->get_base_template()) FATAL_ERROR("TemplateInstance::chk_restriction()"); - template_body->set_base_template(new Template(derived_reference)); + template_body->set_base_template(new Template(Template::TEMPLATE_REFD, derived_reference)); needs_runtime_check = template_body->chk_restriction( definition_name, template_restriction, usage_loc); delete template_body->get_base_template(); diff --git a/compiler2/ttcn3/TtcnTemplate.hh b/compiler2/ttcn3/TtcnTemplate.hh index 51e78ef81f5e0105003317710eded182acfdafdb..8226ec47d9fd5436089d3d76bd5ab73fef373227 100644 --- a/compiler2/ttcn3/TtcnTemplate.hh +++ b/compiler2/ttcn3/TtcnTemplate.hh @@ -69,7 +69,10 @@ namespace Ttcn { CSTR_PATTERN, /**< character string pattern */ USTR_PATTERN, /**< universal charstring pattern */ DECODE_MATCH, /**< decoded content match */ - TEMPLATE_CONCAT /**< concatenation of two templates (runtime2 only) */ + TEMPLATE_CONCAT, /**< concatenation of two templates (runtime2 only) */ + CONJUNCTION_MATCH, /**< conjunction list match */ + IMPLICATION_MATCH, /**< implication match */ + DYNAMIC_MATCH /**< dynamic match */ }; /** Status codes for the verification of template body completeness. */ @@ -186,11 +189,11 @@ namespace Ttcn { * TEMPLATE_CONCAT (in which case it's recursive). */ Template(Value *v); - /** Constructor for TEMPLATE_REFD */ - Template(Reference *p_ref); + /** Constructor for TEMPLATE_REFD and DYNAMIC_MATCH */ + Template(templatetype_t tt, Reference *p_ref); /** Constructor for TEMPLATE_LIST, VALUE_LIST, COMPLEMENTED_LIST, - * SUPERSET_MATCH, SUBSET_MATCH and PERMUTATION_MATCH */ + * SUPERSET_MATCH, SUBSET_MATCH, PERMUTATION_MATCH and CONJUNCTION_MATCH */ Template(templatetype_t tt, Templates *ts); /** Constructor for ALL_FROM */ @@ -214,6 +217,13 @@ namespace Ttcn { /** Constructor for DECODE_MATCH */ Template(Value* v, TemplateInstance* ti); + /** Constructor for IMPLICATION_MATCH */ + Template(Template* prec, TemplateInstance* imp_t); + + /** Constructor for DYNAMIC_MATCH */ + Template(StatementBlock* block); + + virtual ~Template(); virtual Template* clone() const; diff --git a/compiler2/ttcn3/compiler.l b/compiler2/ttcn3/compiler.l index baaf0108ecf14c82025a6e804ecf56bbe65101e6..f66d30924bbb6258a5cd8ad928b701d2f5a83cbf 100644 --- a/compiler2/ttcn3/compiler.l +++ b/compiler2/ttcn3/compiler.l @@ -392,6 +392,7 @@ check RETURN_DOT(CheckOpKeyword); clear RETURN_DOT(ClearOpKeyword); complement RETURN(ComplementKeyword); component RETURN(ComponentKeyword); +conjunct RETURN(ConjunctKeyword); connect RETURN(ConnectKeyword); const RETURN(ConstKeyword); continue RETURN(ContinueKeyword); @@ -431,6 +432,7 @@ halt RETURN_DOT(HaltKeyword); hexstring RETURN(HexStringKeyword); if RETURN(IfKeyword); ifpresent RETURN(IfPresentKeyword); +implies RETURN(ImpliesKeyword); import RETURN(ImportKeyword); in RETURN(InParKeyword); inconc RETURN(InconcKeyword); @@ -637,6 +639,7 @@ object { "@final" RETURN(FinalKeyword); "@abstract" RETURN(AbstractKeyword); "@default" RETURN(DefaultModifier); +"@dynamic" RETURN(DynamicModifier); /* special TITAN specific keywords */ diff --git a/compiler2/ttcn3/compiler.y b/compiler2/ttcn3/compiler.y index 3b5f2dba79a6e2fa450f688de0c74b012bc42d9f..9ccd46f464ce46f89be55293de501f7b12a92ef1 100644 --- a/compiler2/ttcn3/compiler.y +++ b/compiler2/ttcn3/compiler.y @@ -613,6 +613,19 @@ static const string anyname("anytype"); size_t nElements; StatementBlock** elements; } catch_block_list; + + struct { + Template* precondition; + TemplateInstance* implied_template; + } implication_match; + + struct { + bool is_ref; + union { + Ttcn::Reference* ref; + StatementBlock* sb; + }; + } dynamic_match; } /* Tokens of TTCN-3 */ @@ -679,6 +692,7 @@ static const string anyname("anytype"); %token ClearOpKeyword %token ComplementKeyword %token ComponentKeyword +%token ConjunctKeyword %token ConnectKeyword %token ConstKeyword %token ContinueKeyword @@ -720,6 +734,7 @@ static const string anyname("anytype"); %token HexStringKeyword %token IfKeyword %token IfPresentKeyword +%token ImpliesKeyword %token ImportKeyword %token InconcKeyword %token InfinityKeyword @@ -831,6 +846,7 @@ static const string anyname("anytype"); %token FinalKeyword %token AbstractKeyword %token DefaultModifier +%token DynamicModifier /* TITAN specific keywords */ %token TitanSpecificTryKeyword @@ -1076,7 +1092,7 @@ static const string anyname("anytype"); %type <templinsts> optTemplateActualParList seqTemplateActualPar seqTemplateInstance %type <templs> ValueOrAttribList seqValueOrAttrib ValueList Complement - ArrayElementSpecList SubsetMatch SupersetMatch PermutationMatch + ArrayElementSpecList SubsetMatch SupersetMatch PermutationMatch ConjunctionMatch %type <ass> Assignment Step %type <reference> DerivedRefWithParList TemplateRefWithParList DecValueArg FunctionInstance AltstepInstance optBaseConstructorCall @@ -1181,6 +1197,8 @@ AllOrTypeListWithTo TypeListWithFrom TypeListWithTo %type <reference_list> PortTypeList %type <string_vector> AttribSpecEncodings %type <catch_block_list> optCatchBlockList +%type <implication_match> ImplicationMatch +%type <dynamic_match> DynamicMatch /********************************************************************* * Destructors @@ -1276,6 +1294,7 @@ CompoundExpression ConditionalConstruct ConfigurationOps ConfigurationStatements +ConjunctionMatch ConnectStatement ContinueStatement ControlStatement @@ -1957,6 +1976,22 @@ DecodedContentMatch } optDecodedModifier +%destructor { + delete $$.precondition; + delete $$.implied_template; +} +ImplicationMatch + +%destructor { + if ($$.is_ref) { + delete $$.ref; + } + else { + delete $$.sb; + } +} +DynamicMatch + /********************************************************************* * Operator precedences (lowest first) @@ -1977,20 +2012,20 @@ optDecodedModifier %left '*' '/' ModKeyword RemKeyword %left UnarySign -%expect 76 +%expect 92 %start GrammarRoot /* -XXX Source of conflicts (75 S/R): +XXX Source of conflicts (92 S/R): -1.) 12 conflicts in one state +1.) 13 conflicts in one state The Expression after 'return' keyword is optional in ReturnStatement. -For 12 tokens the parser cannot decide whether the token is a part of +For 13 tokens the parser cannot decide whether the token is a part of the return expression (shift) or it is the beginning of the next statement (reduce). -2.) 13 distinct states, each with one conflict caused by token '[' +2.) 14 distinct states, each with one conflict caused by token '[' The local definitions in altsteps can be followed immediately by the guard expression. When the parser sees the '[' token it cannot decide whether it belongs to the local definition as array dimension or array subreference @@ -2009,6 +2044,7 @@ The situations are the following: - var t v := this.field <here> [ - var t v := this.function(...) <here> [ - var t v := super.function(...) <here> [ +- var t v := value<subrefs> <here> [ 3.) 1 conflict The sequence identifier.objid can be either the beginning of a module name @@ -2025,9 +2061,9 @@ non-standard language extension. 6.) 1 Conflict due to pattern concatenation -7.) 30 conflicts in one state +7.) 31 conflicts in one state In the DecodedContentMatch rule a SingleExpression encased in round brackets is -followed by an in-line template. For 30 tokens (after the ')' ) the parser cannot +followed by an in-line template. For 31 tokens (after the ')' ) the parser cannot decide whether the token is the beginning of the in-line template (shift) or the brackets are only part of the SingleExpression itself and the conflicting token is the next segment in the expression (reduce). @@ -2070,6 +2106,38 @@ ex.: 'a(1)' is treated as the objid component with name 'a' and number '1' (shif instead of the component with the number returned by function 'a' with '1' as its parameter (reduce). +14.) 13 conflicts in 9 states +These are caused by the implication matching template rule (i.e. ImplicationMatch), +specifically because the rule ends in a TemplateInstance, and the rule itself can be +embedded inside another TemplateInstance. + - The 'length' and 'ifpresent' keywords after an implication match template can +be interpreted as attributes of the implied template (i.e. the 2nd operand) +in the implication match template (shift), or as attributes of the entire implication +match template (reduce). This causes 2 conflicts (one for each keyword) in 4 states +(the first 4 options of the TemplateBody rule). + - Similarly, if there is an 'ifpresent' after a length restriction at the end of an +implication match template, then it can be considered as an attribute of the implied +template (shift), or as an attribute of the entire implication match template (reduce). + - Implication matching templates can be chained (e.g. 't1 implies t2 implies t3'). +The first 'implies' keyword in this case can be considered as part of the precondition +of the resulting template (whose precondition is 't1 implies t2' and whose implied +template is 't3'). This is the shift case. +It can also be considered as the resulting template's 'implies' keyword (in which case +the precondition would be 't1' and the implied tempalte would be 't2 implies t3'). +This is the reduce case. +Semantically both cases mean the same thing. + - Similarly, if a template instance in the middle of an implication match chain has a +type indicator, a derived reference, or both a type indicator and a derived reference, +then the following 'implies' keyword can be considered as part of the result template's +precondition (shift). In this case the type and/or derived reference only affect the +template operand before the mentioned 'implies' keyword. +Or it can be the 'implies' keyword of the resulting template (reduce), in which case +the type and/or derived reference would affect the entire implication match template that +starts before the mentioned 'implies' keyword and ends after the final 'implies' keyword. +(For example in 't1 implies MyType: t2 implies t3' +'MyType:' could indicate the type of 't2' (shift) or the type of 't2 implies t3' (reduce). + + Note that the parser implemented by bison always chooses to shift instead of reduce in case of conflicts. */ @@ -4206,13 +4274,33 @@ MatchingSymbol: // 116 is a Template* $$ = new Template(Template::SUPERSET_MATCH, $1); $$->set_location(infile, @$); } +| ConjunctionMatch + { + $$ = new Template(Template::CONJUNCTION_MATCH, $1); + $$->set_location(infile, @$); + } +| ImplicationMatch + { + $$ = new Template($1.precondition, $1.implied_template); + $$->set_location(infile, @$); + } +| DynamicMatch + { + if ($1.is_ref) { + $$ = new Template(Template::DYNAMIC_MATCH, $1.ref); + } + else { + $$ = new Template($1.sb); + } + $$->set_location(infile, @$); + } ; optExtraMatchingAttributes: // [117] /* empty */ { - $$.is_ifpresent = false; $$.len_restr = NULL; + $$.is_ifpresent = false; } | LengthMatch { @@ -4340,6 +4428,33 @@ DecodedContentMatch: } ; +ConjunctionMatch: + ConjunctKeyword ValueList { $$ = $2; } +; + +ImplicationMatch: + TemplateBody ImpliesKeyword TemplateInstance + { + $$.precondition = $1; + $$.implied_template = $3; + } +/*| TemplateBody ImpliesKeyword '(' TemplateInstance ')' --- handled by TemplateListElem */ +; + +DynamicMatch: + DynamicModifier StatementBlock + { + $$.is_ref = false; + $$.sb = $2; + } +| DynamicModifier FunctionRef + { + $$.is_ref = true; + $$.ref = new Ttcn::Reference($2.modid, $2.id); + $$.ref->set_location(infile, @2); + } +; + AnyValue: // 140 '?' ; @@ -8888,6 +9003,14 @@ Reference: // 490 ValueReference Free($7.elements); $$.ref->set_location(infile, @$); } +| ValueKeyword optExtendedFieldReference + { + $$.is_ref = true; + $$.ref = new Ttcn::Reference(Ref_simple::REF_VALUE); + for (size_t i = 0; i < $2.nElements; i++) $$.ref->add($2.elements[i]); + Free($2.elements); + $$.ref->set_location(infile, @$); + } ; /* A.1.6.5 Parameterization */ diff --git a/core/Basetype.hh b/core/Basetype.hh index add2b7acc505aa428e8044a81da5ceb5772d5c45..c09c66bcf98eeb29f16b4783ebbf7a8d5011b1a5 100644 --- a/core/Basetype.hh +++ b/core/Basetype.hh @@ -1237,6 +1237,20 @@ public: virtual ~Dec_Match_Interface() {} }; +template <typename T> +class Dynamic_Match_Interface { +public: + virtual boolean match(const T&) = 0; + virtual ~Dynamic_Match_Interface() {} +}; + +template <typename T> +struct dynmatch_struct { + unsigned int ref_count; + Dynamic_Match_Interface<T>* ptr; +}; + + /** Interface/base class for value redirects in RT2 * * For every value redirect the compiler generates a new class that inherits diff --git a/core/Integer.cc b/core/Integer.cc index 18064b080894313b762279f45f881a01347ea7ad..1ac0dc593a9fd46dc9c432f5d2ce7f9aa376f094 100644 --- a/core/Integer.cc +++ b/core/Integer.cc @@ -2077,6 +2077,7 @@ void INTEGER_template::clean_up() break; case VALUE_LIST: case COMPLEMENTED_LIST: + case CONJUNCTION_MATCH: delete [] value_list.list_value; break; case VALUE_RANGE: @@ -2085,6 +2086,17 @@ void INTEGER_template::clean_up() if (value_range.max_is_present && unlikely(!value_range.max_value.native_flag)) BN_free(value_range.max_value.val.openssl); break; + case IMPLICATION_MATCH: + delete implication_.precondition; + delete implication_.implied_template; + break; + case DYNAMIC_MATCH: + dyn_match->ref_count--; + if (dyn_match->ref_count == 0) { + delete dyn_match->ptr; + delete dyn_match; + } + break; default: break; } @@ -2106,6 +2118,7 @@ void INTEGER_template::copy_template(const INTEGER_template& other_value) break; case VALUE_LIST: case COMPLEMENTED_LIST: + case CONJUNCTION_MATCH: value_list.n_values = other_value.value_list.n_values; value_list.list_value = new INTEGER_template[value_list.n_values]; for (unsigned int i = 0; i < value_list.n_values; i++) @@ -2136,6 +2149,14 @@ void INTEGER_template::copy_template(const INTEGER_template& other_value) BN_dup(other_value.value_range.max_value.val.openssl); } break; + case IMPLICATION_MATCH: + implication_.precondition = new INTEGER_template(*other_value.implication_.precondition); + implication_.implied_template = new INTEGER_template(*other_value.implication_.implied_template); + break; + case DYNAMIC_MATCH: + dyn_match = other_value.dyn_match; + dyn_match->ref_count++; + break; default: TTCN_error("Copying an uninitialized/unsupported integer template."); } @@ -2196,6 +2217,21 @@ INTEGER_template::INTEGER_template(const INTEGER_template& other_value) copy_template(other_value); } +INTEGER_template::INTEGER_template(INTEGER_template* p_precondition, INTEGER_template* p_implied_template) +: Base_Template(IMPLICATION_MATCH) +{ + implication_.precondition = p_precondition; + implication_.implied_template = p_implied_template; +} + +INTEGER_template::INTEGER_template(Dynamic_Match_Interface<INTEGER>* p_dyn_match) +: Base_Template(DYNAMIC_MATCH) +{ + dyn_match = new dynmatch_struct<INTEGER>; + dyn_match->ptr = p_dyn_match; + dyn_match->ref_count = 1; +} + INTEGER_template::~INTEGER_template() { clean_up(); @@ -2310,6 +2346,17 @@ boolean INTEGER_template::match(int other_value, boolean /* legacy */) const } } return lower_boundary && upper_boundary; } + case CONJUNCTION_MATCH: + for (unsigned int i = 0; i < value_list.n_values; i++) { + if (!value_list.list_value[i].match(other_value)) { + return FALSE; + } + } + return TRUE; + case IMPLICATION_MATCH: + return !implication_.precondition->match(other_value) || implication_.implied_template->match(other_value); + case DYNAMIC_MATCH: + return dyn_match->ptr->match(other_value); default: TTCN_error("Matching with an uninitialized/unsupported integer " "template."); @@ -2365,6 +2412,17 @@ boolean INTEGER_template::match(const INTEGER& other_value, } } return lower_boundary && upper_boundary; } + case CONJUNCTION_MATCH: + for (unsigned int i = 0; i < value_list.n_values; i++) { + if (!value_list.list_value[i].match(other_value)) { + return FALSE; + } + } + return TRUE; + case IMPLICATION_MATCH: + return !implication_.precondition->match(other_value) || implication_.implied_template->match(other_value); + case DYNAMIC_MATCH: + return dyn_match->ptr->match(other_value); default: TTCN_error("Matching with an uninitialized/unsupported integer " "template."); @@ -2388,6 +2446,7 @@ void INTEGER_template::set_type(template_sel template_type, switch (template_type) { case VALUE_LIST: case COMPLEMENTED_LIST: + case CONJUNCTION_MATCH: set_selection(template_type); value_list.n_values = list_length; value_list.list_value = new INTEGER_template[list_length]; @@ -2407,7 +2466,8 @@ void INTEGER_template::set_type(template_sel template_type, INTEGER_template& INTEGER_template::list_item(unsigned int list_index) { if (template_selection != VALUE_LIST && - template_selection != COMPLEMENTED_LIST) + template_selection != COMPLEMENTED_LIST && + template_selection != CONJUNCTION_MATCH) TTCN_error("Accessing a list element of a non-list integer template."); if (list_index >= value_list.n_values) TTCN_error("Index overflow in an integer value list template."); @@ -2524,6 +2584,11 @@ void INTEGER_template::log() const case COMPLEMENTED_LIST: TTCN_Logger::log_event_str("complement"); // no break + case CONJUNCTION_MATCH: + if (template_selection == CONJUNCTION_MATCH) { + TTCN_Logger::log_event_str("conjunct"); + } + // no break case VALUE_LIST: TTCN_Logger::log_char('('); for (unsigned int i = 0; i < value_list.n_values; i++) { @@ -2559,6 +2624,14 @@ void INTEGER_template::log() const } TTCN_Logger::log_char(')'); break; + case IMPLICATION_MATCH: + implication_.precondition->log(); + TTCN_Logger::log_event_str(" implies "); + implication_.implied_template->log(); + break; + case DYNAMIC_MATCH: + TTCN_Logger::log_event_str("@dynamic template"); + break; default: log_generic(); break; @@ -2840,6 +2913,8 @@ boolean INTEGER_template::match_omit(boolean legacy /* = FALSE */) const case OMIT_VALUE: case ANY_OR_OMIT: return TRUE; + case IMPLICATION_MATCH: + return !implication_.precondition->match_omit() || implication_.implied_template->match_omit(); case VALUE_LIST: case COMPLEMENTED_LIST: if (legacy) { diff --git a/core/Integer.hh b/core/Integer.hh index 42705bfa672aa48d1324341e6b6bbad03ec96003..25d0f9aa07c53936c11d98fe2424a1c39aab71db 100644 --- a/core/Integer.hh +++ b/core/Integer.hh @@ -264,6 +264,11 @@ private: } val; } min_value, max_value; } value_range; + struct { + INTEGER_template* precondition; + INTEGER_template* implied_template; + } implication_; + dynmatch_struct<INTEGER>* dyn_match; }; void copy_template(const INTEGER_template& other_value); @@ -275,6 +280,8 @@ public: INTEGER_template(int other_value); INTEGER_template(const INTEGER& other_value); INTEGER_template(const OPTIONAL<INTEGER>& other_value); + INTEGER_template(INTEGER_template* p_precondition, INTEGER_template* p_implied_template); + INTEGER_template(Dynamic_Match_Interface<INTEGER>* p_dyn_match); ~INTEGER_template(); void clean_up(); diff --git a/core/Template.hh b/core/Template.hh index 26f1ee76643ee9a8624f4647dd0c3e9108a642d6..dc35f42cd66681414900a6278ad2db999a3f7c45 100644 --- a/core/Template.hh +++ b/core/Template.hh @@ -54,7 +54,10 @@ enum template_sel { STRING_PATTERN = 7, SUPERSET_MATCH = 8, SUBSET_MATCH = 9, - DECODE_MATCH = 10 + DECODE_MATCH = 10, + CONJUNCTION_MATCH = 11, + IMPLICATION_MATCH = 12, + DYNAMIC_MATCH = 13 }; enum template_res {