internal BinaryExpression GenBinaryExpression(IScope scope, int maxDepth)
        {
            BinaryExpression be = new BinaryExpression();
            var op = _options.BinaryOperators.ChooseRandom(_rand);

            be.Operator = op;
            var lhs = GenExpression(scope, maxDepth);
            var rhs = GenExpression(scope, maxDepth);

            if (op.Has(OperatorRequirement.StringLengthLimit))
            {
                scope.Require(GlobalFunction.STRL);
            }
            if (op.Has(OperatorRequirement.NumericOnly))
            {
                if (!lhs.IsNumeric)
                {
                    lhs = new NumericExpression(scope, lhs, GenNumericLiteral());
                }
                if (!rhs.IsNumeric)
                {
                    rhs = new NumericExpression(scope, rhs, GenNumericLiteral());
                }
                if (op.Has(OperatorRequirement.RhsNonzero))
                {
                    rhs = new NonZeroExpression(scope, rhs);
                }
            }
            be.Lhs = lhs;
            be.Rhs = rhs;
            return(be);
        }
        internal AssignmentExpression GenAssignmentExpression(IScope scope, Variable v, int maxDepth)
        {
            AssignmentOperator   op = _options.AssignmentOperators.ChooseRandom(_rand);
            AssignmentExpression ae = new AssignmentExpression()
            {
                Operator = op
            };

            if (op.Has(OperatorRequirement.NumericOnly))
            {
                scope.Require(GlobalFunction.CALC);
                ae.DefaultValue = GenNumericLiteral();
            }
            if (!op.Has(OperatorRequirement.WithoutRhs))
            {
                Expression expr = GenExpression(scope, maxDepth);
                if (op.Has(OperatorRequirement.NumericOnly) && !expr.IsNumeric)
                {
                    expr = new NumericExpression(scope, expr, GenNumericLiteral());
                }
                if (op.Has(OperatorRequirement.RhsNonzero))
                {
                    expr = new NonZeroExpression(scope, expr);
                }
                ae.Rhs = expr;
            }
            ae.Variable = v;
            return(ae);
        }
        internal UnaryExpression GenUnaryExpression(IScope scope, int maxDepth)
        {
            UnaryExpression ue = new UnaryExpression();
            UnaryOperator   op = _options.UnaryOperators.ChooseRandom(_rand);

            ue.Operator = op;
            Expression expr = GenExpression(scope, maxDepth);

            if (op.Has(OperatorRequirement.NumericOnly) && !expr.IsNumeric)
            {
                expr = new NumericExpression(scope, expr, GenNumericLiteral());
            }
            if (op.Has(OperatorRequirement.RhsNonnegative))
            {
                expr = new NonNegativeExpression(scope, expr);
            }
            if (op.Has(OperatorRequirement.RhsNonzero))
            {
                expr = new NonZeroExpression(scope, expr);
            }
            if (op.Has(OperatorRequirement.LimitedPrecision))
            {
                scope.Require(GlobalFunction.PREC);
            }
            ue.Value = expr;
            return(ue);
        }
        internal ForLoop GenForLoop(IScope scope, Statement parent, int maxDepth)
        {
            var      fl = new ForLoop(scope);
            Variable i  = fl.IteratorVariable = GenVariable(fl, false, true);

            i.Initializer = GenNumericLiteral(NumericLiteralType.SmallInteger);
            bool       decrease     = _rand.FlipCoin();
            Expression iteratorExpr = null;

            if (_rand.FlipCoin(_options.ForLoopVariableBoundsChance))
            {
                Variable v = _varSelector.ChooseVariable(scope);
                if (v != null)
                {
                    iteratorExpr = new NumericExpression(fl, new VariableExpression(v), GenNumericLiteral());
                }
            }
            if (iteratorExpr == null)
            {
                iteratorExpr = GenNumericLiteral();
            }
            iteratorExpr = new BinaryExpression()
            {
                Operator = _rand.FlipCoin() ? BinaryOperator.Less : BinaryOperator.Greater,
                Lhs      = new VariableExpression(i),
                Rhs      = iteratorExpr
            };
            fl.Control = new LoopControlExpression(iteratorExpr, _cyclesProtection);
            var        op  = _options.AssignmentInForLoop.ChooseRandom(_rand);
            Expression rhs = null;

            if (!op.Has(OperatorRequirement.WithoutRhs))
            {
                rhs = GenNumericLiteral();
                if (op.Has(OperatorRequirement.RhsNonzero))
                {
                    rhs = new NonZeroExpression(fl, rhs);
                }
            }
            fl.IteratorExpression = new AssignmentExpression()
            {
                Operator = op,
                Variable = i,
                Rhs      = rhs
            };
            fl.Body = GenStatement(fl, fl, maxDepth - 1);
            return(fl);
        }