Commit 0cbca390 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

Implemented object-oriented features - stage 2 (bug 552011)



Change-Id: I4ec993e1f59fcc92d9b4924eb2e8e078006176b5
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 1bbb9420
......@@ -83,7 +83,8 @@ namespace Common {
output->intervals.static_function_bodies = NULL;
}
output->temp.constructor_init = NULL;
output->temp.constructor = NULL;
output->temp.constructor_preamble = NULL;
output->temp.constructor_block = NULL;
}
void Code::merge_output(output_struct *dest, output_struct *src)
......@@ -180,7 +181,7 @@ namespace Common {
Free(output->intervals.static_conversion_function_bodies);
Free(output->intervals.static_function_bodies);
Free(output->temp.constructor_init);
Free(output->temp.constructor);
Free(output->temp.constructor_preamble);
init_output(output, TRUE);
}
......@@ -199,9 +200,9 @@ namespace Common {
header = mputstr(header, cdef->decl);
char*& source = in_class ? dest->temp.constructor_init : dest->source.global_vars;
source = mputstr(source, cdef->def);
char*& pre_init = in_class ? dest->temp.constructor : dest->functions.pre_init;
char*& pre_init = in_class ? dest->temp.constructor_preamble : dest->functions.pre_init;
pre_init = mputstr(pre_init, cdef->init);
char*& post_init = in_class ? dest->temp.constructor : dest->functions.post_init;
char*& post_init = in_class ? dest->temp.constructor_preamble : dest->functions.post_init;
post_init = mputstr(post_init, cdef->post);
}
......
......@@ -458,7 +458,6 @@ namespace Common {
{"bitand_", "bitand", "bitand"},
{"bitor_", "bitor", "bitor"},
{"bool_", "bool", "bool"},
{"class_", "class", "class"},
{"compl_", "compl", "compl"},
{"delete_", "delete", "delete"},
{"double_", "double", "double"},
......@@ -500,12 +499,14 @@ namespace Common {
{"case__", "case", "case_"},
{"catch__", "catch", "catch_"},
{"char__", "char", "char_"},
{"class__", "class", "class_"},
{"const__", "const", "const_"},
{"continue__", "continue", "continue_"},
{"default__", "default", "default_"},
{"do__", "do", "do_"},
{"else__", "else", "else_"},
{"false__", "false", "false_"},
{"finally__", "finally", "finally_"},
{"float__", "float", "float_"},
{"for__", "for", "for_"},
{"goto__", "goto", "goto_"},
......@@ -698,6 +699,7 @@ namespace Common {
{"INTEGER", "INTEGER", "integer"},
{"ISO646String", "ISO646String", 0},
{"NumericString", "NumericString", 0},
{"OBJECT", 0, "object"},
{"OBJID", "OBJECT IDENTIFIER", "objid"},
{"OCTETSTRING", "OCTET STRING", "octetstring"},
{"ObjectDescriptor", "ObjectDescriptor", 0},
......@@ -726,6 +728,7 @@ namespace Common {
{"INTEGER_", 0, "INTEGER"},
{"ISO646String_", 0, "ISO646String"},
{"NumericString_", 0, "NumericString"},
{"OBJECT_", "OBJECT", "OBJECT"},
{"OBJID_", "OBJID", "OBJID"},
{"OCTETSTRING_", "OCTETSTRING", "OCTETSTRING"},
{"ObjectDescriptor_", 0, "ObjectDescriptor"},
......
......@@ -749,6 +749,15 @@ namespace Ttcn {
ref_usage_found();
Common::Assignment *ass = get_refd_assignment();
if (!ass) FATAL_ERROR("Reference::generate_code()");
string const_prefix; // empty by default
if (gen_const_prefix) {
if (ass->get_asstype() == Common::Assignment::A_CONST) {
const_prefix = "const_";
}
else if (ass->get_asstype() == Common::Assignment::A_TEMPLATE) {
const_prefix = "template_";
}
}
if (parlist) {
// reference without parameters to a template that has only default formal parameters.
// if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
......@@ -761,7 +770,7 @@ namespace Ttcn {
expr->expr = mputstr(expr->expr,
LazyFuzzyParamData::in_lazy_or_fuzzy() ?
LazyFuzzyParamData::add_ref_genname(ass, my_scope).c_str() :
ass->get_genname_from_scope(my_scope).c_str());
(const_prefix + ass->get_genname_from_scope(my_scope)).c_str());
}
if (subrefs.get_nof_refs() > 0) subrefs.generate_code(expr, ass);
}
......@@ -1037,6 +1046,19 @@ namespace Ttcn {
if (ass && check_parlist && !params_checked) {
params_checked = true;
FormalParList *fplist = ass->get_FormalParList();
if (fplist == NULL && ass->get_asstype() == Common::Assignment::A_TYPE) {
Def_Type* def = dynamic_cast<Def_Type*>(ass);
if (def == NULL) {
FATAL_ERROR("Ref_pard::get_refd_assignment");
}
Type* type = def->get_Type();
if (type->get_typetype() == Common::Type::T_CLASS) {
// if the referred assignment is a class type, then the reference and
// its parameters are meant for the constructor instead
fplist = type->get_class_type_body()->get_constructor()->
get_FormalParList();
}
}
if (fplist) {
Error_Context cntxt(params, "In actual parameter list of %s",
ass->get_description().c_str());
......@@ -3491,7 +3513,7 @@ namespace Ttcn {
chk();
return type;
}
void Def_Type::chk()
{
if (checked) return;
......@@ -4843,7 +4865,7 @@ namespace Ttcn {
header = mputstr(header, cdef.decl);
char*& source = in_class ? target->temp.constructor_init : target->source.global_vars;
source = mputstr(source, cdef.def);
char*& init = in_class ? target->temp.constructor : target->functions.post_init;
char*& init = in_class ? target->temp.constructor_preamble : target->functions.post_init;
init = mputstr(init, cdef.init);
Code::free_cdef(&cdef);
}
......@@ -5109,7 +5131,7 @@ namespace Ttcn {
Code::merge_cdef(target, &cdef, in_class);
Code::free_cdef(&cdef);
if (initial_value) {
char*& init = in_class ? target->temp.constructor :
char*& init = in_class ? target->temp.constructor_preamble :
target->functions.init_comp;
init = initial_value->generate_code_init(init,
initial_value->get_lhs_name().c_str());
......@@ -5324,7 +5346,7 @@ namespace Ttcn {
Code::merge_cdef(target, &cdef, in_class);
Code::free_cdef(&cdef);
if (initial_value) {
char*& init = in_class ? target->temp.constructor :
char*& init = in_class ? target->temp.constructor_preamble :
target->functions.init_comp;
if (Common::Type::T_SEQOF == initial_value->get_my_governor()->get_typetype() ||
Common::Type::T_ARRAY == initial_value->get_my_governor()->get_typetype()) {
......@@ -5684,11 +5706,11 @@ namespace Ttcn {
bool in_class = my_scope->is_class_scope();
char*& header = in_class ? target->header.class_defs :
target->header.global_vars;
char*& source = in_class ? target->temp.constructor :
char*& source = in_class ? target->temp.constructor_preamble :
target->source.global_vars;
char*& pre_init = in_class ? target->temp.constructor :
char*& pre_init = in_class ? target->temp.constructor_preamble :
target->functions.pre_init;
char*& post_init = in_class ? target->temp.constructor :
char*& post_init = in_class ? target->temp.constructor_preamble :
target->functions.post_init;
if (dimensions) {
// timer array
......@@ -8490,6 +8512,8 @@ namespace Ttcn {
if (p_fp_list == NULL || block == NULL) {
FATAL_ERROR("Def_Constructor::Def_Constructor");
}
fp_list->set_my_def(this);
block->set_my_def(this);
}
Def_Constructor::~Def_Constructor()
......@@ -8499,7 +8523,7 @@ namespace Ttcn {
delete block;
}
Def_Constructor *Def_Constructor::clone() const
Def_Constructor* Def_Constructor::clone() const
{
FATAL_ERROR("Def_Constructor::clone");
}
......@@ -8516,13 +8540,14 @@ namespace Ttcn {
void Def_Constructor::set_my_scope(Scope* p_scope)
{
//bridgeScope.set_parent_scope(p_scope);
//bridgeScope.set_scopeMacro_name(id->get_dispname());
bridgeScope.set_parent_scope(p_scope);
bridgeScope.set_scopeMacro_name(id->get_dispname());
//Definition::set_my_scope(&bridgeScope);
Definition::set_my_scope(p_scope); // TODO
Definition::set_my_scope(&bridgeScope);
fp_list->set_my_scope(&bridgeScope);
if (base_call != NULL) {
base_call->set_my_scope(p_scope);
base_call->set_my_scope(fp_list);
}
block->set_my_scope(fp_list);
}
......@@ -8535,12 +8560,36 @@ namespace Ttcn {
void Def_Constructor::chk()
{
// TODO
if (checked) {
return;
}
checked = true;
Error_Context cntxt(this, "In constructor definition");
fp_list->chk(asstype);
if (base_call != NULL) {
Common::Assignment* base_type_ass = base_call->get_refd_assignment(true);
// TODO
}
block->chk();
if (!semantic_check_only) {
// prefix 'create' with the class name when forming parameter names
// to avoid collisions in the generated code
fp_list->set_genname(my_scope->get_scope_class()->get_id()->get_name() +
string("_") + get_genname());
block->set_code_section(GovernedSimple::CS_INLINE);
}
}
void Def_Constructor::generate_code(output_struct *target, bool clean_up)
{
// TODO
fp_list->generate_code_defval(target);
target->temp.constructor_block = block->generate_code(target->temp.constructor_block,
target->header.global_vars, target->source.global_vars);
}
void Def_Constructor::set_parent_path(WithAttribPath* p_path)
......@@ -8609,6 +8658,21 @@ namespace Ttcn {
FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
defval.ti = p_defval;
}
FormalPar::FormalPar(const FormalPar& p)
: Definition(p.asstype, p.id->clone()), type(p.type->clone()), my_parlist(0),
used_as_lvalue(false), template_restriction(p.template_restriction),
eval(p.eval), defval_generated(false), usage_found(false)
{
type->set_ownertype(Type::OT_FORMAL_PAR, this);
checked = p.checked;
if (checked) {
defval.ap = p.defval.ap != NULL ? p.defval.ap->clone() : NULL;
}
else {
defval.ti = p.defval.ti != NULL ? p.defval.ti->clone() : NULL;
}
}
FormalPar::~FormalPar()
{
......@@ -8619,7 +8683,7 @@ namespace Ttcn {
FormalPar* FormalPar::clone() const
{
FATAL_ERROR("FormalPar::clone");
return new FormalPar(*this);
}
void FormalPar::set_fullname(const string& p_fullname)
......@@ -9599,6 +9663,15 @@ namespace Ttcn {
// =================================
// ===== FormalParList
// =================================
FormalParList::FormalParList(const FormalParList& p)
: Scope(), Location(), pars_v(), pars_m(), min_nof_pars(0), my_def(0),
checked(false), is_startable(false)
{
for (size_t i = 0; i < p.pars_v.size(); ++i) {
add_fp(p.pars_v[i]->clone());
}
}
FormalParList::~FormalParList()
{
......@@ -9610,7 +9683,7 @@ namespace Ttcn {
FormalParList *FormalParList::clone() const
{
FATAL_ERROR("FormalParList::clone");
return new FormalParList(*this);
}
void FormalParList::set_fullname(const string& p_fullname)
......@@ -10313,6 +10386,31 @@ namespace Ttcn {
if (!a) FATAL_ERROR("ActualPar::ActualPar()");
act = a;
}
ActualPar::ActualPar(const ActualPar& p)
: Node(), selection(p.selection), my_scope(p.my_scope),
gen_restriction_check(p.gen_restriction_check),
gen_post_restriction_check(p.gen_post_restriction_check)
{
switch(selection) {
case AP_ERROR:
break;
case AP_VALUE:
val = p.val->clone();
break;
case AP_TEMPLATE:
temp = p.temp->clone();
break;
case AP_REF:
ref = p.ref->clone();
break;
case AP_DEFAULT:
act = p.act;
break;
default:
FATAL_ERROR("ActualPar::ActualPar()");
}
}
ActualPar::~ActualPar()
{
......@@ -10337,7 +10435,7 @@ namespace Ttcn {
ActualPar *ActualPar::clone() const
{
FATAL_ERROR("ActualPar::clone");
return new ActualPar(*this);
}
void ActualPar::set_fullname(const string& p_fullname)
......
......@@ -91,7 +91,7 @@ namespace Ttcn {
* runtime checks for out and inout parameters after the call */
template_restriction_t gen_post_restriction_check;
private:
/** Copy constructor not implemented */
/** Copy constructor */
ActualPar(const ActualPar& p);
/** %Assignment disabled */
ActualPar& operator=(const ActualPar& p);
......@@ -325,10 +325,11 @@ namespace Ttcn {
*/
class Reference : public Ref_base {
ActualParList *parlist;
bool gen_const_prefix;
public:
Reference(Identifier *p_id);
Reference(Identifier *p_modid, Identifier *p_id)
: Ref_base(p_modid, p_id), parlist(0) { }
: Ref_base(p_modid, p_id), parlist(0), gen_const_prefix(false) { }
~Reference();
virtual Reference *clone() const;
virtual void set_my_scope(Scope* p_scope);
......@@ -336,6 +337,7 @@ namespace Ttcn {
virtual Common::Assignment *get_refd_assignment(bool check_parlist = true);
virtual const Identifier* get_modid();
virtual const Identifier* get_id();
void set_gen_const_prefix() { gen_const_prefix = true; }
/** Checks whether \a this points to a variable or value parameter.
* Returns the type of the respective variable or variable field or NULL
* in case of error. */
......@@ -1751,7 +1753,7 @@ namespace Ttcn {
StatementBlock* block;
//NameBridgingScope bridgeScope;
NameBridgingScope bridgeScope;
/// Copy constructor disabled
Def_Constructor(const Def_Constructor& p);
......@@ -1764,7 +1766,8 @@ namespace Ttcn {
virtual Def_Constructor* clone() const;
virtual void set_fullname(const string& p_fullname);
virtual void set_my_scope(Scope* p_scope);
virtual FormalParList *get_FormalParList();
virtual FormalParList* get_FormalParList();
virtual Ref_pard* get_base_call() const { return base_call; }
virtual void chk();
virtual void generate_code(output_struct *target, bool clean_up = false);
virtual void set_parent_path(WithAttribPath* p_path);
......
......@@ -3248,6 +3248,10 @@ error:
void Statement::chk_assignment()
{
Error_Context cntxt(this, "In variable assignment");
Definition* sb_def = my_sb->get_my_def();
if (sb_def != NULL && sb_def->get_asstype() == Common::Assignment::A_CONSTRUCTOR) {
ass->set_in_contructor();
}
ass->chk();
}
......@@ -8754,14 +8758,16 @@ error:
Assignment::Assignment(Reference *p_ref, Template *p_templ)
: asstype(ASS_UNKNOWN), ref(p_ref), templ(p_templ), self_ref(false),
template_restriction(TR_NONE), gen_restriction_check(false)
template_restriction(TR_NONE), gen_restriction_check(false),
in_constructor(false)
{
if(!ref || !templ) FATAL_ERROR("Ttcn::Assignment::Assignment");
}
Assignment::Assignment(Reference *p_ref, Value *p_val)
: asstype(ASS_VAR), ref(p_ref), val(p_val), self_ref(false),
template_restriction(TR_NONE), gen_restriction_check(false)
template_restriction(TR_NONE), gen_restriction_check(false),
in_constructor(false)
{
if(!ref || !val) FATAL_ERROR("Ttcn::Assignment::Assignment");
}
......@@ -8863,6 +8869,14 @@ error:
case Common::Assignment::A_PAR_VAL_IN:
t_ass->use_as_lvalue(*ref);
// no break
case Common::Assignment::A_CONST:
if (t_ass->get_asstype() == Common::Assignment::A_CONST &&
!in_constructor) {
ref->error("Reference to a variable or template variable was expected "
"instead of %s", t_ass->get_description().c_str());
goto error;
}
// no break
case Common::Assignment::A_VAR:
case Common::Assignment::A_PAR_VAL_OUT:
case Common::Assignment::A_PAR_VAL_INOUT:
......@@ -8881,6 +8895,14 @@ error:
case Common::Assignment::A_PAR_TEMPL_IN:
t_ass->use_as_lvalue(*ref);
// no break
case Common::Assignment::A_TEMPLATE:
if (t_ass->get_asstype() == Common::Assignment::A_TEMPLATE &&
!in_constructor) {
ref->error("Reference to a variable or template variable was expected "
"instead of %s", t_ass->get_description().c_str());
goto error;
}
// no break
case Common::Assignment::A_VAR_TEMPLATE: {
Type::typetype_t tt = t_ass->get_Type()->get_typetype();
switch (tt) {
......@@ -9180,6 +9202,9 @@ error:
const char *type_genname_str = type_genname.c_str();
expression_struct expr;
Code::init_expr(&expr);
if (in_constructor) {
ref->set_gen_const_prefix();
}
ref->generate_code(&expr);
if (rhs_copied) {
......@@ -9218,6 +9243,9 @@ error:
// C++ equivalent of RHS is a single expression.
expression_struct expr;
Code::init_expr(&expr);
if (in_constructor) {
ref->set_gen_const_prefix();
}
ref->generate_code(&expr);// vu.s()
if (rhs_copied) {
str = mputprintf(str, "%s = %s;\n",
......@@ -9233,8 +9261,12 @@ error:
}
else {
// The LHS is a single identifier.
const string& rhs_name = ref->get_refd_assignment()
->get_genname_from_scope(ref->get_my_scope());
Common::Assignment* refd_ass = ref->get_refd_assignment();
string rhs_name = refd_ass->get_genname_from_scope(ref->get_my_scope());
if (in_constructor &&
refd_ass->get_asstype() == Common::Assignment::A_CONST) {
rhs_name = string("const_") + rhs_name;
}
if (val->can_use_increment(ref)) {
switch (val->get_optype()) {
case Value::OPTYPE_ADD:
......@@ -9275,6 +9307,9 @@ error:
const char *tmp_id_str = tmp_id.c_str();
expression_struct expr;
Code::init_expr(&expr);
if (in_constructor) {
ref->set_gen_const_prefix();
}
ref->generate_code(&expr);
if (rhs_copied) {
......@@ -9319,6 +9354,9 @@ error:
// check. Skipped if conversion needed.
expression_struct expr;
Code::init_expr(&expr);
if (in_constructor) {
ref->set_gen_const_prefix();
}
ref->generate_code(&expr);
if (rhs_copied) {
str = mputprintf(str, "%s = %s;\n",
......@@ -9336,8 +9374,12 @@ error:
}
else {
// LHS is a single identifier
const string& rhs_name = ref->get_refd_assignment()
->get_genname_from_scope(ref->get_my_scope());
Common::Assignment* refd_ass = ref->get_refd_assignment();
string rhs_name = refd_ass->get_genname_from_scope(ref->get_my_scope());
if (in_constructor &&
refd_ass->get_asstype() == Common::Assignment::A_TEMPLATE) {
rhs_name = string("template_") + rhs_name;
}
if (Common::Type::T_SEQOF == templ->get_my_governor()->get_typetype() ||
Common::Type::T_ARRAY == templ->get_my_governor()->get_typetype()) {
str = mputprintf(str, "%s.remove_all_permutations();\n", (rhs_copied ? rhs_copy : rhs_name).c_str());
......
......@@ -952,6 +952,7 @@ namespace Ttcn {
template_restriction_t template_restriction;
/** set in chk(), used by code generation */
bool gen_restriction_check;
bool in_constructor;
Assignment(const Assignment& p);
Assignment& operator=(const Assignment& p);
......@@ -965,6 +966,7 @@ namespace Ttcn {
virtual void set_my_scope(Scope *p_scope);
virtual void set_fullname(const string& p_fullname);
virtual void dump(unsigned int level) const;
void set_in_contructor() { in_constructor = true; }
private:
void chk_unknown_ass();
void chk_var_ass();
......
......@@ -24,6 +24,8 @@
#include "Attributes.hh"
#include <errno.h>
#include "Statement.hh"
#include "Templatestuff.hh"
#include "TtcnTemplate.hh"
// implemented in coding_attrib_p.y
extern Ttcn::ExtensionAttributes * parse_extattributes(
......@@ -2985,7 +2987,8 @@ namespace Ttcn {
Definitions* p_members, StatementBlock* p_finally_block)
: Scope(), Location(), class_id(p_class_id), external(p_external), final(p_final), abstract(p_abstract),
base_type(p_base_type), runs_on_ref(p_runs_on_ref), mtc_ref(p_mtc_ref), system_ref(p_system_ref),
members(p_members), finally_block(p_finally_block), checked(false)
members(p_members), finally_block(p_finally_block), constructor(NULL), checked(false),
default_constructor(false)
{
if (members == NULL) {
FATAL_ERROR("ClassTypeBody::ClassTypeBody");
......@@ -3004,6 +3007,8 @@ namespace Ttcn {
system_ref = p.system_ref != NULL ? p.system_ref->clone() : NULL;
members = p.members->clone();
finally_block = p.finally_block != NULL ? p.finally_block->clone() : NULL;
default_constructor = p.default_constructor;
constructor = default_constructor ? p.constructor->clone() : p.constructor;
checked = p.checked;
}
......@@ -3020,6 +3025,9 @@ namespace Ttcn {
delete mtc_ref;
delete runs_on_ref;
delete system_ref;
if (default_constructor) {
delete constructor;
}
}
void ClassTypeBody::set_fullname(const string& p_fullname)
......@@ -3058,10 +3066,10 @@ namespace Ttcn {
if (system_ref != NULL) {
system_ref->set_my_scope(p_scope);
}
//members->set_my_scope(p_scope);
/*if (finally_block != NULL) {
finally_block->set_my_scope(p_scope);
}*/
members->set_parent_scope(this);
if (finally_block != NULL) {
finally_block->set_parent_scope(this);
}
}
void ClassTypeBody::dump(unsigned level) const
......@@ -3088,6 +3096,12 @@ namespace Ttcn {
"Has" : "Doesn't have");
}
Def_Constructor* ClassTypeBody::get_constructor()
{
chk();
return constructor;
}
bool ClassTypeBody::is_parent_class(const ClassTypeBody* p_class) const
{
if (this == p_class) {
......@@ -3193,12 +3207,87 @@ namespace Ttcn {
// TODO
}
members->set_parent_scope(this);
members->chk_uniq();
members->chk();
for (size_t i = 0; i < members->get_nof_asss(); ++i) {
Common::Assignment* ass = members->get_ass_byIndex(i);
if (ass->get_asstype() == Common::Assignment::A_CONSTRUCTOR) {
// TODO: check for multiple constructors, or is that handled by previous checks?
constructor = dynamic_cast<Def_Constructor*>(ass);
if (constructor == NULL) {
FATAL_ERROR("ClassTypeBody::chk");
}
break;
}
}
if (constructor == NULL) {
// create a default constructor
Ref_pard* base_call = NULL;
FormalParList* fp_list = NULL;
if (base_type != NULL) {
ClassTypeBody* base_class = base_type->get_type_refd_last()->