public Dispose (TemporaryVariable variable, LocalTemporary dispose, Expression expr, Statement statement, Location loc) : base (expr, statement, loc) { base.local_copy = variable; this.dispose = dispose; }
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); var get_enumerator_mg = ResolveGetEnumerator (ec); if (get_enumerator_mg == null) { return false; } var get_enumerator = get_enumerator_mg.BestCandidate; var enumerator = new TemporaryVariable (get_enumerator.ReturnType, loc); enumerator.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; // 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 }.Resolve (ec); if (current_pe == null) return false; VarExpr ve = var_type as VarExpr; if (ve != null) { // Infer implicitly typed local variable from foreach enumerable type var_type = new TypeExpression (current_pe.Type, var_type.Location); } var_type = var_type.ResolveAsTypeTerminal (ec, false); if (var_type == null) return false; var init = new Invocation (get_enumerator_mg, null); init.Resolve (ec); 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.Type; // // Add Dispose method call when enumerator can be IDisposable // if (!enumerator.Type.ImplementsInterface (TypeManager.idisposable_type)) { if (!enum_type.IsSealed && !TypeManager.IsValueType (enum_type)) { // // Runtime Dispose check // var tv = new LocalTemporary (TypeManager.idisposable_type); statement = new Dispose (enumerator, tv, init, statement, loc); } else { // // No Dispose call needed // this.init = new SimpleAssign (enumerator, init); this.init.Resolve (ec); } } else { // // Static Dispose check // statement = new Dispose (enumerator, null, init, statement, loc); } return statement.Resolve (ec); }
protected virtual bool DoResolve (BlockContext ec) { expr = expr.Resolve (ec); if (expr == null) return false; if (!expr.Type.ImplementsInterface (TypeManager.idisposable_type) && Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) { if (expr.Type != InternalType.Dynamic) { Using.Error_IsNotConvertibleToIDisposable (ec, expr); return false; } expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.idisposable_type, loc); } var expr_type = expr.Type; local_copy = new TemporaryVariable (expr_type, loc); local_copy.Resolve (ec); if (TypeManager.void_dispose_void == null) { TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod ( TypeManager.idisposable_type, "Dispose", loc, TypeSpec.EmptyTypes); } var dispose_mg = MethodGroupExpr.CreatePredefined (TypeManager.void_dispose_void, TypeManager.idisposable_type, loc); dispose_mg.InstanceExpression = TypeManager.IsNullableType (expr_type) ? new Cast (new TypeExpression (TypeManager.idisposable_type, loc), local_copy, loc).Resolve (ec) : local_copy; dispose_call = new StatementExpression (new Invocation (dispose_mg, null)); // Add conditional call when disposing possible null variable if (!expr_type.IsStruct || TypeManager.IsNullableType (expr_type)) dispose_call = new If (new Binary (Binary.Operator.Inequality, local_copy, new NullLiteral (loc), loc), dispose_call, loc); return dispose_call.Resolve (ec); }
public override bool Resolve (BlockContext ec) { copy = new TemporaryVariable (for_each.expr.Type, loc); copy.Resolve (ec); int rank = length_exprs.Length; Arguments list = new Arguments (rank); for (int i = 0; i < rank; i++) { counter [i] = new ArrayCounter (loc); counter [i].ResolveIncrement (ec); if (rank == 1) { length_exprs [i] = new MemberAccess (copy, "Length").Resolve (ec); } else { lengths [i] = new TemporaryVariable (TypeManager.int32_type, loc); lengths [i].Resolve (ec); Arguments args = new Arguments (1); args.Add (new Argument (new IntConstant (i, loc))); length_exprs [i] = new Invocation (new MemberAccess (copy, "GetLength"), args).Resolve (ec); } list.Add (new Argument (counter [i])); } access = new ElementAccess (copy, list, loc).Resolve (ec); if (access == null) return false; Expression var_type = for_each.type; VarExpr ve = var_type as VarExpr; if (ve != null) { // Infer implicitly typed local variable from foreach array type var_type = new TypeExpression (access.Type, ve.Location); } var_type = var_type.ResolveAsTypeTerminal (ec, false); if (var_type == null) return false; conv = Convert.ExplicitConversion (ec, access, var_type.Type, loc); if (conv == null) return false; bool ok = true; ec.StartFlowBranching (FlowBranching.BranchingType.Loop, loc); ec.CurrentBranching.CreateSibling (); for_each.variable = for_each.variable.ResolveLValue (ec, conv); if (for_each.variable == null) ok = false; ec.StartFlowBranching (FlowBranching.BranchingType.Embedded, loc); if (!statement.Resolve (ec)) ok = false; ec.EndFlowBranching (); // There's no direct control flow from the end of the embedded statement to the end of the loop ec.CurrentBranching.CurrentUsageVector.Goto (); ec.EndFlowBranching (); return ok; }
public override bool Resolve (BlockContext ec) { expr = expr.Resolve (ec); if (expr == null) return false; if (!TypeManager.IsReferenceType (expr.Type)){ ec.Report.Error (185, loc, "`{0}' is not a reference type as required by the lock statement", TypeManager.CSharpName (expr.Type)); return false; } ec.StartFlowBranching (this); bool ok = Statement.Resolve (ec); ec.EndFlowBranching (); ok &= base.Resolve (ec); // Avoid creating libraries that reference the internal // mcs NullType: TypeSpec t = expr.Type; if (t == TypeManager.null_type) t = TypeManager.object_type; temp = new TemporaryVariable (t, loc); temp.Resolve (ec); if (TypeManager.void_monitor_enter_object == null || TypeManager.void_monitor_exit_object == null) { TypeSpec monitor_type = TypeManager.CoreLookupType (ec.Compiler, "System.Threading", "Monitor", MemberKind.Class, true); TypeManager.void_monitor_enter_object = TypeManager.GetPredefinedMethod ( monitor_type, "Enter", loc, TypeManager.object_type); TypeManager.void_monitor_exit_object = TypeManager.GetPredefinedMethod ( monitor_type, "Exit", loc, TypeManager.object_type); } return ok; }
public override bool Resolve (EmitContext ec) { enumerator_type = TypeManager.ienumerator_type; if (!ProbeCollectionType (ec, expr.Type)) { Error_Enumerator (); return false; } bool is_disposable = !enumerator_type.IsSealed || TypeManager.ImplementsInterface (enumerator_type, TypeManager.idisposable_type); VarExpr ve = var_type as VarExpr; if (ve != null) { // Infer implicitly typed local variable from foreach enumerable type var_type = new TypeExpression (get_current.PropertyInfo.PropertyType, var_type.Location); } var_type = var_type.ResolveAsTypeTerminal (ec, false); if (var_type == null) return false; enumerator = new TemporaryVariable (enumerator_type, loc); enumerator.Resolve (ec); init = new Invocation (get_enumerator, null); init = init.Resolve (ec); if (init == null) return false; Expression move_next_expr; { MemberInfo[] mi = new MemberInfo[] { move_next }; MethodGroupExpr mg = new MethodGroupExpr (mi, var_type.Type, loc); mg.InstanceExpression = enumerator; move_next_expr = new Invocation (mg, null); } get_current.InstanceExpression = enumerator; Statement block = new CollectionForeachStatement ( var_type.Type, variable, get_current, statement, loc); loop = new While (move_next_expr, block, loc); wrapper = is_disposable ? (Statement) new DisposableWrapper (this) : (Statement) new NonDisposableWrapper (this); return wrapper.Resolve (ec); }
public override bool Resolve (EmitContext ec) { expr = expr.Resolve (ec); if (expr == null) return false; expr_type = expr.Type; if (!TypeManager.ImplementsInterface (expr_type, TypeManager.idisposable_type)) { if (Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) { Using.Error_IsNotConvertibleToIDisposable (expr); return false; } } local_copy = new TemporaryVariable (expr_type, loc); local_copy.Resolve (ec); ec.StartFlowBranching (this); bool ok = Statement.Resolve (ec); ec.EndFlowBranching (); ResolveReachability (ec); if (TypeManager.void_dispose_void == null) { TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod ( TypeManager.idisposable_type, "Dispose", loc, Type.EmptyTypes); } return ok; }
public override bool Resolve(BlockContext ec) { expr = expr.Resolve (ec); if (expr == null) return false; expr_type = expr.Type; if (!expr_type.ImplementsInterface (TypeManager.idisposable_type) && Convert.ImplicitConversion (ec, expr, TypeManager.idisposable_type, loc) == null) { if (expr_type != InternalType.Dynamic) { Using.Error_IsNotConvertibleToIDisposable (ec, expr); return false; } expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.idisposable_type, loc); expr_type = expr.Type; } local_copy = new TemporaryVariable (expr_type, loc); local_copy.Resolve (ec); ec.StartFlowBranching (this); bool ok = Statement.Resolve (ec); ec.EndFlowBranching (); ok &= base.Resolve (ec); if (TypeManager.void_dispose_void == null) { TypeManager.void_dispose_void = TypeManager.GetPredefinedMethod ( TypeManager.idisposable_type, "Dispose", loc, TypeSpec.EmptyTypes); } return ok; }
public override bool Resolve(BlockContext ec) { enumerator_type = TypeManager.ienumerator_type; bool is_dynamic = expr.Type == InternalType.Dynamic; if (is_dynamic) expr = Convert.ImplicitConversionRequired (ec, expr, TypeManager.ienumerable_type, loc); if (!ProbeCollectionType (ec, expr.Type)) { Error_Enumerator (ec); return false; } VarExpr ve = var_type as VarExpr; if (ve != null) { // Infer implicitly typed local variable from foreach enumerable type var_type = new TypeExpression ( is_dynamic ? InternalType.Dynamic : get_current.Type, var_type.Location); } var_type = var_type.ResolveAsTypeTerminal (ec, false); if (var_type == null) return false; enumerator = new TemporaryVariable (enumerator_type, loc); enumerator.Resolve (ec); init = new Invocation (get_enumerator, null); init = init.Resolve (ec); if (init == null) return false; Expression move_next_expr; { var mi = new List<MemberSpec> (1) { move_next }; MethodGroupExpr mg = new MethodGroupExpr (mi, var_type.Type, loc); mg.InstanceExpression = enumerator; move_next_expr = new Invocation (mg, null); } get_current.InstanceExpression = enumerator; Statement block = new CollectionForeachStatement ( var_type.Type, variable, get_current, statement, loc); loop = new While (new BooleanExpression (move_next_expr), block, loc); bool implements_idisposable = enumerator_type.ImplementsInterface (TypeManager.idisposable_type); if (implements_idisposable || !enumerator_type.IsSealed) { wrapper = new DisposableWrapper (this, implements_idisposable); } else { wrapper = new NonDisposableWrapper (this); } return wrapper.Resolve (ec); }