Commit bb4951ea authored by BenceJanosSzabo's avatar BenceJanosSzabo
Browse files

Implement ports with translation capability (part4) port variables and port clause (Bug 512359)



Change-Id: I6596a91c1ea4a5f8ee0bbccb95788db17a92e47d
Signed-off-by: default avatarBenceJanosSzabo <bence.janos.szabo@ericsson.com>
parent 582847f5
...@@ -1927,6 +1927,11 @@ namespace Common { ...@@ -1927,6 +1927,11 @@ namespace Common {
{ {
return 0; return 0;
} }
Type *Assignment::get_PortType()
{
return 0;
}
void Assignment::chk_ttcn_id() void Assignment::chk_ttcn_id()
{ {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* Kovacs, Ferenc * Kovacs, Ferenc
* Raduly, Csaba * Raduly, Csaba
* Szabados, Kristof * Szabados, Kristof
* Szabo, Bence Janos
* Szabo, Janos Zoltan – initial implementation * Szabo, Janos Zoltan – initial implementation
* Szalai, Gabor * Szalai, Gabor
* Zalanyi, Balazs Andor * Zalanyi, Balazs Andor
...@@ -588,6 +589,9 @@ namespace Common { ...@@ -588,6 +589,9 @@ namespace Common {
/** Returns the component type referred by the 'runs on' clause of a /** Returns the component type referred by the 'runs on' clause of a
* TTCN-3 definition */ * TTCN-3 definition */
virtual Type *get_RunsOnType(); virtual Type *get_RunsOnType();
/** Returns the port type referred by the 'port' clause of a
* TTCN-3 function definition */
virtual Type *get_PortType();
/** Semantic check */ /** Semantic check */
virtual void chk() = 0; virtual void chk() = 0;
/** Checks whether the assignment has a valid TTCN-3 identifier, /** Checks whether the assignment has a valid TTCN-3 identifier,
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* Kovacs, Ferenc * Kovacs, Ferenc
* Raduly, Csaba * Raduly, Csaba
* Szabados, Kristof * Szabados, Kristof
* Szabo, Bence Janos
* Szabo, Janos Zoltan – initial implementation * Szabo, Janos Zoltan – initial implementation
* Tatarka, Gabor * Tatarka, Gabor
* *
...@@ -571,6 +572,12 @@ namespace Common { ...@@ -571,6 +572,12 @@ namespace Common {
if (parent_scope) return parent_scope->get_scope_runs_on(); if (parent_scope) return parent_scope->get_scope_runs_on();
else return 0; else return 0;
} }
Ttcn::PortScope *Scope::get_scope_port()
{
if (parent_scope) return parent_scope->get_scope_port();
else return 0;
}
Assignments *Scope::get_scope_asss() Assignments *Scope::get_scope_asss()
{ {
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
* Kovacs, Ferenc * Kovacs, Ferenc
* Raduly, Csaba * Raduly, Csaba
* Szabados, Kristof * Szabados, Kristof
* Szabo, Bence Janos
* Szabo, Janos Zoltan – initial implementation * Szabo, Janos Zoltan – initial implementation
* Tatarka, Gabor * Tatarka, Gabor
* Zalanyi, Balazs Andor * Zalanyi, Balazs Andor
...@@ -55,6 +56,7 @@ namespace Ttcn { ...@@ -55,6 +56,7 @@ namespace Ttcn {
class FieldOrArrayRefs; class FieldOrArrayRefs;
class ActualParList; class ActualParList;
class RunsOnScope; class RunsOnScope;
class PortScope;
class StatementBlock; class StatementBlock;
struct ErroneousDescriptor; struct ErroneousDescriptor;
class ErroneousDescriptors; class ErroneousDescriptors;
...@@ -597,6 +599,9 @@ public: ...@@ -597,6 +599,9 @@ public:
/** Returns the scope unit of the hierarchy that belongs to a /** Returns the scope unit of the hierarchy that belongs to a
* 'runs on' clause. */ * 'runs on' clause. */
virtual Ttcn::RunsOnScope *get_scope_runs_on(); virtual Ttcn::RunsOnScope *get_scope_runs_on();
/** Returns the scope unit of the hierarchy that belongs to a
* 'port' clause. */
virtual Ttcn::PortScope *get_scope_port();
/** Returns the assignments/module definitions scope. */ /** Returns the assignments/module definitions scope. */
virtual Assignments *get_scope_asss(); virtual Assignments *get_scope_asss();
/** Gets the module scope. This function returns this scope or a /** Gets the module scope. This function returns this scope or a
......
...@@ -4556,7 +4556,7 @@ namespace Common { ...@@ -4556,7 +4556,7 @@ namespace Common {
maps = encode ? maps : inmaps; maps = encode ? maps : inmaps;
maps->set_my_scope(this->get_my_scope()); maps->set_my_scope(this->get_my_scope());
// The first param should be true, the other is not important if the first is true // The first param should be true, the other is not important if the first is true
maps->chk(true, false); maps->chk(this, true, false);
// look for coding settings // look for coding settings
t = encode ? this : Type::get_pooltype(T_BSTR); t = encode ? this : Type::get_pooltype(T_BSTR);
mapping = maps->get_mapping_byType(t); mapping = maps->get_mapping_byType(t);
......
...@@ -259,6 +259,7 @@ namespace Common { ...@@ -259,6 +259,7 @@ namespace Common {
OT_OCFT, ///< another Type (T_OCFT), ASN.1 obj.class field type OT_OCFT, ///< another Type (T_OCFT), ASN.1 obj.class field type
OT_TEMPLATE_INST, ///< a TemplateInstance (TTCN-3) OT_TEMPLATE_INST, ///< a TemplateInstance (TTCN-3)
OT_RUNSON_SCOPE, ///< a RunsOnScope (TTCN-3) OT_RUNSON_SCOPE, ///< a RunsOnScope (TTCN-3)
OT_PORT_SCOPE, ///< a port scope
OT_EXC_SPEC, ///< exception Specification (ExcSpec) OT_EXC_SPEC, ///< exception Specification (ExcSpec)
OT_SIG_PAR, ///< signature parameter (SignatureParam) OT_SIG_PAR, ///< signature parameter (SignatureParam)
OT_POOL ///< It's a pool type, owned by the type pool OT_POOL ///< It's a pool type, owned by the type pool
......
...@@ -1212,6 +1212,77 @@ namespace Ttcn { ...@@ -1212,6 +1212,77 @@ namespace Ttcn {
|| parent_scope->has_ass_withId(p_id); || parent_scope->has_ass_withId(p_id);
} }
// =================================
// ===== PortScope
// =================================
PortScope::PortScope(Type *p_porttype)
: Scope(), port_type(p_porttype)
{
if (!p_porttype || p_porttype->get_typetype() != Type::T_PORT)
FATAL_ERROR("PortScope::PortScope()");
port_type->set_ownertype(Type::OT_PORT_SCOPE, this);
PortTypeBody* ptb = p_porttype->get_PortBody();
if (!ptb)
FATAL_ERROR("PortScope::PortScope()");
vardefs = ptb->get_vardefs();
set_scope_name("port `" + p_porttype->get_fullname() + "'");
}
PortScope *PortScope::clone() const
{
FATAL_ERROR("PortScope::clone()");
}
void PortScope::chk_uniq()
{
if (!vardefs) return;
if (vardefs->get_nof_asss() == 0) return;
// do not perform this check if the port type is defined in the same
// module as the 'port' clause
if (parent_scope->get_scope_mod() == vardefs->get_scope_mod())
return;
size_t nof_defs = vardefs->get_nof_asss();
for (size_t i = 0; i < nof_defs; i++) {
Common::Assignment *vardef = vardefs->get_ass_byIndex(i);
const Identifier& id = vardef->get_id();
if (parent_scope->has_ass_withId(id)) {
vardef->warning("Imported port element definition `%s' hides a "
"definition at module scope", vardef->get_fullname().c_str());
Reference ref(0, id.clone());
Common::Assignment *hidden_ass = parent_scope->get_ass_bySRef(&ref);
hidden_ass->warning("Hidden definition `%s' is here",
hidden_ass->get_fullname().c_str());
}
}
}
PortScope *PortScope::get_scope_port()
{
return this;
}
Common::Assignment *PortScope::get_ass_bySRef(Ref_simple *p_ref)
{
if (!p_ref) FATAL_ERROR("Ttcn::PortScope::get_ass_bySRef()");
if (p_ref->get_modid()) return parent_scope->get_ass_bySRef(p_ref);
else {
const Identifier& id = *p_ref->get_id();
if (vardefs->has_local_ass_withId(id)) {
Common::Assignment* ass = vardefs->get_local_ass_byId(id);
if (!ass) FATAL_ERROR("Ttcn::PortScope::get_ass_bySRef()");
return ass;
} else return parent_scope->get_ass_bySRef(p_ref);
}
}
bool PortScope::has_ass_withId(const Identifier& p_id)
{
return vardefs->has_ass_withId(p_id)
|| parent_scope->has_ass_withId(p_id);
}
// ================================= // =================================
// ===== FriendMod // ===== FriendMod
// ================================= // =================================
...@@ -2238,6 +2309,9 @@ namespace Ttcn { ...@@ -2238,6 +2309,9 @@ namespace Ttcn {
for (size_t i = 0; i < runs_on_scopes.size(); i++) for (size_t i = 0; i < runs_on_scopes.size(); i++)
delete runs_on_scopes[i]; delete runs_on_scopes[i];
runs_on_scopes.clear(); runs_on_scopes.clear();
for (size_t i = 0; i < port_scopes.size(); i++)
delete port_scopes[i];
port_scopes.clear();
delete w_attrib_path; delete w_attrib_path;
} }
...@@ -2766,7 +2840,15 @@ namespace Ttcn { ...@@ -2766,7 +2840,15 @@ namespace Ttcn {
ret_val->chk_uniq(); ret_val->chk_uniq();
return ret_val; return ret_val;
} }
PortScope *Module::get_port_scope(Type *porttype)
{
PortScope *ret_val = new PortScope(porttype);
port_scopes.add(ret_val);
ret_val->set_parent_scope(asss);
ret_val->chk_uniq();
return ret_val;
}
void Module::dump(unsigned level) const void Module::dump(unsigned level) const
{ {
...@@ -6178,13 +6260,15 @@ namespace Ttcn { ...@@ -6178,13 +6260,15 @@ namespace Ttcn {
// ================================= // =================================
Def_Function::Def_Function(Identifier *p_id, FormalParList *p_fpl, Def_Function::Def_Function(Identifier *p_id, FormalParList *p_fpl,
Reference *p_runs_on_ref, Type *p_return_type, Reference *p_runs_on_ref, Reference *p_port_ref,
Type *p_return_type,
bool returns_template, bool returns_template,
template_restriction_t p_template_restriction, template_restriction_t p_template_restriction,
StatementBlock *p_block) StatementBlock *p_block)
: Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template, : Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
p_template_restriction), p_template_restriction),
runs_on_ref(p_runs_on_ref), runs_on_type(0), block(p_block), runs_on_ref(p_runs_on_ref), runs_on_type(0),
port_ref(p_port_ref), port_type(0), block(p_block),
is_startable(false), transparent(false) is_startable(false), transparent(false)
{ {
if (!p_block) FATAL_ERROR("Def_Function::Def_Function()"); if (!p_block) FATAL_ERROR("Def_Function::Def_Function()");
...@@ -6194,6 +6278,7 @@ namespace Ttcn { ...@@ -6194,6 +6278,7 @@ namespace Ttcn {
Def_Function::~Def_Function() Def_Function::~Def_Function()
{ {
delete runs_on_ref; delete runs_on_ref;
delete port_ref;
delete block; delete block;
} }
...@@ -6206,6 +6291,7 @@ namespace Ttcn { ...@@ -6206,6 +6291,7 @@ namespace Ttcn {
{ {
Def_Function_Base::set_fullname(p_fullname); Def_Function_Base::set_fullname(p_fullname);
if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>"); if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
if (port_ref) port_ref->set_fullname(p_fullname + ".<port_type>");
block->set_fullname(p_fullname + ".<statement_block>"); block->set_fullname(p_fullname + ".<statement_block>");
} }
...@@ -6216,6 +6302,7 @@ namespace Ttcn { ...@@ -6216,6 +6302,7 @@ namespace Ttcn {
Def_Function_Base::set_my_scope(&bridgeScope); Def_Function_Base::set_my_scope(&bridgeScope);
if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope); if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope);
if (port_ref) port_ref->set_my_scope(&bridgeScope);
block->set_my_scope(fp_list); block->set_my_scope(fp_list);
} }
...@@ -6224,6 +6311,12 @@ namespace Ttcn { ...@@ -6224,6 +6311,12 @@ namespace Ttcn {
if (!checked) chk(); if (!checked) chk();
return runs_on_type; return runs_on_type;
} }
Type *Def_Function::get_PortType()
{
if (!checked) chk();
return port_type;
}
RunsOnScope *Def_Function::get_runs_on_scope(Type *comptype) RunsOnScope *Def_Function::get_runs_on_scope(Type *comptype)
{ {
...@@ -6232,12 +6325,23 @@ namespace Ttcn { ...@@ -6232,12 +6325,23 @@ namespace Ttcn {
return my_module->get_runs_on_scope(comptype); return my_module->get_runs_on_scope(comptype);
} }
PortScope *Def_Function::get_port_scope(Type *porttype)
{
Module *my_module = dynamic_cast<Module*>(my_scope->get_scope_mod());
if (!my_module) FATAL_ERROR("Def_Function::get_port_scope()");
return my_module->get_port_scope(porttype);
}
void Def_Function::chk() void Def_Function::chk()
{ {
if (checked) return; if (checked) return;
checked = true; checked = true;
Error_Context cntxt(this, "In function definition `%s'", Error_Context cntxt(this, "In function definition `%s'",
id->get_dispname().c_str()); id->get_dispname().c_str());
// `runs on' clause and `port' clause are mutually exclusive
if (runs_on_ref && port_ref) {
runs_on_ref->error("A `runs on' and a `port' clause cannot be present at the same time.");
}
// checking the `runs on' clause // checking the `runs on' clause
if (runs_on_ref) { if (runs_on_ref) {
Error_Context cntxt2(runs_on_ref, "In `runs on' clause"); Error_Context cntxt2(runs_on_ref, "In `runs on' clause");
...@@ -6249,39 +6353,7 @@ namespace Ttcn { ...@@ -6249,39 +6353,7 @@ namespace Ttcn {
fp_list->set_my_scope(runs_on_scope); fp_list->set_my_scope(runs_on_scope);
} }
} }
// checking the formal parameter list
fp_list->chk(asstype);
// checking of return type
if (return_type) {
Error_Context cntxt2(return_type, "In return type");
return_type->chk();
return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL,"function");
}
// decision of startability
is_startable = runs_on_ref != 0;
if (is_startable && !fp_list->get_startability()) is_startable = false;
if (is_startable && return_type && return_type->is_component_internal())
is_startable = false;
// checking of statement block
block->chk();
if (return_type) {
// checking the presence of return statements
switch (block->has_return()) {
case StatementBlock::RS_NO:
error("The function has return type, but it does not have any return "
"statement");
break;
case StatementBlock::RS_MAYBE:
error("The function has return type, but control might leave it "
"without reaching a return statement");
default:
break;
}
}
if (!semantic_check_only) {
fp_list->set_genname(get_genname());
block->set_code_section(GovernedSimple::CS_INLINE);
}
if (w_attrib_path) { if (w_attrib_path) {
w_attrib_path->chk_global_attrib(); w_attrib_path->chk_global_attrib();
w_attrib_path->chk_no_qualif(); w_attrib_path->chk_no_qualif();
...@@ -6325,8 +6397,65 @@ namespace Ttcn { ...@@ -6325,8 +6397,65 @@ namespace Ttcn {
} }
} }
chk_prototype(); chk_prototype();
// checking the `port' clause
if (port_ref) {
Error_Context cntxt2(port_ref, "In `port' clause");
Assignment *ass = port_ref->get_refd_assignment();
if (ass) {
port_type = ass->get_Type();
if (port_type) {
switch (port_type->get_typetype()) {
case Type::T_PORT: {
Scope *port_scope = get_port_scope(port_type);
port_scope->set_parent_scope(my_scope);
fp_list->set_my_scope(port_scope);
break; }
default:
port_ref->error(
"Reference `%s' does not refer to a port type.",
port_ref->get_dispname().c_str());
}
} else {
FATAL_ERROR("Def_Function::chk()");
}
}
}
// checking the formal parameter list
fp_list->chk(asstype);
// checking of return type
if (return_type) {
Error_Context cntxt2(return_type, "In return type");
return_type->chk();
return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL,"function");
}
// decision of startability
is_startable = runs_on_ref != 0;
if (is_startable && !fp_list->get_startability()) is_startable = false;
if (is_startable && return_type && return_type->is_component_internal())
is_startable = false;
// checking of statement block
block->chk();
if (return_type) {
// checking the presence of return statements
switch (block->has_return()) {
case StatementBlock::RS_NO:
error("The function has return type, but it does not have any return "
"statement");
break;
case StatementBlock::RS_MAYBE:
error("The function has return type, but control might leave it "
"without reaching a return statement");
default:
break;
}
}
if (!semantic_check_only) {
fp_list->set_genname(get_genname());
block->set_code_section(GovernedSimple::CS_INLINE);
}
} }
bool Def_Function::chk_startable() bool Def_Function::chk_startable()
{ {
if (!checked) chk(); if (!checked) chk();
...@@ -6346,8 +6475,14 @@ namespace Ttcn { ...@@ -6346,8 +6475,14 @@ namespace Ttcn {
return false; return false;
} }
void Def_Function::generate_code(output_struct *target, bool) void Def_Function::generate_code(output_struct *target, bool clean_up)
{ {
// Functions with 'port' clause are generated into the port type's class def
// Reuse of clean_up variable to allow or disallow the generation.
// clean_up is true when it is called from PortTypeBody::generate_code())
if (port_type && !clean_up) {
return;
}
transparency_holder glass(*this); transparency_holder glass(*this);
const string& t_genname = get_genname(); const string& t_genname = get_genname();
const char *genname_str = t_genname.c_str(); const char *genname_str = t_genname.c_str();
...@@ -6384,15 +6519,21 @@ namespace Ttcn { ...@@ -6384,15 +6519,21 @@ namespace Ttcn {
fp_list->generate_code_defval(target); fp_list->generate_code_defval(target);
// function prototype // function prototype
target->header.function_prototypes = target->header.function_prototypes =
mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n", mputprintf(target->header.function_prototypes, "%s%s %s(%s);\n",
get_PortType() && clean_up ? "" : "extern ",
return_type_str, genname_str, formal_par_list); return_type_str, genname_str, formal_par_list);
// function body // function body
target->source.function_bodies = mputprintf(target->source.function_bodies, target->source.function_bodies = mputprintf(target->source.function_bodies,
"%s %s(%s)\n" "%s %s%s%s%s(%s)\n"
"{\n" "{\n"
"%s" "%s"
"}\n\n", return_type_str, genname_str, formal_par_list, body); "}\n\n",
return_type_str,
port_type && clean_up ? port_type->get_genname_own().c_str() : "",
port_type && clean_up && port_type->get_PortBody()->get_testport_type() != PortTypeBody::TP_INTERNAL ? "_BASE" : "",
port_type && clean_up ? "::" : "",
genname_str, formal_par_list, body);
Free(formal_par_list); Free(formal_par_list);
Free(body); Free(body);
......
...@@ -457,6 +457,37 @@ namespace Ttcn { ...@@ -457,6 +457,37 @@ namespace Ttcn {
virtual Common::Assignment *get_ass_bySRef(Ref_simple *p_ref); virtual Common::Assignment *get_ass_bySRef(Ref_simple *p_ref);
virtual bool has_ass_withId(const Identifier& p_id); virtual bool has_ass_withId(const Identifier& p_id);
}; };
/**
* Class Ttcn::PortScope.
* Implements the scoping rules for functions that
* have a 'port' clause. First looks for the variable definitions in the given
* port type first then it searches in its parent scope.
* Note: This scope unit cannot access the parent scope of the port type.
*/
class PortScope : public Scope {
/** Points to the port type. */
Type *port_type;
/** Shortcut to the definitions within \a port_type. */
Definitions *vardefs;
/** Not implemented. Causes \a FATAL_ERROR. */
PortScope(const PortScope& p);
/** %Assignment not implemented */
PortScope& operator=(const PortScope& p);
public:
PortScope(Type *p_porttype);
virtual PortScope *clone() const;
Type *get_port_type() const { return port_type; }
/** Checks the uniqueness of definitions within \a portdefs and
* reports warnings in case of hiding. */
void chk_uniq();
virtual PortScope *get_scope_port();
virtual Common::Assignment *get_ass_bySRef(Ref_simple *p_ref);
virtual bool has_ass_withId(const Identifier& p_id);
};
/** /**
* Class Ttcn::Definitions. * Class Ttcn::Definitions.
...@@ -599,8 +630,9 @@ namespace Ttcn { ...@@ -599,8 +630,9 @@ namespace Ttcn {
Imports *imp; Imports *imp;
ControlPart* controlpart; ControlPart* controlpart;
/** For caching the scope objects that are created in /** For caching the scope objects that are created in
* \a get_runs_on_scope(). */ * \a get_runs_on_scope() and get_port_scope(). */
vector<RunsOnScope> runs_on_scopes; vector<RunsOnScope> runs_on_scopes;
vector<PortScope> port_scopes;
private: private:
/** Copy constructor not implemented */ /** Copy constructor not implemented */
Module(const Module& p); Module(const Module& p);
...@@ -638,6 +670,10 @@ namespace Ttcn { ...@@ -638,6 +670,10 @@ namespace Ttcn {
* object has been created for a component type it will be returned later * object has been created for a component type it will be returned later
* instead of creating a new one. */ * instead of creating a new one. */
RunsOnScope *get_runs_on_scope(Type *comptype); RunsOnScope *get_runs_on_scope(Type *comptype);
/* The same as get_runs_on_scope except that the returned scope can access