Skip to content

Commit 9e44b65

Browse files
Fix bitwise comparsion operators
The operators `-band` and `-bor` required conversion for `Enum` types. The comparison is now performed on the underlying type and then converted to the type of the lhs expression if applicable.
1 parent e69fa42 commit 9e44b65

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

src/PSLambda/CompileVisitor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -244,9 +244,9 @@ public object VisitBinaryExpression(BinaryExpressionAst binaryExpressionAst)
244244
case TokenKind.Or:
245245
return OrElse(PSIsTrue(lhs), PSIsTrue(rhs));
246246
case TokenKind.Band:
247-
return And(lhs, rhs);
247+
return PSBitwiseOperation(ExpressionType.And, lhs, rhs);
248248
case TokenKind.Bor:
249-
return Or(lhs, rhs);
249+
return PSBitwiseOperation(ExpressionType.Or, lhs, rhs);
250250
case TokenKind.Is:
251251
if (rhsTypeConstant == null)
252252
{

src/PSLambda/ExpressionUtils.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,39 @@ public static Expression PSDotDot(Expression lhs, Expression rhs)
352352
PSConvertTo<int>(rhs));
353353
}
354354

355+
/// <summary>
356+
/// Creates an <see cref="Expression" /> representing the evaluation of a bitwise comparision
357+
/// operator from the PowerShell engine.
358+
/// </summary>
359+
/// <param name="expressionType">The expression operator.</param>
360+
/// <param name="lhs">The <see cref="Expression" /> on the left hand side.</param>
361+
/// <param name="rhs">The <see cref="Expression" /> on the right hand side.</param>
362+
/// <returns>An <see cref="Expression" /> representing the operation.</returns>
363+
public static Expression PSBitwiseOperation(
364+
ExpressionType expressionType,
365+
Expression lhs,
366+
Expression rhs)
367+
{
368+
var resultType = lhs.Type;
369+
if (typeof(Enum).IsAssignableFrom(lhs.Type))
370+
{
371+
lhs = Convert(lhs, Enum.GetUnderlyingType(lhs.Type));
372+
}
373+
374+
if (typeof(Enum).IsAssignableFrom(rhs.Type))
375+
{
376+
rhs = Convert(rhs, Enum.GetUnderlyingType(rhs.Type));
377+
}
378+
379+
var resultExpression = MakeBinary(expressionType, lhs, rhs);
380+
if (resultType == resultExpression.Type)
381+
{
382+
return resultExpression;
383+
}
384+
385+
return PSConvertTo(resultExpression, resultType);
386+
}
387+
355388
private static bool PSEqualsIgnoreCase(object first, object second)
356389
{
357390
return LanguagePrimitives.Compare(first, second, ignoreCase: true) == 0;

test/Operator.Tests.ps1

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,4 +187,15 @@ Describe 'operator tests' {
187187
(New-PSDelegate { 'this' -ceq 'that' }).Invoke() | Should -Be $false
188188
(New-PSDelegate { 'this' -ceq 'This' }).Invoke() | Should -Be $false
189189
}
190+
It 'Bor' {
191+
(New-PSDelegate { [Reflection.BindingFlags]::Instance -bor [Reflection.BindingFlags]::Public }).Invoke() |
192+
Should -Be ([Reflection.BindingFlags]'Instance, Public')
193+
}
194+
195+
It 'Band' {
196+
$flags = [Reflection.BindingFlags]'Instance, Public'
197+
(New-PSDelegate { $flags -band [Reflection.BindingFlags]::Public }).Invoke() |
198+
Should -Be ([Reflection.BindingFlags]'Public')
199+
}
200+
190201
}

0 commit comments

Comments
 (0)