Commit 589e0edf authored by BenceJanosSzabo's avatar BenceJanosSzabo
Browse files

Implemented mtc and system clauses in altsteps and functions (Bug 519281)



Change-Id: I2dfa85d30b67a3d284464cbaabc9308cb308d5a4
Signed-off-by: default avatarBenceJanosSzabo <bence.janos.szabo@ericsson.com>
parent 247f4fcf
......@@ -1928,6 +1928,16 @@ namespace Common {
return 0;
}
Type *Assignment::get_MtcType()
{
return 0;
}
Type *Assignment::get_SystemType()
{
return 0;
}
Type *Assignment::get_PortType()
{
return 0;
......
......@@ -589,6 +589,12 @@ namespace Common {
/** Returns the component type referred by the 'runs on' clause of a
* TTCN-3 definition */
virtual Type *get_RunsOnType();
/** Returns the component type referred by the 'mtc' clause of a
* TTCN-3 definition */
virtual Type *get_MtcType();
/** Returns the component type referred by the 'system' clause of a
* TTCN-3 definition */
virtual Type *get_SystemType();
/** Returns the port type referred by the 'port' clause of a
* TTCN-3 function definition */
virtual Type *get_PortType();
......
......@@ -692,6 +692,56 @@ namespace Common {
refd_comptype->get_typename().c_str());
}
}
void Scope::chk_mtc_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what, bool in_control_part)
{
// component type of the referred definition
Type *refd_comptype = p_ass->get_MtcType();
// definitions without 'mtc' can be called from anywhere
if (!refd_comptype) return;
if (in_control_part) {
p_loc.error("Function with mtc or system clause is not allowed in control part.");
return;
}
Type *t_comptype = get_mtc_system_comptype(false);
if (t_comptype) {
if (!refd_comptype->is_compatible_component_by_port(t_comptype)) {
// the 'mtc' clause of the referred definition is not compatible
// with that of the current scope (i.e. the referring definition)
p_loc.error("Mtc clause mismatch: A definition that runs on "
"component type `%s' cannot %s %s, which mtc clause is `%s'",
t_comptype->get_typename().c_str(), p_what,
p_ass->get_description().c_str(),
refd_comptype->get_typename().c_str());
}
}
}
void Scope::chk_system_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what, bool in_control_part)
{
// component type of the referred definition
Type *refd_comptype = p_ass->get_SystemType();
// definitions without 'system' can be called from anywhere
if (!refd_comptype) return;
if (in_control_part) {
p_loc.error("Function with mtc or system clause is not allowed in control part.");
return;
}
Type *t_comptype = get_mtc_system_comptype(true);
if (t_comptype) {
if (!refd_comptype->is_compatible_component_by_port(t_comptype)) {
// the 'system' clause of the referred definition is not compatible
// with that of the current scope (i.e. the referring definition)
p_loc.error("System clause mismatch: A definition with system "
"component type `%s' cannot %s %s, which system clause is `%s'",
t_comptype->get_typename().c_str(), p_what,
p_ass->get_description().c_str(),
refd_comptype->get_typename().c_str());
}
}
}
// =================================
// ===== Reference
......
......@@ -635,6 +635,18 @@ public:
* \a p_what contains "call" or "activate". */
void chk_runs_on_clause(Type *p_fat, const Location& p_loc,
const char *p_what);
/** Checks the 'mtc' clause of definition \a p_ass that it can
* be called from this scope unit. Parameters \a p_loc and \a
* p_what are used in error messages. \a p_what contains "call" or
* "activate". */
void chk_mtc_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what, bool in_control_part);
/** Checks the 'system' clause of definition \a p_ass that it can
* be called from this scope unit. Parameters \a p_loc and \a
* p_what are used in error messages. \a p_what contains "call" or
* "activate". */
void chk_system_clause(Assignment *p_ass, const Location& p_loc,
const char *p_what, bool in_control_part);
};
/**
......
......@@ -3695,6 +3695,73 @@ namespace Common {
}
}
}
bool Type::is_compatible_component_by_port(Type *p_type) {
chk();
p_type->chk();
Type *t1 = get_type_refd_last();
Type *t2 = p_type->get_type_refd_last();
if (t1->typetype != T_COMPONENT || t2->typetype != T_COMPONENT) {
return false;
}
ComponentTypeBody* b1 = t1->get_CompBody();
ComponentTypeBody* b2 = t2->get_CompBody();
// Does b2 contains every port with the same type and name as b1?
for (size_t i = 0; i < b1->get_nof_asss(); i++) {
Assignment * ass = b1->get_ass_byIndex(i);
if (ass->get_asstype() == Assignment::A_PORT) {
Type *port_type = ass->get_Type()->get_type_refd_last();
const Identifier& id = ass->get_id();
bool found = false;
for (size_t j = 0; j < b2->get_nof_asss(); j++) {
Assignment * ass2 = b2->get_ass_byIndex(j);
const Identifier& id2 = ass2->get_id();
if (id == id2 && ass2->get_asstype() == Assignment::A_PORT) {
Type *port_type2 = ass2->get_Type()->get_type_refd_last();
if (port_type != port_type2) {
return false;
} else {
found = true;
break;
}
}
}
if (!found) {
return false;
}
}
}
// Does b1 contains every port with the same type and name as b2?
for (size_t i = 0; i < b2->get_nof_asss(); i++) {
Assignment * ass = b2->get_ass_byIndex(i);
if (ass->get_asstype() == Assignment::A_PORT) {
Type *port_type = ass->get_Type()->get_type_refd_last();
const Identifier& id = ass->get_id();
bool found = false;
for (size_t j = 0; j < b1->get_nof_asss(); j++) {
Assignment * ass2 = b1->get_ass_byIndex(j);
const Identifier& id2 = ass2->get_id();
if (id == id2 && ass2->get_asstype() == Assignment::A_PORT) {
Type *port_type2 = ass2->get_Type()->get_type_refd_last();
if (port_type != port_type2) {
return false;
} else {
found = true;
break;
}
}
}
if (!found) {
return false;
}
}
}
return true;
}
bool Type::is_compatible(Type *p_type, TypeCompatInfo *p_info, Location* p_loc,
TypeChain *p_left_chain, TypeChain *p_right_chain,
......
......@@ -682,6 +682,9 @@ namespace Common {
TypeChain *p_left_chain = NULL,
TypeChain *p_right_chain = NULL,
bool p_is_inline_template = false);
/** Check if the port definitions of the component types are the same
*/
bool is_compatible_component_by_port(Type *p_type);
/** Check if the restrictions of a T_SEQOF/T_SETOF are "compatible" with
* the given type \a p_type. Can be called only as a T_SEQOF/T_SETOF.
* Currently, used for structured types only. \a p_type can be any kind
......
......@@ -5628,7 +5628,7 @@ void Type::chk_this_template_incorrect_field() {
case T_SET_T:
case T_OPENTYPE:
for (size_t i = 0; i < t->get_nof_comps(); i++) {
Error_Context cntxt(t->get_comp_byIndex(i), "In field `%s'", t->get_comp_byIndex(i)->get_name().get_dispname().c_str());
Error_Context cntxt2(t->get_comp_byIndex(i), "In field `%s'", t->get_comp_byIndex(i)->get_name().get_dispname().c_str());
t->get_comp_byIndex(i)->get_type()->chk_this_template_incorrect_field();
}
break;
......@@ -5646,7 +5646,7 @@ void Type::chk_this_template_incorrect_field() {
case Assignment::A_VAR_TEMPLATE: /**< template variable, dynamic template (TTCN-3) */
case Assignment::A_PORT: /**< port (TTCN-3) */
{
Error_Context cntxt(ass, "In field `%s'", ass->get_id().get_dispname().c_str());
Error_Context cntxt2(ass, "In field `%s'", ass->get_id().get_dispname().c_str());
ass->get_Type()->chk_this_template_incorrect_field();
}
default:
......
......@@ -6268,7 +6268,8 @@ namespace Ttcn {
// =================================
Def_Function::Def_Function(Identifier *p_id, FormalParList *p_fpl,
Reference *p_runs_on_ref, Reference *p_port_ref,
Reference *p_runs_on_ref, Reference *p_mtc_ref,
Reference *p_system_ref, Reference *p_port_ref,
Type *p_return_type,
bool returns_template,
template_restriction_t p_template_restriction,
......@@ -6276,6 +6277,8 @@ namespace Ttcn {
: Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
p_template_restriction),
runs_on_ref(p_runs_on_ref), runs_on_type(0),
mtc_ref(p_mtc_ref), mtc_type(0),
system_ref(p_system_ref), system_type(0),
port_ref(p_port_ref), port_type(0), block(p_block),
is_startable(false), transparent(false)
{
......@@ -6286,6 +6289,8 @@ namespace Ttcn {
Def_Function::~Def_Function()
{
delete runs_on_ref;
delete mtc_ref;
delete system_ref;
delete port_ref;
delete block;
}
......@@ -6299,6 +6304,8 @@ namespace Ttcn {
{
Def_Function_Base::set_fullname(p_fullname);
if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
if (mtc_ref) mtc_ref->set_fullname(p_fullname + ".<mtc_type>");
if (system_ref) system_ref->set_fullname(p_fullname + ".<system_type>");
if (port_ref) port_ref->set_fullname(p_fullname + ".<port_type>");
block->set_fullname(p_fullname + ".<statement_block>");
}
......@@ -6310,10 +6317,24 @@ namespace Ttcn {
Def_Function_Base::set_my_scope(&bridgeScope);
if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope);
if (mtc_ref) mtc_ref->set_my_scope(&bridgeScope);
if (system_ref) system_ref->set_my_scope(&bridgeScope);
if (port_ref) port_ref->set_my_scope(&bridgeScope);
block->set_my_scope(fp_list);
}
Type *Def_Function::get_MtcType()
{
if (!checked) chk();
return mtc_type;
}
Type *Def_Function::get_SystemType()
{
if (!checked) chk();
return system_type;
}
Type *Def_Function::get_RunsOnType()
{
if (!checked) chk();
......@@ -6362,6 +6383,17 @@ namespace Ttcn {
}
}
// checking the `mtc' clause
if (mtc_ref) {
Error_Context cntxt2(mtc_ref, "In `mtc' clause");
mtc_type = mtc_ref->chk_comptype_ref();
}
// checking the `system' clause
if (system_ref) {
Error_Context cntxt2(system_ref, "In `system' clause");
system_type = system_ref->chk_comptype_ref();
}
// checking the formal parameter list, the check must come before the
// chk_prototype() function call.
......@@ -7584,10 +7616,12 @@ namespace Ttcn {
// =================================
Def_Altstep::Def_Altstep(Identifier *p_id, FormalParList *p_fpl,
Reference *p_runs_on_ref, StatementBlock *p_sb,
Reference *p_runs_on_ref, Reference *p_mtc_ref,
Reference *p_system_ref, StatementBlock *p_sb,
AltGuards *p_ags)
: Definition(A_ALTSTEP, p_id), fp_list(p_fpl), runs_on_ref(p_runs_on_ref),
runs_on_type(0), sb(p_sb), ags(p_ags)
runs_on_type(0), mtc_ref(p_mtc_ref), mtc_type(0),
system_ref(p_system_ref), system_type(0), sb(p_sb), ags(p_ags)
{
if (!p_fpl || !p_sb || !p_ags)
FATAL_ERROR("Def_Altstep::Def_Altstep()");
......@@ -7601,6 +7635,8 @@ namespace Ttcn {
{
delete fp_list;
delete runs_on_ref;
delete mtc_ref;
delete system_ref;
delete sb;
delete ags;
}
......@@ -7615,6 +7651,8 @@ namespace Ttcn {
Definition::set_fullname(p_fullname);
fp_list->set_fullname(p_fullname + ".<formal_par_list>");
if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
if (mtc_ref) mtc_ref->set_fullname(p_fullname + ".<mtc_type>");
if (system_ref) system_ref->set_fullname(p_fullname + ".<system_type>");
sb->set_fullname(p_fullname+".<block>");
ags->set_fullname(p_fullname + ".<guards>");
}
......@@ -7627,6 +7665,8 @@ namespace Ttcn {
Definition::set_my_scope(&bridgeScope);
// the scope of the parameter list is set during checking
if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope);
if (mtc_ref) mtc_ref->set_my_scope(&bridgeScope);
if (system_ref) system_ref->set_my_scope(&bridgeScope);
sb->set_my_scope(fp_list);
ags->set_my_scope(sb);
}
......@@ -7636,6 +7676,18 @@ namespace Ttcn {
if (!checked) chk();
return runs_on_type;
}
Type *Def_Altstep::get_MtcType()
{
if (!checked) chk();
return mtc_type;
}
Type *Def_Altstep::get_SystemType()
{
if (!checked) chk();
return system_type;
}
FormalParList *Def_Altstep::get_FormalParList()
{
......@@ -7666,6 +7718,14 @@ namespace Ttcn {
parlist_scope = runs_on_scope;
}
}
if (mtc_ref) {
Error_Context cntxt2(mtc_ref, "In `mtc' clause");
mtc_type = mtc_ref->chk_comptype_ref();
}
if (system_ref) {
Error_Context cntxt2(system_ref, "In `system' clause");
system_type = system_ref->chk_comptype_ref();
}
fp_list->set_my_scope(parlist_scope);
fp_list->chk(asstype);
sb->chk();
......@@ -7832,6 +7892,14 @@ namespace Ttcn {
DEBUG(level + 1, "Runs on clause:");
runs_on_ref->dump(level + 2);
}
if (mtc_ref) {
DEBUG(level + 1, "Mtc clause:");
mtc_ref->dump(level + 2);
}
if (system_ref) {
DEBUG(level + 1, "System clause:");
system_ref->dump(level + 2);
}
/*
DEBUG(level + 1, "Local definitions:");
sb->dump(level + 2);
......
......@@ -1402,6 +1402,22 @@ namespace Ttcn {
* It is NULL if the function has no 'runs on' clause or \a runs_on_ref is
* erroneous. */
Type *runs_on_type;
/** The 'mtc' clause (i.e. a reference to a TTCN-3 component type)
* It is NULL if the function has no 'mtc' clause. */
Reference *mtc_ref;
/** Points to the object describing the component type referred by
* 'mtc' clause.
* It is NULL if the function has no 'mtc' clause or \a mtc_ref is
* erroneous. */
Type *mtc_type;
/** The 'system' clause (i.e. a reference to a TTCN-3 component type)
* It is NULL if the function has no 'system' clause. */
Reference *system_ref;
/** Points to the object describing the component type referred by
* 'system' clause.
* It is NULL if the function has no 'system' clause or \a system_ref is
* erroneous. */
Type *system_type;
/** The 'port' clause (i.e. a reference to a TTCN-3 port type)
* It is NULL if the function has no 'port' clause. */
Reference *port_ref;
......@@ -1433,6 +1449,8 @@ namespace Ttcn {
* @param p_id function name
* @param p_fpl formal parameter list
* @param p_runs_on_ref "runs on", else NULL
* @param p_mtc_ref "mtc", else NULL
* @param p_system_ref "system", else NULL
* @param p_port_ref "port", else NULL
* @param p_return_type return type, may be NULL
* @param returns_template true if the return value is a template
......@@ -1440,7 +1458,8 @@ namespace Ttcn {
* @param p_block the body of the function
*/
Def_Function(Identifier *p_id, FormalParList *p_fpl,
Reference *p_runs_on_ref, Reference *p_port_ref,
Reference *p_runs_on_ref, Reference *p_mtc_ref,
Reference *p_system_ref, Reference *p_port_ref,
Type *p_return_type,
bool returns_template,
template_restriction_t p_template_restriction,
......@@ -1450,6 +1469,8 @@ namespace Ttcn {
virtual void set_fullname(const string& p_fullname);
virtual void set_my_scope(Scope *p_scope);
virtual Type *get_RunsOnType();
virtual Type *get_MtcType();
virtual Type *get_SystemType();
virtual Type *get_PortType();
/** Returns a scope that can access the definitions within component type
* \a comptype and its parent is \a parent_scope.*/
......@@ -1586,6 +1607,22 @@ namespace Ttcn {
* It is NULL if the altstep has no 'runs on' clause or \a runs_on_ref is
* erroneous. */
Type *runs_on_type;
/** The 'mtc' clause (i.e. a reference to a TTCN-3 component type)
* It is NULL if the altstep has no 'mtc' clause. */
Reference *mtc_ref;
/** Points to the object describing the component type referred by
* 'mtc' clause.
* It is NULL if the altstep has no 'mtc' clause or \a mtc_ref is
* erroneous. */
Type *mtc_type;
/** The 'system' clause (i.e. a reference to a TTCN-3 component type)
* It is NULL if the altstep has no 'system' clause. */
Reference *system_ref;
/** Points to the object describing the component type referred by
* 'system' clause.
* It is NULL if the altstep has no 'system' clause or \a system_ref is
* erroneous. */
Type *system_type;
StatementBlock *sb; /**< contains the local definitions */
AltGuards *ags;
......@@ -1597,13 +1634,16 @@ namespace Ttcn {
Def_Altstep& operator=(const Def_Altstep& p);
public:
Def_Altstep(Identifier *p_id, FormalParList *p_fpl,
Reference *p_runs_on_ref, StatementBlock *p_sb,
Reference *p_runs_on_ref, Reference *p_mtc_ref,
Reference *p_system_ref, StatementBlock *p_sb,
AltGuards *p_ags);
virtual ~Def_Altstep();
virtual Def_Altstep *clone() const;
virtual void set_fullname(const string& p_fullname);
virtual void set_my_scope(Scope *p_scope);
virtual Type *get_RunsOnType();
virtual Type *get_MtcType();
virtual Type *get_SystemType();
virtual FormalParList *get_FormalParList();
/** Returns a scope that can access the definitions within component type
* \a comptype and its parent is \a parent_scope.*/
......
......@@ -3125,6 +3125,11 @@ error:
ref_pard->error("Function with `port' clause cannot be called directly.");
}
my_sb->chk_runs_on_clause(t_ass, *ref_pard, "call");
bool in_control_part = my_sb->get_my_def() == NULL;
my_sb->chk_mtc_clause(t_ass, *ref_pard, "call", in_control_part);
my_sb->chk_system_clause(t_ass, *ref_pard, "call", in_control_part);
if (t_ass->get_Type())
ref_pard->warning("The value returned by %s is not used",
t_ass->get_description().c_str());
......@@ -3375,6 +3380,9 @@ error:
Error_Context cntxt(this, "In altstep instance");
Common::Assignment *t_ass = ref_pard->get_refd_assignment();
my_sb->chk_runs_on_clause(t_ass, *ref_pard, "call");
bool in_control_part = my_sb->get_my_def() == NULL;
my_sb->chk_mtc_clause(t_ass, *ref_pard, "call", in_control_part);
my_sb->chk_system_clause(t_ass, *ref_pard, "call", in_control_part);
}
void Statement::chk_return()
......
......@@ -470,6 +470,11 @@ static const string anyname("anytype");
Ttcn::Reference *runsonref;
Ttcn::Reference *systemref;
} configspec;
struct {
Ttcn::Reference *mtcref;
Ttcn::Reference *systemref;
} alt_tc_configspec;
struct {
Value *name;
......@@ -1023,6 +1028,7 @@ static const string anyname("anytype");
%type <reference> PortType optDerivedDef DerivedDef IndexSpec Signature
VariableRef TimerRef Port PortOrAll ValueStoreSpec
SenderSpec ComponentType optRunsOnSpec RunsOnSpec optSystemSpec optPortSpec
optMtcSpec
%type <reference_or_any> PortOrAny TimerRefOrAny
%type <valuerange> Range
%type <type> NestedEnumDef NestedRecordDef NestedRecordOfDef NestedSetDef
......@@ -1089,6 +1095,7 @@ AllOrTypeListWithTo TypeListWithFrom TypeListWithTo
%type <reforid> Reference
%type <initial> Initial
%type <configspec> ConfigSpec
%type <alt_tc_configspec> AltOrTcConfigSpec
%type <createpar> optCreateParameter
%type <applyop> ApplyOp
%type <identifier_list> IdentifierList IdentifierListOrPredefType
......@@ -1442,6 +1449,7 @@ optExtendsDef
optFromClause
optFunctionActualParList
optFunctionFormalParList
optMtcSpec
optParDefaultValue
optPortCallBody
optReceiveParameter
......@@ -1745,6 +1753,12 @@ Initial
}
ConfigSpec
%destructor {
delete $$.mtcref;
delete $$.systemref;
}
AltOrTcConfigSpec
%destructor {
delete $$.name;
delete $$.loc;
......@@ -4175,11 +4189,11 @@ ValueofOp: // 162
FunctionDef: // 164
FunctionKeyword optDeterministicModifier IDentifier '(' optFunctionFormalParList ')'
optRunsOnSpec optPortSpec optReturnType optError StatementBlock
optRunsOnSpec AltOrTcConfigSpec optPortSpec optReturnType optError StatementBlock
{
$5->set_location(infile, @4, @6);
$$ = new Def_Function($3, $5, $7, $8, $9.type, $9.returns_template,
$9.template_restriction, $11);
$$ = new Def_Function($3, $5, $7, $8.mtcref, $8.systemref, $9, $10.type, $10.returns_template,
$10.template_restriction, $12);
$$->set_location(infile, @$);
}
;
......@@ -4664,12 +4678,26 @@ ConfigSpec: // 202
}
;
AltOrTcConfigSpec:
optMtcSpec optSystemSpec
{
$$.mtcref=$1;
$$.systemref=$2;
}
;
optSystemSpec: // [203]
/* empty */ { $$ = 0; }
| SystemKeyword ComponentType { $$ = $2; }
| SystemKeyword error { $$ = 0; }
;
optMtcSpec:
/* empty */ { $$ = 0; }
| MTCKeyword ComponentType { $$ = $2; }
| MTCKeyword error { $$ = 0; }
;
TestcaseInstance: // 205
ExecuteKeyword '(' TestcaseRef '(' optTestcaseActualParList ')'
optTestcaseTimerValue optError ')'
......@@ -4782,17 +4810,17 @@ TestcaseActualPar:
AltstepDef: // 211
AltstepKeyword IDentifier '(' optAltstepFormalParList ')' optRunsOnSpec
optError '{' AltstepLocalDefList AltGuardList optError '}'
AltOrTcConfigSpec optError '{' AltstepLocalDefList AltGuardList optError '}'
{
StatementBlock *sb = new StatementBlock;
for (size_t i = 0; i < $9.nElements; i++) {
Statement *stmt = new Statement(Statement::S_DEF, $9.elements[i]);
stmt->set_location(*$9.elements[i]);
for (size_t i = 0; i < $10.nElements; i++) {
Statement *stmt = new Statement(Statement::S_DEF, $10.elements[i]);
stmt->set_location(*$10.elements[i]);
sb->add_stmt(stmt);
}
Free($9.elements);
Free($10.elements);
$4->set_location(infile, @4);
$$ = new Def_Altstep($2, $4, $6, sb, $10);
$$ = new Def_Altstep($2, $4, $6, $7.mtcref, $7.systemref, sb, $11);
$$->set_location(infile, @$);
}
;
......
......@@ -13,7 +13,7 @@
#
##############################################################################
SADIRS := ver xer encode param template any_from pattern_ref float recof_index \
port_translation
port_translation mtc_and_system_clause
ifdef RT2
SADIRS += deprecated erroneous_attributes template_concat
endif
......
/******************************************************************************
* Copyright (c) 2000-2017 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials