public static Symbol Unary(MiddleOperator middleOp, Symbol symbol)
        {
            Type type = symbol.Type;

            switch (middleOp)
            {
            case MiddleOperator.Address:
                if (symbol.Value is StaticValue) // &a[i], &s.i
                {
                    StaticValue   staticValue   = (StaticValue)symbol.Value;
                    StaticAddress staticAddress =
                        new StaticAddress(staticValue.UniqueName, staticValue.Offset);
                    return(new Symbol(new Type(type), staticAddress));
                }
                else if (symbol.IsExternOrStatic()) // &i
                {
                    StaticAddress staticAddress =
                        new StaticAddress(symbol.UniqueName, 0);
                    return(new Symbol(new Type(type), staticAddress));
                }
                break;
            }

            return(null);
        }
        /*private static Expression GenerateIndex(Symbol symbol,
         *                                      BigInteger value) {
         * int offset = ((int) value) * symbol.Type.ArrayType.Size();
         * StaticValue resultValue;
         *
         * if (symbol.Value is StaticAddress) {
         *  StaticAddress staticAddress = (StaticAddress) symbol.Value;
         *  resultValue = new StaticValue(staticAddress.UniqueName,
         *                                staticAddress.Offset + offset);
         * }
         * else {
         *  resultValue = new StaticValue(symbol.UniqueName, offset);
         * }
         *
         * Symbol resultSymbol = new Symbol(symbol.Type, resultValue);
         * return (new Expression(resultSymbol, null, null));
         * }*/

        public static Expression Unary(MiddleOperator middleOp, Expression expression)
        {
            Symbol symbol = expression.Symbol;

            switch (middleOp)
            {
            case MiddleOperator.Address:
                if (symbol.Value is StaticValue) // &a[i], &s.i
                {
                    StaticValue   staticValue   = (StaticValue)symbol.Value;
                    StaticAddress staticAddress =
                        new StaticAddress(staticValue.UniqueName, staticValue.Offset);
                    Symbol resultSymbol =
                        new Symbol(new Type(symbol.Type), staticAddress);
                    return(new Expression(resultSymbol, null, null));
                }
                else if (symbol.IsExternOrStatic()) // &i
                {
                    StaticAddress staticAddress =
                        new StaticAddress(symbol.UniqueName, 0);
                    Symbol resultSymbol =
                        new Symbol(new Type(symbol.Type), staticAddress);
                    return(new Expression(resultSymbol, null, null));
                }
                break;

            case MiddleOperator.Dereference:
                if (symbol.Value is StaticAddress)
                {
                    StaticAddress staticAddress = (StaticAddress)symbol.Value;
                    StaticValue   staticValue   =
                        new StaticValue(staticAddress.UniqueName, staticAddress.Offset);
                    Symbol resultSymbol =
                        new Symbol(new Type(symbol.Type), staticValue);
                    return(new Expression(resultSymbol, null, null));
                }
                break;
            }

            return(null);
        }
        public static Expression Binary(MiddleOperator middleOp,
                                        Expression leftExpression,
                                        Expression rightExpression)
        {
            Symbol leftSymbol = leftExpression.Symbol,
                   rightSymbol = rightExpression.Symbol;
            Type   leftType = leftSymbol.Type, rightType = rightSymbol.Type;
            object leftValue = leftSymbol.Value, rightValue = rightSymbol.Value;

            switch (middleOp)
            {
            case MiddleOperator.Add:
                if ((leftValue is StaticAddress) && (rightValue is BigInteger)) // &i + 2
                {
                    return(GenerateAddition(leftSymbol, (BigInteger)rightValue));
                }
                else if ((leftValue is BigInteger) && (rightValue is StaticAddress))// 2 + &i
                {
                    return(GenerateAddition(rightSymbol, (BigInteger)leftValue));
                }
                else if (leftSymbol.IsExternOrStaticArray() && (rightValue is BigInteger)) // a + 2
                {
                    return(GenerateAddition(leftSymbol, (BigInteger)rightValue));
                }
                else if ((leftValue is BigInteger) && rightSymbol.IsExternOrStaticArray()) // 2 + a
                {
                    return(GenerateAddition(rightSymbol, (BigInteger)leftValue));
                }
                break;

            case MiddleOperator.Subtract:
                if ((leftValue is StaticAddress) && (rightValue is BigInteger)) // &i - 2
                {
                    return(GenerateAddition(leftSymbol, -((BigInteger)rightValue)));
                }
                if (leftSymbol.IsExternOrStaticArray() && (rightValue is BigInteger)) // a - 2
                {
                    return(GenerateAddition(leftSymbol, -((BigInteger)rightValue)));
                }
                break;

            /*case MiddleOperator.Index:
             * if ((leftValue is StaticAddress)  && (rightValue is BigInteger)) { // a[2]
             *  return GenerateIndex(leftSymbol, (BigInteger) rightValue);
             * }
             * else if ((leftValue is BigInteger) && (rightValue is StaticAddress)) {
             *  return GenerateIndex(rightSymbol, (BigInteger) leftValue);
             * }
             * else if (leftSymbol.IsExternOrStaticArray() && (rightValue is BigInteger)) { // a[2]
             *  return GenerateIndex(leftSymbol, (BigInteger) rightValue);
             * }
             * else if ((leftValue is BigInteger) && rightSymbol.IsExternOrStaticArray()) {
             *  return GenerateIndex(rightSymbol, (BigInteger) leftValue);
             * }
             * break;*/

            case MiddleOperator.Dot:
                if (leftSymbol.IsExternOrStatic())
                {
                    object resultValue =
                        new StaticValue(leftSymbol.UniqueName,
                                        rightSymbol.Offset); // s.i
                    Symbol resultSymbol = new Symbol(leftType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }
                break;
            }

            return(null);
        }
        public static Expression Binary(MiddleOperator middleOp,
                                        Expression leftExpression,
                                        Expression rightExpression)
        {
            Type leftType     = leftExpression.Symbol.Type,
                 rightType    = rightExpression.Symbol.Type;
            object leftValue  = leftExpression.Symbol.Value,
                   rightValue = rightExpression.Symbol.Value;

            switch (middleOp)
            {
            case MiddleOperator.BinaryAdd: // &i + 2
                if ((leftValue is StaticAddress) && (rightValue is BigInteger))
                {
                    StaticAddress staticAddress = (StaticAddress)leftValue;
                    int           resultOffset  =
                        ((int)rightValue) * leftType.PointerType.Size();
                    object resultValue =
                        new StaticAddress(staticAddress.UniqueName,
                                          staticAddress.Offset + resultOffset);
                    Symbol resultSymbol = new Symbol(leftType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }

                // 2 + &i
                if ((leftValue is BigInteger) && (rightValue is StaticAddress))
                {
                    StaticAddress staticAddress = (StaticAddress)rightValue;
                    int           resultOffset  =
                        ((int)leftValue) * rightType.PointerType.Size();
                    object resultValue =
                        new StaticAddress(staticAddress.UniqueName,
                                          staticAddress.Offset + resultOffset);
                    Symbol resultSymbol = new Symbol(rightType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }

                if (leftExpression.Symbol.IsExternOrStatic() && leftType.IsArray() &&
                    (rightValue is BigInteger)) // a + 2
                {
                    int    resultOffset = ((int)rightValue) * leftType.ArrayType.Size();
                    object resultValue  =
                        new StaticAddress(leftExpression.Symbol.UniqueName,
                                          resultOffset);
                    Symbol resultSymbol = new Symbol(leftType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }

                if (leftExpression.Symbol.IsExternOrStatic() &&
                    (leftValue is BigInteger) && rightType.IsArray()) // 2 + a
                {
                    int    resultOffset = ((int)leftValue) * rightType.ArrayType.Size();
                    object resultValue  =
                        new StaticAddress(rightExpression.Symbol.UniqueName,
                                          resultOffset);
                    Symbol resultSymbol = new Symbol(rightType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }
                break;

            case MiddleOperator.BinarySubtract: // &i - 2
                if ((leftValue is StaticAddress) && (rightValue is BigInteger))
                {
                    StaticAddress staticAddress = (StaticAddress)leftValue;
                    int           resultOffset  = ((int)leftValue) * leftType.PointerType.Size();
                    object        resultValue   =
                        new StaticAddress(staticAddress.UniqueName,
                                          staticAddress.Offset - resultOffset);
                    Symbol resultSymbol = new Symbol(leftType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }

                if (leftExpression.Symbol.IsExternOrStatic() && leftType.IsArray() &&
                    (rightValue is BigInteger)) // a - 2
                {
                    int    resultOffset = ((int)rightValue) * leftType.ArrayType.Size();
                    object resultValue  =
                        new StaticAddress(leftExpression.Symbol.UniqueName,
                                          -resultOffset);
                    Symbol resultSymbol = new Symbol(leftType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }
                break;

            case MiddleOperator.Index:
                if (leftExpression.Symbol.IsExternOrStatic() && leftType.IsArray() &&
                    (rightValue is BigInteger)) // a[2]
                {
                    int         size        = leftType.ArrayType.Size();
                    int         offset      = ((int)((BigInteger)rightValue)) * size;
                    StaticValue resultValue =
                        new StaticValue(leftExpression.Symbol.UniqueName, offset);
                    Symbol resultSymbol = new Symbol(leftType, resultValue);
                    resultSymbol.Addressable = !leftExpression.Symbol.IsRegister() &&
                                               !leftType.ArrayType.IsBitfield();
                    resultSymbol.Assignable =
                        !leftType.ArrayType.IsConstantRecursive() &&
                        !leftType.ArrayType.IsArrayFunctionOrString();
                    return(new Expression(resultSymbol, null, null));
                }
                else if ((leftValue is BigInteger) && rightType.IsArray() &&
                         rightExpression.Symbol.IsExternOrStatic()) // [2]a
                {
                    int         size        = rightType.ArrayType.Size();
                    int         offset      = ((int)((BigInteger)leftValue)) * size;
                    StaticValue resultValue =
                        new StaticValue(rightExpression.Symbol.UniqueName, offset);
                    Symbol resultSymbol = new Symbol(rightType, resultValue);
                    resultSymbol.Addressable = !leftExpression.Symbol.IsRegister() &&
                                               !leftType.ArrayType.IsBitfield();
                    resultSymbol.Assignable =
                        !leftType.ArrayType.IsConstantRecursive() &&
                        !leftType.ArrayType.IsArrayFunctionOrString();
                    return(new Expression(resultSymbol, null, null));
                }
                break;

            case MiddleOperator.Dot:
                if (leftExpression.Symbol.IsExternOrStatic())
                {
                    object resultValue =
                        new StaticValue(leftExpression.Symbol.UniqueName,
                                        rightExpression.Symbol.Offset); // s.i
                    Symbol resultSymbol = new Symbol(leftType, resultValue);
                    return(new Expression(resultSymbol, null, null));
                }
                break;
            }

            return(null);
        }
        public static void GenerateByteList(Type type, object value, List <sbyte> sbyteList,
                                            IDictionary <int, string> accessMap)
        {
            if (type.IsString())
            {
                foreach (char c in ((string)value))
                {
                    sbyteList.Add((sbyte)c);
                }
                sbyteList.Add((sbyte)0);
            }
            else if (value is StaticAddress)
            {
                StaticAddress staticAddress = (StaticAddress)value;
                accessMap[sbyteList.Count] = staticAddress.UniqueName;
                sbyteList.Add((sbyte)((short)staticAddress.Offset));
                sbyteList.Add((sbyte)(((short)staticAddress.Offset) >> 8));
            }
            else if (value is StaticValue)
            {
                StaticValue staticValue = (StaticValue)value;

                foreach (KeyValuePair <int, string> pair in staticValue.AccessMap)
                {
                    accessMap[pair.Key + sbyteList.Count] = pair.Value;
                }

                sbyteList.AddRange(staticValue.ByteList);
            }
            else
            {
                switch (type.Sort)
                {
                case Sort.Signed_Short_Int:
                case Sort.Unsigned_Short_Int: {
                    sbyteList.Add((sbyte)((long)value));
                }
                break;

                case Sort.Signed_Char:
                case Sort.Unsigned_Char: {
                    sbyteList.Add((sbyte)((long)value));
                }
                break;

                case Sort.Signed_Int:
                case Sort.Unsigned_Int:
                case Sort.Pointer: {
                    long longValue = (long)value;
                    sbyteList.Add((sbyte)longValue);
                    sbyteList.Add((sbyte)(longValue >> 8));
                }
                break;

                case Sort.Signed_Long_Int:
                case Sort.Unsigned_Long_Int: {
                    long longValue = (long)value;
                    sbyteList.Add((sbyte)longValue);
                    sbyteList.Add((sbyte)(longValue >> 8));
                    sbyteList.Add((sbyte)(longValue >> 16));
                    sbyteList.Add((sbyte)(longValue >> 24));
                }
                break;

                case Sort.Float: {
                    float  floatValue = (float)((decimal)value);
                    byte[] byteArray  = BitConverter.GetBytes(floatValue);

                    foreach (byte b in byteArray)
                    {
                        sbyteList.Add((sbyte)b);
                    }
                }
                break;

                case Sort.Double:
                case Sort.Long_Double: {
                    double doubleValue = (double)((decimal)value);
                    byte[] byteArray   = BitConverter.GetBytes(doubleValue);

                    foreach (byte b in byteArray)
                    {
                        sbyteList.Add((sbyte)b);
                    }
                }
                break;
                }
            }
        }
        public static void GenerateStatic(Type toType, object fromInit,
                                          List <sbyte> byteList, IDictionary <int, string> accessMap)
        {
            if (fromInit is Expression)
            {
                Symbol fromSymbol = ((Expression)fromInit).Symbol();
                Assert.Error(fromSymbol.IsStaticOrExtern(), fromSymbol,
                             Message.Non__static_initializer);
                Type fromType = fromSymbol.Type;

                if (toType.IsArray() && fromType.IsString())
                {
                    Assert.Error(toType.ArrayType.IsChar());
                    fromInit = TextToCharList((string)fromSymbol.Value);
                }

                if (fromType.IsArrayFunctionOrString() && toType.IsPointer())
                {
                    Assert.Error((fromType.IsString() && toType.PointerType.IsChar()) ||
                                 (fromType.IsArray() && fromType.ArrayType.Equals(toType.PointerType)) ||
                                 (fromType.IsFunction() && fromType.Equals(toType.PointerType)));
                    accessMap[byteList.Count] = fromSymbol.UniqueName;
                    byteList.Add((sbyte)0);
                    byteList.Add((sbyte)0);
                }
                else if (fromSymbol.Value is StaticAddress)
                {
                    Assert.Error(fromType.IsPointer() && toType.IsPointer());
                    StaticAddress staticAddress = (StaticAddress)fromSymbol.Value;
                    accessMap[byteList.Count] = staticAddress.UniqueName;
                    byteList.Add((sbyte)staticAddress.Offset);
                    byteList.Add((sbyte)(staticAddress.Offset >> 8));
                }
                else if (fromSymbol.Value is StaticValue)
                {
                    Assert.Error(fromType.Equals(toType));
                    StaticValue staticValue = (StaticValue)fromSymbol.Value;

                    foreach (KeyValuePair <int, string> entry in staticValue.AccessMap)
                    {
                        accessMap[byteList.Count + entry.Key] = entry.Value;
                    }

                    byteList.AddRange(staticValue.ByteList);
                }
                else
                {
                    Symbol toSymbol = TypeCast.ImplicitCast(null, fromSymbol, toType);

                    foreach (KeyValuePair <int, string> entry in toSymbol.StaticSymbol.AccessMap)
                    {
                        accessMap[byteList.Count + entry.Key] = entry.Value;
                    }

                    byteList.AddRange(toSymbol.StaticSymbol.ByteList);
                }
            }
            else
            {
                List <object> fromList = (List <object>)fromInit;

                switch (toType.Sort)
                {
                case Sort.Array: {
                    if (toType.ArraySize == 0)
                    {
                        toType.ArraySize = fromList.Count;
                    }

                    int toByteListSize = byteList.Count + toType.Size();
                    Assert.Error(fromList.Count <= toType.ArraySize, toType, Message.Too_many_initializers);
                    //Assert.Warning(fromList.Count == toType.ArraySize, toType, Message.Too_few_initializers);
                    Type subType = toType.ArrayType;

                    foreach (object value in fromList)
                    {
                        GenerateStatic(subType, value, byteList, accessMap);
                    }

                    GenerateZeroByteList(toByteListSize - byteList.Count, byteList);
                }
                break;

                case Sort.Struct: {
                    IDictionary <string, Symbol> memberMap = toType.MemberMap;
                    Assert.Error(fromList.Count <= memberMap.Count,
                                 toType, Message.Too_many_initializers);

                    /*Assert.Warning(fromList.Count == memberMap.Count,
                     *             toType, Message.Too_few_initializers);*/

                    int toByteListSize = byteList.Count + toType.Size();
                    KeyValuePair <string, Symbol>[] memberArray = new KeyValuePair <string, Symbol> [memberMap.Count];
                    memberMap.CopyTo(memberArray, 0);
                    for (int index = 0; index < fromList.Count; ++index)
                    {
                        Symbol memberSymbol = memberArray[index].Value;
                        object init         = ModifyInitializer.DoInit(memberSymbol.Type, fromList[index]);
                        GenerateStatic(memberSymbol.Type, init, byteList, accessMap);
                    }

                    GenerateZeroByteList(toByteListSize - byteList.Count, byteList);
                }
                break;

                case Sort.Union: {
                    Assert.Error(fromList.Count == 1, toType, Message.A_union_can_be_initalized_by_one_value_only);
                    int toByteListSize = byteList.Count + toType.Size();
                    IDictionary <string, Symbol> memberMap = toType.MemberMap;
                    Symbol firstSymbol = memberMap.Values.GetEnumerator().Current;
                    object init        = ModifyInitializer.DoInit(firstSymbol.Type, fromList[0]);
                    GenerateStatic(firstSymbol.Type, init, byteList, accessMap);
                    GenerateZeroByteList(toByteListSize - byteList.Count, byteList);
                }
                break;
                }
            }
        }