Commit 95745b3f authored by Botond Baranyi's avatar Botond Baranyi
Browse files

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



Change-Id: Id2222ae91a23b3934e7c175aa163a3eec6f72cad
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 9e81b2d8
......@@ -525,6 +525,7 @@ namespace Common {
A_EXT_FUNCTION_RTEMP, /**< ext. func that returns a template (TTCN-3) */
A_ALTSTEP, /**< altstep (TTCN-3) */
A_TESTCASE, /**< testcase (TTCN-3) */
A_CONSTRUCTOR, /**< constructor (TTCN-3) */
A_PAR_VAL, /**< formal parameter (value) (TTCN-3) */
A_PAR_VAL_IN, /**< formal parameter (in value) (TTCN-3) */
A_PAR_VAL_OUT, /**< formal parameter (out value) (TTCN-3) */
......
......@@ -82,6 +82,8 @@ namespace Common {
output->intervals.static_conversion_function_bodies = NULL;
output->intervals.static_function_bodies = NULL;
}
output->temp.constructor_init = NULL;
output->temp.constructor = NULL;
}
void Code::merge_output(output_struct *dest, output_struct *src)
......@@ -177,6 +179,8 @@ namespace Common {
Free(output->intervals.function_bodies);
Free(output->intervals.static_conversion_function_bodies);
Free(output->intervals.static_function_bodies);
Free(output->temp.constructor_init);
Free(output->temp.constructor);
init_output(output, TRUE);
}
......@@ -189,12 +193,16 @@ namespace Common {
cdef->post = NULL;
}
void Code::merge_cdef(output_struct *dest, const_def *cdef)
void Code::merge_cdef(output_struct *dest, const_def *cdef, boolean in_class)
{
dest->header.global_vars = mputstr(dest->header.global_vars, cdef->decl);
dest->source.global_vars = mputstr(dest->source.global_vars, cdef->def);
dest->functions.pre_init = mputstr(dest->functions.pre_init, cdef->init);
dest->functions.post_init = mputstr(dest->functions.post_init, cdef->post);
char*& header = in_class ? dest->header.class_defs : dest->header.global_vars;
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;
pre_init = mputstr(pre_init, cdef->init);
char*& post_init = in_class ? dest->temp.constructor : dest->functions.post_init;
post_init = mputstr(post_init, cdef->post);
}
void Code::free_cdef(const_def *cdef)
......
......@@ -36,7 +36,7 @@ namespace Common {
static void free_output(output_struct *output);
static void init_cdef(const_def *cdef);
static void merge_cdef(output_struct *dest, const_def *cdef);
static void merge_cdef(output_struct *dest, const_def *cdef, boolean in_class = FALSE);
static void free_cdef(const_def *cdef);
static void init_expr(expression_struct *expr);
......
......@@ -38,6 +38,7 @@
#include "main.hh"
#include "ttcn3/profiler.h"
#include "ttcn3/Attributes.hh"
#include "ttcn3/Ttcnstuff.hh"
namespace Common {
......@@ -604,6 +605,14 @@ namespace Common {
get_scope_name().c_str());
return 0;
}
const Ttcn::ClassTypeBody* Scope::get_scope_class() const
{
if (parent_scope != NULL) {
return parent_scope->get_scope_class();
}
return NULL;
}
bool Scope::has_ass_withId(const Identifier& p_id)
{
......
......@@ -62,6 +62,7 @@ namespace Ttcn {
class ErroneousDescriptors;
class transparency_holder;
class Statement;
class ClassTypeBody;
} // namespace Ttcn
namespace Common {
......@@ -613,6 +614,8 @@ public:
* Module. */
virtual Module* get_scope_mod();
virtual Module* get_scope_mod_gen();
virtual bool is_class_scope() const { return false; }
virtual const Ttcn::ClassTypeBody* get_scope_class() const;
/** Returns the assignment referenced by \a p_ref. If no such
* node, 0 is returned. */
virtual Assignment* get_ass_bySRef(Ref_simple *p_ref) =0;
......
......@@ -130,6 +130,7 @@ namespace Common {
"altstep reference(TTCN-3)", // T_ALTSTEP
"testcase reference(TTCN-3)", // T_TESTCASE
"anytype(TTCN-3)", // T_ANYTYPE
"class(TTCN-3)" // T_CLASS
};
// =================================
......@@ -579,6 +580,9 @@ namespace Common {
u.fatref.returns_template = false;
u.fatref.template_restriction = TR_NONE;
break;
case T_CLASS:
u.class_ = p.u.class_->clone();
break;
default:
FATAL_ERROR("Type::Type()");
} // switch
......@@ -749,6 +753,9 @@ namespace Common {
delete u.fatref.runs_on.ref;
delete u.fatref.system.ref;
break;
case T_CLASS:
delete u.class_;
break;
default:
FATAL_ERROR("Type::clean_up()");
} // switch
......@@ -1120,7 +1127,23 @@ namespace Common {
u.fatref.returns_template = false;
u.fatref.template_restriction = TR_NONE;
}
Type::Type(typetype_t p_tt, Ttcn::ClassTypeBody* p_class)
: Governor(S_T), typetype(p_tt)
{
init();
switch (typetype) {
case T_CLASS:
if (p_class == NULL) {
FATAL_ERROR("Type::Type");
}
u.class_ = p_class;
break;
default:
FATAL_ERROR("Type::Type");
}
}
Type::~Type()
{
clean_up();
......@@ -1446,6 +1469,9 @@ namespace Common {
if (u.fatref.system.ref)
u.fatref.system.ref->set_fullname(p_fullname + ".<system_type>");
break;
case T_CLASS:
u.class_->set_fullname(p_fullname);
break;
default:
break;
} // switch
......@@ -1522,6 +1548,9 @@ namespace Common {
if (u.fatref.system.ref)
u.fatref.system.ref->set_my_scope(p_scope);
break;
case T_CLASS:
u.class_->set_my_scope(p_scope);
break;
default:
break;
} // switch
......@@ -3923,6 +3952,7 @@ namespace Common {
case T_FUNCTION:
case T_ALTSTEP:
case T_TESTCASE:
case T_CLASS:
return p_tt1 == p_tt2;
case T_OSTR:
return p_tt2==T_OSTR || (!p_is_asn11 && p_tt2==T_ANY);
......@@ -4300,6 +4330,7 @@ namespace Common {
case T_FUNCTION:
case T_ALTSTEP:
case T_TESTCASE:
case T_CLASS:
// TODO: Compatibility.
is_type_comp = ( t1 == t2 );
break;
......@@ -5222,6 +5253,7 @@ namespace Common {
case T_FUNCTION:
case T_ALTSTEP:
case T_TESTCASE:
case T_CLASS:
// user-defined structured types must be identical
return t1 == t2;
case T_ARRAY:
......@@ -6034,6 +6066,14 @@ namespace Common {
FATAL_ERROR("Type::Returns_template()");
return u.fatref.returns_template;
}
Ttcn::ClassTypeBody* Type::get_class_type_body()
{
if (typetype != T_CLASS) {
FATAL_ERROR("Type::get_class_type_body()");
}
return u.class_;
}
void Type::add_tag(Tag *p_tag)
{
......@@ -6680,6 +6720,7 @@ namespace Common {
case T_FUNCTION: // TTCN-3
case T_ALTSTEP: // TTCN-3
case T_TESTCASE: // TTCN-3
case T_CLASS: // TTCN-3
return memory.remember(t, ANSWER_NO);
case T_UNDEF:
......@@ -7387,7 +7428,8 @@ namespace Common {
case T_SIGNATURE:
case T_FUNCTION:
case T_ALTSTEP:
case T_TESTCASE: {
case T_TESTCASE:
case T_CLASS: {
// user-defined types
// always use the qualified name (including module identifier)
string ret_val(t_scope->get_scope_mod_gen()->get_modid().get_name());
......@@ -7424,6 +7466,7 @@ namespace Common {
case T_FUNCTION:
case T_ALTSTEP:
case T_TESTCASE:
case T_CLASS:
return t->get_fullname();
case T_ARRAY: {
string dimensions(t->u.array.dimension->get_stringRepr());
......@@ -8065,6 +8108,10 @@ namespace Common {
u.fatref.system.ref->dump(level+2);
}
break;
case T_CLASS:
DEBUG(level,"Type: class");
u.class_->dump(level + 1);
break;
default:
DEBUG(level, "type (%d - %s)", typetype, const_cast<Type*>(this)->get_stringRepr().c_str());
} // switch
......@@ -8222,6 +8269,7 @@ namespace Common {
switch (typetype) {
case T_DEFAULT:
case T_PORT:
case T_CLASS:
return true;
case T_FUNCTION:
case T_ALTSTEP:
......
......@@ -77,6 +77,7 @@ namespace Ttcn {
class PortTypeBody;
class Def_Type;
class Ref_pard;
class ClassTypeBody;
/** Stores the modifier of an attribute */
enum attribute_modifier_t {
......@@ -199,6 +200,7 @@ namespace Common {
T_ALTSTEP, /**< altstep reference (TTCN-3) */
T_TESTCASE, /**< testcase reference (TTCN-3) */
T_ANYTYPE, /**< anytype (TTCN-3) */
T_CLASS, /**< class (TTCN-3) */
// WRITE new type before this line
T_LAST
}; //DO NOT FORGET to update type_as_string[] in Type.cc
......@@ -466,6 +468,7 @@ namespace Common {
template_restriction_t template_restriction;
bool is_startable;
} fatref;
Ttcn::ClassTypeBody* class_;
} u;
static const char* type_as_string[];
......@@ -587,6 +590,7 @@ namespace Common {
/// Create a TTCN3 testcase
Type(typetype_t p_tt,Ttcn::FormalParList *p_params,
Ttcn::Reference* p_runs_on_ref, Ttcn::Reference *p_system_ref);
Type(typetype_t p_tt, Ttcn::ClassTypeBody* p_class);
/** @} */
virtual ~Type();
/** This function must be called to clean up the pool types,
......@@ -1165,6 +1169,8 @@ namespace Common {
bool get_fat_runs_on_self();
/** Applicable only if typetype == T_FUNCTION */
bool get_returns_template();
/** Applicably only if typetype == T_CLASS */
Ttcn::ClassTypeBody* get_class_type_body();
/** Retruns true if it is a tagged type.*/
bool is_tagged() const {return tags!=0;}
......@@ -1320,11 +1326,11 @@ namespace Common {
* Value or Template object in the AST (e.g. in case of variables). */
void generate_code_object(const_def *cdef, Scope* p_scope,
const string& name, const char *prefix, bool is_template,
bool has_err_descr);
bool has_err_descr, bool in_class);
/** Generates the declaration and definition of a C++ value or template
* object governed by \a this into \a cdef based on the attributes of
* \a p_setting. */
void generate_code_object(const_def *cdef, GovernedSimple *p_setting);
void generate_code_object(const_def *cdef, GovernedSimple *p_setting, bool in_class);
private:
virtual string create_stringRepr();
public:
......
......@@ -186,6 +186,9 @@ void Type::chk()
case T_TESTCASE:
chk_Fat();
break;
case T_CLASS:
u.class_->chk();
break;
default:
FATAL_ERROR("Type::chk()");
} // switch
......
......@@ -101,6 +101,9 @@ void Type::generate_code(output_struct *target)
case T_TESTCASE:
generate_code_Fat(target);
break;
case T_CLASS:
u.class_->generate_code(target);
break;
default:
generate_code_alias(target);
break;
......@@ -582,7 +585,7 @@ void Type::generate_code_xerdescriptor(output_struct* target)
dfe_str = xerattrib->defaultValue_->get_genname_own().c_str();
const_def cdef;
Code::init_cdef(&cdef);
t->generate_code_object(&cdef, xerattrib->defaultValue_);
t->generate_code_object(&cdef, xerattrib->defaultValue_, false);
// Generate the initialization of the dfe values in the post init function
// because the module params are not initialized in the pre init function
target->functions.post_init = xerattrib->defaultValue_->generate_code_init
......@@ -1845,7 +1848,7 @@ void Type::generate_code_Se(output_struct *target)
Value *defval = cf->get_defval();
const_def cdef;
Code::init_cdef(&cdef);
type->generate_code_object(&cdef, defval);
type->generate_code_object(&cdef, defval, false);
cdef.init = defval->generate_code_init
(cdef.init, defval->get_lhs_name().c_str());
Code::merge_cdef(target, &cdef);
......@@ -3395,7 +3398,8 @@ bool Type::has_done_attribute()
}
void Type::generate_code_object(const_def *cdef, Scope *p_scope,
const string& name, const char *prefix, bool is_template, bool has_err_descr)
const string& name, const char *prefix, bool is_template, bool has_err_descr,
bool in_class)
{
string type_name;
if (is_template) type_name = get_genname_template(p_scope);
......@@ -3403,23 +3407,32 @@ void Type::generate_code_object(const_def *cdef, Scope *p_scope,
const char *name_str = name.c_str();
const char *type_name_str = type_name.c_str();
if (prefix) {
cdef->decl = mputprintf(cdef->decl, "extern const %s& %s;\n",
type_name_str, name_str);
if (split_to_slices || has_err_descr) {
cdef->decl = mputprintf(cdef->decl, "extern %s %s%s;\n", type_name_str, prefix, name_str);
}
cdef->def = mputprintf(cdef->def, "%s%s %s%s;\n"
"const %s& %s = %s%s;\n", split_to_slices || has_err_descr ? "" : "static ",
type_name_str, prefix, name_str, type_name_str, name_str, prefix, name_str);
cdef->decl = mputprintf(cdef->decl, "%sconst %s& %s;\n",
in_class ? "" : "extern ", type_name_str, name_str);
if (split_to_slices || has_err_descr || in_class) {
cdef->decl = mputprintf(cdef->decl, "%s%s %s%s;\n",
in_class ? "" : "extern ", type_name_str, prefix, name_str);
}
if (!in_class) {
cdef->def = mputprintf(cdef->def, "%s%s %s%s;\n"
"const %s& %s = %s%s;\n", split_to_slices || has_err_descr ? "" : "static ",
type_name_str, prefix, name_str, type_name_str, name_str, prefix, name_str);
}
else {
cdef->def = mputprintf(cdef->def, ", %s(%s%s)", name_str, prefix, name_str);
}
} else {
cdef->decl = mputprintf(cdef->decl, "extern %s %s;\n",
type_name_str, name_str);
cdef->def = mputprintf(cdef->def, "%s %s;\n",
type_name_str, name_str);
cdef->decl = mputprintf(cdef->decl, "%s%s %s;\n",
in_class ? "" : "extern ", type_name_str, name_str);
if (!in_class) {
cdef->def = mputprintf(cdef->def, "%s %s;\n",
type_name_str, name_str);
}
}
}
void Type::generate_code_object(const_def *cdef, GovernedSimple *p_setting)
void Type::generate_code_object(const_def *cdef, GovernedSimple *p_setting,
bool in_class)
{
bool is_template = FALSE;
switch (p_setting->get_st()) {
......@@ -3442,7 +3455,7 @@ void Type::generate_code_object(const_def *cdef, GovernedSimple *p_setting)
// regenerated
generate_code_object(cdef, p_setting->get_my_scope(),
p_setting->get_genname_own(), p_setting->get_genname_prefix(),
is_template, use_runtime_2);
is_template, use_runtime_2, in_class);
}
void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_value)
......
......@@ -1872,7 +1872,7 @@ namespace Asn {
left->generate_code(target);
const_def cdef;
Code::init_cdef(&cdef);
left->generate_code_object(&cdef, right);
left->generate_code_object(&cdef, right, false);
cdef.init = right->generate_code_init(cdef.init,
right->get_lhs_name().c_str());
Code::merge_cdef(target, &cdef);
......
......@@ -722,7 +722,7 @@ namespace Asn {
if(defval) {
const_def cdef;
Code::init_cdef(&cdef);
fixtype->generate_code_object(&cdef, defval);
fixtype->generate_code_object(&cdef, defval, false);
cdef.init = defval->generate_code_init(cdef.init,
defval->get_lhs_name().c_str());
Code::merge_cdef(target, &cdef);
......@@ -1316,7 +1316,7 @@ namespace Asn {
const_def cdef;
Code::init_cdef(&cdef);
Type *type = setting->get_my_governor();
type->generate_code_object(&cdef, setting);
type->generate_code_object(&cdef, setting, false);
cdef.init = setting->generate_code_init(cdef.init,
setting->get_lhs_name().c_str());
Code::merge_cdef(target, &cdef);
......
......@@ -100,7 +100,7 @@ boolean generate_skeleton = FALSE, force_overwrite = FALSE,
warnings_for_bad_variants = FALSE, debugger_active = FALSE,
legacy_unbound_union_fields = FALSE, split_to_slices = FALSE,
legacy_untagged_union, disable_user_info, legacy_codec_handling = FALSE,
realtime_features = FALSE;
realtime_features = FALSE, oop_features = FALSE;
// Default code splitting mode is set to 'no splitting'.
CodeGenHelper::split_type code_splitting_mode = CodeGenHelper::SPLIT_NONE;
......@@ -503,7 +503,7 @@ int main(int argc, char *argv[])
Sflag = false, Kflag = false, jflag = false, zflag = false, Fflag = false,
Mflag = false, Eflag = false, nflag = false, Bflag = false, errflag = false,
print_usage = false, ttcn2json = false, Nflag = false, Dflag = false,
eflag = false, Oflag = false, Iflag = false;
eflag = false, Oflag = false, Iflag = false, kflag = false;
CodeGenHelper cgh;
......@@ -599,7 +599,7 @@ int main(int argc, char *argv[])
if (!ttcn2json) {
for ( ; ; ) {
int c = getopt(argc, argv, "aA:bBcC:dDeEfFgiIjJ:K:lLMnNo:OpP:qQ:rRsStT:uU:vV:wxXyYz:0-");
int c = getopt(argc, argv, "aA:bBcC:dDeEfFgiIjJ:kK:lLMnNo:OpP:qQ:rRsStT:uU:vV:wxXyYz:0-");
if (c == -1) break;
switch (c) {
case 'a':
......@@ -680,6 +680,10 @@ int main(int argc, char *argv[])
case 'J':
file_list_file_name = optarg;
break;
case 'k':
SET_FLAG(k);
oop_features = TRUE;
break;
case 'K':
SET_FLAG(K);
tcov_file_name = optarg;
......@@ -846,7 +850,7 @@ int main(int argc, char *argv[])
bflag || fflag || iflag || lflag || oflag || pflag || qflag ||
rflag || sflag || tflag || uflag || wflag || xflag || Xflag || Rflag ||
Uflag || yflag || Kflag || jflag || zflag || Fflag || Mflag || Eflag ||
nflag || Bflag || Dflag || eflag || Oflag || Iflag || s0flag) {
nflag || Bflag || Dflag || eflag || Oflag || Iflag || s0flag || kflag) {
errflag = true;
print_usage = true;
}
......
......@@ -52,7 +52,7 @@ extern boolean generate_skeleton, force_overwrite, include_line_info,
implicit_json_encoding, json_refs_for_all_types, force_gen_seof,
omit_in_value_list, warnings_for_bad_variants, debugger_active,
legacy_unbound_union_fields, split_to_slices, legacy_untagged_union,
disable_user_info, legacy_codec_handling, realtime_features;
disable_user_info, legacy_codec_handling, realtime_features, oop_features;
extern const char *expected_platform;
......
This diff is collapsed.
......@@ -428,6 +428,7 @@ namespace Ttcn {
virtual string get_scopeMacro_name() const;
virtual NameBridgingScope* clone() const;
virtual Common::Assignment* get_ass_bySRef(Ref_simple *p_ref);
virtual bool is_class_scope() const;
};
/**
......@@ -524,6 +525,7 @@ namespace Ttcn {
virtual Common::Assignment* get_ass_byIndex(size_t p_i);
size_t get_nof_raw_asss();
Definition *get_raw_ass_byIndex(size_t p_i);
virtual bool is_class_scope() const;
/** Checks the uniqueness of identifiers. */
void chk_uniq();
/** Checks all definitions. */
......@@ -1601,6 +1603,24 @@ namespace Ttcn {
* inserted in the schema. */
void generate_json_schema_ref(map<Type*, JSON_Tokenizer>& json_refs);
};
/**
* Represents an abstract function definition (inside a class definition)
*/
class Def_AbsFunction : public Def_Function_Base {
bool deterministic;
public:
Def_AbsFunction(bool p_deterministic, Identifier* p_id, FormalParList* p_fpl,
Type* p_return_type, bool returns_template,
template_restriction_t p_template_restriction)
: Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
p_template_restriction) { }
virtual ~Def_AbsFunction();
virtual Definition* clone() const;
virtual void chk();
virtual void generate_code(output_struct* target, bool clean_up = false);
// TODO
};
/**
* Represents an altstep definition.
......@@ -1717,6 +1737,38 @@ namespace Ttcn {
virtual void set_parent_path(WithAttribPath* p_path);
};
/**
* Represents a constructor definition (inside a class definition).
*/
class Def_Constructor : public Definition {
private:
/** The formal parameter list of the constructor. It is never NULL even if
* the constructor has no parameters. */
FormalParList* fp_list;
Ref_pard* base_call;
StatementBlock* block;
//NameBridgingScope bridgeScope;
/// Copy constructor disabled
Def_Constructor(const Def_Constructor& p);
/// %Assignment disabled
Def_Constructor& operator=(const Def_Constructor& p);
public:
Def_Constructor(FormalParList* p_fp_list, Ref_pard* p_base_call,
StatementBlock* p_block);
virtual ~Def_Constructor();
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 void chk();
virtual void generate_code(output_struct *target, bool clean_up = false);
virtual void set_parent_path(WithAttribPath* p_path);
};
/** General class to represent formal parameters. The inherited
* attribute asstype carries the kind and direction of the
......
......@@ -23,6 +23,7 @@
#include "../main.hh"
#include "Attributes.hh"
#include <errno.h>
#include "Statement.hh"
// implemented in coding_attrib_p.y
extern Ttcn::ExtensionAttributes * parse_extattributes(
......@@ -379,17 +380,17 @@ namespace Ttcn {
void TypeMappingTarget::chk_function(Type *source_type, Type *port_type, bool legacy, bool incoming)
{
Error_Context cntxt(this, "In `function' mapping");
Assignment *t_ass = u.func.function_ref->get_refd_assignment(false);
Common::Assignment *t_ass = u.func.function_ref->get_refd_assignment(false);
if (!t_ass) return;
t_ass->chk();
switch (t_ass->get_asstype()) {
case Assignment::A_FUNCTION:
case Assignment::A_FUNCTION_RVAL:
case Assignment::A_FUNCTION_RTEMP:
case Common::Assignment::A_FUNCTION:
case Common::Assignment::A_FUNCTION_RVAL:
case Common::Assignment::A_FUNCTION_RTEMP:
break;
case Assignment::A_EXT_FUNCTION:
case Assignment::A_EXT_FUNCTION_RVAL:
case Assignment::A_EXT_FUNCTION_RTEMP:
case Common::Assignment::A_EXT_FUNCTION:
case Common::Assignment::A_EXT_FUNCTION_RVAL:
case Common::Assignment::A_EXT_FUNCTION_RTEMP:
// External functions are not allowed when the standard like behaviour is used
if (legacy) {
break;
......@@ -1504,9 +1505,9 @@ namespace Ttcn {
size_t n_prov_t = 0;
for (size_t p = 0; p < provider_refs.size(); p++) {
provider_body = 0;
Assignment *t_ass = provider_refs[p]->get_refd_assignment(); // provider port
Common::Assignment *t_ass = provider_refs[p]->get_refd_assignment(); // provider port
if (t_ass) {
if (t_ass->get_asstype() == Assignment::A_TYPE) {
if (t_ass->get_asstype() == Common::Assignment::A_TYPE) {
Type *t = t_ass->get_Type()->get_type_refd_last();