Commit 0380d065 authored by Botond Baranyi's avatar Botond Baranyi
Browse files

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



Change-Id: I96626b14a57bc5eec6d3e2ece85de87a68d1fb8e
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent b8029bad
......@@ -855,6 +855,11 @@ namespace Common {
void Reference::set_code_section(GovernedSimple::code_section_t)
{
}
Assignment* Reference::get_refd_assignment_last(bool check_parlist)
{
return this->get_refd_assignment(check_parlist);
}
Ttcn::FieldOrArrayRefs *Reference::get_subrefs()
{
......
......@@ -700,6 +700,12 @@ public:
* parameter list of the referred definition. The parameter checking is
* done by default, but it can be disabled in certain cases. */
virtual Assignment* get_refd_assignment(bool check_parlist = true) = 0;
/** Returns the referred TTCN-3 definition or ASN.1 assignment.
* If there are references to class members or methods (in the subreferences),
* then the assignment at the end of the subreferences may differ from the
* referred assignment without subreferences.
* This function returns the assignment at the end of the subreferences. */
virtual Assignment* get_refd_assignment_last(bool check_parlist = true);
/** Returns the field or array subreferences of TTCN-3 references or NULL
* otherwise. */
virtual Ttcn::FieldOrArrayRefs *get_subrefs();
......
......@@ -6145,41 +6145,7 @@ void Type::chk_this_template_ref(Template *t)
// Do not check the actual parameter list of the reference yet to avoid
// endless recursion in case of embedded circular references.
// The parameter lists will be verified later.
Assignment *ass = v->get_reference()->get_refd_assignment(false);
if (ass != NULL && ass->get_asstype() == Assignment::A_VAR) {
// there could be class objects in the subreferences, which would change
// the type of the assignment (e.g. to a var template);
// use the assignment after the last class object in the subreference chain
Ttcn::FieldOrArrayRefs* subrefs = v->get_reference()->get_subrefs();
if (subrefs != NULL) {
Type* type = ass->get_Type();
if (type->get_field_type(subrefs, EXPECTED_DYNAMIC_VALUE) != NULL) {
// subrefs are valid
for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
type = type->get_type_refd_last();
Ttcn::FieldOrArrayRef* subref = subrefs->get_ref(i);
switch (subref->get_type()) {
case Ttcn::FieldOrArrayRef::FIELD_REF:
case Ttcn::FieldOrArrayRef::FUNCTION_REF:
if (type->typetype == T_CLASS) {
ass = type->get_class_type_body()->
get_local_ass_byId(*subref->get_id());
type = ass->get_Type();
}
else {
type = type->get_comp_byName(*subref->get_id())->get_type();
}
break;
case Ttcn::FieldOrArrayRef::ARRAY_REF:
if (type->is_structured_type()) {
type = type->get_ofType();
}
break;
}
}
}
}
}
Assignment *ass = v->get_reference()->get_refd_assignment_last(false);
if (ass) {
switch (ass->get_asstype()) {
case Assignment::A_VAR_TEMPLATE: {
......
......@@ -875,6 +875,44 @@ namespace Ttcn {
}
return ass;
}
Common::Assignment* Reference::get_refd_assignment_last(bool check_parlist)
{
Common::Assignment* ass = get_refd_assignment(check_parlist);
if (ass != NULL && ass->get_asstype() == Common::Assignment::A_VAR &&
subrefs.get_nof_refs() != 0) {
// there could be class objects in the subreferences, which would change
// the type of the last assignment
Type* type = ass->get_Type();
if (type->get_field_type(&subrefs, Common::Type::EXPECTED_DYNAMIC_VALUE) != NULL) {
// subrefs are valid
// TODO: EXPECTED_DYNAMIC_VALUE in all cases?
for (size_t i = 0; i < subrefs.get_nof_refs(); ++i) {
type = type->get_type_refd_last();
FieldOrArrayRef* subref = subrefs.get_ref(i);
switch (subref->get_type()) {
case FieldOrArrayRef::FIELD_REF:
case FieldOrArrayRef::FUNCTION_REF:
if (type->get_typetype() == Common::Type::T_CLASS) {
ass = type->get_class_type_body()->
get_local_ass_byId(*subref->get_id());
type = ass->get_Type();
}
else {
type = type->get_comp_byName(*subref->get_id())->get_type();
}
break;
case FieldOrArrayRef::ARRAY_REF:
if (type->is_structured_type()) {
type = type->get_ofType();
}
break;
}
}
}
}
return ass;
}
const Identifier* Reference::get_modid()
{
......@@ -1228,16 +1266,9 @@ namespace Ttcn {
expression_struct isbound_expr;
Code::init_expr(&isbound_expr);
if (ass->get_Type()->get_type_refd_last()->get_typetype() == Common::Type::T_CLASS) {
isbound_expr.preamble = mputprintf(isbound_expr.preamble,
"boolean %s = %s != NULL_VALUE;\n", tmp_generalid_str,
ass_id_str);
}
else {
isbound_expr.preamble = mputprintf(isbound_expr.preamble,
"boolean %s = %s.is_bound();\n", tmp_generalid_str,
ass_id_str);
}
isbound_expr.preamble = mputprintf(isbound_expr.preamble,
"boolean %s = %s.is_bound();\n", tmp_generalid_str,
ass_id_str);
namedbool p_optype;
if (optype == Value::OPTYPE_ISBOUND) {
p_optype = ISBOUND;
......
......@@ -367,6 +367,7 @@ namespace Ttcn {
virtual void set_my_scope(Scope* p_scope);
virtual string get_dispname();
virtual Common::Assignment *get_refd_assignment(bool check_parlist = true);
virtual Common::Assignment *get_refd_assignment_last(bool check_parlist = true);
virtual reftype_t get_reftype() const { return reftype; }
virtual void set_reftype(reftype_t p_reftype) { reftype = p_reftype; }
virtual const Identifier* get_modid();
......
......@@ -8863,7 +8863,7 @@ error:
void Assignment::chk_unknown_ass()
{
Common::Assignment *t_ass = ref->get_refd_assignment();
Common::Assignment *t_ass = ref->get_refd_assignment_last();
if (!t_ass) goto error;
switch (t_ass->get_asstype()) {
case Common::Assignment::A_ERROR:
......
......@@ -2164,41 +2164,7 @@ namespace Ttcn {
return true;
}
case TEMPLATE_REFD: {
Common::Assignment *ass = u.ref.ref->get_refd_assignment();
if (ass->get_asstype() == Common::Assignment::A_VAR) {
// there could be class objects in the subreferences, which would change
// the type of the assignment (e.g. to a var template);
// use the assignment after the last class object in the subreference chain
FieldOrArrayRefs* subrefs = u.ref.ref->get_subrefs();
if (subrefs != NULL) {
Type* type = ass->get_Type();
if (type->get_field_type(subrefs, Common::Type::EXPECTED_DYNAMIC_VALUE) != NULL) {
// subrefs are valid
for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
type = type->get_type_refd_last();
FieldOrArrayRef* subref = subrefs->get_ref(i);
switch (subref->get_type()) {
case FieldOrArrayRef::FIELD_REF:
case FieldOrArrayRef::FUNCTION_REF:
if (type->get_typetype() == Common::Type::T_CLASS) {
ass = type->get_class_type_body()->
get_local_ass_byId(*subref->get_id());
type = ass->get_Type();
}
else {
type = type->get_comp_byName(*subref->get_id())->get_type();
}
break;
case FieldOrArrayRef::ARRAY_REF:
if (type->is_structured_type()) {
type = type->get_ofType();
}
break;
}
}
}
}
}
Common::Assignment *ass = u.ref.ref->get_refd_assignment_last();
switch (ass->get_asstype()) {
case Common::Assignment::A_EXT_CONST:
case Common::Assignment::A_PAR_VAL:
......
......@@ -145,6 +145,18 @@ public:
ptr->log();
}
}
boolean is_bound() const {
return ptr != NULL;
}
boolean is_value() const {
return ptr != NULL;
}
boolean is_present() const {
return ptr != NULL;
}
};
template<typename T>
......
......@@ -382,6 +382,24 @@ type class C34 extends C25 { //^In type definition//
}
type class C35 {
public const integer c := 3;
public template charstring t := "";
public function f1() return Rec { return { 2, "a" }; }
public function f2() return template charstring { return ?; }
create() {}
}
function f_left_hand_side() { //^In function definition//
var C35 x := C35.create;
x.c := 2; //^In variable assignment// //Reference to a variable or template variable was expected instead of constant `@oop_SE.C35.c'//
x.t := *; //^In variable assignment// //Reference to a variable or template variable was expected instead of template `@oop_SE.C35.t'//
x.f1() := { 3, "b" }; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C35.f1'//
x.f1().num := 3; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C35.f1'//
x.f2() := "x"; //^In variable assignment// //Reference to a variable or template variable was expected instead of function `@oop_SE.C35.f2'//
}
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.//
}
......
......@@ -315,6 +315,7 @@ testcase tc_references() runs on CT {
var BaseClass v_base := BaseClass.create(4, { 1, 2, 4 }, "a", 'FF'O, 1.0);
var SubClass v_sub := SubClass.create(4, { 1, 2, 4 }, "a", 'FF'O, 1.0);
var FinalClass v_final := FinalClass.create(4, { 1, 2, 4 }, "a", 'FF'O, 1.0, 8, "x", -1.5, *);
var BaseClass v_null := null;
var BaseClass v_ref1;
if (v_ref1 != null) {
......@@ -353,6 +354,24 @@ testcase tc_references() runs on CT {
if (match(v_final.get_uni(), v_final.get_uni_temp())) {
setverdict(fail, "#11, ", match(v_final.get_uni(), v_final.get_uni_temp()));
}
if (not isbound(v_sub)) {
setverdict(fail, "#12");
}
if (isbound(v_null)) {
setverdict(fail, "#13");
}
if (not isvalue(v_final)) {
setverdict(fail, "#14");
}
if (isvalue(v_null)) {
setverdict(fail, "#15");
}
if (not ispresent(v_base)) {
setverdict(fail, "#16");
}
if (ispresent(v_null)) {
setverdict(fail, "#17");
}
setverdict(pass);
}
......
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