Commit 64c877b2 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

OOP: classes embedded in structures - part 2 (issue #601)


Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 516715d2
......@@ -4309,6 +4309,11 @@ namespace Ttcn {
t->get_typename().c_str());
break;
default:
if (t->contains_class()) {
error("Constant cannot be defined for type `%s', which contains a class",
t->get_typename().c_str());
break;
}
if (value != NULL) {
value_under_check = true;
namedbool class_member_init = my_scope->is_class_scope() ?
......@@ -4641,10 +4646,6 @@ namespace Ttcn {
error("Type of module parameter cannot be signature `%s'",
t->get_fullname().c_str());
break;
case Type::T_CLASS:
error("Type of module parameter cannot be or embed class type `%s'",
t->get_typename().c_str());
break;
case Type::T_FUNCTION:
case Type::T_ALTSTEP:
case Type::T_TESTCASE:
......@@ -4657,6 +4658,10 @@ namespace Ttcn {
#if defined(MINGW)
checked = true;
#else
if (t->contains_class()) {
error("Type of module parameter cannot be or embed a class type");
break;
}
if (def_value) {
Error_Context cntxt2(def_value, "In default value");
def_value->set_my_governor(type);
......@@ -4821,11 +4826,11 @@ namespace Ttcn {
" `%s' which has runs on self clause", t->get_fullname().c_str());
}
break;
case Type::T_CLASS:
error("Type of template module parameter cannot be class type `%s'",
t->get_typename().c_str());
break;
default:
if (t->contains_class()) {
error("Type of template module parameter cannot be or embed a class type");
break;
}
if (IMPLICIT_OMIT == has_implicit_omit_attr()) {
error("Implicit omit not supported for template module parameters");
}
......@@ -5063,6 +5068,10 @@ namespace Ttcn {
error("Template cannot be defined for class type `%s'",
t->get_typename().c_str());
}
else if (t->contains_class()) {
error("Template cannot be defined for type `%s', which contains a class",
t->get_typename().c_str());
}
type->chk_this_template_incorrect_field();
chk_modified();
chk_recursive_derivation();
......@@ -5950,6 +5959,10 @@ namespace Ttcn {
error("Template variable cannot be defined for class type `%s'",
t->get_typename().c_str());
}
else if (t->contains_class()) {
error("Template variable cannot be defined for type `%s', which contains a class",
t->get_typename().c_str());
}
if (initial_value) {
initial_value->set_my_governor(type);
......@@ -9300,7 +9313,7 @@ namespace Ttcn {
LazyFuzzyParamData::clean();
}
else {
if (use_runtime_2 && fp->get_defpar_wrapper() == Common::Type::NO_DEFPAR_WRAPPER) {
if (use_runtime_2 && !fp->has_defpar_wrapper()) {
string tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id();
expr.preamble = mputprintf(expr.preamble, "%s %s;\n",
fp->get_Type()->get_genname_template(my_scope).c_str(), tmp_id.c_str());
......@@ -9775,7 +9788,7 @@ namespace Ttcn {
my_parlist->get_my_def()->get_asstype() == Definition::A_ALTSTEP) ||
// always shadow 'in' parameters of class type (to avoid having to deal
// with constant OBJECT_REFs at runtime)
(type != NULL && type->get_type_refd_last()->get_typetype() == Type::T_CLASS))) {
(type != NULL && type->contains_class()))) {
use_as_lvalue(*this);
}
break;
......@@ -10397,7 +10410,7 @@ namespace Ttcn {
else {
// update the genname so that all references in the generated code
// will point to the shadow object
if (eval == NORMAL_EVAL && get_defpar_wrapper() == Common::Type::NO_DEFPAR_WRAPPER) {
if (eval == NORMAL_EVAL && !has_defpar_wrapper()) {
set_genname(id->get_name() + "_shadow");
}
used_as_lvalue = true;
......@@ -10432,7 +10445,7 @@ namespace Ttcn {
return str;
}
Common::Type::defpar_wapper_t FormalPar::get_defpar_wrapper() const
bool FormalPar::has_defpar_wrapper() const
{
Definition* def = my_parlist->get_my_def();
if (defval.ap != NULL && def != NULL &&
......@@ -10440,27 +10453,20 @@ namespace Ttcn {
switch (asstype) {
case A_PAR_VAL_IN:
case A_PAR_TEMPL_IN:
return Common::Type::DEFPAR_IN_WRAPPER;
case A_PAR_VAL_OUT:
case A_PAR_VAL_INOUT:
case A_PAR_TEMPL_OUT:
case A_PAR_TEMPL_INOUT:
case A_PAR_TIMER:
case A_PAR_PORT:
return Common::Type::DEFPAR_OUT_WRAPPER;
return true;
default:
FATAL_ERROR("FormalPar::get_defpar_wrapper");
break;
}
}
return Common::Type::NO_DEFPAR_WRAPPER;
return false;
}
char* FormalPar::generate_code_defval(char* str)
{
if (!defval.ap || defval_generated) return str;
defval_generated = true;
Common::Type::defpar_wapper_t defpar_wrapper = get_defpar_wrapper();
if (!usage_found && defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER) {
bool defpar_wrapper = has_defpar_wrapper();
if (!usage_found && defpar_wrapper) {
return str;
}
switch (defval.ap->get_selection()) {
......@@ -10468,7 +10474,7 @@ namespace Ttcn {
Value *val = defval.ap->get_Value();
str = val->update_location_object(str);
string tmp_id;
if (defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER) {
if (defpar_wrapper) {
tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id();
str = mputprintf(str,
"%s %s;\n",
......@@ -10476,22 +10482,22 @@ namespace Ttcn {
val->set_gen_class_defpar_prefix();
}
if (use_runtime_2 && TypeConv::needs_conv_refd(val)) {
str = TypeConv::gen_conv_code_refd(str, defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER ?
str = TypeConv::gen_conv_code_refd(str, defpar_wrapper ?
tmp_id.c_str() : val->get_lhs_name().c_str(), val);
} else {
str = val->generate_code_init(str, defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER ?
str = val->generate_code_init(str, defpar_wrapper ?
tmp_id.c_str() : val->get_lhs_name().c_str());
}
if (defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER) {
if (defpar_wrapper) {
str = mputprintf(str, "def_val = %s;\n", tmp_id.c_str());
}
break; }
case ActualPar::AP_TEMPLATE: {
if (!use_runtime_2 || defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER) {
if (!use_runtime_2 || defpar_wrapper) {
TemplateInstance *ti = defval.ap->get_TemplateInstance();
str = ti->get_Template()->update_location_object(str);
string tmp_id;
if (defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER) {
if (defpar_wrapper) {
tmp_id = my_scope->get_scope_mod_gen()->get_temporary_id();
str = mputprintf(str,
"%s %s;\n",
......@@ -10499,10 +10505,10 @@ namespace Ttcn {
ti->set_gen_class_defpar_prefix();
}
str = generate_code_defval_template(str, ti,
defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER ?
defpar_wrapper ?
tmp_id : ti->get_Template()->get_lhs_name(),
defval.ap->get_gen_restriction_check());
if (defpar_wrapper != Common::Type::NO_DEFPAR_WRAPPER) {
if (defpar_wrapper) {
str = mputprintf(str, "def_val = %s;\n", tmp_id.c_str());
}
}
......@@ -10518,12 +10524,11 @@ namespace Ttcn {
char* FormalPar::generate_code_defpar_init(char* str)
{
if (defval.ap == NULL || !usage_found) return str;
Common::Type::defpar_wapper_t defpar_wrapper = get_defpar_wrapper();
switch (defval.ap->get_selection()) {
case ActualPar::AP_VALUE:
str = mputprintf(str,
"%s%s%s %s = %s_defpar(this);\n",
(defpar_wrapper == Common::Type::DEFPAR_IN_WRAPPER && !used_as_lvalue) ? "const " : "",
!used_as_lvalue ? "const " : "",
type->get_genname_value(my_scope).c_str(), !used_as_lvalue ? "&" : "",
id->get_name().c_str(), id->get_name().c_str());
// this code also works if the parameter is used as lvalue, no need for shadow objects
......@@ -10532,7 +10537,7 @@ namespace Ttcn {
case ActualPar::AP_TEMPLATE:
str = mputprintf(str,
"%s%s%s %s = %s_defpar(this);\n",
(defpar_wrapper == Common::Type::DEFPAR_IN_WRAPPER && !used_as_lvalue) ? "const " : "",
!used_as_lvalue ? "const " : "",
type->get_genname_template(my_scope).c_str(), !used_as_lvalue ? "&" : "",
id->get_name().c_str(), id->get_name().c_str());
// this code also works if the parameter is used as lvalue, no need for shadow objects
......@@ -10551,7 +10556,7 @@ namespace Ttcn {
if (!defval.ap) return;
Definition* def = my_parlist->get_my_def();
Scope* scope = def != NULL ? def->get_my_scope() : NULL;
bool defpar_wrapper = get_defpar_wrapper() != Common::Type::NO_DEFPAR_WRAPPER;
bool defpar_wrapper = has_defpar_wrapper();
switch (defval.ap->get_selection()) {
case ActualPar::AP_VALUE: {
Value *val = defval.ap->get_Value();
......@@ -10563,7 +10568,7 @@ namespace Ttcn {
Code::free_cdef(&cdef);
break; }
case ActualPar::AP_TEMPLATE: {
if (use_runtime_2 && defpar_wrapper == Common::Type::NO_DEFPAR_WRAPPER) {
if (use_runtime_2 && !defpar_wrapper) {
break;
}
TemplateInstance *ti = defval.ap->get_TemplateInstance();
......@@ -10589,7 +10594,7 @@ namespace Ttcn {
{
Definition* def = my_parlist->get_my_def();
Scope* scope = def != NULL ? def->get_my_scope() : NULL;
bool defpar_wrapper = get_defpar_wrapper() != Common::Type::NO_DEFPAR_WRAPPER;
bool defpar_wrapper = has_defpar_wrapper();
// the name of the parameter should not be displayed if the parameter is not
// used (to avoid a compiler warning)
bool display_name = (usage_found || display_unused || debugger_active ||
......@@ -11029,7 +11034,7 @@ namespace Ttcn {
case Common::Assignment::A_PAR_TEMPL_OUT:
if (is_startable &&
(par->get_Type()->is_component_internal() ||
(par->get_Type()->get_type_refd_last()->get_typetype() == Common::Type::T_CLASS))) {
(par->get_Type()->contains_class()))) {
is_startable = false;
}
break;
......@@ -11081,9 +11086,9 @@ namespace Ttcn {
Free(err_str);
}
if (!is_startable &&
par->get_Type()->get_type_refd_last()->get_typetype() == Common::Type::T_CLASS) {
par->get_Type()->contains_class()) {
caller_location->error("%s `%s' cannot be started on a parallel test component "
"because parameter `%s' is of a class type",
"because the type of parameter `%s' is or embeds a class type",
p_what, p_name, par->get_id().get_dispname().c_str());
}
break;
......@@ -11919,8 +11924,7 @@ namespace Ttcn {
}
}
if (val_expr.postamble == NULL) {
if (formal_par != NULL &&
formal_par->get_defpar_wrapper() != Common::Type::NO_DEFPAR_WRAPPER) {
if (formal_par != NULL && formal_par->has_defpar_wrapper()) {
expr_expr = mputprintf(expr_expr, "%s(%s)",
val->get_my_governor()->get_genname_value(my_scope).c_str(), val_expr.expr);
}
......@@ -12136,8 +12140,7 @@ namespace Ttcn {
LazyFuzzyParamData::generate_code_ap_default_ti(expr, act->temp, my_scope,
param_eval == LAZY_EVAL);
}
else if (use_runtime_2 && (formal_par == NULL ||
formal_par->get_defpar_wrapper() == Common::Type::NO_DEFPAR_WRAPPER)) {
else if (use_runtime_2 && (formal_par == NULL || !formal_par->has_defpar_wrapper())) {
// use the actual parameter's scope, not the formal parameter's
act->temp->set_my_scope(my_scope);
Template* temp_ = act->temp->get_Template();
......
......@@ -1983,7 +1983,7 @@ namespace Ttcn {
/** Returns whether a wrapper class is used for the formal parameter in the
* generated code.
* (Wrappers are used for class function parameters with default values.) */
Common::Type::defpar_wapper_t get_defpar_wrapper() const;
bool has_defpar_wrapper() const;
};
/** Class to represent a list of formal parameters. Owned by a
......
......@@ -3365,9 +3365,12 @@ namespace Ttcn {
case Definition::A_PAR_VAL_OUT:
case Definition::A_PAR_VAL_INOUT:
case Definition::A_PAR_TEMPL_OUT:
case Definition::A_PAR_TEMPL_INOUT:
// valid assignment types
break;
case Definition::A_PAR_TEMPL_INOUT: {
Common::Type* ref_type = refd_ass->get_Type()->get_type_refd_last();
if (ref_type->contains_class()) {
convert_op.ref->error("The type of the second parameter cannot be or embed a class type");
}
break; }
default:
convert_op.ref->error("Reference to '%s' cannot be used as the second parameter", refd_ass->get_assname());
goto error;
......
......@@ -1353,6 +1353,10 @@ namespace Ttcn {
t->error("Data type `%s' cannot be %s on a procedure based port",
t_last->get_typename().c_str(), err_msg);
}
if (t->contains_class()) {
t->error("Type `%s' is not a data type, since it is or contains a class, and cannot be "
"sent or received through a port", t->get_typename().c_str());
}
if (is_in) {
if (in_msgs && in_msgs->has_type(t_last)) {
const string& type_name = t_last->get_typename();
......@@ -4231,19 +4235,19 @@ namespace Ttcn {
par_type->get_genname_value(this);
local_struct->header.class_defs = mputprintf(local_struct->header.class_defs,
"class %s : public DEFPAR_%s_WRAPPER<%s> {\n" // 1
"class %s : public DEFPAR_WRAPPER<%s> {\n" // 1
"public:\n"
"%s(): DEFPAR_%s_WRAPPER<%s>() { }\n" // 2
"%s(%s%s& par): DEFPAR_%s_WRAPPER<%s>(par) { }\n" // 3
"%s(const %s& par): DEFPAR_%s_WRAPPER<%s>(par) { }\n" // 4
"%s%s& operator()(%s* p_class);\n" // 5
"};\n\n", defpar_list.get_nth_elem(i), in_par ? "IN" : "OUT", par_type_str.c_str(), // 1
defpar_list.get_nth_elem(i), in_par ? "IN" : "OUT", par_type_str.c_str(), // 2
defpar_list.get_nth_elem(i), in_par ? "const " : "", par_type_str.c_str(), // 3
in_par ? "IN" : "OUT", par_type_str.c_str(), // 3
"%s(): DEFPAR_WRAPPER<%s>() { }\n" // 2
"%s(const %s& par): DEFPAR_WRAPPER<%s>(par) { }\n" // 3
"%s(const %s& par): DEFPAR_WRAPPER<%s>(par) { }\n" // 4
"const %s& operator()(%s* p_class);\n" // 5
"};\n\n", defpar_list.get_nth_elem(i), par_type_str.c_str(), // 1
defpar_list.get_nth_elem(i), par_type_str.c_str(), // 2
defpar_list.get_nth_elem(i), par_type_str.c_str(), // 3
par_type_str.c_str(), // 3
defpar_list.get_nth_elem(i), defpar_list.get_nth_elem(i), // 4
in_par ? "IN" : "OUT", par_type_str.c_str(), // 4
in_par ? "const " : "", par_type_str.c_str(), class_id->get_name().c_str()); // 5
par_type_str.c_str(), // 4
par_type_str.c_str(), class_id->get_name().c_str()); // 5
local_struct->source.methods = mputprintf(local_struct->source.methods,
"%s%s& %s::operator()(%s* p_class)\n"
......
......@@ -411,27 +411,15 @@ public:
#endif // C++11
template<typename T>
class DEFPAR_IN_WRAPPER {
class DEFPAR_WRAPPER {
protected:
boolean def_;
T def_val;
const T& act_val;
public:
DEFPAR_IN_WRAPPER(): def_(TRUE), def_val(), act_val(def_val) { }
DEFPAR_IN_WRAPPER(const T& par): def_(FALSE), def_val(), act_val(par) { }
DEFPAR_IN_WRAPPER(const DEFPAR_IN_WRAPPER& par): def_(par.def_), def_val(), act_val(def_ ? def_val : par.act_val) { }
};
template<typename T>
class DEFPAR_OUT_WRAPPER {
protected:
boolean def_;
T dummy;
T& act_val;
public:
DEFPAR_OUT_WRAPPER(): def_(TRUE), dummy(), act_val(dummy) { }
DEFPAR_OUT_WRAPPER(T& par): def_(FALSE), dummy(), act_val(par) { }
DEFPAR_OUT_WRAPPER(const DEFPAR_OUT_WRAPPER& par): def_(par.def_), dummy(), act_val(par.act_val) { }
DEFPAR_WRAPPER(): def_(TRUE), def_val(), act_val(def_val) { }
DEFPAR_WRAPPER(const T& par): def_(FALSE), def_val(), act_val(par) { }
DEFPAR_WRAPPER(const DEFPAR_WRAPPER& par): def_(par.def_), def_val(), act_val(def_ ? def_val : par.act_val) { }
};
#endif /* OOP_HH */
......
......@@ -138,10 +138,10 @@ type class C9 extends C8 { } //^In type definition// //^In superclass or supertr
external const C0 ec_c0; //^In external constant definition// //External constant cannot be defined for class type `@oop_SE.C0'//
external const object ec_obj; //^In external constant definition// //External constant cannot be defined for class type `object'//
modulepar C0 mp_c0; //^In module parameter definition// //Type of module parameter cannot be or embed class type `@oop_SE.C0'//
modulepar object mp_obj; //^In module parameter definition// //Type of module parameter cannot be or embed class type `object'//
modulepar template C0 mpt_c0; //^In template module parameter definition// //Type of template module parameter cannot be class type `@oop_SE.C0'//
modulepar template object mpt_obj; //^In template module parameter definition// //Type of template module parameter cannot be class type `object'//
modulepar C0 mp_c0; //^In module parameter definition// //Type of module parameter cannot be or embed a class type//
modulepar object mp_obj; //^In module parameter definition// //Type of module parameter cannot be or embed a class type//
modulepar template C0 mpt_c0; //^In template module parameter definition// //Type of template module parameter cannot be or embed a class type//
modulepar template object mpt_obj; //^In template module parameter definition// //Type of template module parameter cannot be or embed a class type//
function f_defs() { //^In function definition//
const C0 c_c0 := null; //^In constant definition// //Constant cannot be defined for class type `@oop_SE.C0'//
......@@ -160,6 +160,11 @@ type record RecClass {
object y
}
type record RecClassOpt {
C0 x optional,
object y optional
}
type set SetClass {
C0 x,
object y
......@@ -175,14 +180,71 @@ type union UniClass {
C0 x,
object y
}
const RecClassOpt v_rec_opt := { } with { optional "implicit omit" }; //^In constant definition// //Constant cannot be defined for type `@oop_SE.RecClassOpt', which contains a class//
modulepar RecOfObject mp_recof; //^In module parameter definition// //Type of module parameter cannot be or embed a class type//
modulepar template SetOfObject mpt_setof; //^In template module parameter definition// //Type of template module parameter cannot be or embed a class type//
type port ClassPort message { //^In type definition//
inout C0, //^In `inout' list// //Type `@oop_SE.C0' is not a data type, since it is or contains a class, and cannot be sent or received through a port//
RecOfClass //Type `@oop_SE.RecOfClass' is not a data type, since it is or contains a class, and cannot be sent or received through a port//
}
with { extension "internal" };
type component CT_w_port {
port ClassPort pt;
}
function f_embedded_types() { //^In function definition//
function f_behavior(in RecClass p) runs on Comp { }
function f_embedded_types() runs on CT_w_port { //^In function definition//
var RecClass v_rec := { x := C0.create };
var SetClass v_set := { x := C0.create };
var RecOfClass v_recof := { C0.create };
var SetOfClass v_setof := { C0.create };
var UniClass v_uni := { x := C0.create };
var anytype v_any; //^In variable definition// //^In type definition//
const UniClass c_uni := { x := C0.create }; //^In constant definition// //Constant cannot be defined for type `@oop_SE.UniClass', which contains a class//
template SetOfClass t_setof := ?; //^In template definition// //Template cannot be defined for type `@oop_SE.SetOfClass', which contains a class//
var template RecClass vt_rec; //^In template variable definition// //Template variable cannot be defined for type `@oop_SE.RecClass', which contains a class//
log(sizeof(v_rec));
log(sizeof(v_recof));
string2ttcn("a", v_rec); //^In string2ttcn\(\) statement// //The type of the second parameter cannot be or embed a class type//
pt.send(v_recof);
var Comp v_comp := Comp.create;
v_comp.start(f_behavior(v_rec)); //^In start test component statement// //Function `@oop_SE.f_behavior' cannot be started on a parallel test component because the type of parameter `p' is or embeds a class type//
}
type record RecClassJson { //^In type definition// //Type `@oop_SE.RecClassJson' cannot have JSON encoding. Encode attribute ignored.//
C0 x
}
with {
encode "JSON";
}
type set SetClassRaw { //^In type definition// //Type `@oop_SE.SetClassRaw' cannot have RAW encoding. Encode attribute ignored.//
C0 x
}
with {
encode "RAW";
}
type record of C0 RecOfClassText //^In type definition// //Type `@oop_SE.RecOfClassText' cannot have TEXT encoding. Encode attribute ignored.//
with {
encode "TEXT"
}
type union UniClassXer { //^In type definition// //Type `@oop_SE.UniClassXer' cannot have XER encoding. Encode attribute ignored.//
C0 x
}
with {
encode "XML"
}
......@@ -558,7 +620,7 @@ function f_start_comp() { //^In function definition//
var C39 x := C39.create;
ct.start(x.f_def(1)); //^In start test component statement// //A method of a class cannot be started on a parallel test component//
ct.done;
ct.start(f_class_param(x)); //^In start test component statement// //Function `@oop_SE.f_class_param' cannot be started on a parallel test component because parameter `x' is of a class type//
ct.start(f_class_param(x)); //^In start test component statement// //Function `@oop_SE.f_class_param' cannot be started on a parallel test component because the type of parameter `x' is or embeds a class type//
ct.done;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment