# encoding: ascii
# api: powershell
# title: Invoke-LostOperator
# description: Cool script which allows you to do some things more easily. For example, it became possible use bitwise shift in PowerShell v2 or c-style ternary operation.
# version: 0.1
# type: function
# author: roger
# license: CC0
# function: Invoke-LostOperator
# x-poshcode-id: 6467
# x-archived: 2016-08-09T11:09:01
# x-published: 2016-08-07T16:43:00
#
# Original script found at https://github.com/gregzakh/alt-ps/blob/master/Invoke-LostOperator.ps1
#
Set-Alias ~! Invoke-LostOperator
function Invoke-LostOperator {
<#
.SYNOPSIS
Compensates lack of some operators.
.EXAMPLE
PS C:\> Invoke-LostOperator { 1 + 1 }
2
.EXAMPLE
PS C:\> ~! { 1 + 1 }
2
Same that's above but shortly.
.EXAMPLE
PS C:\> ~! 7 -shl 3
56
Note that shift operations works only in PowerShell v2, on
higher version there are native operators -shl and -shr.
.EXAMPLE
PS C:\> ~! 7 -shr 1
3
.EXAMPLE
PS C:\> ~! (100 -lt (Get-ChildItem).Count) ? 'yes' : 'no'
no
You can also use script blocks in ternary operation.
.NOTES
This function is experimental that's why there are some
possible issues.
#>
begin {
if (($maj = $PSVersionTable.PSVersion.Major) -eq 2) {
@(
[Reflection.Emit.DynamicMethod],
[Reflection.Emit.OpCodes]
) | ForEach-Object {
$keys = ($ta = [PSObject].Assembly.GetType(
'System.Management.Automation.TypeAccelerators'
))::Get.Keys
$collect = @()
}{
if ($keys -notcontains $_.Name) {
$ta::Add($_.Name, $_)
}
$collect += $_.Name
}
function private:Set-ShiftMethod {
param(
[Parameter(Position=0)]
[ValidateNotNullOrEmpty()]
[ValidateSet('Left', 'Right')]
[String]$X = 'Left',
[Parameter(Position=1)]
[ValidateNotNull()]
[Object]$Type = [Int32]
)
@(
'Ldarg_0'
'Ldarg_1'
'Ldc_I4_S, 31'
'And'
$(if ($X -eq 'Right') { 'Shr' } else { 'Shl' })
'Ret'
) | ForEach-Object {
$def = New-Object DynamicMethod(
$X, $Type, @($Type, $Type)
)
$il = $def.GetILGenerator()
}{
if ($_ -notmatch ',') { $il.Emit([OpCodes]::$_) }
else {
$il.Emit(
[OpCodes]::(($$ = $_.Split(','))[0]), ($$[1].Trim() -as $Type)
)}
}
$def.CreateDelegate((
Invoke-Expression "[Func[$($Type.Name), $($Type.Name), $($Type.Name)]]"
))
}
}
function private:eval {
param(
[Parameter(Mandatory=$true)]
[Object]$Object
)
if ($Object -ne $null) {
if ($Object -is 'ScriptBlock') {
return &$Object
}
return $Object
}
return $null
}
}
process {
if ($args) {
#shifts (only for PowerShell v2)
if ($ta) {
# -shl
if ($l = [Array]::IndexOf($args, '-shl') + 1) {
return (Set-ShiftMethod Left).Invoke($args[0], $args[$l])
}
# -shr
if ($l = [Array]::IndexOf($args, '-shr') + 1) {
return (Set-ShiftMethod Right).Invoke($args[0], $args[$l])
}
}
#ternary operation
if ($l = [Array]::IndexOf($args, '?') + 1) {
if (eval($args[0])) {
return eval($args[$l])
}
return eval($args[[Array]::IndexOf($args, ':', $l) + 1])
}
return eval($args[0])
}
}
end {
if ($ta) {
$collect | ForEach-Object { [void]$ta::Remove($_) }
}
}
}