<commit_before>﻿using EOBot.Interpreter.Extensions;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace EOBot.Interpreter.States
{
    public class IfEvaluator : BlockEvaluator
    {
        public IfEvaluator(IEnumerable<IScriptEvaluator> evaluators)
            : base(evaluators) { }

        public override async Task<(EvalResult, string, BotToken)> EvaluateAsync(ProgramState input)
        {
            // ensure we have the right keyword before advancing the program
            var current = input.Current();
            if (current.TokenType != BotTokenType.Keyword || current.TokenValue != "if")
                return (EvalResult.NotMatch, string.Empty, input.Current());

            var ifStartIndex = input.ExecutionIndex;

            var (result, reason, token) = await EvaluateConditionAsync(ifStartIndex, input);
            if (result == EvalResult.Ok)
            {
                if (bool.TryParse(token.TokenValue, out var conditionValue) && conditionValue)
                    return await EvaluateBlockAsync(input);

                SkipBlock(input);

                if (IsElse(input))
                {
                    input.Expect(BotTokenType.Keyword);

                    var elseIfRes = await Evaluator<IfEvaluator>().EvaluateAsync(input);
                    if (elseIfRes.Result == EvalResult.Failed)
                        return elseIfRes;
                    else if (elseIfRes.Result == EvalResult.Ok)
                    {
                        input.Expect(BotTokenType.NewLine);

                        // skip the rest of the following blocks if evaluated
                        while (IsElse(input))
                        {
                            input.Expect(BotTokenType.Keyword);
                            SkipBlock(input);
                        }

                        return elseIfRes;
                    }

                    // if not a match for else if, it is an else block
                    return await EvaluateBlockAsync(input);
                }
            }

            return (result, reason, token);
        }

        private bool IsElse(ProgramState input)
        {
            var current = input.Current();
            return current.TokenType == BotTokenType.Keyword && current.TokenValue == "else";
        }
    }
}<commit_msg>Hack to make block skipping work on single-statement ifs<commit_after>﻿using EOBot.Interpreter.Extensions;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace EOBot.Interpreter.States
{
    public class IfEvaluator : BlockEvaluator
    {
        public IfEvaluator(IEnumerable<IScriptEvaluator> evaluators)
            : base(evaluators) { }

        public override async Task<(EvalResult, string, BotToken)> EvaluateAsync(ProgramState input)
        {
            // ensure we have the right keyword before advancing the program
            var current = input.Current();
            if (current.TokenType != BotTokenType.Keyword || current.TokenValue != "if")
                return (EvalResult.NotMatch, string.Empty, input.Current());

            var ifStartIndex = input.ExecutionIndex;

            var (result, reason, token) = await EvaluateConditionAsync(ifStartIndex, input);
            if (result == EvalResult.Ok)
            {
                if (bool.TryParse(token.TokenValue, out var conditionValue) && conditionValue)
                    return await EvaluateBlockAsync(input);

                SkipBlock(input);

                if (IsElse(input))
                {
                    input.Expect(BotTokenType.Keyword);

                    var elseIfRes = await Evaluator<IfEvaluator>().EvaluateAsync(input);
                    if (elseIfRes.Result == EvalResult.Failed)
                        return elseIfRes;
                    else if (elseIfRes.Result == EvalResult.Ok)
                    {
                        input.Expect(BotTokenType.NewLine);

                        // skip the rest of the following blocks if evaluated
                        while (IsElse(input))
                        {
                            input.Expect(BotTokenType.Keyword);
                            SkipBlock(input);
                        }

                        // hack: put the \n token back since StatementList/Statement will have consumed it
                        if (input.Program[input.ExecutionIndex - 1].TokenType == BotTokenType.NewLine)
                            input.Goto(input.ExecutionIndex - 1);

                        return elseIfRes;
                    }

                    // if not a match for else if, it is an else block
                    return await EvaluateBlockAsync(input);
                }
            }

            return (result, reason, token);
        }

        private bool IsElse(ProgramState input)
        {
            var current = input.Current();
            return current.TokenType == BotTokenType.Keyword && current.TokenValue == "else";
        }
    }
}
{'fraction_non_alphanumeric': 0.08114035087719298, 'fraction_numerical': 0.00039872408293460925, 'mean_word_length': 1.524911927528938, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5756637', 'n_tokens_mistral': 1219, 'n_tokens_neox': 1151, 'n_words': 290}