Mono.CSharp.Foreach.CollectionForeach.Resolve C# (CSharp) Method

Resolve() public method

public Resolve ( BlockContext ec ) : bool
ec BlockContext
return bool
			public override bool Resolve (BlockContext ec)
			{
				bool is_dynamic = expr.Type == InternalType.Dynamic;

				if (is_dynamic) {
					expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.ienumerable_type, loc);
				} else if (TypeManager.IsNullableType (expr.Type)) {
					expr = new Nullable.UnwrapCall (expr).Resolve (ec);
				}

				var get_enumerator_mg = ResolveGetEnumerator (ec);
				if (get_enumerator_mg == null) {
					return false;
				}

				var get_enumerator = get_enumerator_mg.BestCandidate;
				enumerator_variable = TemporaryVariableReference.Create (get_enumerator.ReturnType, variable.Block, loc);
				enumerator_variable.Resolve (ec);

				// Prepare bool MoveNext ()
				var move_next_mg = ResolveMoveNext (ec, get_enumerator);
				if (move_next_mg == null) {
					return false;
				}

				move_next_mg.InstanceExpression = enumerator_variable;

				// Prepare ~T~ Current { get; }
				var current_prop = ResolveCurrent (ec, get_enumerator);
				if (current_prop == null) {
					return false;
				}

				var current_pe = new PropertyExpr (current_prop, loc) { InstanceExpression = enumerator_variable }.Resolve (ec);
				if (current_pe == null)
					return false;

				VarExpr ve = var_type as VarExpr;
				if (ve != null) {
					if (is_dynamic) {
						// Source type is dynamic, set element type to dynamic too
						var_type = new TypeExpression (InternalType.Dynamic, var_type.Location);
					} else {
						// Infer implicitly typed local variable from foreach enumerable type
						var_type = new TypeExpression (current_pe.Type, var_type.Location);
					}
				} else if (is_dynamic) {
					// Explicit cast of dynamic collection elements has to be done at runtime
					current_pe = EmptyCast.Create (current_pe, InternalType.Dynamic);
				}

				var_type = var_type.ResolveAsTypeTerminal (ec, false);
				if (var_type == null)
					return false;

				variable.Type = var_type.Type;

				var init = new Invocation (get_enumerator_mg, null);

				statement = new While (new BooleanExpression (new Invocation (move_next_mg, null)),
					new Body (var_type.Type, variable, current_pe, statement, loc), loc);

				var enum_type = enumerator_variable.Type;

				//
				// Add Dispose method call when enumerator can be IDisposable
				//
				if (!enum_type.ImplementsInterface (TypeManager.idisposable_type, false)) {
					if (!enum_type.IsSealed && !TypeManager.IsValueType (enum_type)) {
						//
						// Runtime Dispose check
						//
						var vd = new RuntimeDispose (enumerator_variable.LocalInfo, loc);
						vd.Initializer = init;
						statement = new Using (vd, statement, loc);
					} else {
						//
						// No Dispose call needed
						//
						this.init = new SimpleAssign (enumerator_variable, init);
						this.init.Resolve (ec);
					}
				} else {
					//
					// Static Dispose check
					//
					var vd = new Using.VariableDeclaration (enumerator_variable.LocalInfo, loc);
					vd.Initializer = init;
					statement = new Using (vd, statement, loc);
				}

				return statement.Resolve (ec);
			}