public override Expression CoerceAnonymousNestedFunction(AnonymousNestedFunction func, TypeNode targetType, bool explicitCoercion, TypeViewer typeViewer) { if (func is AnonymousNestedDelegate && !(targetType is DelegateNode)) { this.HandleError(func, Error.AnonMethToNonDel, this.GetTypeName(targetType)); return null; } return base.CoerceAnonymousNestedFunction(func, targetType, explicitCoercion, typeViewer); }
public override Expression ImplicitCoercion(Expression source, TypeNode targetType, TypeViewer typeViewer) { // LJW: added third parameter "typeViewer" so we override the correct thing if (source == null || source.Type == null || targetType == null) return null; if (source.Type is EnumNode && targetType == SystemTypes.Int32) { return source; } if (source.Type == SystemTypes.Object) { if (targetType is Chan || targetType is Set || targetType is ZArray || targetType is Class) return source; else { this.HandleError(source, System.Compiler.Error.NoImplicitCoercion, "object", targetType.FullName); return null; } } if (targetType == SystemTypes.Object) { if (!(source.Type is Chan || source.Type is Set || source.Type is ZArray || source.Type is Class)) { this.HandleError(source, System.Compiler.Error.NoImplicitCoercion, source.Type.FullName, "object"); return null; } } if (source.Type == SystemTypes.Int32 && targetType == SystemTypes.UInt8) { BinaryExpression binExpr = new BinaryExpression(source, new MemberBinding(null, SystemTypes.UInt8), NodeType.Castclass, source.SourceContext); binExpr.Type = SystemTypes.UInt8; return binExpr; } if (source.Type == SystemTypes.UInt8 && targetType == SystemTypes.Int32) { BinaryExpression binExpr = new BinaryExpression(source, new MemberBinding(null, SystemTypes.Int32), NodeType.Castclass, source.SourceContext); binExpr.Type = SystemTypes.Int32; return binExpr; } return base.ImplicitCoercion(source, targetType, typeViewer); }
public override Expression ExplicitLiteralCoercion(Literal lit, TypeNode sourceType, TypeNode targetType, TypeViewer typeViewer) { if (sourceType == targetType && (sourceType == SystemTypes.Double || sourceType == SystemTypes.Single)) return lit; TypeNode originalTargetType = targetType; EnumNode sourceEnum = sourceType as EnumNode; if (sourceEnum != null) sourceType = sourceEnum.UnderlyingType; bool needsRuntimeCoercion = this.suppressOverflowCheck; if (!sourceType.IsPrimitiveInteger || sourceType == SystemTypes.IntPtr || sourceType == SystemTypes.UIntPtr) needsRuntimeCoercion = true; else if (!targetType.IsPrimitiveInteger || targetType == SystemTypes.IntPtr || targetType == SystemTypes.UIntPtr) needsRuntimeCoercion = true; if (needsRuntimeCoercion){ if (lit != null && lit.Value != null) targetType = TypeNode.StripModifier(targetType, SystemTypes.NonNullType); return this.ExplicitCoercion(lit, targetType, typeViewer); }else return this.LiteralCoercion(lit, sourceType, targetType, true, originalTargetType, null, false); }
private Literal LiteralCoercion(Literal/*!*/ lit, TypeNode sourceType, TypeNode targetType, bool explicitCoercion, TypeNode originalTargetType, TypeViewer typeViewer, bool forLabel) { if (sourceType == targetType){ if (sourceType == lit.Type) return lit; return new Literal(Convert.ChangeType(lit.Value, sourceType.TypeCode), sourceType, lit.SourceContext); } object val = lit.Value; EnumNode eN = targetType as EnumNode; if (eN != null){ if (sourceType.IsPrimitiveInteger && val is IConvertible && ((IConvertible)val).ToDouble(null) == 0.0){ if (eN.UnderlyingType == SystemTypes.Int64 || eN.UnderlyingType == SystemTypes.UInt64) val = 0L; else val = 0; return new Literal(val, eN, lit.SourceContext); } goto error; } if (targetType.TypeCode == TypeCode.Boolean){ this.HandleError(lit, Error.ConstOutOfRange, lit.SourceContext.SourceText, "bool"); lit.SourceContext.Document = null; return null; } if (targetType.TypeCode == TypeCode.String){ if (val != null || lit.Type != SystemTypes.Object){ this.HandleError(lit, Error.NoImplicitConversion, this.GetTypeName(sourceType), this.GetTypeName(targetType)); lit.SourceContext.Document = null; return null; } return lit; } if (targetType.TypeCode == TypeCode.Object){ if (val == null && sourceType == SystemTypes.Object && (explicitCoercion || !this.IsNonNullType(targetType))) return lit; if (val is string && this.IsNonNullType(targetType) && TypeNode.StripModifiers(targetType) == SystemTypes.String) return lit; Method coercion = null; if (explicitCoercion) coercion = this.UserDefinedExplicitCoercionMethod(lit, sourceType, targetType, true, originalTargetType, typeViewer); else coercion = this.UserDefinedImplicitCoercionMethod(lit, sourceType, targetType, true, typeViewer); if (coercion != null) return null; this.HandleError(lit, Error.NoImplicitConversion, this.GetTypeName(sourceType), this.GetTypeName(targetType)); lit.SourceContext.Document = null; return null; } if ((targetType.TypeCode == TypeCode.Char || sourceType.TypeCode == TypeCode.Boolean || sourceType.TypeCode == TypeCode.Decimal) && !forLabel) goto error; switch (sourceType.TypeCode){ case TypeCode.Double: switch (targetType.TypeCode){ case TypeCode.Single: this.HandleError(lit, Error.LiteralDoubleCast, "float", "F"); return lit; case TypeCode.Decimal: this.HandleError(lit, Error.LiteralDoubleCast, "decimal", "M"); return lit; default: this.HandleError(lit, Error.NoImplicitConversion, this.GetTypeName(sourceType), this.GetTypeName(targetType)); lit.SourceContext.Document = null; return null; } case TypeCode.Single: switch (targetType.TypeCode){ case TypeCode.Double: break; default: this.HandleError(lit, Error.NoImplicitConversion, this.GetTypeName(sourceType), this.GetTypeName(targetType)); lit.SourceContext.Document = null; return null; } break; case TypeCode.Int64: case TypeCode.UInt64: switch (targetType.TypeCode){ case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Decimal: case TypeCode.Single: case TypeCode.Double: break; default: if (explicitCoercion || !lit.TypeWasExplicitlySpecifiedInSource) break; this.HandleError(lit, Error.NoImplicitConversion, this.GetTypeName(sourceType), this.GetTypeName(targetType)); lit.SourceContext.Document = null; return null; } break; } try{ if (val == null){ if (targetType.IsValueType) goto error; }else val = System.Convert.ChangeType(val, targetType.TypeCode); return new Literal(val, targetType, lit.SourceContext); }catch(InvalidCastException){ }catch(OverflowException){ }catch(FormatException){} error: if (sourceType.IsPrimitiveNumeric && lit.SourceContext.Document != null){ Error e = Error.ConstOutOfRange; if (explicitCoercion) e = Error.ConstOutOfRangeChecked; this.HandleError(lit, e, lit.SourceContext.SourceText, this.GetTypeName(targetType)); }else this.HandleError(lit, Error.NoImplicitConversion, this.GetTypeName(sourceType), this.GetTypeName(targetType)); if (this.ErrorHandler != null) lit.SourceContext.Document = null; return null; }
public override Literal ImplicitLiteralCoercion(Literal lit, TypeNode sourceType, TypeNode targetType, TypeViewer typeViewer) { return this.LiteralCoercion(lit, sourceType, targetType, false, targetType, typeViewer, false); }
/// <summary> /// Return a scope's view of the argument type, where the scope's view is represented /// by a type viewer. /// [The identity function, except for dialects (e.g. Extensible Sing#) that allow /// extensions and differing views of types]. /// Defined as a static method to allow the type viewer to be null, /// meaning an identity-function view. /// </summary> public static TypeNode/*!*/ GetTypeView(TypeViewer typeViewer, TypeNode/*!*/ type) { return typeViewer == null ? type.EffectiveTypeNode : typeViewer.GetTypeView(type); }