Skip to content

Commit

Permalink
Fix matching JS strings (#9203)
Browse files Browse the repository at this point in the history
- Fixes #9202
  • Loading branch information
radeusgd authored Feb 29, 2024
1 parent 874e9ef commit 386132c
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 67 deletions.
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,
@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
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

0 comments on commit 386132c

Please sign in to comment.