Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference actualType, Cecil.TypeReference reqType)
        {
            if (actualType == null || reqType == null || TypeAnalysis.IsSameType(actualType, reqType)) {
                return expr;
            } else if (actualType is ByReferenceType && reqType is PointerType && expr is DirectionExpression) {
                return Convert(
                    new UnaryOperatorExpression(UnaryOperatorType.AddressOf, ((DirectionExpression)expr).Expression.Detach()),
                    new PointerType(((ByReferenceType)actualType).ElementType),
                    reqType);
            } else if (actualType is PointerType && reqType is ByReferenceType) {
                expr = Convert(expr, actualType, new PointerType(((ByReferenceType)reqType).ElementType));
                return new DirectionExpression {
                    FieldDirection = FieldDirection.Ref,
                    Expression = new UnaryOperatorExpression(UnaryOperatorType.Dereference, expr)
                };
            } else if (actualType is PointerType && reqType is PointerType) {
                if (actualType.FullName != reqType.FullName)
                    return expr.CastTo(AstBuilder.ConvertType(reqType));
                else
                    return expr;
            } else {
                bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType);
                bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType);

                if (TypeAnalysis.IsBoolean(reqType)) {
                    if (TypeAnalysis.IsBoolean(actualType))
                        return expr;
                    if (actualIsIntegerOrEnum) {
                        return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType));
                    } else {
                        return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression());
                    }
                }
                if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) {
                    return new ConditionalExpression {
                        Condition = expr,
                        TrueExpression = AstBuilder.MakePrimitive(1, reqType),
                        FalseExpression = AstBuilder.MakePrimitive(0, reqType)
                    };
                }

                if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType))
                {
                    return expr.CastTo(AstBuilder.ConvertType(actualType));
                }

                bool actualIsPrimitiveType = actualIsIntegerOrEnum
                    || actualType.MetadataType == MetadataType.Single || actualType.MetadataType == MetadataType.Double;
                bool requiredIsPrimitiveType = requiredIsIntegerOrEnum
                    || reqType.MetadataType == MetadataType.Single || reqType.MetadataType == MetadataType.Double;
                if (actualIsPrimitiveType && requiredIsPrimitiveType) {
                    return expr.CastTo(AstBuilder.ConvertType(reqType));
                }
                return expr;
            }
        }
        Ast.Expression Convert(Ast.Expression expr, Cecil.TypeReference actualType, Cecil.TypeReference reqType)
        {
            if (reqType == null || actualType == reqType) {
                return expr;
            } else {
                bool actualIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(actualType);
                bool requiredIsIntegerOrEnum = TypeAnalysis.IsIntegerOrEnum(reqType);

                if (TypeAnalysis.IsBoolean(reqType)) {
                    if (TypeAnalysis.IsBoolean(actualType))
                        return expr;
                    if (actualIsIntegerOrEnum) {
                        return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, MakePrimitive(0, actualType));
                    } else {
                        return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression());
                    }
                }
                if (TypeAnalysis.IsBoolean(actualType) && requiredIsIntegerOrEnum) {
                    return new ConditionalExpression {
                        Condition = expr,
                        TrueExpression = MakePrimitive(1, reqType),
                        FalseExpression = MakePrimitive(0, reqType)
                    };
                }
                if (actualIsIntegerOrEnum && requiredIsIntegerOrEnum) {
                    return expr.CastTo(AstBuilder.ConvertType(reqType));
                }
                return expr;
            }
        }