1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 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
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "ArrayDimensions.hh"
9 #include "../string.hh"
10 #include "../CompilerError.hh"
12 #include "../Value.hh"
13 #include "AST_ttcn3.hh"
19 using namespace Common
;
21 // =================================
22 // ===== ArrayDimension
23 // =================================
25 ArrayDimension::ArrayDimension(const ArrayDimension
& p
)
26 : Node(p
), Location(p
), checked(false), is_range(p
.is_range
),
27 has_error(false), size(0), offset(0)
30 u
.range
.lower
= p
.u
.range
.lower
->clone();
31 u
.range
.upper
= p
.u
.range
.upper
->clone();
33 u
.single
= p
.u
.single
->clone();
37 ArrayDimension::ArrayDimension(Value
*p_single
)
38 : Node(), checked(false), is_range(false), has_error(false),
41 if (!p_single
) FATAL_ERROR("ArrayDimension::ArrayDimension()");
45 ArrayDimension::ArrayDimension(Value
*p_lower
, Value
*p_upper
)
46 : Node(), checked(false), is_range(true), has_error(false),
49 if (!p_lower
|| !p_upper
) FATAL_ERROR("ArrayDimension::ArrayDimension()");
50 u
.range
.lower
= p_lower
;
51 u
.range
.upper
= p_upper
;
54 ArrayDimension::~ArrayDimension()
64 ArrayDimension
*ArrayDimension::clone() const
66 return new ArrayDimension(*this);
69 void ArrayDimension::set_my_scope(Scope
*p_scope
)
71 if (!p_scope
) FATAL_ERROR("ArrayDimension::set_my_scope()");
74 u
.range
.lower
->set_my_scope(p_scope
);
75 u
.range
.upper
->set_my_scope(p_scope
);
77 u
.single
->set_my_scope(p_scope
);
81 void ArrayDimension::set_fullname(const string
& p_fullname
)
83 Node::set_fullname(p_fullname
);
85 u
.range
.lower
->set_fullname(p_fullname
+ ".<lower>");
86 u
.range
.upper
->set_fullname(p_fullname
+ ".<upper>");
88 u
.single
->set_fullname(p_fullname
);
92 void ArrayDimension::chk()
100 Error_Context
cntxt(u
.range
.lower
, "In lower bound of array indices");
101 u
.range
.lower
->chk_expr_int(Type::EXPECTED_CONSTANT
);
104 Error_Context
cntxt(u
.range
.upper
, "In upper bound of array indices");
105 u
.range
.upper
->chk_expr_int(Type::EXPECTED_CONSTANT
);
107 Value
*v_lower
= u
.range
.lower
->get_value_refd_last();
108 if (v_lower
->get_valuetype() != Value::V_INT
) has_error
= true;
109 Value
*v_upper
= u
.range
.upper
->get_value_refd_last();
110 if (v_upper
->get_valuetype() != Value::V_INT
) has_error
= true;
112 const int_val_t
*lower_int
= v_lower
->get_val_Int();
113 const int_val_t
*upper_int
= v_upper
->get_val_Int();
114 if (*lower_int
> INT_MAX
) {
115 u
.range
.lower
->error("The lower bound of an array index should be "
116 "less than `%d' instead of `%s'", INT_MAX
,
117 (lower_int
->t_str()).c_str());
120 if (*upper_int
> INT_MAX
) {
121 u
.range
.upper
->error("The upper bound of an array index should be "
122 "less than `%d' instead of `%s'", INT_MAX
,
123 (upper_int
->t_str()).c_str());
127 Int lower
= lower_int
->get_val();
128 Int upper
= upper_int
->get_val();
130 error("The lower bound of array index (%s) is "
131 "greater than the upper bound (%s)", Int2string(lower
).c_str(),
132 Int2string(upper
).c_str());
135 int_size
= upper
- lower
+ 1;
142 Error_Context
cntxt(u
.single
, "In array size");
143 u
.single
->chk_expr_int(Type::EXPECTED_CONSTANT
);
145 Value
*v
= u
.single
->get_value_refd_last();
146 if (v
->get_valuetype() != Value::V_INT
) has_error
= true;
148 const int_val_t
*int_size_int
= v
->get_val_Int();
149 if (*int_size_int
> INT_MAX
) {
150 u
.single
->error("The array size should be less than `%d' instead "
151 "of `%s'", INT_MAX
, (int_size_int
->t_str()).c_str());
155 int_size
= int_size_int
->get_val();
157 u
.single
->error("A positive integer value was expected as array "
158 "size instead of `%s'", Int2string(int_size
).c_str());
168 size
= static_cast<size_t>(int_size
);
169 if (static_cast<Int
>(size
) != int_size
) {
170 error("Array size `%s' is too large for being represented in memory",
171 Int2string(int_size
).c_str());
177 void ArrayDimension::chk_index(Value
*index
, Type::expected_value_t exp_val
)
180 index
->chk_expr_int(exp_val
);
181 if (has_error
|| index
->is_unfoldable()) return;
182 const int_val_t
*v_index_int
= index
->get_value_refd_last()
184 if (*v_index_int
< offset
) {
185 index
->error("Array index underflow: the index value must be at least "
186 "`%s' instead of `%s'", Int2string(offset
).c_str(),
187 (v_index_int
->t_str()).c_str());
188 index
->set_valuetype(Value::V_ERROR
);
189 } else if (*v_index_int
>= offset
+ static_cast<Int
>(size
)) {
190 index
->error("Array index overflow: the index value must be at most "
191 "`%s' instead of `%s'", Int2string(offset
+ size
- 1).c_str(),
192 (v_index_int
->t_str()).c_str());
193 index
->set_valuetype(Value::V_ERROR
);
197 size_t ArrayDimension::get_size()
200 if (has_error
) return 0;
204 Int
ArrayDimension::get_offset()
207 if (has_error
) return 0;
211 string
ArrayDimension::get_stringRepr()
215 if (has_error
) ret_val
+= "<erroneous>";
217 ret_val
+= Int2string(offset
);
219 ret_val
+= Int2string(offset
+ size
- 1);
220 } else ret_val
+= Int2string(size
);
225 bool ArrayDimension::is_identical(ArrayDimension
*p_dim
)
227 if (!p_dim
) FATAL_ERROR("ArrayDimension::is_identical()");
229 if (!p_dim
->checked
) p_dim
->chk();
230 if (has_error
|| p_dim
->has_error
) return true;
231 else return size
== p_dim
->size
&& offset
== p_dim
->offset
;
234 string
ArrayDimension::get_value_type(Type
*p_element_type
, Scope
*p_scope
)
237 if (has_error
) FATAL_ERROR("ArrayDimension::get_value_type()");
238 string
ret_val("VALUE_ARRAY<");
239 ret_val
+= p_element_type
->get_genname_value(p_scope
);
241 ret_val
+= Int2string(size
);
243 ret_val
+= Int2string(offset
);
248 string
ArrayDimension::get_template_type(Type
*p_element_type
, Scope
*p_scope
)
251 if (has_error
) FATAL_ERROR("ArrayDimension::get_template_type()");
252 string
ret_val("TEMPLATE_ARRAY<");
253 ret_val
+= p_element_type
->get_genname_value(p_scope
);
255 ret_val
+= p_element_type
->get_genname_template(p_scope
);
257 ret_val
+= Int2string(size
);
259 ret_val
+= Int2string(offset
);
264 void ArrayDimension::dump(unsigned level
) const
266 DEBUG(level
, "Array dimension:");
268 u
.range
.lower
->dump(level
+ 1);
270 u
.range
.upper
->dump(level
+ 1);
272 u
.single
->dump(level
+ 1);
276 // =================================
277 // ===== ArrayDimensions
278 // =================================
280 ArrayDimensions::~ArrayDimensions()
282 for (size_t i
= 0; i
< dims
.size(); i
++) delete dims
[i
];
286 ArrayDimensions
*ArrayDimensions::clone() const
288 FATAL_ERROR("ArrayDimensions::clone");
291 void ArrayDimensions::set_my_scope(Scope
*p_scope
)
293 for (size_t i
= 0; i
< dims
.size(); i
++) dims
[i
]->set_my_scope(p_scope
);
296 void ArrayDimensions::set_fullname(const string
& p_fullname
)
298 Node::set_fullname(p_fullname
);
299 for (size_t i
= 0; i
< dims
.size(); i
++)
300 dims
[i
]->set_fullname(p_fullname
+ "." + Int2string(i
+ 1));
303 void ArrayDimensions::add(ArrayDimension
*dim
)
305 if (!dim
) FATAL_ERROR("ArrayDimensions::add()");
309 void ArrayDimensions::chk()
311 for (size_t i
= 0; i
< dims
.size(); i
++) {
312 ArrayDimension
*dim
= dims
[i
];
313 Error_Context
cntxt(dim
, "In array dimension #%lu", (unsigned long)(i
+1));
318 void ArrayDimensions::chk_indices(Common::Reference
*ref
, const char *def_name
,
319 bool allow_slicing
, Type::expected_value_t exp_val
)
321 FieldOrArrayRefs
*subrefs
= ref
->get_subrefs();
324 ref
->error("Reference to a %s array without array index", def_name
);
327 size_t nof_refs
= subrefs
->get_nof_refs(), nof_dims
= dims
.size();
328 size_t upper_limit
= nof_refs
> nof_dims
? nof_dims
: nof_refs
;
329 for (size_t i
= 0; i
< upper_limit
; i
++) {
330 FieldOrArrayRef
*subref
= subrefs
->get_ref(i
);
331 if (subref
->get_type() != FieldOrArrayRef::ARRAY_REF
) {
332 subref
->error("Invalid field reference `%s' in a %s array",
333 subref
->get_id()->get_dispname().c_str(), def_name
);
336 Error_Context
cntxt(subref
, "In array index #%lu", (unsigned long)(i
+1));
337 dims
[i
]->chk_index(subref
->get_val(), exp_val
);
339 if (nof_refs
< nof_dims
) {
340 if (!allow_slicing
) ref
->error("Too few indices in a reference to a %s "
341 "array: the array has %lu dimensions, but the reference has only %lu "
342 "array %s", def_name
, (unsigned long)nof_dims
, (unsigned long)nof_refs
,
343 nof_refs
> 1 ? "indices" : "index");
344 } else if (nof_refs
> nof_dims
) {
345 ref
->error("Too many indices in a reference to a %s array: the reference "
346 "has %lu array indices, but the array has only %lu dimension%s",
347 def_name
, (unsigned long) nof_refs
, (unsigned long) nof_dims
,
348 nof_dims
> 1 ? "s" : "");
352 size_t ArrayDimensions::get_array_size()
355 for (size_t i
= 0; i
< dims
.size(); i
++)
356 ret_val
*= dims
[i
]->get_size();
360 char *ArrayDimensions::generate_element_names(char *str
,
361 const string
& p_name
, size_t start_dim
)
363 ArrayDimension
*dim
= dims
[start_dim
];
364 size_t dim_size
= dim
->get_size();
365 Int dim_offset
= dim
->get_offset();
366 if (start_dim
+ 1 < dims
.size()) {
367 // there are more dimensions to generate
368 for (size_t i
= 0; i
< dim_size
; i
++) {
369 if (i
> 0) str
= mputstr(str
, ", ");
370 str
= generate_element_names(str
,
371 p_name
+ "[" + Int2string(dim_offset
+ i
) + "]", start_dim
+ 1);
374 // we are in the last dimension
375 for (size_t i
= 0; i
< dim_size
; i
++) {
376 if (i
> 0) str
= mputstr(str
, ", ");
377 str
= mputprintf(str
, "\"%s[%s]\"", p_name
.c_str(),
378 Int2string(dim_offset
+ i
).c_str());
384 string
ArrayDimensions::get_timer_type(size_t start_dim
)
386 string
ret_val("TIMER");
387 // the wrapping is started with the rightmost array dimension
388 for (size_t i
= dims
.size(); i
> start_dim
; i
--) {
389 ArrayDimension
*dim
= dims
[i
- 1];
390 ret_val
= "TIMER_ARRAY<" + ret_val
+ ", " + Int2string(dim
->get_size()) +
391 ", " + Int2string(dim
->get_offset()) + ">";
396 string
ArrayDimensions::get_port_type(const string
& p_genname
)
398 string
ret_val(p_genname
);
399 // the wrapping is started with the rightmost array dimension
400 for (size_t i
= dims
.size(); i
> 0; i
--) {
401 ArrayDimension
*dim
= dims
[i
- 1];
402 ret_val
= "PORT_ARRAY<" + ret_val
+ ", " + Int2string(dim
->get_size()) +
403 ", " + Int2string(dim
->get_offset()) + ">";
408 void ArrayDimensions::dump(unsigned level
) const
410 DEBUG(level
, "Array dimensions: (%lu pcs.)", (unsigned long) dims
.size());
411 for (size_t i
= 0; i
< dims
.size(); i
++) dims
[i
]->dump(level
+ 1);
414 bool ArrayDimensions::is_identical(ArrayDimensions
*other
)
416 if (!other
) FATAL_ERROR("ArrayDimensions::is_identical()");
417 if (dims
.size()!=other
->dims
.size()) return false;
418 for (size_t i
= 0; i
< dims
.size(); i
++)
419 if (!dims
[i
]->is_identical(other
->dims
[i
])) return false;
This page took 0.04008 seconds and 5 git commands to generate.