private void FromASSIGN(byte[] bytes, Prg prg, ref int offset,
                                FileVersion version = FileVersion.Current)
        {
            Expressions.Add(new VariableExpression(bytes, prg, ref offset, FileVersion));

            var        first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
            var        second     = new VariableExpression(bytes, prg, ref offset, FileVersion);
            var        type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
            Expression expression = new BinaryExpression(first, second, type, FileVersion);

            //var temp = offset;
            var check = bytes.ToByte(ref offset);

            --offset;
            //Console.WriteLine($"{Number} {check} before");
            if (check != (byte)TYPE_TOKEN.NUMBER)
            {
                if (ProgramCodeUtilities.IsVariable(check))
                {
                    var third = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var type2 = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    expression = new BinaryExpression(expression, third, type2, FileVersion);
                }
                else if (ProgramCodeUtilities.IsFunction(check))
                {
                    var token = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    expression = new FunctionExpression(token, FileVersion, expression);
                }

                //++offset;
                //check = (ExpressionType)bytes.ToByte(ref offset);
                //--offset;
                //Console.WriteLine($"{Number} {check} after");
            }

            Expressions.Add(expression);
        }
        //DEPRECATED: Not used, because it's a obsolte method too, just like LINE
        /////// <summary>
        /////// Raw Lines Constructor
        /////// </summary>
        /////// <remarks>Author: LRUIZ</remarks>

        ////static public byte[] RawLine(string line)
        ////{

        ////    List<byte> returnvalue = new List<byte>();
        ////    List<byte> Data = new List<byte>();
        ////    byte Type, Token;
        ////    short Number;

        ////    Type = (byte)TYPE_TOKEN.NUMBER; //1 Byte
        ////    returnvalue.Add((byte)Type);


        ////    string[] separators = { " " };
        ////    string[] LineParts = line.Split(separators, StringSplitOptions.RemoveEmptyEntries);

        ////    if (!LineParts.Any())
        ////    {
        ////        throw new Exception($"Not enough tokens in line: {line}");
        ////    }

        ////    if (String.IsNullOrEmpty(LineParts[0]))
        ////    {
        ////        Number = 0;
        ////    }
        ////    else
        ////    {
        ////        Number = Convert.ToInt16(LineParts[0]);
        ////    }



        ////    byte[] intBytes = BitConverter.GetBytes(Number);
        ////    //if (BitConverter.IsLittleEndian)
        ////    //    Array.Reverse(intBytes);
        ////    if (intBytes.Count() < 2)
        ////    {
        ////        throw new Exception("Line Number less than 2 bytes");
        ////    }
        ////    byte[] result = intBytes;


        ////    Debug.WriteLine($"Converting {Number} to bytes[] : {result}");
        ////    returnvalue.AddRange(result);


        ////    switch (LineParts[1] ?? "RAW")
        ////    {
        ////        case "REM":
        ////            Token = (byte)LINE_TOKEN.REM;
        ////            break;
        ////        //case "IF+":
        ////        //    Token = (byte)LineToken.IFP;
        ////        //    break;

        ////        //case "IF-":
        ////        //    Token = (byte)LineToken.IFM;
        ////        //    break;
        ////        //case "IF":
        ////        //    Token = (byte)LineToken.IF;
        ////        //    break;
        ////        default:
        ////            Token = (byte)LINE_TOKEN.RAWLINE;
        ////            break;


        ////    }
        ////    returnvalue.Add(Token);


        ////    //Number = bytes.ToInt16(ref offset); //2 Bytes
        ////    int OffSet = (Token == (byte)LINE_TOKEN.RAWLINE ? 1 : 2);

        ////    line = string.Join(" ", LineParts, OffSet, LineParts.Count() - OffSet);

        ////    Data.AddRange(line.ToBytes());

        ////    //Data = PRGReaderLibrary.BytesExtensions.ToBytes(line.ToBytes());
        ////    byte size = (byte)Data.Count();

        ////    returnvalue.Add(size);
        ////    returnvalue.AddRange(Data);

        ////    return returnvalue.ToArray();
        ////}


        //DEPRECATED: Incomplete and obsolete version to decode line by line a Program.

        public Line(byte[] bytes, Prg prg, ref int offset,
                    FileVersion version = FileVersion.Current)
            : base(version)
        {
            Type   = (TYPE_TOKEN)bytes.ToByte(ref offset); //1 Byte
            Number = bytes.ToInt16(ref offset);            //2 Bytes
            Token  = (LINE_TOKEN)bytes.ToByte(ref offset); //1 Byte


            //Offset is 4

            try
            {
                if (Number == 140) //8C 00
                {
                    var ifPart = GetLinePart(bytes, ref offset, FileVersion);
                    Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
                    var check = bytes.ToByte(ref offset);
                    if (check != 0xFF)
                    {
                        throw new OffsetException(offset, ifPart.Length);
                    }
                    var nextOffset = bytes.ToUInt16(ref offset);

                    //Expressions.Add(new FunctionExpression(bytes, prg, ref offset, FileVersion));
                    //offset += 4;
                    //offset += 3;
                    //var type = (ExpressionType)bytes.ToByte(ref offset);
                    //var first = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    //var second = new FunctionExpression(bytes, prg, ref offset, FileVersion);
                    //Expressions.Add(new BinaryExpression(first, second, type, FileVersion));
                    //offset += 2;

                    var thenPart = GetLinePart(bytes, ref offset, FileVersion, nextOffset);
                    Expressions.Add(ToExpression(thenPart, prg, 0, FileVersion, isTrace: true));
                    if (bytes[offset] == 0xFF)
                    {
                        offset += 1; //0xFF byte
                    }
                    if (offset != nextOffset)
                    {
                        throw new OffsetException(offset, nextOffset);
                    }

                    return;
                }

                if (Number == 300) //2C 01
                {
                    Expressions.Add(new UnaryExpression(bytes, prg, ref offset, FileVersion));
                    offset += 3;
                    var type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var expression = new VariableExpression(bytes, prg, ref offset, FileVersion) +
                                     new VariableExpression(bytes, prg, ref offset, FileVersion);
                    expression.Type = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    expression      = new FunctionExpression(
                        (FUNCTION_TOKEN)bytes.ToByte(ref offset), FileVersion,
                        expression);
                    expression      = first + expression;
                    expression.Type = type;
                    Expressions.Add(expression);
                    offset += 1;
                    return;
                }

                if (Number == 350) //5E 01
                {
                    var ifPart = GetLinePart(bytes, ref offset, FileVersion);
                    Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
                    offset += 3;
                    var type   = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var first  = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var second = new UnaryExpression(bytes, prg, ref offset, FileVersion);
                    var third  = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var four   = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var type2  = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    offset += 1;
                    var type3 = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    offset += 1;
                    Expression expression = new FunctionExpression(type2, FileVersion, third, four);
                    expression = new FunctionExpression(type3, FileVersion, second, expression);
                    expression = new BinaryExpression(first, expression, type, FileVersion);
                    Expressions.Add(expression);
                    offset += 1;
                    return;
                }

                if (Number == 360) //68 01
                {
                    var ifPart = GetLinePart(bytes, ref offset, FileVersion);
                    Expressions.Add(ToExpression(ifPart, prg, 0, FileVersion));
                    offset += 3;
                    var        type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var        first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        second     = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        third      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        type2      = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    var        four       = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    var        type3      = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    Expression expression = new BinaryExpression(second, third, type2, FileVersion);
                    expression = new BinaryExpression(expression, four, type3, FileVersion);
                    expression = new BinaryExpression(first, expression, type, FileVersion);
                    Expressions.Add(expression);
                    offset    += 5;
                    type       = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    first      = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    second     = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    expression = new BinaryExpression(first, second, type, FileVersion);
                    Expressions.Add(expression);
                    offset += 1;
                    return;
                }

                switch (Token)
                {
                case LINE_TOKEN.IF:
                    FromIF(bytes, prg, ref offset, FileVersion);
                    break;

                case LINE_TOKEN.IFM:
                    FromIFM(bytes, prg, ref offset, FileVersion);
                    break;

                case LINE_TOKEN.ASSIGN:
                    FromASSIGN(bytes, prg, ref offset, FileVersion);
                    break;

                case LINE_TOKEN.REM:
                case LINE_TOKEN.RAWLINE:
                default:
                    var size = bytes.ToByte(ref offset);
                    Data = bytes.ToBytes(ref offset, size);
                    break;
                }

                if (Number == 380) //7C 01
                {
                    offset += 115;
                }
            }
            catch (Exception exception)
            {
                Debug.WriteLine($@"Exception on line: 
        Type: {Type}
        Number: {Number}
        Token: {Token}
        {exception.Message}");
                throw;
            }
        }
        private List <Expression> GetExpressions(byte[] bytes, Prg prg, ref int offset,
                                                 FileVersion version = FileVersion.Current, LINE_TOKEN lineToken = 0,
                                                 bool isTrace        = false)
        {
            if (isTrace)
            {
                Debug.WriteLine("----------------------------");
                Debug.WriteLine(DebugUtilities.CompareBytes(bytes, bytes,
                                                            onlyDif: false, toText: false, offset: offset));
            }

            var expressions = new List <Expression>();

            while (offset < bytes.Length)
            {
                var byteType = ProgramCodeUtilities.GetByteType(bytes, offset);

                if (byteType == ProgramCodeUtilities.ByteType.Variable)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsVariable {offset}");
                    }
                    var expression = new VariableExpression(bytes, prg, ref offset, FileVersion);
                    expressions.Add(expression);
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Line)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsLine {offset}");
                    }
                    var token           = (LINE_TOKEN)bytes.ToByte(ref offset);
                    var lineExpressions = GetExpressions(bytes, prg, ref offset, version, token, isTrace);
                    var expression      = lineExpressions.Count > 1 ? new BinaryExpression(
                        lineExpressions[0],
                        lineExpressions[1],
                        (TYPE_TOKEN)token, FileVersion) :
                                          lineExpressions[0];
                    expressions.Add(expression);
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Function)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsFunction {offset}");
                    }
                    var token = (FUNCTION_TOKEN)bytes.ToByte(ref offset);
                    if ((byte)token == (byte)LINE_TOKEN.STOP)
                    {
                        var variable   = new VariableExpression(bytes, prg, ref offset, FileVersion);
                        var expression = new UnaryExpression(variable, (TYPE_TOKEN)LINE_TOKEN.STOP, version);

                        expressions.Add(expression);
                    }
                    else if (expressions.Count == 0)
                    {
                        Debug.WriteLine("expressions.Count = 0");
                        var temp = 0;
                        offset -= 1;
                        expressions.Add(new VariableExpression(bytes, prg, ref offset, FileVersion));
                        expressions.AddRange(
                            GetExpressions(bytes.ToBytes(ref offset, 3), prg, ref temp, FileVersion, lineToken));

                        var prevLastExpression = expressions[expressions.Count - 2];
                        var lastExpression     = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new BinaryExpression(prevLastExpression, lastExpression, TYPE_TOKEN.DELIMITER, FileVersion);
                        expressions.Add(expression);
                    }
                    else
                    {
                        var expression = new FunctionExpression(token, FileVersion, expressions.ToArray());
                        expressions.Clear();
                        expressions.Add(expression);
                    }
                }
                else if (byteType == ProgramCodeUtilities.ByteType.Expression)
                {
                    if (isTrace)
                    {
                        Debug.WriteLine($"IsExpression {offset}");
                    }
                    var type = (TYPE_TOKEN)bytes.ToByte(ref offset);
                    if (ProgramCodeUtilities.IsBinaryExpression(type))
                    {
                        var prevLastExpression = expressions[expressions.Count - 2];
                        var lastExpression     = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new BinaryExpression(prevLastExpression, lastExpression, type, FileVersion);
                        expressions.Add(expression);
                    }
                    else
                    {
                        var lastExpression = expressions[expressions.Count - 1];
                        expressions.RemoveAt(expressions.Count - 1);
                        var expression = new UnaryExpression(lastExpression, type, FileVersion);
                        expressions.Add(expression);
                    }
                }
                else
                {
                    break;
                }
            }

            if (isTrace)
            {
                Debug.WriteLine($"Result: {expressions.Count} expressions. Line token: {lineToken}");
                for (var i = 0; i < expressions.Count; ++i)
                {
                    Debug.WriteLine($"Expression {i + 1}: {expressions[i].ToString()}");
                }
                Debug.WriteLine("----------------------------");
                Debug.WriteLine("");
            }

            return(expressions);
        }