Commit c0c35304 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

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



Change-Id: I6eb1eb5cc878496b6bed19656cbb23b5759bd40c
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 93fd0543
......@@ -6625,6 +6625,31 @@ namespace Ttcn {
if (!checked) chk();
return output_type;
}
bool Def_Function_Base::is_identical(Def_Function_Base* p_other)
{
if (asstype != p_other->get_asstype()) {
return false;
}
else if (return_type != NULL &&
!p_other->return_type->is_identical(return_type)) {
return false;
}
FormalParList* other_fp_list = p_other->get_FormalParList();
if (other_fp_list->get_nof_fps() != fp_list->get_nof_fps()) {
return false;
}
for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
FormalPar* fp1 = fp_list->get_fp_byIndex(i);
FormalPar* fp2 = other_fp_list->get_fp_byIndex(i);
if (fp1->get_asstype() != fp2->get_asstype() ||
!fp1->get_Type()->is_identical(fp2->get_Type()) ||
fp1->get_id().get_name() != fp2->get_id().get_name()) {
return false;
}
}
return true;
}
// =================================
......@@ -7475,7 +7500,7 @@ namespace Ttcn {
checked = true;
Error_Context cntxt(this, "In external function definition `%s'",
id->get_dispname().c_str());
if (!ext_keyword && my_scope->get_scope_class()->is_external()) {
if (!ext_keyword && !my_scope->get_scope_class()->is_external()) {
error("Missing function body or `external' keyword");
}
fp_list->chk(asstype);
......@@ -8087,59 +8112,6 @@ namespace Ttcn {
// TODO: with attributes
}
void Def_AbsFunction::chk_implementation(Common::Assignment* p_ass, Location* p_loc)
{
switch (p_ass->get_asstype()) {
case A_FUNCTION:
case A_FUNCTION_RVAL:
case A_FUNCTION_RTEMP: {
Def_Function* def_func = dynamic_cast<Def_Function*>(p_ass);
if (def_func == NULL) {
// it's an abstract function, which means it hasn't been implemented
p_loc->error("Missing implementation of abstract method `%s'",
get_fullname().c_str());
}
else {
// check whether they're identical
bool match = true;
if (asstype != p_ass->get_asstype()) {
match = false;
}
else if (return_type != NULL &&
!def_func->get_return_type()->is_identical(return_type)) {
match = false;
}
else {
FormalParList* other_fp_list = def_func->get_FormalParList();
if (other_fp_list->get_nof_fps() != fp_list->get_nof_fps()) {
match = false;
}
else {
for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
FormalPar* fp1 = fp_list->get_fp_byIndex(i);
FormalPar* fp2 = other_fp_list->get_fp_byIndex(i);
if (fp1->get_asstype() != fp2->get_asstype() ||
!fp1->get_Type()->is_identical(fp2->get_Type()) ||
fp1->get_id().get_name() != fp2->get_id().get_name()) {
match = false;
}
}
}
}
if (!match) {
p_ass->error("The prototype of method `%s' is not identical to that "
"of inherited abstract method `%s'",
def_func->get_id().get_dispname().c_str(), get_fullname().c_str());
}
}
break; }
default:
p_ass->error("%s shadows inherited abstract method `%s'",
p_ass->get_description().c_str(), get_fullname().c_str());
break;
}
}
void Def_AbsFunction::generate_code(output_struct* target, bool)
{
const string& t_genname = get_genname();
......
......@@ -1390,6 +1390,7 @@ namespace Ttcn {
Type *get_output_type();
Type* get_return_type() const { return return_type; }
//virtual Type *get_RunsOnType();
bool is_identical(Def_Function_Base* p_other);
template_restriction_t get_template_restriction()
{ return template_restriction; }
/** Checks and returns whether the function is startable.
......@@ -1620,7 +1621,6 @@ namespace Ttcn {
virtual ~Def_AbsFunction();
virtual Definition* clone() const;
virtual void chk();
void chk_implementation(Common::Assignment* p_ass, Location* p_loc);
virtual void generate_code(output_struct* target, bool clean_up = false);
};
......
......@@ -3200,7 +3200,7 @@ namespace Ttcn {
if (members->has_local_ass_withId(p_id)) {
return true;
}
if (base_type != NULL) {
if (base_class != NULL) {
return base_class->has_local_ass_withId(p_id);
}
else {
......@@ -3415,7 +3415,56 @@ namespace Ttcn {
}
}
if (constructor == NULL) {
bool name_clash = false;
if (base_class != NULL) {
for (size_t i = 0; i < members->get_nof_asss(); ++i) {
Common::Assignment* local_def = members->get_ass_byIndex(i, false);
const Common::Identifier& local_id = local_def->get_id();
if (local_def->get_asstype() != Common::Assignment::A_CONSTRUCTOR &&
base_class->has_local_ass_withId(local_id)) {
Common::Assignment* base_def = base_class->get_local_ass_byId(local_id);
switch (local_def->get_asstype()) {
case Common::Assignment::A_FUNCTION:
case Common::Assignment::A_FUNCTION_RVAL:
case Common::Assignment::A_FUNCTION_RTEMP:
case Common::Assignment::A_EXT_FUNCTION:
case Common::Assignment::A_EXT_FUNCTION_RVAL:
case Common::Assignment::A_EXT_FUNCTION_RTEMP:
switch (base_def->get_asstype()) {
case Common::Assignment::A_FUNCTION:
case Common::Assignment::A_FUNCTION_RVAL:
case Common::Assignment::A_FUNCTION_RTEMP:
case Common::Assignment::A_EXT_FUNCTION:
case Common::Assignment::A_EXT_FUNCTION_RVAL:
case Common::Assignment::A_EXT_FUNCTION_RTEMP: {
Def_Function_Base* local_func = dynamic_cast<Def_Function_Base*>(local_def);
Def_Function_Base* base_func = dynamic_cast<Def_Function_Base*>(base_def);
if (!local_func->is_identical(base_func)) {
local_def->error("The prototype of method `%s' is not identical "
"to that of inherited method `%s'",
local_id.get_dispname().c_str(), base_def->get_fullname().c_str());
}
break; }
default:
local_def->error("%s shadows inherited member `%s'",
local_def->get_description().c_str(), base_def->get_fullname().c_str());
name_clash = true;
break;
}
break;
default:
local_def->error("%s shadows inherited %s `%s'",
local_def->get_description().c_str(),
dynamic_cast<Def_Function_Base*>(base_def) != NULL ? "method" : "member",
base_def->get_fullname().c_str());
name_clash = true;
break;
}
}
}
}
if (constructor == NULL && !name_clash) {
// create a default constructor
Reference* base_call = NULL;
FormalParList* fp_list = NULL;
......@@ -3521,10 +3570,7 @@ namespace Ttcn {
Def_AbsFunction* def_abs_func = dynamic_cast<Def_AbsFunction*>(ass);
if (def_abs_func != NULL) {
const string& def_name = def_abs_func->get_id().get_name();
if (abstract_functions.has_key(def_name)) {
// TODO
}
else {
if (!abstract_functions.has_key(def_name)) {
abstract_functions.add(def_name, def_abs_func);
}
}
......@@ -3539,10 +3585,25 @@ namespace Ttcn {
// all abstract methods from the base class have to be implemented in this class
for (size_t i = 0; i < base_class->abstract_functions.size(); ++i) {
Def_AbsFunction* def_abs_func = base_class->abstract_functions.get_nth_elem(i);
def_abs_func->chk_implementation(get_local_ass_byId(def_abs_func->get_id()), this);
Common::Assignment* ass = get_local_ass_byId(def_abs_func->get_id());
switch (ass->get_asstype()) {
case Common::Assignment::A_FUNCTION:
case Common::Assignment::A_FUNCTION_RVAL:
case Common::Assignment::A_FUNCTION_RTEMP: {
if (dynamic_cast<Def_AbsFunction*>(ass) != NULL) {
error("Missing implementation of abstract method `%s'",
def_abs_func->get_fullname().c_str());
}
// whether the new function is identical to the abstract one has
// already been checked
break; }
default:
// it's either an external function (which is OK), or
// it's shadowed by a member (error has already been reported)
break;
}
}
}
// todo: name clashes with defs in the base class?
}
void ClassTypeBody::chk_recursions(ReferenceChain& refch)
......
......@@ -3578,6 +3578,7 @@ optAbstractModifier:
optExtendsClassDef:
/* empty */ { $$ = NULL; }
| ExtendsKeyword ReferencedType { $$ = $2; }
| ExtendsKeyword ObjectKeyword { $$ = NULL; }
;
optFinallyDef:
......
......@@ -114,15 +114,11 @@ type class C6 { //^In type definition//
}
type class C7 extends C9 { //^In type definition// //^In superclass definition//
public const integer x1 := 1;
}
type class C7 extends C9 { } //^In type definition// //^In superclass definition//
type class C8 extends C7 { //^In type definition// //While checking embedded recursions\: Circular reference\: `@oop_SE.C8' -> `@oop_SE.C8.<superclass>' -> `@oop_SE.C7' -> `@oop_SE.C7.<superclass>' -> `@oop_SE.C9' -> `@oop_SE.C9.<superclass>' -> `@oop_SE.C8'//
private var integer x2;
}
type class C8 extends C7 { } //^In type definition// //While checking embedded recursions\: Circular reference\: `@oop_SE.C8' -> `@oop_SE.C8.<superclass>' -> `@oop_SE.C7' -> `@oop_SE.C7.<superclass>' -> `@oop_SE.C9' -> `@oop_SE.C9.<superclass>' -> `@oop_SE.C8'//
type class C9 extends C8 {} //^In type definition// //^In superclass definition//
type class C9 extends C8 { } //^In type definition// //^In superclass definition//
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'//
......@@ -343,42 +339,42 @@ function f_inst_abstract() { //^In function definition//
}
type class @abstract C25 {
public function @abstract f_abs() return integer;
public function @abstract f_abs(inout template integer p) return integer;
}
type class @abstract C26 extends C25 {
public function @abstract f_abs2(inout template integer p);
public function @abstract f_abs2();
}
type class C27 extends C26 { } //^In type definition// //Missing implementation of abstract method `@oop_SE.C25.f_abs'// //Missing implementation of abstract method `@oop_SE.C26.f_abs2'//
type class C28 extends C25 { //^In type definition//
public var integer f_abs; //variable `@oop_SE.C28.f_abs' shadows inherited abstract method `@oop_SE.C25.f_abs'//
public var integer f_abs; //variable `@oop_SE.C28.f_abs' shadows inherited method `@oop_SE.C25.f_abs'//
}
type class C29 extends C26 { //^In type definition// //Missing implementation of abstract method `@oop_SE.C25.f_abs'//
public function f_abs2(inout template integer p) { }
public function f_abs2() { }
}
type class C30 extends C26 {
public function f_abs() return integer { return 1; }
public function f_abs2(inout template integer p) { }
public function f_abs(inout template integer p) return integer { return 1; }
public function f_abs2() { }
}
type class C31 extends C25 { //^In type definition//
public function f_abs(in template integer p) { } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
public function f_abs(in template integer p) { } //The prototype of method `f_abs' is not identical to that of inherited method `@oop_SE.C25.f_abs'//
}
type class C32 extends C25 { //^In type definition//
public function f_abs(inout integer p) { } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
public function f_abs(inout integer p) { } //The prototype of method `f_abs' is not identical to that of inherited method `@oop_SE.C25.f_abs'//
}
type class C33 extends C25 { //^In type definition//
public function f_abs(inout template integer q) { } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
public function f_abs(inout template integer q) { } //The prototype of method `f_abs' is not identical to that of inherited method `@oop_SE.C25.f_abs'//
}
type class C34 extends C25 { //^In type definition//
public function f_abs(inout template integer p) return boolean { return false; } //The prototype of method `f_abs' is not identical to that of inherited abstract method `@oop_SE.C25.f_abs'//
public function f_abs(inout template integer p) return boolean { return false; } //The prototype of method `f_abs' is not identical to that of inherited method `@oop_SE.C25.f_abs'//
}
type class @abstract C35 {
......@@ -433,8 +429,8 @@ function f_default() { //^In function definition//
}
type external class C40 { //^In type definition//
function f1(in integer p) return octetstring; //^In external function definition// //Missing function body or `external' keyword//
type external class C40 {
function f1(in integer p) return octetstring;
external function f2();
}
......@@ -459,6 +455,26 @@ type class C44 extends C40 {
external function f();
}
type class C45 { //^In type definition//
function f(); //^In external function definition// //Missing function body or `external' keyword//
}
type class C46 extends object { }
type class C47 {
const integer m1 := 3;
function m2() return boolean { return true; }
function m3(in integer p) return charstring { return int2str(p); }
}
type class C48 extends C47 { //^In type definition//
var template octetstring m1; //template variable `@oop_SE.C48.m1' shadows inherited member `@oop_SE.C47.m1'//
var integer m2; //variable `@oop_SE.C48.m2' shadows inherited method `@oop_SE.C47.m2'//
function m3() return charstring { return "1"; } //The prototype of method `m3' is not identical to that of inherited method `@oop_SE.C47.m3'//
}
control { //^In control part//
var C11 x := C11.create; //^In variable definition// //A definition without `runs on' clause cannot create a value of class type `@oop_SE.C11', which runs on component type `@oop_SE.CT_RunsOn'// //Cannot create value of class type `@oop_SE.C11', which has an `mtc' clause, in the control part.// //Cannot create value of class type `@oop_SE.C11', which has a `system' clause, in the control part.//
......
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