212
var next_method = iterator_type.get_member ("next") as Method;
213
if (next_method == null) {
214
Report.error (collection.source_reference, "`%s' does not have a `next' method".printf (iterator_type.to_string ()));
218
if (next_method.get_parameters ().size != 0) {
219
Report.error (collection.source_reference, "`%s' must not have any parameters".printf (next_method.get_full_name ()));
223
if (!next_method.return_type.compatible (analyzer.bool_type)) {
224
Report.error (collection.source_reference, "`%s' must return a boolean value".printf (next_method.get_full_name ()));
228
var get_method = iterator_type.get_member ("get") as Method;
229
if (get_method == null) {
230
Report.error (collection.source_reference, "`%s' does not have a `get' method".printf (iterator_type.to_string ()));
234
if (get_method.get_parameters ().size != 0) {
235
Report.error (collection.source_reference, "`%s' must not have any parameters".printf (get_method.get_full_name ()));
239
var element_type = get_method.return_type.get_actual_type (iterator_type, null, this);
240
if (element_type is VoidType) {
241
Report.error (collection.source_reference, "`%s' must return an element".printf (get_method.get_full_name ()));
246
// analyze element type
247
if (type_reference == null) {
249
type_reference = element_type.copy ();
250
} else if (!element_type.compatible (type_reference)) {
252
Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_type.to_string (), type_reference.to_string ()));
254
} else if (element_type.is_disposable () && element_type.value_owned && !type_reference.value_owned) {
256
Report.error (source_reference, "Foreach: Invalid assignment from owned expression to unowned variable");
260
213
var iterator_call = new MethodCall (new MemberAccess (collection, "iterator"));
261
214
add_statement (new DeclarationStatement (new LocalVariable (iterator_type, "_%s_it".printf (variable_name), iterator_call, source_reference), source_reference));
263
var next_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("_%s_it".printf (variable_name), source_reference), "next", source_reference), source_reference);
264
var loop = new WhileStatement (next_call, body, source_reference);
265
add_statement (loop);
267
var get_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("_%s_it".printf (variable_name), source_reference), "get", source_reference), source_reference);
268
body.insert_statement (0, new DeclarationStatement (new LocalVariable (type_reference, variable_name, get_call, source_reference), source_reference));
216
var next_value_method = iterator_type.get_member ("next_value") as Method;
217
var next_method = iterator_type.get_member ("next") as Method;
218
if (next_value_method != null) {
219
if (next_value_method.get_parameters ().size != 0) {
220
Report.error (collection.source_reference, "`%s' must not have any parameters".printf (next_value_method.get_full_name ()));
224
var element_type = next_value_method.return_type.get_actual_type (iterator_type, null, this);
225
if (!element_type.nullable) {
226
Report.error (collection.source_reference, "return type of `%s' must be nullable".printf (next_value_method.get_full_name ()));
231
if (!analyze_element_type (element_type)) {
235
add_statement (new DeclarationStatement (new LocalVariable (type_reference, variable_name, null, source_reference), source_reference));
237
var next_value_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("_%s_it".printf (variable_name), source_reference), "next_value", source_reference), source_reference);
238
var assignment = new Assignment (new MemberAccess (null, variable_name, source_reference), next_value_call, AssignmentOperator.SIMPLE, source_reference);
239
var conditional = new BinaryExpression (BinaryOperator.INEQUALITY, assignment, new NullLiteral (source_reference), source_reference);
240
var loop = new WhileStatement (conditional, body, source_reference);
241
add_statement (loop);
242
} else if (next_method != null) {
243
if (next_method.get_parameters ().size != 0) {
244
Report.error (collection.source_reference, "`%s' must not have any parameters".printf (next_method.get_full_name ()));
248
if (!next_method.return_type.compatible (analyzer.bool_type)) {
249
Report.error (collection.source_reference, "`%s' must return a boolean value".printf (next_method.get_full_name ()));
253
var get_method = iterator_type.get_member ("get") as Method;
254
if (get_method == null) {
255
Report.error (collection.source_reference, "`%s' does not have a `get' method".printf (iterator_type.to_string ()));
259
if (get_method.get_parameters ().size != 0) {
260
Report.error (collection.source_reference, "`%s' must not have any parameters".printf (get_method.get_full_name ()));
264
var element_type = get_method.return_type.get_actual_type (iterator_type, null, this);
265
if (element_type is VoidType) {
266
Report.error (collection.source_reference, "`%s' must return an element".printf (get_method.get_full_name ()));
271
if (!analyze_element_type (element_type)) {
275
var next_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("_%s_it".printf (variable_name), source_reference), "next", source_reference), source_reference);
276
var loop = new WhileStatement (next_call, body, source_reference);
277
add_statement (loop);
279
var get_call = new MethodCall (new MemberAccess (new MemberAccess.simple ("_%s_it".printf (variable_name), source_reference), "get", source_reference), source_reference);
280
body.insert_statement (0, new DeclarationStatement (new LocalVariable (type_reference, variable_name, get_call, source_reference), source_reference));
282
Report.error (collection.source_reference, "`%s' does not have a `next_value' or `next' method".printf (iterator_type.to_string ()));
271
288
return base.check (analyzer);
291
bool analyze_element_type (DataType element_type) {
292
// analyze element type
293
if (type_reference == null) {
295
type_reference = element_type.copy ();
296
} else if (!element_type.compatible (type_reference)) {
298
Report.error (source_reference, "Foreach: Cannot convert from `%s' to `%s'".printf (element_type.to_string (), type_reference.to_string ()));
300
} else if (element_type.is_disposable () && element_type.value_owned && !type_reference.value_owned) {
302
Report.error (source_reference, "Foreach: Invalid assignment from owned expression to unowned variable");
274
309
bool check_without_iterator (SemanticAnalyzer analyzer, DataType collection_type, DataType element_type) {
275
310
// analyze element type
276
311
if (type_reference == null) {