<commit_before>﻿using System.Collections.Generic;

namespace SharpExpressions.Compiler
{
    class CodeGenerator
    {
        public static CompiledExpression generate(Parser.Queue queue, Registry registry)
        {
            var types = Types.types;
            Stack<Value> work = new Stack<Value>();
            Queue<Instruction> instructions = new Queue<Instruction>();

            foreach (var entry in queue)
            {
                Instruction instruction = new Instruction();

                switch (entry.type)
                {
                    case Parser.Entry.Type.Double:
                    {
                        double value = (double)entry.value;
                        work.Push(new Value { doubleValue = value });
                        instruction.execute = (Value[] _, ref Value result) => result.doubleValue = value;
                        break;
                    }

                    case Parser.Entry.Type.Boolean:
                    {
                        bool value = (bool)entry.value;
                        work.Push(new Value { boolValue = value });
                        instruction.execute = (Value[] _, ref Value result) => result.boolValue = value;
                        break;
                    }

                    case Parser.Entry.Type.String:
                    {
                        string value = (string)entry.value;
                        work.Push(new Value { stringValue = value });
                        instruction.execute = (Value[] _, ref Value result) => result.stringValue = value;
                        break;
                    }

                    case Parser.Entry.Type.Operator:
                    {
                        switch ((Parser.Operator)entry.value)
                        {
                            case Parser.Operator.Add:
                            {
                                Value param1 = work.Pop();
                                Value param0 = work.Pop();
                                var expectedType = param0.type;

                                instruction.numOperands = 2;
                                instruction.execute = types[param0.type].add;

                                if (param1.type != expectedType)
                                {
                                    var converters = new convert[2];
                                    converters[0] = null;
                                    converters[1] = param1.type == expectedType ? null : types[param0.type].convert;
                                    instruction.converters = converters;
                                }
                                
                                break;
                            }
                        }
                        break;
                    }
                }

                instructions.Enqueue(instruction);
            }

            return new CompiledExpression()
            {
                instructions = instructions.ToArray()
            };
        }
    }
}<commit_msg>Make common factor of CodeGenerator<commit_after>﻿using System.Collections.Generic;

namespace SharpExpressions.Compiler
{
    class CodeGenerator
    {
        public static CompiledExpression generate(Parser.Queue queue, Registry registry)
        {
            var types = Types.types;
            Stack<Value> work = new Stack<Value>();
            Queue<Instruction> instructions = new Queue<Instruction>();

            foreach (var entry in queue)
            {
                Instruction instruction = new Instruction();

                switch (entry.type)
                {
                    case Parser.Entry.Type.Double:
                    {
                        double value = (double)entry.value;
                        work.Push(new Value { doubleValue = value });
                        instruction.execute = (Value[] _, ref Value result) => result.doubleValue = value;
                        break;
                    }

                    case Parser.Entry.Type.Boolean:
                    {
                        bool value = (bool)entry.value;
                        work.Push(new Value { boolValue = value });
                        instruction.execute = (Value[] _, ref Value result) => result.boolValue = value;
                        break;
                    }

                    case Parser.Entry.Type.String:
                    {
                        string value = (string)entry.value;
                        work.Push(new Value { stringValue = value });
                        instruction.execute = (Value[] _, ref Value result) => result.stringValue = value;
                        break;
                    }

                    case Parser.Entry.Type.Operator:
                    {
                        switch ((Parser.Operator)entry.value)
                        {
                            case Parser.Operator.Add:
                            {
                                Value param1 = work.Pop();
                                Value param0 = work.Pop();
                                setInstruction(instruction, 2, param0.type, types[param0.type].add, types[param0.type].convert, param0, param1);
                                work.Push(param0);
                                break;
                            }
                        }
                        break;
                    }
                }

                instructions.Enqueue(instruction);
            }

            return new CompiledExpression()
            {
                instructions = instructions.ToArray()
            };
        }

        private static void setInstruction(Instruction instruction, int operandCount, Value.Type expectedType, execute executor, convert converter, params Value[] operands)
        {
            if (executor != null)
            {
                instruction.numOperands = operandCount;
                instruction.execute = executor;

                bool any = false;
                var converters = new convert[operandCount];
                for (int i = 0; i < operandCount; ++i)
                {
                    if (operands[i].type != expectedType)
                    {
                        converters[i] = converter;
                        any = true;
                    }
                    else
                    {
                        converters[i] = null;
                    }
                }

                if (any)
                {
                    instruction.converters = converters;
                }
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.0763335837716003, 'fraction_numerical': 0.0031555221637866266, 'mean_word_length': 0.8935988620199147, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5911017', 'n_tokens_mistral': 1446, 'n_tokens_neox': 1321, 'n_words': 298}