diff --git a/compiler2/ttcn3/TtcnTemplate.cc b/compiler2/ttcn3/TtcnTemplate.cc index bb13b36b80132024644db3a28a1b6c2d887d0f98..3aedcec5a0b356a7057ba6f4a29e82d7d45b3134 100644 --- a/compiler2/ttcn3/TtcnTemplate.cc +++ b/compiler2/ttcn3/TtcnTemplate.cc @@ -3914,56 +3914,30 @@ end: // ^^^^^^^--- these ------------------------^^^^^ // are known at compile time, but the length of the "all from" // is only known at run time. - // Collect the indices where there is an "all from". - - // variables.size() and templates.size() will be equal. - // templates[i] contains the variables[i] template. - dynamic_array<size_t> variables; - dynamic_array<size_t> templates; + size_t fixed_part = 0; - if (has_permutation) { - for (size_t i = 0; i < nof_ts; i++) { + char* str_set_size = NULL; + char* str_preamble = NULL; + char* str_body = NULL; + string counter = get_temporary_id(); + + if (has_permutation || has_allfrom()) { + str_body = mputprintf(str_body, "int %s = %lld;\n", counter.c_str(), index_offset); + for (size_t i = 0; i < nof_ts; ++i) { Template *t = u.templates->get_t_byIndex(i); - if (t->templatetype == PERMUTATION_MATCH) { - size_t num_p = t->u.templates->get_nof_ts(); - // t->u.templates is 2: "hello" and all from ... - for (size_t j = 0; j < num_p; ++j) { - Template *subt = t->u.templates->get_t_byIndex(j); - if (subt->templatetype == ALL_FROM) { - templates.add(i); - variables.add(j); - } - else fixed_part++; - } - } - else fixed_part++; - } - - char* str_preamble = 0; - char* str_set_size = mputprintf(0, "%s.set_size(%lu", name, - (unsigned long)fixed_part); - - // variable part - for (size_t i = 0, v = variables.size(); i < v; ++i) { - Template *t = u.templates->get_t_byIndex(templates[i]); - if (t->templatetype != PERMUTATION_MATCH) continue; // ?? really nothing to do ?? - Template *subt = t->u.templates->get_t_byIndex(variables[i]); - if (subt->templatetype == ALL_FROM) { - Value *refv = subt->u.all_from->u.specific_value; + if (t->templatetype == ALL_FROM) { + Value *refv = t->u.all_from->u.specific_value; // don't call get_Value(), it rips out the value from the template - if (refv->get_valuetype()!=Value::V_REFD) FATAL_ERROR("%s", __FUNCTION__); Common::Reference *ref = refv->get_reference(); FieldOrArrayRefs *subrefs = ref->get_subrefs(); Common::Assignment *ass = ref->get_refd_assignment(); - str_set_size = mputstrn(str_set_size, " + ", 3); - Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref); if (ref_pard) { - // in case of parametrised references: - // - temporary parameters need to be declared (stored in str_preamble) - // - the same temporary needs to be used at each call (generate_code_cached call) + // in case of parametrised references: + // - temporary parameters need to be declared (stored in str_preamble) + // - the same temporary needs to be used at each call (generate_code_cached call) expression_struct expr; Code::init_expr(&expr); @@ -3971,18 +3945,14 @@ end: str_set_size = mputprintf(str_set_size, "%s", expr.expr); if (expr.preamble) str_preamble = mputstr(str_preamble, expr.preamble); - Code::free_expr(&expr); - } - else { + } else { str_set_size = mputstr (str_set_size, ass->get_id().get_name().c_str()); if (subrefs) { expression_struct expr; Code::init_expr(&expr); - subrefs->generate_code(&expr, ass); str_set_size = mputprintf(str_set_size, "%s", expr.expr); - Code::free_expr(&expr); } } @@ -4006,39 +3976,133 @@ end: } str_set_size = mputstr(str_set_size, ".n_elem()"); - } - } - - str = mputstr(str, str_preamble); - str = mputstr(str, str_set_size); + expression_struct expr; + Code::init_expr(&expr); + switch (t->u.all_from->templatetype) { + case SPECIFIC_VALUE: { + Value *spec = t->u.all_from->u.specific_value; + switch (spec->get_valuetype()) { + case Common::Value::V_REFD: { + ref = spec->get_reference(); + ref_pard = dynamic_cast<Ref_pard*>(ref); + if (ref_pard) + ref_pard->generate_code_cached(&expr); + else + ref->generate_code(&expr); - Free(str_preamble); - Free(str_set_size); + ass = ref->get_refd_assignment(); + switch(ass->get_asstype()) { + case Common::Assignment::A_CONST: + case Common::Assignment::A_EXT_CONST: + case Common::Assignment::A_MODULEPAR: + case Common::Assignment::A_VAR: + case Common::Assignment::A_PAR_VAL_IN: + case Common::Assignment::A_PAR_VAL_OUT: + case Common::Assignment::A_PAR_VAL_INOUT: + case Common::Assignment::A_FUNCTION_RVAL: + case Common::Assignment::A_EXT_FUNCTION_RVAL: + if (ass->get_Type()->field_is_optional(ref->get_subrefs())) { + expr.expr = mputstrn(expr.expr, "()", 2); + } + break; + default: + break; + } - str = mputstrn(str, ");\n", 3); // finally done set_size - - size_t index = 0; - string skipper, hopper; - for (size_t i = 0; i < nof_ts; i++) { - Template *t = u.templates->get_t_byIndex(i); - switch (t->templatetype) { - case ALL_FROM: { - break; } - case PERMUTATION_MATCH: { + break; } + default: + FATAL_ERROR("vtype %d", spec->get_valuetype()); + break; + } + break; } + default: { + FATAL_ERROR("ttype %d", t->u.all_from->templatetype); + break; } + } + str_body = mputprintf(str_body, + "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n", + expr.expr); + str_body = t->generate_code_init_seof_element(str_body, name, + (counter + " + i_i").c_str(), + oftype_name_str); + str_body = mputstrn(str_body, "}\n", 2); + str_body = mputprintf(str_body, "%s += %s.n_elem();\n", counter.c_str(), expr.expr); + Code::free_expr(&expr); + t->set_code_generated(); + } else if (t->templatetype == PERMUTATION_MATCH) { + string permutation_start = get_temporary_id(); + str_body = mputprintf(str_body, "int %s = %s;\n", + permutation_start.c_str(), counter.c_str()); size_t nof_perm_ts = t->u.templates->get_nof_ts(); for (size_t j = 0; j < nof_perm_ts; j++) { - Int ix(index_offset + index + j); - Template *permut_elem = t->u.templates->get_t_byIndex(j); - if (permut_elem->templatetype == ALL_FROM) { + Template *subt = t->u.templates->get_t_byIndex(j); + if (subt->templatetype == ALL_FROM) { + Value *refv = subt->u.all_from->u.specific_value; + // don't call get_Value(), it rips out the value from the template + if (refv->get_valuetype()!=Value::V_REFD) FATAL_ERROR("%s", __FUNCTION__); + Common::Reference *ref = refv->get_reference(); + FieldOrArrayRefs *subrefs = ref->get_subrefs(); + Common::Assignment *ass = ref->get_refd_assignment(); + str_set_size = mputstrn(str_set_size, " + ", 3); + Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref); + if (ref_pard) { + // in case of parametrised references: + // - temporary parameters need to be declared (stored in str_preamble) + // - the same temporary needs to be used at each call (generate_code_cached call) + expression_struct expr; + Code::init_expr(&expr); + + ref_pard->generate_code_cached(&expr); + str_set_size = mputprintf(str_set_size, "%s", expr.expr); + if (expr.preamble) + str_preamble = mputstr(str_preamble, expr.preamble); + Code::free_expr(&expr); + } + else { + str_set_size = mputstr (str_set_size, ass->get_id().get_name().c_str()); + if (subrefs) { + expression_struct expr; + Code::init_expr(&expr); + subrefs->generate_code(&expr, ass); + str_set_size = mputprintf(str_set_size, "%s", expr.expr); + Code::free_expr(&expr); + } + } + + switch(ass->get_asstype()) { + case Common::Assignment::A_CONST: + case Common::Assignment::A_EXT_CONST: + case Common::Assignment::A_MODULEPAR: + case Common::Assignment::A_VAR: + case Common::Assignment::A_PAR_VAL_IN: + case Common::Assignment::A_PAR_VAL_OUT: + case Common::Assignment::A_PAR_VAL_INOUT: + case Common::Assignment::A_FUNCTION_RVAL: + case Common::Assignment::A_EXT_FUNCTION_RVAL: + if (ass->get_Type()->field_is_optional(subrefs)) { + str_set_size = mputstrn(str_set_size, "()", 2); + } + break; + default: + break; + } + + str_set_size = mputstr(str_set_size, ".n_elem()"); + } else { + fixed_part++; + str_body = subt->generate_code_init_seof_element(str_body, name, + counter.c_str(), oftype_name_str); + } + + if (subt->templatetype == ALL_FROM) { expression_struct expr; Code::init_expr(&expr); - switch (permut_elem->u.all_from->templatetype) { + switch (subt->u.all_from->templatetype) { case SPECIFIC_VALUE: { - Value *spec = permut_elem->u.all_from->u.specific_value; + Value *spec = subt->u.all_from->u.specific_value; switch (spec->get_valuetype()) { case Common::Value::V_REFD: { Common::Reference *ref = spec->get_reference(); - Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref); if (ref_pard) ref_pard->generate_code_cached(&expr); @@ -4063,221 +4127,63 @@ end: default: break; } - + break; } default: FATAL_ERROR("vtype %d", spec->get_valuetype()); break; } break; } - - default: - FATAL_ERROR("ttype %d", permut_elem->u.all_from->templatetype); + FATAL_ERROR("ttype %d", subt->u.all_from->templatetype); break; } - str = mputprintf(str, + str_body = mputprintf(str_body, "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n", expr.expr); - str = permut_elem->generate_code_init_seof_element(str, name, - (Int2string(ix) + skipper + " + i_i").c_str(), + str_body = subt->generate_code_init_seof_element(str_body, name, + (counter + " + i_i").c_str(), oftype_name_str); - str = mputstrn(str, "}\n", 2); - skipper += "-1+"; - skipper += expr.expr; - skipper += ".n_elem() /* 3005 */ "; + str_body = mputstrn(str_body, "}\n", 2); + str_body = mputprintf(str_body, "%s += %s.n_elem();\n", counter.c_str(), expr.expr); Code::free_expr(&expr); } else { - str = permut_elem->generate_code_init_seof_element(str, name, - (Int2string(ix) + skipper).c_str(), oftype_name_str); + str_body = subt->generate_code_init_seof_element(str_body, name, + counter.c_str(), oftype_name_str); + str_body = mputprintf(str_body, "%s++;\n", counter.c_str()); } + } // do not consider index_offset in case of permutation indicators - str = mputprintf(str, "%s.add_permutation(%lu%s, %lu%s);\n", name, - (unsigned long)index, hopper.c_str(), - (unsigned long)(index + nof_perm_ts - 1), skipper.c_str()); - hopper = skipper; + str_body = mputprintf(str_body, "%s.add_permutation(%s-%lld, %s-%lld-1);\n", name, + permutation_start.c_str(), index_offset, counter.c_str(), index_offset); t->set_code_generated(); - index += nof_perm_ts; - break; } - - default: - str = t->generate_code_init_seof_element(str, name, - (Int2string(index_offset + index) + skipper).c_str(), oftype_name_str); - // no break - case TEMPLATE_NOTUSED: - index++; - break; - } - } - - break; - - } - - - if (!has_permutation && has_allfrom()) { - for (size_t i = 0; i < nof_ts; i++) { - Template *t = u.templates->get_t_byIndex(i); - if (t->templatetype == ALL_FROM) { - variables.add(i); - } - else { + } else { fixed_part++; - } - } - char* str_preamble = 0; - char* str_set_size = mputprintf(0, "%s.set_size(%lu", name, - (unsigned long)fixed_part); - - // variable part - for (size_t i = 0, v = variables.size(); i < v; ++i) { - Template *t = u.templates->get_t_byIndex(variables[i]); - if (t->templatetype == ALL_FROM) { - Value *refv = t->u.all_from->u.specific_value; - // don't call get_Value(), it rips out the value from the template - if (refv->get_valuetype()!=Value::V_REFD) FATAL_ERROR("%s", __FUNCTION__); - Common::Reference *ref = refv->get_reference(); - FieldOrArrayRefs *subrefs = ref->get_subrefs(); - Common::Assignment *ass = ref->get_refd_assignment(); - str_set_size = mputstrn(str_set_size, " + ", 3); - Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref); - if (ref_pard) { - // in case of parametrised references: - // - temporary parameters need to be declared (stored in str_preamble) - // - the same temporary needs to be used at each call (generate_code_cached call) - expression_struct expr; - Code::init_expr(&expr); - - ref_pard->generate_code_cached(&expr); - str_set_size = mputprintf(str_set_size, "%s", expr.expr); - if (expr.preamble) - str_preamble = mputstr(str_preamble, expr.preamble); - Code::free_expr(&expr); - } - else { - str_set_size = mputstr (str_set_size, ass->get_id().get_name().c_str()); - if (subrefs) { - expression_struct expr; - Code::init_expr(&expr); - subrefs->generate_code(&expr, ass); - str_set_size = mputprintf(str_set_size, "%s", expr.expr); - Code::free_expr(&expr); - } - } - - switch(ass->get_asstype()) { - case Common::Assignment::A_CONST: - case Common::Assignment::A_EXT_CONST: - case Common::Assignment::A_MODULEPAR: - case Common::Assignment::A_VAR: - case Common::Assignment::A_PAR_VAL_IN: - case Common::Assignment::A_PAR_VAL_OUT: - case Common::Assignment::A_PAR_VAL_INOUT: - case Common::Assignment::A_FUNCTION_RVAL: - case Common::Assignment::A_EXT_FUNCTION_RVAL: - if (ass->get_Type()->field_is_optional(subrefs)) { - str_set_size = mputstrn(str_set_size, "()", 2); - } - break; - default: - break; - } - - str_set_size = mputstr(str_set_size, ".n_elem()"); + str_body = t->generate_code_init_seof_element(str_body, name, + counter.c_str(), oftype_name_str); + str_body = mputprintf(str_body, "%s++;\n", counter.c_str()); } } str = mputstr(str, str_preamble); - str = mputstr(str, str_set_size); + str = mputprintf(str, "%s.set_size(%lu", name, fixed_part); + if (str_set_size != NULL) { + str = mputstr(str, str_set_size); + } + str = mputstr(str, ");\n"); + str = mputstr(str, str_body); Free(str_preamble); Free(str_set_size); - str = mputstrn(str, ");\n", 3); // finally done set_size - - size_t index = 0; - string skipper; - for (size_t i = 0; i < nof_ts; i++) { - Template *t = u.templates->get_t_byIndex(i); - Int ix(index_offset + i); - switch (t->templatetype) { - case ALL_FROM: { - expression_struct expr; - Code::init_expr(&expr); - switch (t->u.all_from->templatetype) { - case SPECIFIC_VALUE: { - Value *spec = t->u.all_from->u.specific_value; - switch (spec->get_valuetype()) { - case Common::Value::V_REFD: { - Common::Reference *ref = spec->get_reference(); - Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref); - if (ref_pard) - ref_pard->generate_code_cached(&expr); - else - ref->generate_code(&expr); - - Common::Assignment* ass = ref->get_refd_assignment(); - switch(ass->get_asstype()) { - case Common::Assignment::A_CONST: - case Common::Assignment::A_EXT_CONST: - case Common::Assignment::A_MODULEPAR: - case Common::Assignment::A_VAR: - case Common::Assignment::A_PAR_VAL_IN: - case Common::Assignment::A_PAR_VAL_OUT: - case Common::Assignment::A_PAR_VAL_INOUT: - case Common::Assignment::A_FUNCTION_RVAL: - case Common::Assignment::A_EXT_FUNCTION_RVAL: - if (ass->get_Type()->field_is_optional(ref->get_subrefs())) { - expr.expr = mputstrn(expr.expr, "()", 2); - } - break; - default: - break; - } - - break; } - default: - FATAL_ERROR("vtype %d", spec->get_valuetype()); - break; - } - break; } - default: { - FATAL_ERROR("ttype %d", t->u.all_from->templatetype); - break; } - } - str = mputprintf(str, - "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n", - expr.expr); - str = t->generate_code_init_seof_element(str, name, - (Int2string(ix) + skipper + " + i_i").c_str(), - oftype_name_str); - str = mputstrn(str, "}\n", 2); - skipper += "-1+"; - skipper += expr.expr; - skipper += ".n_elem() "; - Code::free_expr(&expr); - t->set_code_generated(); - ++index; - break; } - default: { - str = t->generate_code_init_seof_element(str, name, - (Int2string(index_offset + index) + skipper).c_str(), oftype_name_str); - // no break - case TEMPLATE_NOTUSED: - ++index; - break; } - } - } - break; + Free(str_body); + return str; } - - // else carry on } compile_time: // setting the size first - if (!has_allfrom()) - str = mputprintf(str, "%s.set_size(%lu);\n", name, (unsigned long) get_nof_listitems()); + str = mputprintf(str, "%s.set_size(%lu);\n", name, (unsigned long) get_nof_listitems()); // determining the index offset based on the governor size_t index = 0; diff --git a/regression_test/all_from/all_from_permutation.ttcn b/regression_test/all_from/all_from_permutation.ttcn index e4688229e3c86aa780f2780eec1b4cde2b520a03..b627857d41c57596d3b8755159a8056836668ce8 100644 --- a/regression_test/all_from/all_from_permutation.ttcn +++ b/regression_test/all_from/all_from_permutation.ttcn @@ -1803,5 +1803,16 @@ testcase tc_perm_varTemplate_two_var_unfoldable() runs on A f_checkRoITemplateEquivalence(tl_len_res, tl_len_res_eq); } +testcase tc_perm_varTemplate_array_unfoldable() runs on A +{ + var template RoI tl_unfoldable4 := { 6 }; + var template IntArray tl_arr_res := { 1, permutation ( 2, all from tl_unfoldable4, 3), 4, 5 }; + var template IntArray tl_arr_res_eq := { 1, permutation ( 2, 6, 3 ), 4, 5 }; + if (log2str(tl_arr_res) != log2str(tl_arr_res_eq)) { + setverdict(fail, match(log2str(tl_arr_res), log2str(tl_arr_res_eq))); + } + setverdict(pass); +} + } // end of module diff --git a/regression_test/all_from/types.ttcn b/regression_test/all_from/types.ttcn index 83d90eaba43e2bd97b743ba113dc4c3f9a343fa7..90e5ed67af7fdccd31c6b78d9f4d18b54c980348 100644 --- a/regression_test/all_from/types.ttcn +++ b/regression_test/all_from/types.ttcn @@ -9,6 +9,7 @@ * Balasko, Jeno * Baranyi, Botond * Raduly, Csaba + * Szabo, Bence Janos * ******************************************************************************/ module types { @@ -57,6 +58,8 @@ type union MyUnion { type record of MyRecord RoMyRec; type record of MyUnion RoMyUnion; +type integer IntArray[3..8]; + //==== Function Reference ==== //this is just a dummy type to test all from for function references type function F_int2int(in integer pl_i) return integer;