+
+ private fun do_typing(v: TypingVisitor)
+ do
+ # Create the automatic variables
+ var vas = new Array[AutoVariable]
+ for n_id in n_ids do
+ var va = new AutoVariable(n_id.to_symbol, n_id)
+ v.scope_ctx.add_variable(va)
+ vas.add(va)
+ end
+ _variables = vas
+
+ # Process reciever
+ v.enter_visit(n_expr)
+ if not v.check_expr(n_expr) then return
+ var expr_type = n_expr.stype
+
+ if expr_type.is_nullable then
+ v.error(n_expr, "Type error: 'for' on a nullable expression.")
+ return
+ end
+
+ # Get iterate
+ var iterate_name = once "iterate".to_symbol
+ if not expr_type.local_class.has_global_property_by_name(iterate_name) then
+ v.error(n_expr, "Type error: Expected a type with an 'iterate' method. Found {expr_type}.")
+ return
+ end
+ var prop = expr_type.local_class.select_method(iterate_name)
+ prop.global.check_visibility(v, self, v.mmmodule, n_expr.is_self)
+ var psig = prop.signature_for(expr_type)
+ if not n_expr.is_self then psig = psig.not_for_self
+ if psig.arity != 0 then
+ v.error(self, "Error: 'iterate' incompatible with 'for': require no arguments.")
+ return
+ else if psig.closures.length != 1 then
+ v.error(self, "Error: 'iterate' incompatible with 'for': require one closure.")
+ return
+ end
+ psig = psig.closures.first.signature
+ if psig.return_type != null then
+ v.error(self, "Error: 'iterate' incompatible with 'for': require one procedural closure.")
+ return
+ end
+ if vas.length != psig.arity then
+ if psig.arity == 1 then
+ v.error(self, "Error: Expected {psig.arity} variable {psig}, found {vas.length}.")
+ else
+ v.error(self, "Error: Expected {psig.arity} variables {psig}, found {vas.length}.")
+ end
+ return
+ end
+
+ # Type the automatic variables
+ for i in [0..vas.length[ do
+ vas[i].stype = psig[i]
+ end
+ end