public override void EnterWhileStatement([NotNull] SBP.WhileStatementContext context)
 {
     this.AddEnterStatement(context);
     //m_lastPropertyBlock = null;
     m_expressionData.PushStackLevel("WhileStatement");
     m_enteredLoopStatement = true;
 }
        public override void ExitWhileStatement([NotNull] SBP.WhileStatementContext context)
        {
            var stack         = m_expressionData.PopStackLevel();
            var condition     = stack.Pop();
            var subStatements = m_scopeStack.Peek().GetSubExpressions();
            var attributes    = m_scopeStack.Peek().GetAttributes();
            ProcedureVariable varLoopIndex   = null;
            ProcedureVariable varEntryTime   = null;
            ProcedureVariable varTimeoutTime = null;
            Expression        timeout        = null;

            var props = m_lastElementPropertyBlock;

            m_lastElementPropertyBlock = null;

            condition = this.ResolveForGetOperation(condition);
            var conditionExpression = condition.ExpressionCode;

            if (condition.IsValueType && condition.DataType.Type != typeof(bool))
            {
                throw new NotImplementedException("Something wrong with the condition expression.");
            }

            var breakLabel = Expression.Label();

            var isBlockSub = (subStatements[0].Type == ProcedureParsingScope.ScopeType.Block);

            if (isBlockSub)
            {
                breakLabel = m_scopeStack.Peek().BreakLabel;
            }

            var statementExpressions = new List <Expression>();
            var loopExpressions      = new List <Expression>();

            loopExpressions.Add(
                Expression.IfThen(
                    Expression.Not(conditionExpression),
                    Expression.Break(breakLabel)));

            varLoopIndex = m_scopeStack.Peek().AddVariable(
                CreateStatementVariableName(context, "whileLoop_index"),
                TypeReference.TypeInt64,
                new SBExpressionData(Expression.Constant(0L)),
                EntryModifiers.Private);
            loopExpressions.Add(Expression.Increment(varLoopIndex.VariableExpression));     // index++; therefore index = 1 inside and after first iteration.

            // TODO: Add some logging, interactive break check, timeout and other stuff
            #region Attribute Handling

            if ((m_currentProcedure.Flags & ProcedureFlags.IsFunction) == ProcedureFlags.None && props != null)
            {
                foreach (var property in props)
                {
                    if (property.Is("Timeout", PropertyBlockEntryType.Value))
                    {
                        object toValue = (((PropertyBlockValue)property).Value);
                        if (toValue is TimeSpan)
                        {
                            timeout = Expression.Constant((TimeSpan)toValue);
                        }
                        else
                        {
                            throw new NotImplementedException("Timeout data type or expression not implemented or supported.");
                        }

                        varEntryTime = m_scopeStack.Peek().AddVariable(
                            CreateStatementVariableName(context, "whileLoop_EntryTime"),
                            TypeReference.TypeDateTime,
                            new SBExpressionData(Expression.Field(null, typeof(DateTime).GetField("MinValue"))),
                            EntryModifiers.Private);
                        varTimeoutTime = m_scopeStack.Peek().AddVariable(
                            CreateStatementVariableName(context, "whileLoop_TimeoutTime"),
                            TypeReference.TypeDateTime,
                            new SBExpressionData(Expression.Field(null, typeof(DateTime).GetField("MinValue"))),
                            EntryModifiers.Private);
                        //loopExpressions.Add(Expression.Assign(varTimeoutTime.VariableExpression,
                        //    Expression.IfThen(
                        //        Expression.Not(conditionExpression),
                        //        Expression.Block(
                        //            Expression.Break(breakLabel))));
                        //new TSExpressionData(Expression.Property(null, typeof(DateTime).GetProperty("Now"))),
                    }
                }
            }
            #endregion

            if (varEntryTime != null)
            {
                m_scopeStack.Peek().AddStatementCode(
                    Expression.Assign(varEntryTime.VariableExpression,
                                      Expression.Property(null, typeof(DateTime).GetProperty("Now"))));
            }
            if (varTimeoutTime != null)
            {
                m_scopeStack.Peek().AddStatementCode(
                    Expression.Assign(varTimeoutTime.VariableExpression,
                                      Expression.Add(
                                          varEntryTime.VariableExpression,
                                          timeout)));
                loopExpressions.Add(
                    Expression.IfThen(
                        Expression.Not(conditionExpression),
                        Expression.Break(breakLabel)));
                loopExpressions.Add(
                    Expression.IfThen(
                        Expression.GreaterThan(
                            Expression.Property(null, typeof(DateTime).GetProperty("Now")),
                            varTimeoutTime.VariableExpression),
                        Expression.Block(
                            // TODO: log timeout
                            Expression.Break(breakLabel))));
                //new TSExpressionData(Expression.Property(null, typeof(DateTime).GetProperty("Now"))),
            }

            if (isBlockSub)
            {
                statementExpressions.Add(
                    Expression.Loop(
                        subStatements[0].GetBlockCode(loopExpressions, null),
                        breakLabel,
                        subStatements[0].ContinueLabel));
            }
            else
            {
                loopExpressions.Add(subStatements[0].GetOnlyStatementCode());
                statementExpressions.Add(
                    Expression.Loop(
                        Expression.Block(loopExpressions),
                        breakLabel));
            }

            m_scopeStack.Peek().AddStatementCode(statementExpressions.ToArray());
        }