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

Intersection types & type checks #11600

Open
wants to merge 25 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c0c2fc5
Splitting types in EnsoMultiValue to methodDispatchTypes and the rest
JaroslavTulach Nov 20, 2024
c780c37
Merging with latest chances in develop
JaroslavTulach Nov 22, 2024
515e134
Don't expose EnsoMultiValue methods directly
JaroslavTulach Nov 25, 2024
d0460a4
TypeOf UnresolvedConstructor and UnresolvedSymbol test
JaroslavTulach Nov 25, 2024
a101fe6
Merge branch 'wip/jtulach/UseTypeOfNode11482' into wip/jtulach/Comple…
JaroslavTulach Nov 25, 2024
4e08d8f
UnsupportedMessageException.create accepts only AbstractTruffleException
JaroslavTulach Nov 25, 2024
acebbc1
Unwrap EnsoMultiValue before composing new EnsoMultiValue.create
JaroslavTulach Nov 25, 2024
af85b11
Avoid double wrapping test
JaroslavTulach Nov 25, 2024
ba5953f
Only consider booleans up to methodDispatchTypes
JaroslavTulach Nov 25, 2024
c2d1911
EqualsMultiValueTest
JaroslavTulach Nov 25, 2024
11f8ebc
Two unit tests showing a difference between success and failure
JaroslavTulach Nov 25, 2024
0278257
Special EqualsNode for EnsoMultiValue
JaroslavTulach Nov 25, 2024
720f644
Primitive interop types are mutually exclusive - we need to use one f…
JaroslavTulach Nov 25, 2024
ebaf492
Merge remote-tracking branch 'origin/develop' into wip/jtulach/Comple…
JaroslavTulach Nov 25, 2024
b5fc062
Interop value cannot be both isString and isNumber
JaroslavTulach Nov 25, 2024
02ec775
Handle EnsoMultiValue in a special way
JaroslavTulach Nov 25, 2024
57da6eb
Base EnsoMultiValue.equals on findAllTypesOrNull
JaroslavTulach Nov 26, 2024
3d048be
Documenting the example of Text and extra Integer equality check
JaroslavTulach Nov 26, 2024
be5dbe8
Don't consider extra multi value types in equals
JaroslavTulach Nov 26, 2024
0a81038
Note in the changelog
JaroslavTulach Nov 26, 2024
9fc4bb4
No need for StructsLibrary hack anymore
JaroslavTulach Nov 26, 2024
3a09a8d
No changes in GetFieldNode needed
JaroslavTulach Nov 26, 2024
20973d0
Intersection type and additional conversions tests
JaroslavTulach Nov 26, 2024
ce4c738
Verify dispatch of methods behaves as expected
JaroslavTulach Nov 27, 2024
a6ff51b
Only consider methodDispatchTypes for from conversions
JaroslavTulach Nov 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,10 @@
#### Enso Language & Runtime

- [Arguments in constructor definitions may now be on their own lines][11374]
- [Intersection types & type checks][11600]

[11374]: https://github.com/enso-org/enso/pull/11374
[11600]: https://github.com/enso-org/enso/pull/11600

# Enso 2024.4

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ private static void registerValue(
var rawValue = ContextUtils.unwrapValue(ctx(), polyValue);
var rawType = ContextUtils.unwrapValue(ctx(), t);
if (rawType instanceof Type type) {
var singleMultiValue = EnsoMultiValue.create(new Type[] {type}, new Object[] {rawValue});
var singleMultiValue = EnsoMultiValue.create(new Type[] {type}, 1, new Object[] {rawValue});
var n = t.getMetaSimpleName();
data.add(new Object[] {singleMultiValue, n, 0});
var rawInt = (Type) ContextUtils.unwrapValue(ctx(), g.typeInteger());
var secondMultiValue =
EnsoMultiValue.create(new Type[] {rawInt, type}, new Object[] {5L, rawValue});
EnsoMultiValue.create(new Type[] {rawInt, type}, 2, new Object[] {5L, rawValue});
data.add(new Object[] {secondMultiValue, n, 1});
var firstMultiValue =
EnsoMultiValue.create(new Type[] {type, rawInt}, new Object[] {rawValue, 6L});
EnsoMultiValue.create(new Type[] {type, rawInt}, 2, new Object[] {rawValue, 6L});
data.add(new Object[] {firstMultiValue, n, 0});
} else {
if (!t.isHostObject()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.enso.interpreter.node.typecheck;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import com.oracle.truffle.api.CallTarget;
import org.enso.interpreter.runtime.data.EnsoMultiValue;
import org.enso.interpreter.runtime.data.Type;
import org.enso.test.utils.ContextUtils;
import org.enso.test.utils.TestRootNode;
import org.graalvm.polyglot.Context;
import org.junit.Test;

public class TypeCheckValueTest {
private static Context ctx;

private static Context ctx() {
if (ctx == null) {
ctx = ContextUtils.defaultContextBuilder().build();
}
return ctx;
}

@Test
public void avoidDoubleWrappingOfEnsoMultiValue() {
var convert = allOfIntegerAndText();

ContextUtils.executeInContext(
ctx(),
() -> {
var builtins = ContextUtils.leakContext(ctx).getBuiltins();
var m1 =
EnsoMultiValue.create(
new Type[] {builtins.text(), builtins.number().getInteger()},
2,
new Object[] {"Hi", 42});
assertEquals("Text & Integer", m1.toDisplayString(true));

var res = convert.call(m1);
assertTrue("Got multivalue again", res instanceof EnsoMultiValue);
var emv = (EnsoMultiValue) res;

assertEquals("Integer & Text", emv.toDisplayString(true));
return null;
});
}

private static CallTarget allOfIntegerAndText() {
var call = new CallTarget[1];
ContextUtils.executeInContext(
ctx(),
() -> {
var builtins = ContextUtils.leakContext(ctx).getBuiltins();
var intNode = TypeCheckValueNode.single("int", builtins.number().getInteger());
var textNode = TypeCheckValueNode.single("text", builtins.text());
var bothNode = TypeCheckValueNode.allOf("int&text", intNode, textNode);
var root =
new TestRootNode(
(frame) -> {
var arg = frame.getArguments()[0];
var res = bothNode.handleCheckOrConversion(frame, arg, null);
return res;
});
root.insertChildren(bothNode);
call[0] = root.getCallTarget();
return null;
});
return call[0];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package org.enso.interpreter.test;

import com.oracle.truffle.api.interop.InteropLibrary;
import java.util.ArrayList;
import org.enso.interpreter.runtime.data.EnsoMultiValue;
import org.enso.interpreter.runtime.data.Type;
import org.enso.test.utils.ContextUtils;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import org.junit.AfterClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class EnsoMultiValueInteropTest {

@Parameterized.Parameter(0)
public Object value;

private static Context ctx;

private static Context ctx() {
if (ctx == null) {
ctx = ContextUtils.defaultContextBuilder().build();
}
return ctx;
}

@Parameterized.Parameters
public static Object[][] allEnsoMultiValuePairs() throws Exception {
var g = ValuesGenerator.create(ctx());
var typeOf =
ContextUtils.evalModule(
ctx(),
"""
from Standard.Base import all

typ obj = Meta.type_of obj
main = typ
""");
var data = new ArrayList<Object[]>();
for (var v1 : g.allValues()) {
for (var v2 : g.allValues()) {
registerValue(g, typeOf, v1, v2, data);
}
}
return data.toArray(new Object[0][]);
}

private static void registerValue(
ValuesGenerator g, Value typeOf, Value v1, Value v2, ArrayList<Object[]> data) {
var t1 = typeOf.execute(v1);
var t2 = typeOf.execute(v2);
if (!t1.isNull() && !t2.isNull()) {
var rawT1 = ContextUtils.unwrapValue(ctx(), t1);
var rawT2 = ContextUtils.unwrapValue(ctx(), t2);
if (rawT1 instanceof Type typ1 && rawT2 instanceof Type typ2) {
var r1 = ContextUtils.unwrapValue(ctx, v1);
var r2 = ContextUtils.unwrapValue(ctx, v2);
var both = EnsoMultiValue.create(new Type[] {typ1, typ2}, 2, new Object[] {r1, r2});
data.add(new Object[] {both});
}
}
}

@AfterClass
public static void disposeCtx() throws Exception {
if (ctx != null) {
ctx.close();
ctx = null;
}
}

@Test
public void isStringDoesntFail() {
ContextUtils.executeInContext(
ctx,
() -> {
return InteropLibrary.getUncached().isString(value);
});
}
}
Loading
Loading