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); }