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

Generate IR definitions by annotation processor - 1st step #11770

Open
wants to merge 170 commits into
base: develop
Choose a base branch
from

Conversation

Akirathan
Copy link
Member

@Akirathan Akirathan commented Dec 4, 2024

This PR is the initial step for migrating all the IR elements implemented as Scala case classes to Java classes generated by an annotation processor.

This PR was created from the abandoned #11267 that tried to generated subclasses.

Pull Request Description

The overall description is the same as in #11267, but this approach tries to generate super classes as suggested in https://github.com/enso-org/enso/pull/11267/files#r1869342527

References

Important Notes

Apart from the annotation processor implementation and tests, CallArgument.Specified was migrated to the new approach from Scala case class. I uploaded its generated class code in this gist so you can see it without compilation.

Checklist

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

  • Benchmarks are OK
  • 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,
    TypeScript,
    and
    Rust
    style guides. In case you are using a language not listed above, follow the Rust style guide.
  • Unit tests have been written where possible.
  • If meaningful changes were made to logic or tests affecting Enso Cloud integration in the libraries,
    or the Snowflake database integration, a run of the Extra Tests has been scheduled.
    • If applicable, it is suggested to paste a link to a successful run of the Extra Tests.

This will be important for mapExpressions method implementation
This is the only way to retain 100% backward compatibility.
@Akirathan Akirathan changed the title [Poc] Generate IR definitions - superclass approach Generate IR definitions by annotation processor - 1st step Dec 30, 2024
@Akirathan Akirathan marked this pull request as ready for review December 30, 2024 20:21
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 am surprised there is hand written implementation of copy method in CallArgument.Specified - it'd be better if it was generated. The amount of arguments sent to super constructor is surprising.

@@ -2,6 +2,8 @@
requires org.enso.syntax;
requires scala.library;
requires org.enso.persistance;
requires static org.enso.runtime.parser.dsl;
requires static org.enso.runtime.parser.processor;
Copy link
Member

Choose a reason for hiding this comment

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

Requires static is correct.

}

public Specified copy(Expression value) {
if (value != this.value()) {
Copy link
Member

Choose a reason for hiding this comment

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

Looks like boiler plate code. I was hoping this code would be generated.

public final class Empty extends EmptyGen {
@GenerateFields
public Empty(IdentifiedLocation identifiedLocation, MetadataStorage passData) {
super(null, passData, identifiedLocation, null);
Copy link
Member

Choose a reason for hiding this comment

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

What does it mean super(null, ..., null)? Why two null parameters?

Copy link
Member Author

Choose a reason for hiding this comment

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

IRNodeClassGenerator generates two constructors - the "main" constructor which has all user-defined and meta fields as parameters, and another one that has only user-defined fields as parameters. This super calls the constructor which has meta fields. There are four meta fields. It is possible, and probably better, to generate constructor in the super class that exactly matches the constructor here though.

@Test
public void parserProcessorIsAvailable() {
try {
var clazz = Class.forName("org.enso.runtime.parser.processor.IRProcessor");
Copy link
Member

Choose a reason for hiding this comment

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

Strange test. Why are we testing this class can be loaded? Of course, because it on module path of runtime-parser project as provided and that implies it is visible in the tests of the runtime-parser project.

I'd rather have a test in runtime-integration-tests that IRProcessor class cannot be loaded. Because we don't want this class in the final JARs that we deploy.

Copy link
Collaborator

@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.

I feel like processor would become much more readable if we used String templates which are now available. A combination of StringBuilders and text replacing can be sometimes hard to read.

build.sbt Outdated Show resolved Hide resolved
/** Call-site arguments in Enso. */
public interface JCallArgument extends IR {
/** The name of the argument, if present. */
Option<Name> name();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why Scala option?

Copy link
Member Author

Choose a reason for hiding this comment

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

To retain backward compatibility. We use scala.Option all over the place in IR types.

"JSpecifiedGen" should "have generated parameter names with javac compiler" in {
val lit = Literal.Text("foo", null, new MetadataStorage())
val callArg = new JSpecified(isSynthetic = true, value = lit, name = None)
callArg should not be null
Copy link
Collaborator

Choose a reason for hiding this comment

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

that's always guaranteed to be true, no?

Copy link
Member Author

Choose a reason for hiding this comment

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

It is. This test is here just to ensure that new JSpecified can be used with named arguments.


var code =
"""
public static final class Builder {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could use string templates since we are on latest jdk?

Copy link
Member Author

Choose a reason for hiding this comment

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

Unfortunately, Frgaal still does not support string templates.

public final class MapExpressionsMethodGenerator {
private final ExecutableElement mapExpressionsMethod;
private final GeneratedClassContext ctx;
private static final String METHOD_NAME = "mapExpressions";
Copy link
Collaborator

Choose a reason for hiding this comment

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

Probably should use came case, as everywhere else

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't know about "everywhere else". For example, in Constants.java we use upper case, as well as in Builtins.java

// it.
// This is because runtime-parser-processor project does not depend on runtime-parser
// and
// so the org.enso.compiler.core.IR interface is not available in the classpath.
Copy link
Collaborator

Choose a reason for hiding this comment

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

:(

Copy link
Member Author

Choose a reason for hiding this comment

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

I assume the sad face is there because we have not yet separated the runtime-parser project into a separate project that would contain the IR interface.

@hubertp
Copy link
Collaborator

hubertp commented Dec 31, 2024

Is there any impact on benchmarks with all this machinery?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI: Clean build required CI runners will be cleaned before and after this PR is built.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants