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

Implemented template concatenation, part 1 (bug 512878)



Change-Id: Ie5b4d9f00fdcb2aed99ec668be74e632c874506d
Signed-off-by: Botond Baranyi's avatarBotond Baranyi <botond.baranyi@ericsson.com>
parent 980120ca
......@@ -67,6 +67,10 @@ struct ttcn3float {
/// Address-of, for scanf
double* operator&() { return &value; }
double operator+(const ttcn3float& x) const {
return value + x.value;
}
const ttcn3float& operator+=(double d) {
value += d;
......
......@@ -5879,6 +5879,32 @@ bool Type::chk_this_template_Str(Template *t, namedbool implicit_omit,
}
}
break;
case Ttcn::Template::TEMPLATE_CONCAT:
{
Error_Context cntxt(t, "In template concatenation");
t->set_lowerid_to_ref();
Template* t_left = t->get_concat_operand(true);
Template* t_right = t->get_concat_operand(false);
if (tt == T_CSTR || tt == T_USTR) {
if (t_left->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE &&
t_left->get_templatetype() != Ttcn::Template::TEMPLATE_CONCAT &&
t_left->get_templatetype() != Ttcn::Template::TEMPLATE_REFD) {
t_left->error("Operands of %s template concatenation must be "
"specific value templates", get_typename_builtin(tt));
}
if (t_right->get_templatetype() != Ttcn::Template::SPECIFIC_VALUE &&
t_right->get_templatetype() != Ttcn::Template::TEMPLATE_CONCAT &&
t_right->get_templatetype() != Ttcn::Template::TEMPLATE_REFD) {
t_right->error("Operands of %s template concatenation must be "
"specific value templates", get_typename_builtin(tt));
}
}
self_ref = chk_this_template_generic(t_left, INCOMPLETE_NOT_ALLOWED,
OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs);
self_ref = chk_this_template_generic(t_right, INCOMPLETE_NOT_ALLOWED,
OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs);
}
break;
default:
report_error = true;
break;
......@@ -6406,6 +6432,18 @@ bool Type::chk_this_template_SeqOf(Template *t, namedbool incomplete_allowed,
delete index_map.get_nth_elem(i);
index_map.clear();
break; }
case Ttcn::Template::TEMPLATE_CONCAT:
{
Error_Context cntxt(t, "In template concatenation");
Template* t_left = t->get_concat_operand(true);
Template* t_right = t->get_concat_operand(false);
t->set_lowerid_to_ref();
self_ref = chk_this_template_generic(t_left, incomplete_allowed,
OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs);
self_ref = chk_this_template_generic(t_right, incomplete_allowed,
OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs);
}
break;
default:
t->error("%s cannot be used for `record of' type `%s'",
t->get_templatetype_str(), get_typename().c_str());
......@@ -6540,6 +6578,18 @@ bool Type::chk_this_template_SetOf(Template *t, namedbool incomplete_allowed,
delete index_map.get_nth_elem(i);
index_map.clear();
break; }
case Ttcn::Template::TEMPLATE_CONCAT:
{
Error_Context cntxt(t, "In template concatenation");
Template* t_left = t->get_concat_operand(true);
Template* t_right = t->get_concat_operand(false);
t->set_lowerid_to_ref();
self_ref = chk_this_template_generic(t_left, incomplete_allowed,
OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs);
self_ref = chk_this_template_generic(t_right, incomplete_allowed,
OMIT_NOT_ALLOWED, ANY_OR_OMIT_ALLOWED, NO_SUB_CHK, implicit_omit, lhs);
}
break;
default:
t->error("%s cannot be used for `set of' type `%s'",
t->get_templatetype_str(), get_typename().c_str());
......
......@@ -375,6 +375,10 @@ namespace Common {
case V_REFER:
u.refered = p.u.refered->clone();
break;
case V_ANY_VALUE:
case V_ANY_OR_OMIT:
u.len_res = p.u.len_res != NULL ? p.u.len_res->clone() : NULL;
break;
default:
FATAL_ERROR("Value::Value()");
} // switch
......@@ -467,6 +471,10 @@ namespace Common {
case V_UNDEF_BLOCK:
delete u.block;
break;
case V_ANY_VALUE:
case V_ANY_OR_OMIT:
delete u.len_res;
break;
default:
FATAL_ERROR("Value::clean_up()");
} // switch
......@@ -1419,6 +1427,20 @@ namespace Common {
FATAL_ERROR("Value::Value()");
} // switch
}
// V_ANY_VALUE, V_ANY_OR_OMIT
Value::Value(valuetype_t p_vt, Ttcn::LengthRestriction* p_len_res)
: GovernedSimple(S_V), valuetype(p_vt), my_governor(0)
{
switch(p_vt) {
case V_ANY_VALUE:
case V_ANY_OR_OMIT:
u.len_res = p_len_res;
break;
default:
FATAL_ERROR("Value::Value()");
} // switch
}
Value::~Value()
{
......@@ -1436,6 +1458,24 @@ namespace Common {
FATAL_ERROR("Value::get_optype()");
return u.expr.v_optype;
}
Value* Value::get_concat_operand(bool first_operand) const
{
if (valuetype != V_EXPR || u.expr.v_optype != OPTYPE_CONCAT) {
FATAL_ERROR("Value::get_concat_operand()");
}
return first_operand ? u.expr.v1 : u.expr.v2;
}
Ttcn::LengthRestriction* Value::take_length_restriction()
{
if (valuetype != V_ANY_VALUE && valuetype != V_ANY_OR_OMIT) {
FATAL_ERROR("Value::take_length_restriction()");
}
Ttcn::LengthRestriction* ptr = u.len_res;
u.len_res = NULL;
return ptr;
}
void Value::set_my_governor(Type *p_gov)
{
......@@ -10355,6 +10395,10 @@ error:
case Ttcn::Template::TEMPLATE_ERROR:
//FATAL_ERROR("Value::chk_expr_self_ref_templ()");
break;
case Ttcn::Template::TEMPLATE_CONCAT:
self_ref |= chk_expr_self_ref_templ(t->get_concat_operand(true), lhs);
self_ref |= chk_expr_self_ref_templ(t->get_concat_operand(false), lhs);
break;
// default:
// FATAL_ERROR("todo ttype %d", t->get_templatetype());
// break; // and hope for the best
......
......@@ -50,6 +50,7 @@ namespace Ttcn {
class ParsedActualParameters;
class LogArguments;
class JsonOmitCombination;
class LengthRestriction;
}
namespace Common {
......@@ -125,7 +126,9 @@ namespace Common {
V_ALTSTEP, /**< altstep */
V_TESTCASE, /**< testcase */
V_INVOKE, /**< invoke operation */
V_REFER /**< refer(function) */
V_REFER, /**< refer(function) */
V_ANY_VALUE, /**< any value (?) - used by template concatenation */
V_ANY_OR_OMIT /**< any or omit (*) - used by template concatenation */
};
enum verdict_t {
......@@ -359,6 +362,7 @@ namespace Common {
Block *block;
verdict_t verdict;
Common::Assignment *refd_fat; /** function, altstep, testcase */
Ttcn::LengthRestriction* len_res; /** any value, any or omit */
} u;
/** Used to avoid infinite recursions of is_unfoldable() */
......@@ -454,11 +458,15 @@ namespace Common {
Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2);
/** Constructor used by decvalue_unichar*/
Value(operationtype_t p_optype, Ttcn::Ref_base *p_r1, Ttcn::Ref_base *p_r2, Value *p_v3);
/** Constructor used by V_ANY_VALUE and V_ANY_OR_OMIT */
Value(valuetype_t p_vt, Ttcn::LengthRestriction* p_len_res);
virtual ~Value();
virtual Value* clone() const;
valuetype_t get_valuetype() const {return valuetype;}
/** it it is not V_EXPR then fatal error. */
operationtype_t get_optype() const;
Value* get_concat_operand(bool first_operand) const;
Ttcn::LengthRestriction* take_length_restriction();
/** Sets the governor type. */
virtual void set_my_governor(Type *p_gov);
/** Gets the governor type. */
......
......@@ -39,6 +39,22 @@ namespace Common {
if (!p_indexed) vs = new vector<Value>();
else ivs = new vector<IndexedValue>();
}
Values::Values(const Values& p) : Node(p), indexed(p.indexed)
{
if (indexed) {
ivs = new vector<IndexedValue>();
for (size_t i = 0; i < p.ivs->size(); ++i) {
ivs->add((*p.ivs)[i]->clone());
}
}
else {
vs = new vector<Value>();
for (size_t i = 0; i < p.vs->size(); ++i) {
vs->add((*p.vs)[i]->clone());
}
}
}
Values::~Values()
{
......@@ -55,7 +71,7 @@ namespace Common {
Values *Values::clone() const
{
FATAL_ERROR("Values::clone");
return new Values(*this);
}
void Values::set_fullname(const string& p_fullname)
......@@ -165,6 +181,12 @@ namespace Common {
if (!p_index || !p_value)
FATAL_ERROR("NULL parameter: IndexedValue::IndexedValue()");
}
IndexedValue::IndexedValue(const IndexedValue& p) : Node(p), Location(p)
{
index = p.index->clone();
value = p.value->clone();
}
IndexedValue::~IndexedValue()
{
......@@ -174,7 +196,7 @@ namespace Common {
IndexedValue *IndexedValue::clone() const
{
FATAL_ERROR("IndexedValue::clone");
return new IndexedValue(*this);
}
void IndexedValue::set_fullname(const string& p_fullname)
......
This diff is collapsed.
......@@ -1953,6 +1953,7 @@ void SubType::chk_this_template(Template *templ)
case Template::ALL_FROM:
case Template::VALUE_LIST_ALL_FROM:
case Template::DECODE_MATCH:
case Template::TEMPLATE_CONCAT:
break;
case Template::SUPERSET_MATCH:
case Template::SUBSET_MATCH:
......
......@@ -8358,6 +8358,10 @@ namespace Ttcn {
case Template::DECODE_MATCH:
chk_defpar_template(body->get_decode_target()->get_Template(), exp_val);
break;
case Template::TEMPLATE_CONCAT:
chk_defpar_template(body->get_concat_operand(true), exp_val);
chk_defpar_template(body->get_concat_operand(false), exp_val);
break;
} // switch templatetype
}
......
......@@ -169,6 +169,22 @@ namespace Ttcn {
case Template::SPECIFIC_VALUE:
v_last = templ->get_specific_value();
break;
case Template::TEMPLATE_CONCAT:
if (templ->is_Value()) {
v = templ->get_Value();
v->set_my_governor(refcheckertype);
v->set_my_scope(ref->get_my_scope());
v->set_location(*ref);
refcheckertype->chk_this_value(v, 0, expected_value,
INCOMPLETE_NOT_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
v_last = v->get_value_refd_last();
}
else {
TTCN_pattern_error("Unable to resolve referenced '%s' to character "
"string type. Result of template concatenation is not a specific "
"value.", ref->get_dispname().c_str());
}
break;
case Template::CSTR_PATTERN:
if (!with_N) {
Ttcn::PatternString* ps = templ->get_cstr_pattern();
......
......@@ -10656,6 +10656,31 @@ error:
if (!p_ti) FATAL_ERROR("LogArgument::LogArgument()");
ti = p_ti;
}
LogArgument::LogArgument(const LogArgument& p) : logargtype(p.logargtype)
{
switch (logargtype) {
case L_ERROR:
break;
case L_UNDEF:
case L_TI:
ti = p.ti->clone();
break;
case L_VAL:
case L_MATCH:
case L_MACRO:
val = p.val->clone();
break;
case L_REF:
ref = p.ref->clone();
break;
case L_STR:
cstr = new string(*cstr);
break;
default:
FATAL_ERROR("LogArgument::LogArgument()");
} // switch
}
LogArgument::~LogArgument()
{
......@@ -10684,7 +10709,7 @@ error:
LogArgument *LogArgument::clone() const
{
FATAL_ERROR("LogArgument::clone");
return new LogArgument(*this);
}
void LogArgument::set_my_scope(Scope *p_scope)
......@@ -11115,6 +11140,13 @@ error:
// ===== LogArguments
// =================================
LogArguments::LogArguments(const LogArguments& p)
{
for (size_t i = 0; i < logargs.size(); ++i) {
logargs[i] = p.logargs[i]->clone();
}
}
LogArguments::~LogArguments()
{
for(size_t i=0; i<logargs.size(); i++) delete logargs[i];
......@@ -11123,7 +11155,7 @@ error:
LogArguments *LogArguments::clone() const
{
FATAL_ERROR("LogArguments::clone");
return new LogArguments(*this);
}
void LogArguments::add_logarg(LogArgument *p_logarg)
......
......@@ -520,6 +520,18 @@ namespace Ttcn {
range.lower = p_lower;
range.upper = p_upper;
}
LengthRestriction::LengthRestriction(const LengthRestriction& p)
: Node(), checked(p.checked), is_range(p.is_range)
{
if (is_range) {
range.lower = p.range.lower->clone();
range.upper = p.range.upper != NULL ? p.range.upper->clone() : NULL;
}
else {
single = p.single->clone();
}
}
LengthRestriction::~LengthRestriction()
{
......@@ -531,7 +543,7 @@ namespace Ttcn {
LengthRestriction *LengthRestriction::clone() const
{
FATAL_ERROR("LengthRestriction::clone");
return new LengthRestriction(*this);
}
void LengthRestriction::set_fullname(const string& p_fullname)
......
......@@ -238,7 +238,6 @@ namespace Ttcn {
} range;
};
/** Copy constructor disabled. */
LengthRestriction(const LengthRestriction& p);
/** Copy assignment disabled */
LengthRestriction& operator=(const LengthRestriction& p);
......
......@@ -97,6 +97,10 @@ namespace Ttcn {
p.u.dec_match.str_enc->clone() : NULL;
u.dec_match.target = p.u.dec_match.target->clone();
break;
case TEMPLATE_CONCAT:
u.concat.op1 = p.u.concat.op1->clone();
u.concat.op2 = p.u.concat.op2->clone();
break;
// default:
// FATAL_ERROR("Template::Template()");
}
......@@ -160,6 +164,10 @@ namespace Ttcn {
}
delete u.dec_match.target;
break;
case TEMPLATE_CONCAT:
delete u.concat.op1;
delete u.concat.op2;
break;
// default:
// FATAL_ERROR("Template::clean_up()");
}
......@@ -299,6 +307,11 @@ namespace Ttcn {
ret_val += ": ";
ret_val += u.dec_match.target->get_Template()->create_stringRepr();
break;
case TEMPLATE_CONCAT:
ret_val += u.concat.op1->create_stringRepr();
ret_val += " & ";
ret_val += u.concat.op2->create_stringRepr();
break;
default:
ret_val += "<unknown template>";
break;
......@@ -318,8 +331,8 @@ namespace Ttcn {
case TEMPLATE_ERROR:
case TEMPLATE_NOTUSED:
case OMIT_VALUE:
case ANY_VALUE:
case ANY_OR_OMIT:
//case ANY_VALUE:
//case ANY_OR_OMIT:
break;
default:
FATAL_ERROR("Template::Template()");
......@@ -328,12 +341,40 @@ namespace Ttcn {
Template::Template(Value *v)
: GovernedSimple(S_TEMPLATE),
templatetype(SPECIFIC_VALUE), my_governor(0), length_restriction(0),
templatetype(TEMPLATE_ERROR), my_governor(0), length_restriction(0),
is_ifpresent(false), specific_value_checked(false),
has_permutation(false), flattened(true), base_template(0)
{
if (!v) FATAL_ERROR("Template::Template()");
u.specific_value = v;
switch (v->get_valuetype()) {
case Value::V_ANY_VALUE:
case Value::V_ANY_OR_OMIT:
templatetype = v->get_valuetype() == Value::V_ANY_VALUE ?
ANY_VALUE : ANY_OR_OMIT;
set_length_restriction(v->take_length_restriction());
delete v;
break;
case Value::V_OMIT:
templatetype = OMIT_VALUE;
delete v;
break;
case Value::V_EXPR:
if (v->get_optype() == Value::OPTYPE_CONCAT) {
// convert the operands to templates with recursive calls to this constructor
templatetype = TEMPLATE_CONCAT;
u.concat.op1 = new Template(v->get_concat_operand(true)->clone());
u.concat.op1->set_location(*v->get_concat_operand(true));
u.concat.op2 = new Template(v->get_concat_operand(false)->clone());
u.concat.op2->set_location(*v->get_concat_operand(false));
delete v;
break;
}
// other expressions are specific value templates
default:
templatetype = SPECIFIC_VALUE;
u.specific_value = v;
break;
}
}
Template::Template(Ref_base *p_ref)
......@@ -559,6 +600,10 @@ namespace Ttcn {
}
u.dec_match.target->set_fullname(p_fullname + ".<decoding_target>");
break;
case TEMPLATE_CONCAT:
u.concat.op1->set_fullname(p_fullname + ".operand1");
u.concat.op2->set_fullname(p_fullname + ".operand2");
break;
// default:
// FATAL_ERROR("Template::set_fullname()");
}
......@@ -621,6 +666,10 @@ namespace Ttcn {
}
u.dec_match.target->set_my_scope(p_scope);
break;
case TEMPLATE_CONCAT:
u.concat.op1->set_my_scope(p_scope);
u.concat.op2->set_my_scope(p_scope);
break;
// default:
// FATAL_ERROR("Template::set_my_scope()");
}
......@@ -739,6 +788,10 @@ namespace Ttcn {
}
u.dec_match.target->set_code_section(p_code_section);
break;
case TEMPLATE_CONCAT:
u.concat.op1->set_code_section(p_code_section);
u.concat.op2->set_code_section(p_code_section);
break;
default:
break;
}
......@@ -909,6 +962,8 @@ namespace Ttcn {
return "universal string pattern";
case DECODE_MATCH:
return "decoded content match";
case TEMPLATE_CONCAT:
return "template concatenation";
default:
return "unknown template";
}
......@@ -953,6 +1008,10 @@ namespace Ttcn {
case VALUE_RANGE:
u.value_range->set_lowerid_to_ref();
break;
case TEMPLATE_CONCAT:
u.concat.op1->set_lowerid_to_ref();
u.concat.op2->set_lowerid_to_ref();
break;
default:
break;
}
......@@ -996,6 +1055,29 @@ namespace Ttcn {
return Type::T_CSTR;
case USTR_PATTERN:
return Type::T_USTR;
case TEMPLATE_CONCAT: {
Type::typetype_t tt1 = u.concat.op1->get_expr_returntype(exp_val);
Type::typetype_t tt2 = u.concat.op2->get_expr_returntype(exp_val);
if (tt1 == Type::T_UNDEF) {
if (tt2 == Type::T_UNDEF) {
return Type::T_UNDEF;
}
return tt2;
}
else {
if (tt2 == Type::T_UNDEF) {
return tt1;
}
if ((tt1 == Type::T_CSTR && tt2 == Type::T_USTR) ||
(tt1 == Type::T_USTR && tt2 == Type::T_CSTR)) {
return Type::T_USTR;
}
if (tt1 != tt2) {
return Type::T_ERROR;
}
return tt1;
}
}
default:
return Type::T_UNDEF;
}
......@@ -1047,6 +1129,35 @@ namespace Ttcn {
goto error;
}
break; }
case TEMPLATE_CONCAT: {
Type* t1 = u.concat.op1->get_expr_governor(exp_val);
Type* t2 = u.concat.op2->get_expr_governor(exp_val);
if (t1 == NULL) {
if (t2 == NULL) {
return NULL;
}
return t2;
}
else {
if (t2 == NULL) {
return t1;
}
Type::typetype_t tt1 = t1->get_type_refd_last()->get_typetype_ttcn3();
Type::typetype_t tt2 = t2->get_type_refd_last()->get_typetype_ttcn3();
if (tt1 == Type::T_CSTR && tt2 == Type::T_USTR) {
return t2;
}
if (tt1 == Type::T_USTR && tt2 == Type::T_CSTR) {
return t1;
}
if (tt1 != tt2) {
error("Operands of template concatenation are not compatible with "
"each other");
goto error;
}
return t1;
}
}
default:
return Type::get_pooltype(get_expr_returntype(exp_val));
}
......@@ -1069,6 +1180,7 @@ namespace Ttcn {
void Template::set_length_restriction(LengthRestriction *p_lr)
{
if (p_lr == NULL) return;
if (length_restriction) FATAL_ERROR("Template::set_length_restriction()");
length_restriction = p_lr;
}
......@@ -1372,7 +1484,7 @@ namespace Ttcn {