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

Add method call info for infix operators #7090

Merged
merged 18 commits into from
Jun 27, 2023

Conversation

4e6
Copy link
Contributor

@4e6 4e6 commented Jun 20, 2023

Pull Request Description

close #6374

In order to provide the method pointer information, the IrToTruffle pass sets the module name and the type name of the builtin node.

Important Notes

Checklist

Please ensure that the following checklist has been satisfied before submitting the PR:

  • The documentation has been updated, if necessary.
  • Screenshots/screencasts have been attached, if there are any visual changes. For interactive or animated visual changes, a screencast is preferred.
  • All code follows the
    Scala,
    Java,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • All code has been tested:
    • Unit tests have been written where possible.

@4e6 4e6 self-assigned this Jun 20, 2023
@4e6 4e6 marked this pull request as ready for review June 26, 2023 15:05
Copy link
Contributor

@hubertp hubertp left a comment

Choose a reason for hiding this comment

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

Tested the changes to builtins' registration. Seems alright and the changes are minimal.

@4e6 4e6 added the CI: Ready to merge This PR is eligible for automatic merge label Jun 27, 2023
@mergify mergify bot merged commit 22259e6 into develop Jun 27, 2023
@mergify mergify bot deleted the wip/db/6374-methodcall-info-for-infix-operators branch June 27, 2023 13:11
Copy link
Member

@JaroslavTulach JaroslavTulach left a comment

Choose a reason for hiding this comment

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

I don't like the setters!

moduleName = ensoRootNode.getModuleScope().getModule().getName();
typeName = null;
functionName = rootNode.getName();
case BuiltinRootNode builtinRootNode -> {
Copy link
Member

Choose a reason for hiding this comment

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

I am surprised the case for EnsoRootNode is removed and nothing gets broken!?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

EnsoRootNode does not contain enough information to build the method pointer. We can simply skip it

@@ -1692,6 +1692,187 @@ class RuntimeServerTest
)
}

it should "send method pointer updates of a builtin method" in {
Copy link
Member

Choose a reason for hiding this comment

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

What is the builtin method? The + operator?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, Text.+

@@ -12,6 +13,29 @@ protected BuiltinRootNode(EnsoLanguage language) {
super(language);
}

protected QualifiedName moduleName = null;
Copy link
Member

Choose a reason for hiding this comment

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

Why protected? There is public getter, public setter. Usually such fields are made private then.


/** Set the module name where the builtin is defined. */
public void setModuleName(QualifiedName moduleName) {
this.moduleName = moduleName;
Copy link
Member

Choose a reason for hiding this comment

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

I don't like mutability of things that should be immutable. I'd prefer to remove the setters completely. If that is not possible, please throw exception if the value is already set and somebody wants to redefine it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I'll update the setters in the next PR

val builtinRootNode =
m.getFunction.getCallTarget.getRootNode
.asInstanceOf[BuiltinRootNode]
builtinRootNode.setModuleName(moduleScope.getModule.getName)
Copy link
Member

Choose a reason for hiding this comment

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

Can't this information be passed to the factory that creates the node?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's not enough information on that stage. The BuiltinMethod annotation contains an unqualified method name. There is also no information on whether the method is static or not (to derive the self-type). Although the BuiltinType annotation contains a qualified type name. But I'm not sure if we can correctly match builtin methods and types because there's not always a 1-1 correspondence (i.e. like with numbers subtypes)

Copy link
Member

Choose a reason for hiding this comment

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

CCing @hubertp as the creator of these annotations and author of Builtins::readBuiltinTypes and Buitins::readBuiltinMethodsMethods.

I see that BuiltinTypes.metadata contains

Date_Time:org.enso.interpreter.node.expression.builtin.date.DateTime:Standard.Base.Data.Time.Date_Time.Date_Time:EnsoDateTime

which represents:

  • Enso type name
  • fully qualified Java class name
  • fully qualified name as available in stdlib
  • underlying type name of the builtin

then I also see that BuiltinMethods.metadata contains:

Date.month:org.enso.interpreter.node.expression.builtin.date.MonthDateMethodGen:false:true

which represents:

  • the language-level name of this method
  • fully qualified Java class name
  • is static information
  • is autoregistered information

not enough information on that stage

Given the combined content of the BuiltinMethods.metadata and BuiltinTypes.metadata I am a believer in having all (most of) the needed information already available...

no information on whether the method is static or not

...that information seems to be present in BuiltinMethods.metadata.

Should any information be missing in BuiltinMethods.metadata and BuiltinTypes.metadata files, then I'd rather add such information there than trying to supply it later via setters in IrToTruffle stage. Immutability creates better systems that are easier to reason about. Having half-initialized objects floating around the system is just asking for troubles.

Please accept my apology for not providing this review sooner than this PR got merged.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if this will cover static wrappers. But yes, in general that information is ready in the metadata files that are being read in static initializers.

Copy link
Member

Choose a reason for hiding this comment

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

So if I understand that correctly, instead of providing the moduleName and typeName here via setters on BuiltinRootNode, you are suggesting to tweak Builtins$LoadedBuiltinMethod::toFunction method (and any other affected locations in the code) such that it will create a BuiltinRootNode with already initialized moduleName and typeName? That sounds like a good idea.

Immutability creates better systems that are easier to reason about.

Indeed. Let me also add a note that setters are twice as much problematic in the Truffle environment than in pure Java. What if BuiltinRootNode.setModuleName is used during runtime? Should we manually invalidate any assumptions? Is it safe not to call CompilerDirectives.transferToInterpreterAndInvalidate() in these setters? Should the moduleName and typeName fields be marked as @CompilationFinal? (They probably should, theoretically, BuiltinRootNode can be shared among multiple contexts and can be a compilation constant; therefore, these fields can also be compilation constants). etc ...

TL;DR; I agree with Jaroslav, and I favor a follow-up PR that removes these setters (or tracking it in a separate issue). The sooner we do it, the better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Ready to merge This PR is eligible for automatic merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

MethodCall info for infix operators
6 participants