Skip to content

Commit

Permalink
Fix bug where logical_and and logical_or rules were always emitting IL
Browse files Browse the repository at this point in the history
  • Loading branch information
paulirwin committed Oct 26, 2024
1 parent 7cb9e20 commit ccd9836
Showing 1 changed file with 61 additions and 47 deletions.
108 changes: 61 additions & 47 deletions src/Lucene.Net.Expressions/JS/JavascriptCompiler.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
using Antlr4.Runtime;
using Antlr4.Runtime.Tree;
using J2N;
using J2N.Text;
using Lucene.Net.Queries.Function;
using Lucene.Net.Support;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using JCG = J2N.Collections.Generic;
using J2N;
using System.Text;
using System.Diagnostics.CodeAnalysis;
using JCG = J2N.Collections.Generic;

namespace Lucene.Net.Expressions.JS
{
Expand Down Expand Up @@ -548,70 +548,84 @@ public override void EnterBitwise_or(JavascriptParser.Bitwise_orContext context)

public override void EnterLogical_and(JavascriptParser.Logical_andContext context)
{
// Evaluate the first operand and check if it is false
EnterBitwise_or(context.bitwise_or(0));
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);

// Iterate over the remaining operands
for (int i = 2; i < context.children.Count; i += 2)
if (context.children.Count == 1)
{
EnterBitwise_or(context.bitwise_or(0));
}
else
{
if (context.children[i] is not JavascriptParser.Bitwise_orContext bitwiseOrContext)
// Evaluate the first operand and check if it is false
EnterBitwise_or(context.bitwise_or(0));
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);

// Iterate over the remaining operands
for (int i = 2; i < context.children.Count; i += 2)
{
throw new InvalidOperationException("Unexpected child of logical_and");
if (context.children[i] is not JavascriptParser.Bitwise_orContext bitwiseOrContext)
{
throw new InvalidOperationException("Unexpected child of logical_and");
}

// Evaluate the next operand and check if it is false
EnterBitwise_or(bitwiseOrContext);
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);

// Combine the results using OR
_compiler.gen.Emit(OpCodes.Or);
}

// Evaluate the next operand and check if it is false
EnterBitwise_or(bitwiseOrContext);
// Check if the combined result is false
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);

// Combine the results using OR
_compiler.gen.Emit(OpCodes.Or);
// Convert the result to a double
_compiler.gen.Emit(OpCodes.Conv_R8);
}

// Check if the combined result is false
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);

// Convert the result to a double
_compiler.gen.Emit(OpCodes.Conv_R8);
}

public override void EnterLogical_or(JavascriptParser.Logical_orContext context)
{
// Evaluate the first operand and check if it is true
EnterLogical_and(context.logical_and(0));
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);
_compiler.gen.Emit(OpCodes.Ldc_I4_1);
_compiler.gen.Emit(OpCodes.Xor);

// Iterate over the remaining operands
for (int i = 2; i < context.children.Count; i += 2)
if (context.children.Count == 1)
{
if (context.children[i] is not JavascriptParser.Logical_andContext logicalAndContext)
{
throw new InvalidOperationException("Unexpected child of logical_or");
}

// Evaluate the next operand and check if it is true
EnterLogical_and(logicalAndContext);
EnterLogical_and(context.logical_and(0));
}
else
{
// Evaluate the first operand and check if it is true
EnterLogical_and(context.logical_and(0));
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);
_compiler.gen.Emit(OpCodes.Ldc_I4_1);
_compiler.gen.Emit(OpCodes.Xor);

// Combine the results using OR
_compiler.gen.Emit(OpCodes.Or);
}
// Iterate over the remaining operands
for (int i = 2; i < context.children.Count; i += 2)
{
if (context.children[i] is not JavascriptParser.Logical_andContext logicalAndContext)
{
throw new InvalidOperationException("Unexpected child of logical_or");
}

// Evaluate the next operand and check if it is true
EnterLogical_and(logicalAndContext);
_compiler.gen.Emit(OpCodes.Ldc_I4_0);
_compiler.gen.Emit(OpCodes.Ceq);
_compiler.gen.Emit(OpCodes.Ldc_I4_1);
_compiler.gen.Emit(OpCodes.Xor);

// Check if the combined result is true
_compiler.gen.Emit(OpCodes.Ldc_I4_1);
_compiler.gen.Emit(OpCodes.Ceq);
// Combine the results using OR
_compiler.gen.Emit(OpCodes.Or);
}

// Convert the result to a double
_compiler.gen.Emit(OpCodes.Conv_R8);
// Check if the combined result is true
_compiler.gen.Emit(OpCodes.Ldc_I4_1);
_compiler.gen.Emit(OpCodes.Ceq);

// Convert the result to a double
_compiler.gen.Emit(OpCodes.Conv_R8);
}
}

public override void EnterConditional(JavascriptParser.ConditionalContext context)
Expand Down

0 comments on commit ccd9836

Please sign in to comment.