-
Botond Baranyi authored
Signed-off-by:
Botond Baranyi <botond.baranyi@ericsson.com>
Botond Baranyi authoredSigned-off-by:
Botond Baranyi <botond.baranyi@ericsson.com>
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
TtcnTemplate.hh 27.71 KiB
/******************************************************************************
* Copyright (c) 2000-2021 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* Baji, Laszlo
* Balasko, Jeno
* Baranyi, Botond
* Delic, Adam
* Kovacs, Ferenc
* Raduly, Csaba
* Szabados, Kristof
* Zalanyi, Balazs Andor
*
******************************************************************************/
#ifndef _Ttcn_Template_HH
#define _Ttcn_Template_HH
#include "../Int.hh"
#include "../Value.hh"
#include "../vector.hh"
#include "AST_ttcn3.hh"
#include "Templatestuff.hh"
namespace Ttcn {
using namespace Common;
class PatternString;
class ValueRange;
class LengthRestriction;
class Templates;
class NamedTemplate;
class NamedTemplates;
class IndexedTemplate;
class IndexedTemplates;
/** Represents a (single or compound) template body. */
class Template : public GovernedSimple {
public:
/** type of template */
enum templatetype_t {
TEMPLATE_ERROR, /**< erroneous template */
TEMPLATE_NOTUSED, /**< not used symbol (-) */
OMIT_VALUE, /**< omit */
ANY_VALUE, /**< any value (?) */
ANY_OR_OMIT, /**< any or omit (*) */
SPECIFIC_VALUE, /**< specific value */
TEMPLATE_REFD, /**< reference to another template */
TEMPLATE_INVOKE, /** template returning invoke */
TEMPLATE_LIST, /**< value list notation */
NAMED_TEMPLATE_LIST, /**< assignment notation */
INDEXED_TEMPLATE_LIST, /**< assignment notation with array indices */
VALUE_LIST, /**< value list match */
COMPLEMENTED_LIST, /**< complemented list match */
VALUE_RANGE, /**< value range match */
SUPERSET_MATCH, /**< superset match */
SUBSET_MATCH, /**< subset match */
PERMUTATION_MATCH, /**< permutation match */
ALL_FROM, /**< "all from" clause */
BSTR_PATTERN, /**< bitstring pattern */
HSTR_PATTERN, /**< hexstring pattern */
OSTR_PATTERN, /**< octetstring pattern */
CSTR_PATTERN, /**< character string pattern */
USTR_PATTERN, /**< universal charstring pattern */
DECODE_MATCH, /**< decoded content match */
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. */
enum completeness_t {
C_MUST_COMPLETE, /**< the body must be completely specified */
C_MAY_INCOMPLETE, /**< the body may be incompletely specified */
C_PARTIAL /**< some parts of the body may be incomplete,
* the others must be complete */
};
private:
/** Determines type of the template. Only this field is used at
* ANY_VALUE, ANY_OR_OMIT and OMIT_VALUE templates */
templatetype_t templatetype;
/** This union holds the ``body'' of the template. The
* templatetype field is used to select between different
* containers. */
union {
/** Holds the concrete single value of the template for single
* types */
Value *specific_value;
struct {
Reference *ref;
Template *refd; /**< cache */
Template *refd_last; /**< cache */
} ref;
/** Used for TEMPLATE_LIST, VALUE_LIST, COMPLEMENTED_LIST,
* SUPERSET_MATCH, SUBSET_MATCH and PERMUTATION_MATCH constructs. */
Templates *templates;
/** Used by NAMED_TEMPLATE_LIST */
NamedTemplates *named_templates;
/** Used by INDEXED_TEMPLATE_LIST */
IndexedTemplates *indexed_templates;
/** Used by ALL_FROM */
Template *all_from;
/** This is used for VALUE_RANGE template upper and lower
* bound. */
ValueRange *value_range;
/** Pattern contains basic string templates containing the any
* element (?), any element or no element (*) wildcards .
* Used by BSTR_PATTERN, HSTR_PATTERN, OSTR_PATTERN */
string *pattern;
/** PatternString contains the character string pattern matching
* constructions (including references).
* Used by CSTR_PATTERN, USTR_PATTERN */
PatternString *pstring;
/** Used by TEMPLATE_INVOKE */
struct {
Value *v;
Ttcn::ParsedActualParameters *t_list;
Ttcn::ActualParList *ap_list;
} invoke;
/** Used by DECODE_MATCH */
struct {
Value* str_enc;
TemplateInstance* target;
} dec_match;
/** Used by TEMPLATE_CONCAT */
struct {
Template* op1;
Template* op2;
bool in_brackets;
} concat;
} u;
/** This points to the type of the template */
Type *my_governor;
/** Length restriction */
LengthRestriction *length_restriction;
/** Ifpresent flag. */
bool is_ifpresent;
/** Indicates whether it has been verified that the template is free of
* matching symbols. */
bool specific_value_checked;
/** Indicates whether the embedded templates contain PERMUTATION_MATCH.
* Used only in case of TEMPLATE_LIST */
bool has_permutation;
/** If false, it indicates that some all from could not be computed
* at compile-time, so it will need to be computed at runtime.
* It starts out as true. TODO find a better name */
bool flattened;
/** Pointer to the base template (or template field) that this
* template is derived from. It is set in modified templates
* (including in-line modified templates) and only if the
* compiler is able to determine the base template. It is NULL
* otherwise. */
Template *base_template;
/** Copy constructor. For Template::clone() only.
* This is a hit-and-miss affair. Some template types can be cloned;
* others cause an immediate FATAL_ERROR. */
Template(const Template& p);
/** Copy assignment disabled */
Template& operator=(const Template& p);
/** Destroys the innards of the template */
void clean_up();
string create_stringRepr();
public:
/** Constructor for TEMPLATE_ERROR and TEMPLATE_NOTUSED */
Template(templatetype_t tt);
/** Constructor for SPECIFIC_VALUE, ANY_VALUE, ANY_OR_OMIT, OMIT_VALUE and
* TEMPLATE_CONCAT (in which case it's recursive). */
Template(Value *v);
/** 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, PERMUTATION_MATCH and CONJUNCTION_MATCH */
Template(templatetype_t tt, Templates *ts);
/** Constructor for ALL_FROM */
Template(Template*);
/** Constructor for NAMED_TEMPLATE_LIST */
Template(NamedTemplates *nts);
/** Constructor for INDEXED_TEMPLATE_LIST */
Template(IndexedTemplates *its);
/** Constructor for VALUE_RANGE */
Template(ValueRange *vr);
/** Constructor for BSTR_PATTERN, HSTR_PATTERN and OSTR_PATTERN */
Template(templatetype_t tt, string *p_patt);
/** Constructor for CSTR_PATTERN. */
Template(PatternString *p_ps);
/** 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;
virtual void set_fullname(const string& p_fullname);
virtual void set_my_scope(Scope *p_scope);
void set_genname_recursive(const string& p_genname);
void set_genname_prefix(const char *p_genname_prefix);
void set_code_section(code_section_t p_code_section);
/** Transforms the template to type \a p_templatetype.
* Works only if the change is possible */
void set_templatetype(templatetype_t p_templatetype);
templatetype_t get_templatetype() const { return templatetype; }
/** Returns a C string containing the type (e.g. "any or omit")
* of the template. */
const char *get_templatetype_str() const;
/** Returns whether the template is a specific value containing a single
* identifier. */
bool is_undef_lowerid();
/** If the embedded specific value contains a single identifier it converts
* that to a referenced value or referenced template. */
void set_lowerid_to_ref();
/** If this template is used in an expression, what is its return type? */
Type::typetype_t get_expr_returntype(Type::expected_value_t exp_val);
/** If this template is used in an expression, what is its governor?
* If has no governor, but is reference, then tries the
* referenced stuff... If not known, returns NULL. */
Type *get_expr_governor(Type::expected_value_t exp_val);
/** Sets the governor type. */
virtual void set_my_governor(Type *p_gov);
/** Gets the governor type. */
virtual Type* get_my_governor() const;
void set_length_restriction(LengthRestriction *p_lr);
LengthRestriction *get_length_restriction() const
{ return length_restriction; }
bool is_length_restricted() const { return length_restriction != 0; }
void set_ifpresent(bool p_ifpr) { is_ifpresent = p_ifpr; }
bool get_ifpresent() const { return is_ifpresent; }
void set_base_template(Template *p_base) { base_template = p_base; }
Template *get_base_template() const { return base_template; }
/** Returns the condition for the completeness of template body \a this,
* which is a 'record of' or 'set of' template.
* Argument \a incomplete_allowed indicates whether incomplete template
* bodies are allowed in the context at all. */
completeness_t get_completeness_condition_seof(bool incomplete_allowed);
/** Returns the condition for the completeness of template body \a this,
* which is a union template.
* Argument \a incomplete_allowed indicates whether incomplete template
* bodies are allowed in the context at all. Argument \a p_fieldname points
* to a field of \a this that is examined. It is useful when \a this is
* erroneous and contains multiple fields. */
completeness_t get_completeness_condition_choice(bool incomplete_allowed,
const Identifier& p_fieldname);
void add_named_temp(NamedTemplate* nt);
Value *get_specific_value() const;
Reference *get_reference() const;
ValueRange *get_value_range() const;
PatternString* get_cstr_pattern() const;
PatternString* get_ustr_pattern() const;
size_t get_nof_comps() const;
Template *get_temp_byIndex(size_t n) const;
NamedTemplate *get_namedtemp_byIndex(size_t n) const;
NamedTemplate* get_namedtemp_byName(const Identifier& name) const;
IndexedTemplate *get_indexedtemp_byIndex(size_t n) const;
Template *get_all_from() const;
/** Returns the number of elements in a VALUE_LIST. The elements of
* embedded PERMUTATION_MATCH constructs are counted recursively. */
size_t get_nof_listitems() const;
/** Returns the \a n th element of a VALUE_LIST. The embedded
* PERMUTATION_MATCH constructs are also counted. */
Template *get_listitem_byIndex(size_t n) const;
/** Converts the template into a named template list, with one element that
* has the union type's @default alternative as its name and the original template (cloned)
* as its value.
* Used when a template of a different type appears in a context, where a template of
* the specified union type was expected.
* This attempts to use the template as the union's default alternative instead. */
void use_default_alternative(Type* p_union_type);
Template* get_template_refd_last(ReferenceChain *refch=0);
Template* get_refd_sub_template(Ttcn::FieldOrArrayRefs *subrefs,
bool usedInIsbound,
ReferenceChain *refch,
bool silent = false);
/** Converts this template to a pattern of the specified binary string type,
* and adds it to the result. Used when evaluating concatenations between
* binary string templates.
* @param patt_str contains the resulting binary string pattern
* @param exp_tt contains the type of the resulting binary string pattern */
bool concat_to_bin_pattern(string& patt_str, Type::typetype_t exp_tt) const;
Value* get_string_encoding() const;
TemplateInstance* get_decode_target() const;
Template* get_concat_operand(bool first) const;
bool is_optional_value_ref() const;
private:
Template* get_template_refd(ReferenceChain *refch);
Template* get_refd_field_template(const Identifier& field_id,
const Location& loc, bool usedInIsbound, ReferenceChain *refch, bool silent);
Template* get_refd_array_template(Value *array_index, bool usedInIsbound,
ReferenceChain *refch, bool silent);
bool compile_time() const;
public:
/** Returns whether \a this contains '*' as inside value. Applicable to:
* TEMPLATE_LIST, SUPERSET_MATCH, SUBSET_MATCH, PERMUTATION_MATCH */
bool temps_contains_anyornone_symbol() const;
/** Returns the number of elements not counting the '*'s. Applicable to:
* TEMPLATE_LIST, SUPERSET_MATCH, SUBSET_MATCH, PERMUTATION_MATCH */
size_t get_nof_comps_not_anyornone() const;
/** Returns whether the string pattern contains '*' as inside value.
* Applicable to: BSTR_PATTERN, HSTR_PATTERN, OSTR_PATTERN, CSTR_PATTERN */
bool pattern_contains_anyornone_symbol() const;
/** Returns the length of string pattern not counting the '*'s.
* Applicable to: BSTR_PATTERN, HSTR_PATTERN, OSTR_PATTERN, CSTR_PATTERN */
size_t get_min_length_of_pattern() const;
/** Returns whether the template can be converted to a value
* (i.e. it is a specific value without wildcards). */
bool is_Value() const;
/** Converts the template to a value recursively. The returned
* value is newly allocated (i.e. the caller is responsible for
* the deallocation).
* If the template type was SPECIFIC_VALUE, the value returned is
* extracted from the template, which becomes TEMPLATE_ERROR. */
Value *get_Value();
/** Returns whether the template consists of a single reference
* (i.e. it is a single specific value with an embedded
* non-parameterized reference). */
bool is_Ref() const;
/** Converts the template to a reference. The returned reference
* is newly allocated (i.e. the caller is responsible for the
* deallocation). */
Reference *get_Ref();
/** Checks for circular references within embedded templates */
void chk_recursions(ReferenceChain& refch);
/** Checks whether the template (including the embedded fields) contains
* no matching symbols. Argument \a allow_omit is used because OMIT_VALUE
* is allowed only in embedded fields. */
void chk_specific_value(bool allow_omit);
void chk_specific_value_generic();
void chk_invoke();
void chk_concat_double_length_res();
void chk_immutability();
/** Copy template elements from the "all from" into the template.
*
* @param from_permutation \a true if the "all from" occurs inside
* a permutation_match (in which case the target of the "all from"
* is allowed to be AnyElementsOrNone).
* @return \a false if some elements could not be computed at compile time,
* else \a true.
*/
bool flatten(bool from_permutation);
bool is_flattened() const { return flattened; }
bool has_allfrom() const;
static Templates *harbinger(Template *t, bool from_permutation, bool killer);
/** helper functions used by definitions which check their template restr.*/
/** returns the restriction name token */
static const char* get_restriction_name(template_restriction_t tr);
/** if a template has restriction \a tr then what is the restriction
on it's subfields */
static template_restriction_t get_sub_restriction(
template_restriction_t tr, Reference* ref);
/** returns C++ code that checks the restriction */
static char* generate_restriction_check_code(char* str,
const char* name, template_restriction_t tr);
/** Return if the required template restriction \a needed_tr is
* not satisfied by the given \a refd_tr */
static bool is_less_restrictive(template_restriction_t needed_tr,
template_restriction_t refd_tr);
private:
/** helper functions used by chk_restriction() */
bool chk_restriction_named_list(const char* definition_name,
map<string, void>& checked_map, size_t needed_checked_cnt,
const Location* usage_loc);
bool chk_restriction_refd(const char* definition_name,
template_restriction_t template_restriction, const Location* usage_loc);
public:
/** Checks if this template conforms to the restriction, return value:
* false = always satisfies restriction -> no runtime check needed or
* never satisfies restriction -> compiler error(s)
* true = possibly violates restriction, cannot be determined at compile
* time -> runtime check needed and compiler warning given when
* inadequate restrictions are used, in other cases there's
* no warning
* The return value is used by code generation to avoid useless checks
* @param usage_loc contains the location, where the template is used
* (errors are issued here, instead of where the template is declared) */
bool chk_restriction(const char* definition_name,
template_restriction_t template_restriction,
const Location* usage_loc);
/** Sets the flag \a code_generated to false in this template and all of its
* parts. */
virtual void reset_code_generated();
/** Public entry points for code generation. */
/** Generates the equivalent C++ code for the template. It is used
* when the template is part of a complex expression
* (e.g. argument of a function that accepts a template). The
* generated code fragments are appended to the fields of visitor
* \a expr. */
void generate_code_expr(expression_struct *expr,
template_restriction_t template_restriction = TR_NONE);
/** Generates a C++ code sequence, which initializes the C++
* object named \a name with the contents of the template. The
* code sequence is appended to argument \a str and the resulting
* string is returned. */
char *generate_code_init(char *str, const char *name);
/** Walks through the template recursively and appends the C++
* initialization sequence of all (directly or indirectly)
* referenced non-parameterized templates and the default values of all
* parameterized templates to \a str and returns the resulting string.
* Only objects belonging to module \a usage_mod are initialized. */
char *rearrange_init_code(char *str, Common::Module* usage_mod);
private:
/** Private helper functions for code generation. */
/** Helper function for \a generate_code_init_refd(). Returns whether
* the string returned by \a get_single_expr() can be used to initialize
* the template instead of using the re-arrangement algorithm.
* Applicable to referenced templates only. */
bool use_single_expr_for_init();
/** Helper function for \a generate_code_init(). It handles the
* referenced templates. */
char *generate_code_init_refd(char *str, const char *name);
char *generate_code_init_invoke(char *str, const char *name);
/** Generates the C++ equivalent of \a this into \a expr and
* performs the necessary reordering: appends the initializer
* sequence of the dependent templates to \a str and returns the
* resulting string. It is used when \a this is a referenced
* template that is embedded into the body of a non-parameterized
* template. Note that the final content of \a expr is not
* necessarily identical to the C++ equivalent of \a
* u.ref.ref. */
char *generate_rearrange_init_code_refd(char *str, expression_struct *expr);
/** Helper function for \a generate_code_init(). It handles the value list
* notation and the assignment notation with array indices (for 'record
* of' and 'set of' types). Embedded permutation matching constructs are
* also handled. */
char *generate_code_init_seof(char *str, const char *name);
/** Helper function for \a generate_code_init_seof(). Used when \a this is
* a member of a value list notation or an embedded permutation match.
* Parameter \a name contains the C++ reference that points to the parent
* template. Parameter \a index is a straightened index in case of
* embedded permutations. Parameter \a element_type_genname contains a
* C++ class name that represents the element type of the 'record of' or
* 'set of' construct (which is the governor of \a this); if a temporary
* variable is created, this would be used as its type. */
char *generate_code_init_seof_element(char *str, const char *name,
const char* index, const char *element_type_genname);
/** Helper function for \a generate_code_init(). It handles the
* assignment notation for record/set/union types. */
char *generate_code_init_se(char *str, const char *name);
/** Helper function for \a generate_code_init(). It handles the
* value list and complemented list matching constructs. Flag \a
* is_complemented is set to true for complemented lists and
* false for value lists. */
char *generate_code_init_list(char *str, const char *name,
bool is_complemented);
/** Helper function for \a generate_code_init(). It handles the superset
* and subset constructs. Flag \a is_superset is set to true for superset
* and false for subset. Note that both constructs have similar data
* representations in runtime. */
char *generate_code_init_set(char *str, const char *name,
bool is_superset);
char* generate_code_init_dec_match(char* str, const char* name);
char* generate_code_init_concat(char* str, const char* name);
char *generate_code_init_all_from(char *str, const char *name);
char *generate_code_init_all_from_list(char *str, const char *name);
string generate_code_str_pattern(bool cast_needed, string& preamble);
/** Helper function for \a generate_code_expr() and get_single_expr().
* It handles the invoke operation. */
void generate_code_expr_invoke(expression_struct *expr);
/** Helper function for \a rearrange_init_code(). It handles the
* referenced templates (i.e. it does the real work). */
char *rearrange_init_code_refd(char *str, Common::Module* usage_mod);
char *rearrange_init_code_invoke(char *str, Common::Module* usage_mod);
/** Returns whether the C++ initialization sequence requires a
* temporary variable reference to be introduced for efficiency
* reasons. */
bool needs_temp_ref();
public:
/** Returns whether the template can be represented by an in-line
* C++ expression. */
bool has_single_expr();
/** Returns the equivalent C++ expression. It can be used only if
* \a has_single_expr() returns true. Argument \a cast_needed
* indicates whether the generic wildcards have to be explicitly
* converted to the appropriate type. */
string get_single_expr(bool cast_needed);
virtual void dump(unsigned level) const;
};
/** Represents an in-line template. Consists of:
* - an optional type
* - an optional template reference with or without actual parameter list
* (in case of in-line modified template)
* - a mandatory template body
*/
class TemplateInstance : public Node, public Location {
private: // all pointers owned
Type *type; // type before the colon, may be null
Reference *derived_reference; // base template, may be null
Template *template_body; // must not be null
char* last_gen_expr; // last expression generated from this template instance
// (used if this template needs to be used multiple times)
/** Copy constructor disabled. */
TemplateInstance(const TemplateInstance& p);
/** Copy assignment disabled. */
TemplateInstance& operator=(const TemplateInstance& p);
public:
/** Constructor
*
* @param p_type type (the one before the colon, optional)
* @param p_ref reference to the base template (for a modified template)
* @param p_body template body (must not be NULL)
*/
TemplateInstance(Type *p_type, Reference *p_ref, Template *p_body);
~TemplateInstance();
virtual TemplateInstance *clone() const;
virtual void set_fullname(const string& p_fullname);
virtual void set_my_scope(Scope *p_scope);
Type* get_Type() const { return type; }
Reference* get_DerivedRef() const { return derived_reference; }
Template* get_Template() const { return template_body; }
char* get_last_gen_expr() const { return last_gen_expr; }
// it can return null pointer
Def_Template* get_Referenced_Base_Template();
/** Give up ownership of \a type, \a derived_reference and
* \a template_body */
void release();
/** If this template instance is used in an expression, what is its
* return type? */
Type::typetype_t get_expr_returntype(Type::expected_value_t exp_val);
/** If this template instance is used in an expression, what is its
* governor? Returns NULL if the governor cannot be determined. */
Type *get_expr_governor(Type::expected_value_t exp_val);
/** Checks the entire template instance against \a governor. */
void chk(Type *governor);
/** Checks the member \a type (if present) against \a governor.
* Returns the type that shall be considered in further checks. */
Type *chk_Type(Type *governor);
/** Checks the derived reference against \a governor.
* If \a governor is NULL it is checked against the \a type member.
* Returns the type that shall be considered when checking
* \a template_body. */
Type *chk_DerivedRef(Type *governor);
/** Checks for circular references. */
void chk_recursions(ReferenceChain& refch);
bool is_string_type(Type::expected_value_t exp_val);
bool chk_restriction(const char* definition_name,
template_restriction_t template_restriction, const Location* usage_loc);
void chk_immutability() const ;
/** Returns whether the template instance can be represented by an in-line
* C++ expression. */
bool has_single_expr();
void set_code_section(GovernedSimple::code_section_t p_code_section);
bool needs_temp_ref();
void generate_code(expression_struct *expr,
template_restriction_t template_restriction = TR_NONE,
bool has_decoded_redirect = false);
/** Appends the initialization sequence of the referred templates
* and their default values to \a str. Only templates from module
* \a usage_mod are considered. */
char *rearrange_init_code(char *str, Common::Module* usage_mod);
/** Appends the string representation of the template instance to
* \a str. */
void append_stringRepr(string& str) const;
virtual void dump(unsigned level) const;
/** Returns the single value if the template is single value or NULL. */
Value* get_specific_value() const;
bool is_only_specific_value() const {
return (derived_reference==NULL &&
template_body->get_templatetype()==Template::SPECIFIC_VALUE &&
!template_body->is_length_restricted() &&
!template_body->get_ifpresent());
}
};
} // namespace Ttcn
#endif // _Ttcn_Template_HH