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

Members on Atom and Type include inherited methods from Any #12099

Merged
merged 39 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
87cece0
Test members on Atom and Type include inherited methods from Any
Akirathan Jan 21, 2025
bd458d0
Add test for consistency between Meta.get_type_methods and interop me…
Akirathan Jan 21, 2025
58b825b
Type has methods from Any as members
Akirathan Jan 22, 2025
8aa5131
Atom has instance methods from Any as members
Akirathan Jan 22, 2025
ede07e2
Update AtomInteropTest
Akirathan Jan 22, 2025
34bd4e2
Update TypeMembersTest
Akirathan Jan 22, 2025
d8ebddf
Member names are not qualified
Akirathan Jan 22, 2025
8ced357
GetTypeMethodsNode delegates to Type.getMethods
Akirathan Jan 22, 2025
d2c0d2d
Update Meta_Spec test
Akirathan Jan 22, 2025
5bb54a4
Fix Locale.predefined_locale_fields
Akirathan Jan 22, 2025
3ec63bc
Update Array_Spec test
Akirathan Jan 22, 2025
6ed4a20
Fix constants in RuntimeTypesTest
Akirathan Jan 22, 2025
3c6050d
Remove member key size test from ExecCompilerTest
Akirathan Jan 22, 2025
049dd6d
Remove prop size test from DebuggingEnsoTest
Akirathan Jan 22, 2025
d5d7d05
Fix constants in RuntimeErrorsTest
Akirathan Jan 22, 2025
f94e7c1
Merge branch 'develop' into wip/akirathan/12045-type-get-members
Akirathan Jan 22, 2025
cae43f7
Update engine/runtime-integration-tests/src/test/java/org/enso/interp…
Akirathan Jan 23, 2025
9b98189
Add test for members from Number hierarchy
Akirathan Jan 23, 2025
106b35d
Include methods from the whole type hierarchy
Akirathan Jan 23, 2025
2edaa22
Collect expected methods
Akirathan Jan 23, 2025
80e80e4
Keep overriden methods.
Akirathan Jan 23, 2025
e69ce1c
Type.Invoke member uses InvokeCallableNode
Akirathan Jan 24, 2025
07c403c
Don't replace instance methods with static methods from eigen type
Akirathan Jan 24, 2025
8a4d67e
Add minimal reproducer for failing RUntimeErrorsTest
Akirathan Jan 24, 2025
9d99e37
Add tests for MethodResolverNode
Akirathan Jan 24, 2025
b95e3ea
Add MethodInvocationOnTypeConsistencyTest
Akirathan Jan 27, 2025
d14550b
Merge branch 'develop' into wip/akirathan/12045-type-get-members
Akirathan Jan 28, 2025
af32b43
Merge branch 'develop' into wip/akirathan/12045-type-get-members
Akirathan Feb 7, 2025
def8d62
Add ArgumentMappingTest
Akirathan Feb 7, 2025
63f0df0
Use resolveFunction from InvokeMethodNode
Akirathan Feb 7, 2025
8eddeae
Extract shouldPrependSyntheticSelfArg from InvokeMethodNode
Akirathan Feb 7, 2025
5040b02
Ignore consistency tests
Akirathan Feb 12, 2025
f81d2ed
Merge branch 'develop' into wip/akirathan/12045-type-get-members
Akirathan Feb 25, 2025
be6444d
Methods are found on eigen types
Akirathan Feb 25, 2025
9cb327b
When invoking members on type, the type must be first argument
Akirathan Feb 25, 2025
e274bb9
Add TypeMembersTest.builtinMethodIsPresent
Akirathan Feb 25, 2025
f3c6f3a
Fix slow context access error
Akirathan Feb 25, 2025
7ba1361
When invoking members on type, the type must be first argument
Akirathan Feb 25, 2025
d245a4d
fmt
Akirathan Feb 25, 2025
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
21 changes: 19 additions & 2 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Data/Locale.enso
Original file line number Diff line number Diff line change
Expand Up @@ -467,8 +467,25 @@ type Locale
predefined_locale_fields : Vector Text
predefined_locale_fields =
locale_meta = Meta.meta Locale
remove_us = locale_meta.methods + ["Value", "new", "default", "from_language_tag", "from_java", "predefined_locale_fields", "default_widget", "widget_options"]
Meta.Type.Value (Meta.type_of locale_meta.value) . methods . filter (Filter_Condition.Is_In remove_us ..Remove) . sort
methods_to_remove = Vector.build bldr->
bldr.append "Value"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one should be private unless something horribly breaks.

bldr.append "new"
bldr.append "default"
bldr.append "from_language_tag"
bldr.append "from_java"
bldr.append "java_locale"
bldr.append "predefined_locale_fields"
bldr.append "default_widget"
bldr.append "widget_options"
bldr.append "display_country"
bldr.append "display_variant"
bldr.append "display_language"
bldr.append "variant"
bldr.append "language"
bldr.append "country"
bldr.append "default"
bldr.append_vector_range <| Meta.meta Any . methods
locale_meta . methods . filter (Filter_Condition.Is_In methods_to_remove ..Remove) . sort

## PRIVATE
widget_options : Vector Option
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.enso.interpreter.test.interop;

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;
Expand All @@ -11,8 +13,11 @@
import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import java.util.ArrayList;
import java.util.List;
import org.enso.test.utils.ContextUtils;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.Value;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -35,6 +40,25 @@ public void disposeCtx() {
ctx = null;
}

@Test
public void atomMemberNames_AreNotQualified() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
import Standard.Base.Any.Any

type My_Type
Cons field_1 field_2

main =
My_Type.Cons 1 2
""");
assertThat(myTypeAtom.hasMembers(), is(true));
var memberNames = myTypeAtom.getMemberKeys();
assertThat("Member names are not qualified", memberNames, hasItem(not(containsString("."))));
}

@Test
public void atomMembersAreConstructorFields_SingleConstructor() {
var myTypeAtom =
Expand All @@ -49,13 +73,11 @@ public void atomMembersAreConstructorFields_SingleConstructor() {
""");
assertThat(myTypeAtom.hasMembers(), is(true));
var memberNames = myTypeAtom.getMemberKeys();
assertThat("Has two fields", memberNames.size(), is(2));
assertThat(
"Member names are not qualified", memberNames, containsInAnyOrder("field_1", "field_2"));
for (var memberName : memberNames) {
var member = myTypeAtom.getMember(memberName);
assertThat("Member " + memberName + " should be readable", member, is(notNullValue()));
assertThat("All fields are numbers", member.isNumber(), is(true));
assertThat("Has at least two fields", memberNames.size(), is(greaterThan(2)));
for (var consName : List.of("field_1", "field_2")) {
var member = myTypeAtom.getMember(consName);
assertThat("Member " + consName + " should be readable", member, is(notNullValue()));
assertThat("Cons field is number", member.isNumber(), is(true));
}
}

Expand Down Expand Up @@ -111,7 +133,7 @@ public void atomMembersAreConstructorFields_ManyConstructors() {
assertThat(
"Member names correspond to constructor field names for a single constructor",
myTypeAtom.getMemberKeys(),
containsInAnyOrder("g1", "g2", "g3"));
allOf(hasItem("g1"), hasItem("g2"), hasItem("g3"), not(hasItem("h1"))));
}

@Test
Expand Down Expand Up @@ -142,12 +164,17 @@ public void methodIsAtomMember_InteropLibrary() {

main = My_Type.Cons "a" "b"
""");
var atom = ContextUtils.unwrapValue(ctx, 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));
ContextUtils.executeInContext(
ctx,
() -> {
var atom = ContextUtils.unwrapValue(ctx, 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));
return null;
});
}

@Test
Expand Down Expand Up @@ -225,6 +252,67 @@ public void allMethodsAreInternalMembers() {
is(true));
}

/**
* Builtin methods from Any are present even if the Standard.Base.Any module is not imported.
*
* @throws Exception
*/
@Test
public void internalMembersIncludeMethodsFromAny_WithoutImport() throws Exception {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a

main = My_Type.Cons "a"
""");
ContextUtils.executeInContext(
ctx,
() -> {
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var memberNames = getAllMemberNames(atom);
var anyBuiltinMethods = ContextUtils.builtinMethodsFromAny(ctx);
for (var method : anyBuiltinMethods) {
assertThat(
"Builtin method (from Any) is a member of atom", memberNames, hasItem(method));
}
return null;
});
}

/**
* When Standard.Base.Any module is imported, all the methods (both builtin and non-builtin) from
* Any should be present as internal members of the atom.
*/
@Test
public void internalMembersIncludeMethodsFromAny_WithImport() throws Exception {
ContextUtils.executeInContext(
ctx,
() -> {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
from Standard.Base.Any import all

type My_Type
Cons a

main = My_Type.Cons "a"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var memberNames = getAllMemberNames(atom);
var anyMethods = ContextUtils.allMethodsFromAny(ctx);
for (var method : anyMethods) {
assertThat(
"Non-builtin method (from Any) is a member of atom", memberNames, hasItem(method));
}
return null;
});
}

@Test
public void allMembersAreReadableAndInvocable()
throws UnsupportedMessageException, InvalidArrayIndexException {
Expand All @@ -239,20 +327,25 @@ public void allMembersAreReadableAndInvocable()

main = My_Type.Cons "a"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
var members = interop.getMembers(atom, true);
for (long i = 0; i < interop.getArraySize(members); i++) {
var memberName = interop.asString(interop.readArrayElement(members, i));
assertThat(
"Member " + memberName + " should be readable",
interop.isMemberReadable(atom, memberName),
is(true));
assertThat(
"Member " + memberName + " should be invocable",
interop.isMemberInvocable(atom, memberName),
is(true));
}
ContextUtils.executeInContext(
ctx,
() -> {
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
var members = interop.getMembers(atom, true);
for (long i = 0; i < interop.getArraySize(members); i++) {
var memberName = interop.asString(interop.readArrayElement(members, i));
assertThat(
"Member " + memberName + " should be readable",
interop.isMemberReadable(atom, memberName),
is(true));
assertThat(
"Member " + memberName + " should be invocable",
interop.isMemberInvocable(atom, memberName),
is(true));
}
return null;
});
}

@Test
Expand Down Expand Up @@ -335,19 +428,24 @@ public void staticMethodIsNotAtomMember() {

@Test
public void constructorIsNotAtomMember_InteropLibrary() {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a b
method self = 42

main = My_Type.Cons "a" "b"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Cons is not atom member", interop.isMemberExisting(atom, "Cons"), is(false));
ContextUtils.executeInContext(
ctx,
() -> {
var myTypeAtom =
ContextUtils.evalModule(
ctx,
"""
type My_Type
Cons a b
method self = 42

main = My_Type.Cons "a" "b"
""");
var atom = ContextUtils.unwrapValue(ctx, myTypeAtom);
var interop = InteropLibrary.getUncached();
assertThat("Cons is not atom member", interop.isMemberExisting(atom, "Cons"), is(false));
return null;
});
}

@Test
Expand All @@ -369,4 +467,20 @@ public void typeMembersAreConstructors() {
myType.getMember("Cons_1").canInstantiate(),
is(true));
}

/**
* @param obj {@link ContextUtils#unwrapValue(Context, Value) unwrapped} {@link Value value}.
*/
private List<String> getAllMemberNames(Object obj)
throws UnsupportedMessageException, InvalidArrayIndexException {
var interop = InteropLibrary.getUncached();
var allMembers = interop.getMembers(obj, true);
var memberNames = new ArrayList<String>();
for (var i = 0; i < interop.getArraySize(allMembers); i++) {
var member = interop.readArrayElement(allMembers, i);
var memberName = interop.asString(member);
memberNames.add(memberName);
}
return memberNames;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
package org.enso.interpreter.test.interop;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import com.oracle.truffle.api.interop.InteropLibrary;
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.enso.test.utils.ContextUtils;
import org.graalvm.polyglot.Context;
Expand Down Expand Up @@ -102,7 +111,76 @@ public void ensureNonBuiltinMembersArePresent() throws Exception {

var module = ctx.eval(src);
var compileError = module.invokeMember("eval_expression", "v");
assertEquals("all members", Set.of("to_display_text", "message"), compileError.getMemberKeys());
assertEquals(
"all members",
Set.of("to_display_text", "message", "to_text", "==", "catch_primitive", "pretty"),
compileError.getMemberKeys());
}

@Test
public void inheritedMembersFromAnyAreIncluded() {
var type =
ContextUtils.evalModule(
ctx,
"""
from Standard.Base.Any import all

type My_Type
method self = 42

main = My_Type
""");
ContextUtils.executeInContext(
ctx,
() -> {
var typeUnwrapped = ContextUtils.unwrapValue(ctx, type);
var memberNames = getAllMemberNames(typeUnwrapped);
var anyMethods = ContextUtils.allMethodsFromAny(ctx);
for (var anyMethod : anyMethods) {
assertThat("Has method from Any", memberNames, hasItem(containsString(anyMethod)));
}
return null;
});
}

@Test
public void typeMemberNames_AreNotQualified() {
var type =
ContextUtils.evalModule(
ctx,
"""
from Standard.Base.Any import all

type My_Type
method self = 42

main = My_Type
""");
ContextUtils.executeInContext(
ctx,
() -> {
var typeUnwrapped = ContextUtils.unwrapValue(ctx, type);
var memberNames = getAllMemberNames(typeUnwrapped);
assertThat(
"Member names are not qualified", memberNames, not(hasItem(containsString("."))));
return null;
});
}

/**
* @param obj {@link ContextUtils#unwrapValue(Context, Value) unwrapped} {@link Value value}.
*/
private List<String> getAllMemberNames(Object obj)
throws UnsupportedMessageException, InvalidArrayIndexException {
var interop = InteropLibrary.getUncached();
var allMembers = interop.getMembers(obj, true);
var memberNames = new ArrayList<String>();
for (var i = 0; i < interop.getArraySize(allMembers); i++) {
var member = interop.readArrayElement(allMembers, i);
var memberName = interop.asString(member);
memberNames.add(memberName);
}
return memberNames;
}

private static void assertMembers(String msg, Value v, String... keys) {
Expand Down
Loading
Loading