Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
Expand All @@ -20,9 +20,11 @@
import com.oracle.truffle.api.interop.UnknownIdentifierException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.interop.UnsupportedTypeException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.enso.test.utils.ContextUtils;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;
import org.junit.ClassRule;
import org.junit.Test;
Expand All @@ -34,6 +36,58 @@
public class AtomInteropTest {
@ClassRule public static final ContextUtils ctxRule = ContextUtils.createDefault();

@Test
public void checkAtomMembers() throws Exception {
final URI uri = new URI("memory://how_long.enso");
final Source src =
Source.newBuilder(
"enso",
"""
from Standard.Base.Data.Boolean import True, False

type IntList
End
Head h t

is_empty self = case self of
IntList.End -> True
_ -> False

tail self = case self of
IntList.Head _ t -> t
_ -> IntList.End

head self = case self of
IntList.Head h _ -> h
_ -> -1

list1 = IntList.Head 7 <| IntList.Head 3 <| IntList.End

""",
"compare.enso")
.uri(uri)
.buildLiteral();

var module = ctxRule.eval(src);

var headAtom = module.invokeMember("eval_expression", "list1");
var seven = module.invokeMember("eval_expression", "list1.head");
var three = module.invokeMember("eval_expression", "list1.tail.head");
var endAtom = module.invokeMember("eval_expression", "list1.tail.tail");

assertTrue("seven is number-like: " + seven, seven.fitsInInt());
assertTrue("three is number-like: " + three, three.fitsInInt());
assertFalse("list1 is not number-like: " + headAtom, headAtom.fitsInInt());
assertFalse("list2 is not number-like: " + endAtom, endAtom.fitsInInt());

assertEquals("seven check", 7, seven.asInt());
assertEquals("three check", 3, three.asInt());

assertMembers("Keys in list1", headAtom, "head", "tail", "is_empty");
assertMembers("Keys in list2", endAtom, "head", "tail", "is_empty");
assertMembers("Keys in list1", headAtom, "h", "t");
}

@Test
public void atomMemberNames_AreNotQualified() {
var myTypeAtom =
Expand Down Expand Up @@ -88,25 +142,6 @@ public void atomIsNotMetaObject() {
assertThat(myTypeAtom.getMetaObject().getMetaSimpleName(), is("My_Type"));
}

@Test
public void typeHasAnyAsSuperType() {
var myTypeAtom =
ctxRule.evalModule(
"""
type My_Type
Cons

main = My_Type.Cons
""");
var myType = myTypeAtom.getMetaObject();
assertThat(myType.hasMetaParents(), is(true));
var metaParents = myType.getMetaParents();
assertThat(metaParents.hasArrayElements(), is(true));
assertThat("Has just one meta parent - Any", metaParents.getArraySize(), is(1L));
var anyType = metaParents.getArrayElement(0);
assertThat(anyType.getMetaSimpleName(), is("Any"));
}

@Test
public void atomMembersAreConstructorFields_ManyConstructors() {
var myTypeAtom =
Expand All @@ -126,7 +161,7 @@ public void atomMembersAreConstructorFields_ManyConstructors() {
}

@Test
public void methodIsAtomMember() {
public void instanceMethod_IsAtomMember_Polyglot() {
var myTypeAtom =
ctxRule.evalModule(
"""
Expand All @@ -141,7 +176,26 @@ public void methodIsAtomMember() {
}

@Test
public void methodIsAtomMember_InteropLibrary() {
public void instanceMethod_IsInternalAtomMember() {
var myTypeAtom =
ctxRule.evalModule(
"""
type My_Type
Cons a b
method self = 42

main = My_Type.Cons "a" "b"
""");
var interop = InteropLibrary.getUncached();
var atom = ctxRule.unwrapValue(myTypeAtom);
assertThat(
"Method is an internal member of the atom",
interop.isMemberInternal(atom, "method"),
is(true));
}

@Test
public void instanceMethod_IsAtomMember() {
var myTypeAtom =
ctxRule.evalModule(
"""
Expand All @@ -153,49 +207,43 @@ public void methodIsAtomMember_InteropLibrary() {
""");
var atom = ctxRule.unwrapValue(myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Atom has members", interop.hasMembers(atom), is(true));
assertThat("Method is readable", interop.isMemberReadable(atom, "method"), is(true));
assertThat("Method is invocable", interop.isMemberInvocable(atom, "method"), is(true));
assertThat("Field is readable", interop.isMemberReadable(atom, "a"), is(true));
assertThat(interop.isMemberExisting(atom, "method"), is(true));
}

@Test
public void fieldsFromPrivateConstructorAreInternalMembers() {
public void instanceMethod_IsInvocableMember() {
var myTypeAtom =
ctxRule.evalModule(
"""
type My_Type
private Cons a
Cons a b
method self = 42

main = My_Type.Cons "a"
main = My_Type.Cons "a" "b"
""");
var atom = ctxRule.unwrapValue(myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("field a is internal", interop.isMemberInternal(atom, "a"), is(true));
assertThat(interop.isMemberInvocable(atom, "method"), is(true));
}

@Test
public void methodsAreVisibleEvenWithPrivateConstructors() throws Exception {
public void fieldsFromPrivateConstructorAreInternalMembers() {
var myTypeAtom =
ctxRule.evalModule(
"""
type My_Type
private Cons a

read self = self.a

main = My_Type.Cons "a"
""");
var atom = ctxRule.unwrapValue(myTypeAtom);
var interop = InteropLibrary.getUncached();
var read = interop.readMember(atom, "read");
assertNotNull("Found read member", read);
assertEquals("a", read.toString());
assertThat("field a is internal", interop.isMemberInternal(atom, "a"), is(true));
}

@Test
public void methodsAreVisibleOnTypeEvenWithPrivateConstructors() throws Exception {
var atom =
public void methodsAreVisibleEvenWithPrivateConstructors() throws Exception {
var myTypeAtom =
ctxRule.evalModule(
"""
type My_Type
Expand All @@ -205,13 +253,11 @@ public void methodsAreVisibleOnTypeEvenWithPrivateConstructors() throws Exceptio

main = My_Type.Cons "a"
""");
var type = ctxRule.unwrapValue(atom.getMetaObject());
var rawAtom = ctxRule.unwrapValue(atom);
var atom = ctxRule.unwrapValue(myTypeAtom);
var interop = InteropLibrary.getUncached();
var read = interop.readMember(type, "read");
var read = interop.readMember(atom, "read");
assertNotNull("Found read member", read);
assertTrue("Can read", interop.isExecutable(read));
assertEquals("a", interop.execute(read, rawAtom).toString());
assertEquals("a", read.toString());
}

@Test
Expand Down Expand Up @@ -383,7 +429,7 @@ public void fieldIsInvocable()
}

@Test
public void fieldIsReadable() {
public void fieldIsReadable() throws UnsupportedMessageException, UnknownIdentifierException {
var myTypeAtom =
ctxRule.evalModule(
"""
Expand All @@ -395,6 +441,8 @@ public void fieldIsReadable() {
var atom = ctxRule.unwrapValue(myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Field a is readable", interop.isMemberReadable(atom, "a"), is(true));
var aField = interop.readMember(atom, "a");
assertThat("Field is a number", interop.asInt(aField), is(1));
}

@Test
Expand All @@ -415,38 +463,36 @@ public void staticMethodIsNotAtomMember() {
}

@Test
public void constructorIsNotAtomMember_InteropLibrary() {
public void privateStaticMethodIsNotAtomMember() {
var myTypeAtom =
ctxRule.evalModule(
"""
type My_Type
Cons a b
method self = 42
Cons
private static_method = 42

main = My_Type.Cons "a" "b"
main = My_Type.Cons
""");
var atom = ctxRule.unwrapValue(myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Cons is not atom member", interop.isMemberExisting(atom, "Cons"), is(false));
assertThat(
"Private static method is not atom member",
myTypeAtom.getMemberKeys(),
not(hasItem(containsString("static_method"))));
}

@Test
public void typeMembersAreConstructors() {
var myType =
public void constructorIsNotAtomMember_InteropLibrary() {
var myTypeAtom =
ctxRule.evalModule(
"""
type My_Type
Cons_1
Cons_2
Cons a b
method self = 42

main = My_Type
main = My_Type.Cons "a" "b"
""");
assertThat("type has constructors as members", myType.hasMembers(), is(true));
assertThat(myType.getMemberKeys(), containsInAnyOrder("Cons_1", "Cons_2"));
assertThat(
"Constructor (type member) is instantiable",
myType.getMember("Cons_1").canInstantiate(),
is(true));
var atom = ctxRule.unwrapValue(myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Cons is not atom member", interop.isMemberExisting(atom, "Cons"), is(false));
}

@Test
Expand Down Expand Up @@ -492,35 +538,6 @@ public void instanceMethod_CanBeInvokedViaAtom() {
assertThat(res.asInt(), is(42));
}

@Test
public void instanceMethod_IsMemberOfType() {
var type =
ctxRule.evalModule(
"""
type My_Type
Cons
method self = 42
main = My_Type
""");
assertThat(type.hasMember("method"), is(true));
assertThat(type.canInvokeMember("method"), is(true));
}

@Test
public void instanceMethod_CanBeInvokedViaType() {
var atom =
ctxRule.evalModule(
"""
type My_Type
Cons
method self = 42
main = My_Type.Cons
""");
var type = atom.getMetaObject();
var res = type.invokeMember("method", atom);
assertThat(res.asInt(), is(42));
}

@Test
public void invokeVsReadAndExecute() throws Exception {
var atom =
Expand Down Expand Up @@ -567,4 +584,13 @@ private List<String> getAllMemberNames(Object obj)
}
return memberNames;
}

private static void assertMembers(String msg, Value v, String... keys) {
var realKeys = v.getMemberKeys();
for (var k : keys) {
assertTrue(msg + " - found " + k + " in " + realKeys, realKeys.contains(k));
assertTrue(msg + " - has member " + k, v.hasMember(k));
assertNotNull(msg + " - can be invoked", v.invokeMember(k));
}
}
}
Loading
Loading