protected override void emitCode(Context ctx, bool mustReturn) { var gen = ctx.CurrentMethod.Generator; var fromType = Expression.Resolve(ctx); var toType = Resolve(ctx); if (toType.IsExtendablyAssignableFrom(fromType, true)) Expression.Emit(ctx, true); else if (fromType.IsNumericType() && toType.IsNumericType(true)) // (decimal -> T) is processed via op_Explicit() castNumeric(ctx, fromType, toType); else if(fromType.IsCallableType() && toType.IsCallableType()) castDelegate(ctx, fromType, toType); else if (fromType == typeof (NullType)) { if (toType.IsNullableType()) { var tmpVar = ctx.Scope.DeclareImplicit(ctx, toType, true); gen.EmitLoadLocal(tmpVar.LocalBuilder, true); gen.EmitInitObject(toType); gen.EmitLoadLocal(tmpVar.LocalBuilder); } else if (!toType.IsValueType) gen.EmitNull(); else error(CompilerMessages.CastNullValueType, toType); } else if (toType.IsNullableType()) { Expression.Emit(ctx, true); var underlying = Nullable.GetUnderlyingType(toType); if(underlying.IsNumericType() && fromType.IsNumericType() && underlying != fromType) gen.EmitConvert(underlying); else if(underlying != fromType) error(fromType, toType); var ctor = toType.GetConstructor(new[] { underlying }); gen.EmitCreateObject(ctor); } else if (toType.IsExtendablyAssignableFrom(fromType)) { Expression.Emit(ctx, true); // box if (fromType.IsValueType && toType == typeof (object)) gen.EmitBox(fromType); else { var castOp = ctx.ResolveConvertorToType(fromType, toType); if (castOp != null) gen.EmitCall(castOp.MethodInfo); else gen.EmitCast(toType); } } else if (fromType.IsExtendablyAssignableFrom(toType)) { Expression.Emit(ctx, true); // unbox if (fromType == typeof (object) && toType.IsValueType) gen.EmitUnbox(toType); // cast ancestor to descendant else if (!fromType.IsValueType && !toType.IsValueType) gen.EmitCast(toType); else { var castOp = ctx.ResolveConvertorToType(fromType, toType); if (castOp != null) gen.EmitCall(castOp.MethodInfo); else error(fromType, toType); } } else error(fromType, toType); }