Ast.Expression Convert(Ast.Expression expr, TypeSig actualType, TypeSig reqType) { if (actualType == null || reqType == null || TypeAnalysis.IsSameType(actualType, reqType)) { return expr; } else if (actualType is ByRefSig && reqType is PtrSig && expr is DirectionExpression) { return Convert( new UnaryOperatorExpression(UnaryOperatorType.AddressOf, ((DirectionExpression)expr).Expression.Detach()), new PtrSig(((ByRefSig)actualType).Next), reqType); } else if (actualType is PtrSig && reqType is ByRefSig) { expr = Convert(expr, actualType, new PtrSig(((ByRefSig)reqType).Next)); return new DirectionExpression { FieldDirection = FieldDirection.Ref, Expression = new UnaryOperatorExpression(UnaryOperatorType.Dereference, expr) }; } else if (actualType is PtrSig && reqType is PtrSig) { 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 (reqType.GetElementType() == ElementType.Boolean) { if (actualType.GetElementType() == ElementType.Boolean) return expr; if (actualIsIntegerOrEnum) { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, AstBuilder.MakePrimitive(0, actualType.ToTypeDefOrRef())); } else { return new BinaryOperatorExpression(expr, BinaryOperatorType.InEquality, new NullReferenceExpression()); } } if (actualType.GetElementType() == ElementType.Boolean && requiredIsIntegerOrEnum) { return new ConditionalExpression { Condition = expr, TrueExpression = AstBuilder.MakePrimitive(1, reqType.ToTypeDefOrRef()), FalseExpression = AstBuilder.MakePrimitive(0, reqType.ToTypeDefOrRef()) }; } if (expr is PrimitiveExpression && !requiredIsIntegerOrEnum && TypeAnalysis.IsEnum(actualType)) { return expr.CastTo(AstBuilder.ConvertType(actualType)); } bool actualIsPrimitiveType = actualIsIntegerOrEnum || actualType.GetElementType() == ElementType.R4 || actualType.GetElementType() == ElementType.R8; bool requiredIsPrimitiveType = requiredIsIntegerOrEnum || reqType.GetElementType() == ElementType.R4 || reqType.GetElementType() == ElementType.R8; if (actualIsPrimitiveType && requiredIsPrimitiveType) { return expr.CastTo(AstBuilder.ConvertType(reqType)); } return expr; } }
static Ast.DirectionExpression MakeRef(Ast.Expression expr) { return new DirectionExpression { Expression = expr, FieldDirection = FieldDirection.Ref }; }