symja: quadratic inequation and modulus - symja

public static void solveInequalitiesEquationSymja(){
EvalUtilities util = new EvalUtilities(false, true);
IExpr result = util.evaluate("x^2<x");
IExpr result2 = Solve(result,x);
System.out.println("################## Inequalities equation ##################");
System.out.println(result);
System.out.println(result2);
}
result is x^2 < x
result2 is Solve(x^2< x,x)
public static void solveModuleEquationSymja() {
ExprEvaluator util = new ExprEvaluator();
Parser parser = new Parser();
ASTNode exprNode = parser.parse("Sqrt[x^2] == 7");
AST2Expr ast2Expr = new AST2Expr();
IExpr ast = ast2Expr.convert(exprNode);
IAST function = Solve(ast, x);
IExpr result = util.evaluate(function);
System.out.println("################## Module equation ##################");
System.out.println(result);
}
{{x->-7},{x->7}}
Is there any solution not to use sqrt(x^2),but directly modulus(x) ?
Thank you in advance

At the moment inequalities aren't supported in Solve().
Did you mean something like "x^2==49"?
public static void solveModuleEquationSymja() {
ExprEvaluator util = new ExprEvaluator();
IExpr result = util.evaluate("Solve(x^2 == 49,x)");
System.out.println("################## Module equation ##################");
System.out.println(result);
}

Related

Syntax Highlighting for go in vb.net

Ok so I have been making a simple code editor in vb.net for go.. (for personal uses)
I tried this code -
Dim tokens As String = "(break|default|func|interface|select|case|defer|go|map|struct|chan|else|goto|package|switch|const|fallthrough|if|range|type|continue|for|import|return|var)"
Dim rex As New Regex(tokens)
Dim mc As MatchCollection = rex.Matches(TextBox2.Text)
Dim StartCursorPosition As Integer = TextBox2.SelectionStart
For Each m As Match In mc
Dim startIndex As Integer = m.Index
Dim StopIndex As Integer = m.Length
TextBox2.[Select](startIndex, StopIndex)
TextBox2.SelectionColor = Color.FromArgb(0, 122, 204)
TextBox2.SelectionStart = StartCursorPosition
TextBox2.SelectionColor = Color.RebeccaPurple
Next
but I couldn't add something like print statements say I want a fmt.Println("Hello World"), that is not possible, anyone help me?
I want a simple result that will do proper syntax without glitching text colors like this current code does.
Here's a code showing how to update highlighting with strings and numbers.
You would need to tweak it further to support syntax like comments, etc.
private Regex BuildExpression()
{
string[] exprs = {
"(break|default|func|interface|select|case|defer|go|map|struct|chan|else|goto|package|switch|const|fallthrough|if|range|type|continue|for|import|return|var)",
#"([0-9]+\.[0-9]*(e|E)(\+|\-)?[0-9]+)|([0-9]+\.[0-9]*)|([0-9]+)",
"(\"\")|\"((((\\\\\")|(\"\")|[^\"])*\")|(((\\\\\")|(\"\")|[^\"])*))"
};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < exprs.Length; i++)
{
string expr = exprs[i];
if ((expr != null) && (expr != string.Empty))
sb.Append(string.Format("(?<{0}>{1})", "_" + i.ToString(), expr) + "|");
}
if (sb.Length > 0)
sb.Remove(sb.Length - 1, 1);
RegexOptions options = RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase;
return new Regex(sb.ToString(), options);
}
private void HighlightSyntax()
{
var colors = new Dictionary<int, Color>();
var expression = BuildExpression();
Color[] clrs = { Color.Teal, Color.Red, Color.Blue };
int[] intarray = expression.GetGroupNumbers();
foreach (int i in intarray)
{
var name = expression.GroupNameFromNumber(i);
if ((name != null) && (name.Length > 0) && (name[0] == '_'))
{
var idx = int.Parse(name.Substring(1));
if (idx < clrs.Length)
colors.Add(i, clrs[idx]);
}
}
foreach (Match match in expression.Matches(richTextBox1.Text))
{
int index = match.Index;
int length = match.Length;
richTextBox1.Select(index, length);
for (int i = 0; i < match.Groups.Count; i++)
{
if (match.Groups[i].Success)
{
if (colors.ContainsKey(i))
{
richTextBox1.SelectionColor = colors[i];
break;
}
}
}
}
}
What we found during development of our Code Editor libraries, is that the regular expression-based parsers are hard to adapt to fully support advanced syntax like contextual keywords (LINQ) or interpolated strings.
You might find a bit more information here:
https://www.alternetsoft.com/blog/code-parsing-explained
The most accurate syntax highlighting for VB.NET can be implemented using Microsoft.CodeAnalysis API, it's the same API used internally by Visual Studio text editor.
Below is sample code showing how to get classified spans for VB.NET code (every span contains start/end position within the text and classification type, i.e. keyword, string, etc.). These spans then can be used to highlight text inside a textbox.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Text;
public class VBClassifier
{
private Workspace workspace;
private static string FileContent = #"
Public Sub Run()
Dim test as TestClass = new TestClass()
End Sub";
public void Classify()
{
var project = InitProject();
var doc = AddDocument(project, "file1.vb", FileContent);
var spans = Classify(doc);
}
protected IEnumerable<ClassifiedSpan> Classify(Document document)
{
var text = document.GetTextAsync().Result;
var span = new TextSpan(0, text.Length);
return Classifier.GetClassifiedSpansAsync(document, span).Result;
}
protected Document AddDocument(Project project, string fileName, string code)
{
var documentId = DocumentId.CreateNewId(project.Id, fileName);
ApplySolutionChanges(s => s.AddDocument(documentId, fileName, code, filePath: fileName));
return workspace.CurrentSolution.GetDocument(documentId);
}
protected virtual void ApplySolutionChanges(Func<Solution, Solution> action)
{
var solution = workspace.CurrentSolution;
solution = action(solution);
workspace.TryApplyChanges(solution);
}
protected MefHostServices GetRoslynCompositionHost()
{
IEnumerable<Assembly> assemblies = MefHostServices.DefaultAssemblies;
var compositionHost = MefHostServices.Create(assemblies);
return compositionHost;
}
protected Project CreateDefaultProject()
{
var solution = workspace.CurrentSolution;
var projectId = ProjectId.CreateNewId();
var projectName = "VBTest";
ProjectInfo projectInfo = ProjectInfo.Create(
projectId,
VersionStamp.Default,
projectName,
projectName,
LanguageNames.VisualBasic,
filePath: null);
ApplySolutionChanges(s => s.AddProject(projectInfo));
return workspace.CurrentSolution.Projects.FirstOrDefault();
}
protected Project InitProject()
{
var host = GetRoslynCompositionHost();
workspace = new AdhocWorkspace(host);
return CreateDefaultProject();
}
}
Update:
Here's a Visual Studio project demonstrating both approaches:
https://drive.google.com/file/d/1LLuzy7yDFAE-v40I7EswECYQSthxheEf/view?usp=sharing

Problems with Scanner input

I am new to JAVA. I don't understand why JAVA give me two souts.
(Input row & column (throw 1 space): Input row & column (throw 1 space): )
In the first pass, it does not wait for my input and think str = "". And in the second pass its waiting for my input.
Ssory, I forgot to tell that beforе this block of code - my Scanner was opened. I asked program:
while (true) {
System.out.print("Enter game size (3 - 20): ");
if (SCAN.hasNextInt()) {
return SCAN.nextInt();
}
System.out.println(SCAN.next() + " - not a number!");
I think I should clear scanners buffer ( /n ). But I dont know how.
private static void humanTurn() {
System.out.println("HUMAN TURN");
String str;
String regex = "\\d{1,2}\\s\\d{1,2}";
Pattern myPattern = Pattern.compile(regex); // Pattern for checking
boolean checkPattern;
int x, y;
do {
do {
System.out.print("Input row & column (throw 1 space): ");
str = SCAN.nextLine();
Matcher myMatcher = myPattern.matcher(str);
checkPattern = myMatcher.matches();
} while (!checkPattern);
String[] strArr = str.split(" ");
x = Integer.parseInt(strArr[0]) - 1;
y = Integer.parseInt(strArr[1]) - 1;
} while (!isValidCell(x, y));
I have tried to guess your code. This is what I come up with. Still works fine. Let me know if anything else.
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
private static Scanner sc = new Scanner(System.in);
private static int size = 0;
public static void main(String[] args) {
size = getBoardSize();
humanTurn();
}
private static int getBoardSize() {
while (true) {
System.out.print("Enter game size (3 - 20): ");
if (sc.hasNextInt()) {
return sc.nextInt();
}
System.out.println(sc.next() + " - not a number!");
}
}
private static void humanTurn() {
System.out.println("HUMAN TURN");
String str;
String regex = "\\d{1,2}\\s\\d{1,2}";
Pattern myPattern = Pattern.compile(regex); // Pattern for checking
boolean checkPattern;
int x, y;
do {
do {
System.out.print("Input row & column (throw 1 space): ");
str = sc.nextLine();
Matcher myMatcher = myPattern.matcher(str);
checkPattern = myMatcher.matches();
} while (!checkPattern);
String[] strArr = str.split(" ");
x = Integer.parseInt(strArr[0]) - 1;
y = Integer.parseInt(strArr[1]) - 1;
} while (!isValidCell(x, y));
}
private static boolean isValidCell(int x, int y) {
return x < size && y < size && x >= 0 && y >= 0;
}
}

I can't figure out how to call a variable from another method

I am am trying to call a variable in another method to my array.
var Com = the difficulty for the game. But the method below I'm trying to call the var Com, for: var c = Com.GetChoice();
Not sure why I can not figure out how to call it.
public object SetDiff()
{
Console.WriteLine("Enter difficulty #: (1 = Easy, 2 = Normal, 3 = Impossible)");
var diff = Console.ReadLine();
int mode;
int.TryParse(diff, out mode);
if (mode == 1)
{
Console.Clear();
var Com = new Easy();
return Com;
}
if (mode == 2)
{
Console.Clear();
var Com = new Medium();
return Com;
}
if (mode == 3)
{
Console.Clear();
var Com = new Hard();
return Com;
}
else
{
Console.WriteLine("That is not a valid input.");
return SetDiff();
}
} // Apparently you can't set variables in a switch.
public int[] FaceOff(int num)
{
int PlayerWin = 0;
int ComWin = 0;
int Tie = num + 1;
// TODO : Get rid of TIES!
for (int i = 0; i < num; i++)
{
var p = p1.GetChoice();
var c = Com.GetChoice();
You have many different options:
Pass as parameter
public int[] FaceOff(int num, int Com){...}
make a "global" variable
private int Com;
I would also recommend you to learn OOP (Object Orientated Programming) basics.

Create a Gson TypeAdapter for a Guava Range

I am trying to serialize Guava Range objects to JSON using Gson, however the default serialization fails, and I'm unsure how to correctly implement a TypeAdapter for this generic type.
Gson gson = new Gson();
Range<Integer> range = Range.closed(10, 20);
String json = gson.toJson(range);
System.out.println(json);
Range<Integer> range2 = gson.fromJson(json,
new TypeToken<Range<Integer>>(){}.getType());
System.out.println(range2);
assertEquals(range2, range);
This fails like so:
{"lowerBound":{"endpoint":10},"upperBound":{"endpoint":20}}
PASSED: typeTokenInterface
FAILED: range
java.lang.RuntimeException: Unable to invoke no-args constructor for
com.google.common.collect.Cut<java.lang.Integer>. Register an
InstanceCreator with Gson for this type may fix this problem.
at com.google.gson.internal.ConstructorConstructor$12.construct(
ConstructorConstructor.java:210)
...
Note that the default serialization actually loses information - it fails to report whether the endpoints are open or closed. I would prefer to see it serialized similar to its toString(), e.g. [10‥20] however simply calling toString() won't work with generic Range instances, as the elements of the range may not be primitives (Joda-Time LocalDate instances, for example). For the same reason, implementing a custom TypeAdapter seems difficult, as we don't know how to deserialize the endpoints.
I've implemented most of a TypeAdaptorFactory based on the template provided for Multimap which ought to work, but now I'm stuck on the generics. Here's what I have so far:
public class RangeTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
Type type = typeToken.getType();
if (typeToken.getRawType() != Range.class
|| !(type instanceof ParameterizedType)) {
return null;
}
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
TypeAdapter<?> elementAdapter = (TypeAdapter<?>)gson.getAdapter(TypeToken.get(elementType));
// Bound mismatch: The generic method newRangeAdapter(TypeAdapter<E>) of type
// GsonUtils.RangeTypeAdapterFactory is not applicable for the arguments
// (TypeAdapter<capture#4-of ?>). The inferred type capture#4-of ? is not a valid
// substitute for the bounded parameter <E extends Comparable<?>>
return (TypeAdapter<T>) newRangeAdapter(elementAdapter);
}
private <E extends Comparable<?>> TypeAdapter<Range<E>> newRangeAdapter(final TypeAdapter<E> elementAdapter) {
return new TypeAdapter<Range<E>>() {
#Override
public void write(JsonWriter out, Range<E> value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
String repr = (value.lowerBoundType() == BoundType.CLOSED ? "[" : "(") +
(value.hasLowerBound() ? elementAdapter.toJson(value.lowerEndpoint()) : "-\u221e") +
'\u2025' +
(value.hasLowerBound() ? elementAdapter.toJson(value.upperEndpoint()) : "+\u221e") +
(value.upperBoundType() == BoundType.CLOSED ? "]" : ")");
out.value(repr);
}
public Range<E> read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
String[] endpoints = in.nextString().split("\u2025");
E lower = elementAdapter.fromJson(endpoints[0].substring(1));
E upper = elementAdapter.fromJson(endpoints[1].substring(0,endpoints[1].length()-1));
return Range.range(lower, endpoints[0].charAt(0) == '[' ? BoundType.CLOSED : BoundType.OPEN,
upper, endpoints[1].charAt(endpoints[1].length()-1) == '[' ? BoundType.CLOSED : BoundType.OPEN);
}
};
}
}
However the return (TypeAdapter<T>) newRangeAdapter(elementAdapter); line has a compilation error and I'm now at a loss.
What's the best way to resolve this error? Is there a better way to serialize Range objects that I'm missing? What about if I want to serialize RangeSets?
Rather frustrating that the Google utility library and Google serialization library seem to require so much glue to work together :(
This feels somewhat like reinventing the wheel, but it was a lot quicker to put together and test than the time spent trying to get Gson to behave, so at least presently I'll be using the following Converters to serialize Range and RangeSet*, rather than Gson.
/**
* Converter between Range instances and Strings, essentially a custom serializer.
* Ideally we'd let Gson or Guava do this for us, but presently this is cleaner.
*/
public static <T extends Comparable<? super T>> Converter<Range<T>, String> rangeConverter(final Converter<T, String> elementConverter) {
final String NEG_INFINITY = "-\u221e";
final String POS_INFINITY = "+\u221e";
final String DOTDOT = "\u2025";
return new Converter<Range<T>, String>() {
#Override
protected String doForward(Range<T> range) {
return (range.hasLowerBound() && range.lowerBoundType() == BoundType.CLOSED ? "[" : "(") +
(range.hasLowerBound() ? elementConverter.convert(range.lowerEndpoint()) : NEG_INFINITY) +
DOTDOT +
(range.hasUpperBound() ? elementConverter.convert(range.upperEndpoint()) : POS_INFINITY) +
(range.hasUpperBound() && range.upperBoundType() == BoundType.CLOSED ? "]" : ")");
}
#Override
protected Range<T> doBackward(String range) {
String[] endpoints = range.split(DOTDOT);
Range<T> ret = Range.all();
if(!endpoints[0].substring(1).equals(NEG_INFINITY)) {
T lower = elementConverter.reverse().convert(endpoints[0].substring(1));
ret = ret.intersection(Range.downTo(lower, endpoints[0].charAt(0) == '[' ? BoundType.CLOSED : BoundType.OPEN));
}
if(!endpoints[1].substring(0,endpoints[1].length()-1).equals(POS_INFINITY)) {
T upper = elementConverter.reverse().convert(endpoints[1].substring(0,endpoints[1].length()-1));
ret = ret.intersection(Range.upTo(upper, endpoints[1].charAt(endpoints[1].length()-1) == ']' ? BoundType.CLOSED : BoundType.OPEN));
}
return ret;
}
};
}
/**
* Converter between RangeSet instances and Strings, essentially a custom serializer.
* Ideally we'd let Gson or Guava do this for us, but presently this is cleaner.
*/
public static <T extends Comparable<? super T>> Converter<RangeSet<T>, String> rangeSetConverter(final Converter<T, String> elementConverter) {
return new Converter<RangeSet<T>, String>() {
private final Converter<Range<T>, String> rangeConverter = rangeConverter(elementConverter);
#Override
protected String doForward(RangeSet<T> rs) {
ArrayList<String> ls = new ArrayList<>();
for(Range<T> range : rs.asRanges()) {
ls.add(rangeConverter.convert(range));
}
return Joiner.on(", ").join(ls);
}
#Override
protected RangeSet<T> doBackward(String rs) {
Iterable<String> parts = Splitter.on(",").trimResults().split(rs);
ImmutableRangeSet.Builder<T> build = ImmutableRangeSet.builder();
for(String range : parts) {
build.add(rangeConverter.reverse().convert(range));
}
return build.build();
}
};
}
*For inter-process communication, Java serialization would likely work just fine, as both classes implement Serializable. However I'm serializing to disk for more permanent storage, meaning I need a format I can trust won't change over time. Guava's serialization doesn't provide that guarantee.
Here is a Gson JsonSerializer and JsonDeserializer that generically supports a Range: https://github.com/jamespedwards42/Fava/wiki/Range-Marshaller
#Override
public JsonElement serialize(final Range src, final Type typeOfSrc, final JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
if ( src.hasLowerBound() ) {
jsonObject.add( "lowerBoundType", context.serialize( src.lowerBoundType() ) );
jsonObject.add( "lowerBound", context.serialize( src.lowerEndpoint() ) );
} else
jsonObject.add( "lowerBoundType", context.serialize( BoundType.OPEN ) );
if ( src.hasUpperBound() ) {
jsonObject.add( "upperBoundType", context.serialize( src.upperBoundType() ) );
jsonObject.add( "upperBound", context.serialize( src.upperEndpoint() ) );
} else
jsonObject.add( "upperBoundType", context.serialize( BoundType.OPEN ) );
return jsonObject;
}
#Override
public Range<? extends Comparable<?>> deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
if ( !( typeOfT instanceof ParameterizedType ) )
throw new IllegalStateException( "typeOfT must be a parameterized Range." );
final JsonObject jsonObject = json.getAsJsonObject();
final JsonElement lowerBoundTypeJsonElement = jsonObject.get( "lowerBoundType" );
final JsonElement upperBoundTypeJsonElement = jsonObject.get( "upperBoundType" );
if ( lowerBoundTypeJsonElement == null || upperBoundTypeJsonElement == null )
throw new IllegalStateException( "Range " + json
+ "was not serialized with this serializer! The default serialization does not store the boundary types, therfore we can not deserialize." );
final Type type = ( ( ParameterizedType ) typeOfT ).getActualTypeArguments()[0];
final BoundType lowerBoundType = context.deserialize( lowerBoundTypeJsonElement, BoundType.class );
final JsonElement lowerBoundJsonElement = jsonObject.get( "lowerBound" );
final Comparable<?> lowerBound = lowerBoundJsonElement == null ? null : context.deserialize( lowerBoundJsonElement, type );
final BoundType upperBoundType = context.deserialize( upperBoundTypeJsonElement, BoundType.class );
final JsonElement upperBoundJsonElement = jsonObject.get( "upperBound" );
final Comparable<?> upperBound = upperBoundJsonElement == null ? null : context.deserialize( upperBoundJsonElement, type );
if ( lowerBound == null && upperBound != null )
return Range.upTo( upperBound, upperBoundType );
else if ( lowerBound != null && upperBound == null )
return Range.downTo( lowerBound, lowerBoundType );
else if ( lowerBound == null && upperBound == null )
return Range.all();
return Range.range( lowerBound, lowerBoundType, upperBound, upperBoundType );
}
Here is a straight forward solution. Works very well
import com.google.common.collect.BoundType;
import com.google.common.collect.Range;
import com.google.gson.*;
import java.lang.reflect.Type;
public class GoogleRangeAdapter implements JsonSerializer, JsonDeserializer {
public static String TK_hasLowerBound = "hasLowerBound";
public static String TK_hasUpperBound = "hasUpperBound";
public static String TK_lowerBoundType = "lowerBoundType";
public static String TK_upperBoundType = "upperBoundType";
public static String TK_lowerBound = "lowerBound";
public static String TK_upperBound = "upperBound";
#Override
public Object deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jsonObject = (JsonObject)json;
boolean hasLowerBound = jsonObject.get(TK_hasLowerBound).getAsBoolean();
boolean hasUpperBound = jsonObject.get(TK_hasUpperBound).getAsBoolean();
if (!hasLowerBound && !hasUpperBound) {
return Range.all();
}
else if (!hasLowerBound && hasUpperBound){
double upperBound = jsonObject.get(TK_upperBound).getAsDouble();
BoundType upperBoundType = BoundType.valueOf(jsonObject.get(TK_upperBoundType).getAsString());
if (upperBoundType == BoundType.OPEN)
return Range.lessThan(upperBound);
else
return Range.atMost(upperBound);
}
else if (hasLowerBound && !hasUpperBound){
double lowerBound = jsonObject.get(TK_lowerBound).getAsDouble();
BoundType lowerBoundType = BoundType.valueOf(jsonObject.get(TK_lowerBoundType).getAsString());
if (lowerBoundType == BoundType.OPEN)
return Range.greaterThan(lowerBound);
else
return Range.atLeast(lowerBound);
}
else {
double lowerBound = jsonObject.get(TK_lowerBound).getAsDouble();
double upperBound = jsonObject.get(TK_upperBound).getAsDouble();
BoundType upperBoundType = BoundType.valueOf(jsonObject.get(TK_upperBoundType).getAsString());
BoundType lowerBoundType = BoundType.valueOf(jsonObject.get(TK_lowerBoundType).getAsString());
if (lowerBoundType == BoundType.OPEN && upperBoundType == BoundType.OPEN)
return Range.open(lowerBound, upperBound);
else if (lowerBoundType == BoundType.OPEN && upperBoundType == BoundType.CLOSED)
return Range.openClosed(lowerBound, upperBound);
else if (lowerBoundType == BoundType.CLOSED && upperBoundType == BoundType.OPEN)
return Range.closedOpen(lowerBound, upperBound);
else
return Range.closed(lowerBound, upperBound);
}
}
#Override
public JsonElement serialize(Object src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
Range<Double> range = (Range<Double>)src;
boolean hasLowerBound = range.hasLowerBound();
boolean hasUpperBound = range.hasUpperBound();
jsonObject.addProperty(TK_hasLowerBound, hasLowerBound);
jsonObject.addProperty(TK_hasUpperBound, hasUpperBound);
if (hasLowerBound) {
jsonObject.addProperty(TK_lowerBound, range.lowerEndpoint());
jsonObject.addProperty(TK_lowerBoundType, range.lowerBoundType().name());
}
if (hasUpperBound) {
jsonObject.addProperty(TK_upperBound, range.upperEndpoint());
jsonObject.addProperty(TK_upperBoundType, range.upperBoundType().name());
}
return jsonObject;
}
}

Why expressions doesn't support IdentityEquality?

There is no IdentityEqual item in ExpressionType enumeration. How can I construct expreesion tree with VB.NET Is operator?
Have you tried using Expression.Equal, specifying the implementation to use?
In C#:
MethodInfo referenceEquality = typeof(object).GetMethod("ReferenceEquals",
BindingFlags.Static | BindingFlags.Public);
Expression equality = Expression.Equal(lhs, rhs, true, referenceEquality);
Here's a complete example (again, C# - but you should be able to translate it easily):
using System;
using System.Reflection;
using System.Linq.Expressions;
class Test
{
static void Main()
{
var lhs = Expression.Parameter(typeof(string), "lhs");
var rhs = Expression.Parameter(typeof(string), "rhs");
MethodInfo referenceEquality = typeof(object).GetMethod
("ReferenceEquals", BindingFlags.Static | BindingFlags.Public);
var equality = Expression.Equal(lhs, rhs, true, referenceEquality);
var lambda = Expression.Lambda<Func<string, string, bool>>
(equality, new[] { lhs, rhs });
var compiled = lambda.Compile();
string x = "hello";
string y = x;
string z = new string(x.ToCharArray());
Console.WriteLine(compiled(x, y)); // True
Console.WriteLine(compiled(x, z)); // False
}
}