1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
14 ******************************************************************************/
15 #include "ArrayDimensions.hh"
16 #include "../string.hh"
17 #include "../CompilerError.hh"
19 #include "../Value.hh"
20 #include "AST_ttcn3.hh"
26 using namespace Common
;
28 // =================================
29 // ===== ArrayDimension
30 // =================================
32 ArrayDimension::ArrayDimension(const ArrayDimension
& p
)
33 : Node(p
), Location(p
), checked(false), is_range(p
.is_range
),
34 has_error(false), size(0), offset(0)
37 u
.range
.lower
= p
.u
.range
.lower
->clone();
38 u
.range
.upper
= p
.u
.range
.upper
->clone();
40 u
.single
= p
.u
.single
->clone();
44 ArrayDimension::ArrayDimension(Value
*p_single
)
45 : Node(), checked(false), is_range(false), has_error(false),
48 if (!p_single
) FATAL_ERROR("ArrayDimension::ArrayDimension()");
52 ArrayDimension::ArrayDimension(Value
*p_lower
, Value
*p_upper
)
53 : Node(), checked(false), is_range(true), has_error(false),
56 if (!p_lower
|| !p_upper
) FATAL_ERROR("ArrayDimension::ArrayDimension()");
57 u
.range
.lower
= p_lower
;
58 u
.range
.upper
= p_upper
;
61 ArrayDimension::~ArrayDimension()
71 ArrayDimension
*ArrayDimension::clone() const
73 return new ArrayDimension(*this);
76 void ArrayDimension::set_my_scope(Scope
*p_scope
)
78 if (!p_scope
) FATAL_ERROR("ArrayDimension::set_my_scope()");
81 u
.range
.lower
->set_my_scope(p_scope
);
82 u
.range
.upper
->set_my_scope(p_scope
);
84 u
.single
->set_my_scope(p_scope
);
88 void ArrayDimension::set_fullname(const string
& p_fullname
)
90 Node::set_fullname(p_fullname
);
92 u
.range
.lower
->set_fullname(p_fullname
+ ".<lower>");
93 u
.range
.upper
->set_fullname(p_fullname
+ ".<upper>");
95 u
.single
->set_fullname(p_fullname
);
99 void ArrayDimension::chk()
107 Error_Context
cntxt(u
.range
.lower
, "In lower bound of array indices");
108 u
.range
.lower
->chk_expr_int(Type::EXPECTED_CONSTANT
);
111 Error_Context
cntxt(u
.range
.upper
, "In upper bound of array indices");
112 u
.range
.upper
->chk_expr_int(Type::EXPECTED_CONSTANT
);
114 Value
*v_lower
= u
.range
.lower
->get_value_refd_last();
115 if (v_lower
->get_valuetype() != Value::V_INT
) has_error
= true;
116 Value
*v_upper
= u
.range
.upper
->get_value_refd_last();
117 if (v_upper
->get_valuetype() != Value::V_INT
) has_error
= true;
119 const int_val_t
*lower_int
= v_lower
->get_val_Int();
120 const int_val_t
*upper_int
= v_upper
->get_val_Int();
121 if (*lower_int
> INT_MAX
) {
122 u
.range
.lower
->error("The lower bound of an array index should be "
123 "less than `%d' instead of `%s'", INT_MAX
,
124 (lower_int
->t_str()).c_str());
127 if (*upper_int
> INT_MAX
) {
128 u
.range
.upper
->error("The upper bound of an array index should be "
129 "less than `%d' instead of `%s'", INT_MAX
,
130 (upper_int
->t_str()).c_str());
134 Int lower
= lower_int
->get_val();
135 Int upper
= upper_int
->get_val();
137 error("The lower bound of array index (%s) is "
138 "greater than the upper bound (%s)", Int2string(lower
).c_str(),
139 Int2string(upper
).c_str());
142 int_size
= upper
- lower
+ 1;
149 Error_Context
cntxt(u
.single
, "In array size");
150 u
.single
->chk_expr_int(Type::EXPECTED_CONSTANT
);
152 Value
*v
= u
.single
->get_value_refd_last();
153 if (v
->get_valuetype() != Value::V_INT
) has_error
= true;
155 const int_val_t
*int_size_int
= v
->get_val_Int();
156 if (*int_size_int
> INT_MAX
) {
157 u
.single
->error("The array size should be less than `%d' instead "
158 "of `%s'", INT_MAX
, (int_size_int
->t_str()).c_str());
162 int_size
= int_size_int
->get_val();
164 u
.single
->error("A positive integer value was expected as array "
165 "size instead of `%s'", Int2string(int_size
).c_str());
175 size
= static_cast<size_t>(int_size
);
176 if (static_cast<Int
>(size
) != int_size
) {
177 error("Array size `%s' is too large for being represented in memory",
178 Int2string(int_size
).c_str());
184 void ArrayDimension::chk_index(Value
*index
, Type::expected_value_t exp_val
)
187 index
->chk_expr_int(exp_val
);
188 if (has_error
|| index
->is_unfoldable()) return;
189 const int_val_t
*v_index_int
= index
->get_value_refd_last()
191 if (*v_index_int
< offset
) {
192 index
->error("Array index underflow: the index value must be at least "
193 "`%s' instead of `%s'", Int2string(offset
).c_str(),
194 (v_index_int
->t_str()).c_str());
195 index
->set_valuetype(Value::V_ERROR
);
196 } else if (*v_index_int
>= offset
+ static_cast<Int
>(size
)) {
197 index
->error("Array index overflow: the index value must be at most "
198 "`%s' instead of `%s'", Int2string(offset
+ size
- 1).c_str(),
199 (v_index_int
->t_str()).c_str());
200 index
->set_valuetype(Value::V_ERROR
);
204 size_t ArrayDimension::get_size()
207 if (has_error
) return 0;
211 Int
ArrayDimension::get_offset()
214 if (has_error
) return 0;
218 string
ArrayDimension::get_stringRepr()
222 if (has_error
) ret_val
+= "<erroneous>";
224 ret_val
+= Int2string(offset
);
226 ret_val
+= Int2string(offset
+ size
- 1);
227 } else ret_val
+= Int2string(size
);
232 bool ArrayDimension::is_identical(ArrayDimension
*p_dim
)
234 if (!p_dim
) FATAL_ERROR("ArrayDimension::is_identical()");
236 if (!p_dim
->checked
) p_dim
->chk();
237 if (has_error
|| p_dim
->has_error
) return true;
238 else return size
== p_dim
->size
&& offset
== p_dim
->offset
;
241 string
ArrayDimension::get_value_type(Type
*p_element_type
, Scope
*p_scope
)
244 if (has_error
) FATAL_ERROR("ArrayDimension::get_value_type()");
245 string
ret_val("VALUE_ARRAY<");
246 ret_val
+= p_element_type
->get_genname_value(p_scope
);
248 ret_val
+= Int2string(size
);
250 ret_val
+= Int2string(offset
);
255 string
ArrayDimension::get_template_type(Type
*p_element_type
, Scope
*p_scope
)
258 if (has_error
) FATAL_ERROR("ArrayDimension::get_template_type()");
259 string
ret_val("TEMPLATE_ARRAY<");
260 ret_val
+= p_element_type
->get_genname_value(p_scope
);
262 ret_val
+= p_element_type
->get_genname_template(p_scope
);
264 ret_val
+= Int2string(size
);
266 ret_val
+= Int2string(offset
);
271 void ArrayDimension::dump(unsigned level
) const
273 DEBUG(level
, "Array dimension:");
275 u
.range
.lower
->dump(level
+ 1);
277 u
.range
.upper
->dump(level
+ 1);
279 u
.single
->dump(level
+ 1);
283 // =================================
284 // ===== ArrayDimensions
285 // =================================
287 ArrayDimensions::~ArrayDimensions()
289 for (size_t i
= 0; i
< dims
.size(); i
++) delete dims
[i
];
293 ArrayDimensions
*ArrayDimensions::clone() const
295 FATAL_ERROR("ArrayDimensions::clone");
298 void ArrayDimensions::set_my_scope(Scope
*p_scope
)
300 for (size_t i
= 0; i
< dims
.size(); i
++) dims
[i
]->set_my_scope(p_scope
);
303 void ArrayDimensions::set_fullname(const string
& p_fullname
)
305 Node::set_fullname(p_fullname
);
306 for (size_t i
= 0; i
< dims
.size(); i
++)
307 dims
[i
]->set_fullname(p_fullname
+ "." + Int2string(i
+ 1));
310 void ArrayDimensions::add(ArrayDimension
*dim
)
312 if (!dim
) FATAL_ERROR("ArrayDimensions::add()");
316 void ArrayDimensions::chk()
318 for (size_t i
= 0; i
< dims
.size(); i
++) {
319 ArrayDimension
*dim
= dims
[i
];
320 Error_Context
cntxt(dim
, "In array dimension #%lu", (unsigned long)(i
+1));
325 void ArrayDimensions::chk_indices(Common::Reference
*ref
, const char *def_name
,
326 bool allow_slicing
, Type::expected_value_t exp_val
)
328 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
331 ref
->error("Reference to a %s array without array index", def_name
);
334 size_t nof_refs
= subrefs
->get_nof_refs(), nof_dims
= dims
.size();
335 size_t upper_limit
= nof_refs
> nof_dims
? nof_dims
: nof_refs
;
336 for (size_t i
= 0; i
< upper_limit
; i
++) {
337 FieldOrArrayRef
*subref
= subrefs
->get_ref(i
);
338 if (subref
->get_type() != FieldOrArrayRef::ARRAY_REF
) {
339 subref
->error("Invalid field reference `%s' in a %s array",
340 subref
->get_id()->get_dispname().c_str(), def_name
);
343 Error_Context
cntxt(subref
, "In array index #%lu", (unsigned long)(i
+1));
344 dims
[i
]->chk_index(subref
->get_val(), exp_val
);
346 if (nof_refs
< nof_dims
) {
347 if (!allow_slicing
) ref
->error("Too few indices in a reference to a %s "
348 "array: the array has %lu dimensions, but the reference has only %lu "
349 "array %s", def_name
, (unsigned long)nof_dims
, (unsigned long)nof_refs
,
350 nof_refs
> 1 ? "indices" : "index");
351 } else if (nof_refs
> nof_dims
) {
352 ref
->error("Too many indices in a reference to a %s array: the reference "
353 "has %lu array indices, but the array has only %lu dimension%s",
354 def_name
, (unsigned long) nof_refs
, (unsigned long) nof_dims
,
355 nof_dims
> 1 ? "s" : "");
359 size_t ArrayDimensions::get_array_size()
362 for (size_t i
= 0; i
< dims
.size(); i
++)
363 ret_val
*= dims
[i
]->get_size();
367 char *ArrayDimensions::generate_element_names(char *str
,
368 const string
& p_name
, size_t start_dim
)
370 ArrayDimension
*dim
= dims
[start_dim
];
371 size_t dim_size
= dim
->get_size();
372 Int dim_offset
= dim
->get_offset();
373 if (start_dim
+ 1 < dims
.size()) {
374 // there are more dimensions to generate
375 for (size_t i
= 0; i
< dim_size
; i
++) {
376 if (i
> 0) str
= mputstr(str
, ", ");
377 str
= generate_element_names(str
,
378 p_name
+ "[" + Int2string(dim_offset
+ i
) + "]", start_dim
+ 1);
381 // we are in the last dimension
382 for (size_t i
= 0; i
< dim_size
; i
++) {
383 if (i
> 0) str
= mputstr(str
, ", ");
384 str
= mputprintf(str
, "\"%s[%s]\"", p_name
.c_str(),
385 Int2string(dim_offset
+ i
).c_str());
391 string
ArrayDimensions::get_timer_type(size_t start_dim
)
393 string
ret_val("TIMER");
394 // the wrapping is started with the rightmost array dimension
395 for (size_t i
= dims
.size(); i
> start_dim
; i
--) {
396 ArrayDimension
*dim
= dims
[i
- 1];
397 ret_val
= "TIMER_ARRAY<" + ret_val
+ ", " + Int2string(dim
->get_size()) +
398 ", " + Int2string(dim
->get_offset()) + ">";
403 string
ArrayDimensions::get_port_type(const string
& p_genname
)
405 string
ret_val(p_genname
);
406 // the wrapping is started with the rightmost array dimension
407 for (size_t i
= dims
.size(); i
> 0; i
--) {
408 ArrayDimension
*dim
= dims
[i
- 1];
409 ret_val
= "PORT_ARRAY<" + ret_val
+ ", " + Int2string(dim
->get_size()) +
410 ", " + Int2string(dim
->get_offset()) + ">";
415 void ArrayDimensions::dump(unsigned level
) const
417 DEBUG(level
, "Array dimensions: (%lu pcs.)", (unsigned long) dims
.size());
418 for (size_t i
= 0; i
< dims
.size(); i
++) dims
[i
]->dump(level
+ 1);
421 bool ArrayDimensions::is_identical(ArrayDimensions
*other
)
423 if (!other
) FATAL_ERROR("ArrayDimensions::is_identical()");
424 if (dims
.size()!=other
->dims
.size()) return false;
425 for (size_t i
= 0; i
< dims
.size(); i
++)
426 if (!dims
[i
]->is_identical(other
->dims
[i
])) return false;
This page took 0.039688 seconds and 5 git commands to generate.