internal override Node Bind(Binder b)
        {
            b.OpenScope();

            b.Bind(ref Expr);
            Expr.RequireGetAccess();

            if (Expr.Datatype.IsArray && Expr.Datatype.ArrayRank == 1)
            {
                var array = b.Cache(ref Expr);
                var iter  = b.AddLocal(Compilation.Get(NativeType.Int32));
                IterDecl  = VarDecl.Bound(iter, LiteralExpr.Bound(Constant.Create(b.Options.ArrayBase)), b.Options.Binding);
                WhileExpr = BinaryExpr.Bound(IdExpr.Bound(iter), Token,
                                             MethodCallExpr.Bound(array, Compilation.Get(WellKnownMembers.System_Array_get_Length), array, ArgList.Empty),
                                             b.Options.ArrayZero ? BinaryOperatorKind.LessThan : BinaryOperatorKind.LessThanOrEqual, b.Options.Binding);
                IncrExpr            = AssignOpExpr.Bound(IdExpr.Bound(iter), LiteralExpr.Bound(Constant.Create(1)), BinaryOperatorKind.Addition, b);
                ForDecl.Initializer = ArrayAccessExpr.Bound(array, new ArgList(new List <Arg>(1)
                {
                    new Arg(IdExpr.Bound(iter))
                }), b);
            }
            else
            {
                if (Expr.Datatype.IsUsualOrObject() && b.Options.Binding.HasFlag(BindOptions.AllowDynamic))
                {
                    b.Convert(ref Expr, Compilation.Get(NativeType.Array));
                }
                Expr e          = b.Cache(ref Expr);
                var  getIterSym = e.Datatype.GetEnumeratorGetter() ?? throw Error(ErrorCode.NoSuitableEnumerator);
                var  getIter    = MethodCallExpr.Bound(e, getIterSym, e, ArgList.Empty);
                var  iter       = b.AddLocal(getIter.Datatype);
                IterDecl  = VarDecl.Bound(iter, getIter, b.Options.Binding);
                WhileExpr = MethodCallExpr.Bound(b, IdExpr.Bound(iter), SystemNames.MoveNext, ArgList.Empty);
                b.Convert(ref WhileExpr, Compilation.Get(NativeType.Boolean));
                ForDecl.Initializer = MethodCallExpr.Bound(b, IdExpr.Bound(iter), SystemNames.CurrentGetter, ArgList.Empty);
                Dispose             = Compilation.Get(WellKnownTypes.System_IDisposable).IsAssignableFrom(getIter.Datatype);
                if (Dispose)
                {
                    RequireExceptionHandling = true;
                }
            }

            b.Bind(ref ForDecl);
            InnerDecl = ForDecl;

            Expr Iter;

            Iter = (ForDecl.Initializer as AssignExpr).Left;
            Iter.RequireGetAccess();

            b.Bind(ref Stmt);

            b.CloseScope();
            return(null);
        }
        internal override Node Bind(Binder b)
        {
            b.OpenScope();

            if (AssignExpr != null)
            {
                b.Bind(ref AssignExpr);
                IterInit = AssignExpr;
            }
            else
            {
                b.Bind(ref ForDecl);
                IterDecl   = ForDecl;
                AssignExpr = ForDecl.Initializer as AssignExpr;
            }

            Expr Iter;

            Iter = AssignExpr.Left;
            Iter.RequireGetAccess();

            b.Bind(ref Final);
            Final.RequireGetAccess();

            if (Step != null)
            {
                b.Bind(ref Step);
                Step.RequireGetAccess();
            }
            else
            {
                Step = LiteralExpr.Bound(Constant.Create(1));
            }

            switch (Dir.Type)
            {
            case TokenType.UPTO:
                WhileExpr = BinaryExpr.Bound(Iter, Dir, Final, BinaryOperatorKind.LessThanOrEqual, b.Options.Binding);
                IncrExpr  = AssignOpExpr.Bound(Iter, Step, BinaryOperatorKind.Addition, b);
                break;

            case TokenType.DOWNTO:
                WhileExpr = BinaryExpr.Bound(Iter, Dir, Final, BinaryOperatorKind.GreaterThanOrEqual, b.Options.Binding);
                IncrExpr  = AssignOpExpr.Bound(Iter, Step, BinaryOperatorKind.Subtraction, b);
                break;

            case TokenType.TO:
                var step_pos        = BinaryExpr.Bound(Step, Dir, LiteralExpr.Bound(Constant.Create(0)), BinaryOperatorKind.GreaterThanOrEqual, b.Options.Binding);
                var whileExprUpTo   = BinaryExpr.Bound(Iter, Dir, Final, BinaryOperatorKind.LessThanOrEqual, b.Options.Binding);
                var whileExprDownTo = BinaryExpr.Bound(Iter, Dir, Final, BinaryOperatorKind.GreaterThanOrEqual, b.Options.Binding);
                WhileExpr = IifExpr.Bound(step_pos, whileExprUpTo, whileExprDownTo, b.Options.Binding);
                IncrExpr  = AssignOpExpr.Bound(Iter, Step, BinaryOperatorKind.Addition, b);
                break;

            default:
                throw Error(ErrorCode.Internal);
            }
            b.Convert(ref WhileExpr, Compilation.Get(NativeType.Boolean));

            b.Bind(ref Stmt);

            b.CloseScope();
            return(null);
        }