Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix matching JS strings #9203

Merged
merged 9 commits into from
Feb 29, 2024
Merged
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package org.enso.interpreter.node.controlflow.caseexpr;

import com.ibm.icu.text.Normalizer;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.profiles.CountingConditionProfile;
import org.enso.interpreter.node.expression.builtin.text.util.ToJavaStringNode;
import org.enso.interpreter.runtime.data.text.Text;
import org.enso.polyglot.common_utils.Core_Text_Utils;

@NodeInfo(shortName = "StringLiteralMatch", description = "Allows matching on String literals")
public abstract class StringLiteralBranchNode extends BranchNode {
Expand Down Expand Up @@ -39,9 +42,26 @@ void doText(
}
}

@Specialization(
guards = {"targetInterop.isString(target)"},
limit = "3")
void doInteropString(
VirtualFrame frame,
Object state,
Object target,
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
@CachedLibrary("target") InteropLibrary targetInterop) {
try {
if (textProfile.profile(equalStrings(literal, targetInterop.asString(target)))) {
accept(frame, state, new Object[0]);
}
} catch (UnsupportedMessageException e) {
throw CompilerDirectives.shouldNotReachHere(e);
}
}

@CompilerDirectives.TruffleBoundary
JaroslavTulach marked this conversation as resolved.
Show resolved Hide resolved
private boolean equalStrings(String s1, String s2) {
return Normalizer.compare(s1, s2, Normalizer.FOLD_CASE_DEFAULT) == 0;
return Core_Text_Utils.equals(s1, s2);
}

@Fallback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
import com.oracle.truffle.api.dsl.ReportPolymorphism;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.library.CachedLibrary;
import com.oracle.truffle.api.nodes.Node;
import org.enso.interpreter.node.expression.foreign.CoerceNothing;
import com.oracle.truffle.api.profiles.CountingConditionProfile;
import org.enso.interpreter.runtime.EnsoContext;
import org.enso.interpreter.runtime.data.text.Text;
import org.enso.interpreter.runtime.error.WarningsLibrary;
import org.enso.interpreter.runtime.error.WithWarnings;

/**
* Converts a value returned by a polyglot call back to a value that can be further used within Enso
Expand Down Expand Up @@ -66,12 +70,23 @@ Text doString(String txt) {
return Text.create(txt);
}

@Specialization(guards = {"o != null", "iop.isNull(o)"})
@Specialization(guards = {"value != null", "iop.isNull(value)"})
Object doNull(
Object o,
Object value,
@CachedLibrary(limit = "3") InteropLibrary iop,
@Cached CoerceNothing coerceNothing) {
return coerceNothing.execute(o);
@CachedLibrary(limit = "3") WarningsLibrary warningsLibrary,
@Cached CountingConditionProfile nullWarningProfile) {
var ctx = EnsoContext.get(this);
var nothing = ctx.getBuiltins().nothing();
if (nothing != value && nullWarningProfile.profile(warningsLibrary.hasWarnings(value))) {
try {
var attachedWarnings = warningsLibrary.getWarnings(value, null, false);
return WithWarnings.wrap(ctx, nothing, attachedWarnings);
} catch (UnsupportedMessageException e) {
return nothing;
}
}
return nothing;
}

@Fallback
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.profiles.BranchProfile;
import org.enso.interpreter.node.ExpressionNode;
import org.enso.interpreter.node.expression.builtin.interop.syntax.HostValueToEnsoNode;
import org.enso.interpreter.runtime.error.DataflowError;

/** Performs a call into a given foreign call target. */
public class ForeignMethodCallNode extends ExpressionNode {
private @Children ExpressionNode[] arguments;
private @Child DirectCallNode callNode;
private @Child CoerceNothing coerceNothingNode;
private @Child HostValueToEnsoNode coerceNode;
private final BranchProfile[] errorProfiles;

ForeignMethodCallNode(ExpressionNode[] arguments, CallTarget foreignCt) {
this.arguments = arguments;
this.callNode = DirectCallNode.create(foreignCt);
this.coerceNothingNode = CoerceNothing.build();
this.coerceNode = HostValueToEnsoNode.build();

this.errorProfiles = new BranchProfile[arguments.length];
for (int i = 0; i < arguments.length; i++) {
Expand Down Expand Up @@ -48,6 +49,6 @@ public Object executeGeneric(VirtualFrame frame) {
return args[i];
}
}
return coerceNothingNode.execute(callNode.call(args));
return coerceNode.execute(callNode.call(args));
}
}
21 changes: 20 additions & 1 deletion test/Base_Tests/src/Semantic/Case_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Standard.Base.Data.Vector as Vector_Module
polyglot java import java.lang.Class
polyglot java import java.lang.Long as Java_Long
polyglot java import java.lang.Object as Java_Object
polyglot java import java.lang.StringBuilder as Java_StringBuilder
polyglot java import java.util.Random as Java_Random
polyglot java import java.util.AbstractList
polyglot java import java.util.ArrayList
Expand Down Expand Up @@ -301,6 +302,25 @@ add_specs suite_builder = suite_builder.group "Pattern Matches" group_builder->
u = v.map foo
u.should_equal ["text", "array", "array"]

group_builder.specify "should correctly pattern match strings from JS" <|
json = """
{"x": "foo"}
js_txt = json.parse_json.get "x"
r = case js_txt of
"foo" -> "OK"
other -> "not ok: "+other.to_text
r.should_equal "OK"

group_builder.specify "should correctly pattern match strings from Java" <|
sb = Java_StringBuilder.new
sb.append "b"
sb.append "ar"
java_txt = sb.toString
r = case java_txt of
"bar" -> "OK"
other -> "not ok: "+other.to_text
r.should_equal "OK"

group_builder.specify "should correctly pattern match on supertype" <|
case 1 of
_ : Any -> Nothing
Expand Down Expand Up @@ -331,4 +351,3 @@ main filter=Nothing =
suite = Test.build suite_builder->
add_specs suite_builder
suite.run_with_filter filter

Loading