private void EmitCast(BoundValueType source, BoundValueType target) { if (source == target) return; if (target == BoundValueType.Unknown) { if (source.IsValueType()) IL.Emit(OpCodes.Box, source.GetNativeType()); return; } MethodInfo method; switch (target) { case BoundValueType.Boolean: switch (source) { case BoundValueType.Boolean: throw new InvalidOperationException(); case BoundValueType.Number: method = _numberToBoolean; break; case BoundValueType.String: method = _stringToBoolean; break; default: method = _toBoolean; break; } break; case BoundValueType.Number: switch (source) { case BoundValueType.Boolean: method = _booleanToNumber; break; case BoundValueType.Number: throw new InvalidOperationException(); case BoundValueType.String: method = _stringToNumber; break; default: method = _toNumber; break; } break; case BoundValueType.String: switch (source) { case BoundValueType.Boolean: method = _booleanToString; break; case BoundValueType.Number: method = _numberToString; break; case BoundValueType.String: throw new InvalidOperationException(); default: method = _toString; break; } break; default: throw new ArgumentOutOfRangeException("source", String.Format("Cannot cast '{0}' to '{1}'", source, target)); } IL.EmitCall(method); }