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 Support for Nested Module Syntax #2012

Merged

Conversation

InsertCreativityHere
Copy link
Member

@InsertCreativityHere InsertCreativityHere commented Apr 2, 2024

This PR adds support for 'nested module syntax' to Ice-Slice.
So now instead of: module A { module B { ... } } you can write: module A::B { ... }.

Note that these syntaxes are literally equivalent. Both introduce two modules, in the same order.
This is purely a syntactical shorthand.

Metadata applied to this thing is now applied to the outer-most module:

[metadata-for-A]
module A::B

Does this seem correct to everyone?


It also updates our Slice files to use this new syntax where it was possible,
and where "having separate modules" didn't feel like it was important to the test.

For the reviewers:
Where are there other Slice files I should look through?


Yes, our Slice style is inconsistent and sometimes bad looking.
I tried not to touch it, lest this PR would take a day instead of an hour.

@bernardnormier
Copy link
Member

Metadata applied to this thing is applied to the inner-most module:

[metadata-for-b]
module A::B

Does this seem correct to everyone?

No, this is wrong. We discussed this at length for IceRPC. See icerpc/icerpc-csharp#3187.

@bernardnormier
Copy link
Member

Yes, our Slice style is inconsistent and sometimes bad looking.

I don't know what you're talking about. If some Slice files are poorly formatted, we should fix them.

@InsertCreativityHere
Copy link
Member Author

InsertCreativityHere commented Apr 2, 2024

I don't know what you're talking about. If some Slice files are poorly formatted, we should fix them.

Yes, I just don't want to do it in this particular PR.
I'll fix their formatting in a separate PR after this one.
There's little point to doing this when the Slice files are changing so much.

@@ -385,6 +385,75 @@ module_def
$$ = nullptr;
}
}
| ICE_MODULE ICE_SCOPED_IDENTIFIER
{
auto ident = dynamic_pointer_cast<StringTok>($2);
Copy link
Member

Choose a reason for hiding this comment

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

Can ICE_SCOPED_IDENTIFIER start with ::?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes it can, but if you type: ::Hello::There, we'll pick up 3 modules: ["", "Hello", "There"].
And "" is not a valid module identifier, so it fails.

// Where `N` is the number of scope separators ("::").
size_t scopePos = 0;
auto ident = dynamic_pointer_cast<StringTok>($2);
while ((scopePos = ident->v.find("::", scopePos + 2)) != string::npos)
Copy link
Member

Choose a reason for hiding this comment

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

Why the +2, does ident always start with ::?

Copy link
Member Author

Choose a reason for hiding this comment

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

The intent was to skip over "::" in between module identifiers...
But you're right, this won't work for something like A::B...

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

@InsertCreativityHere
Copy link
Member Author

After talking it over during lunch, I switch the metadata, so it now applies to the outermost module.
This may be counter-intuitive to users, but it's the most pragmatic option.

All module metadata falls into 2 categories:

  • It renames the module (Or prefixes it). These metadata only make sense for top-level modules (ie. the outer module).
  • metadata that is inherited by the module's contents. Since these are inherited, it makes no difference whether they're on an outer or inner module.

Copy link
Contributor

@ReeceHumphreys ReeceHumphreys left a comment

Choose a reason for hiding this comment

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

Looks good

// Check that the identifier isn't empty.
if (name.empty())
{
currentUnit->error("missing identifier: illegal empty identifier");
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
currentUnit->error("missing identifier: illegal empty identifier");
currentUnit->error("missing identifier: invalid empty identifier");

Copy link
Member Author

Choose a reason for hiding this comment

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

This message was removed entirely.
It should now be impossible for this function to ever have an empty identifier.

Comment on lines 1 to 10
NestedModule.ice:9: illegal identifier `Holder': `Holder' suffix is reserved
NestedModule.ice:11: illegal identifier `Holder': `Holder' suffix is reserved
NestedModule.ice:15: illegal leading underscore in identifier `__Iceberg'
NestedModule.ice:18: illegal identifier `Holder': `Holder' suffix is reserved
NestedModule.ice:20: illegal identifier `Holder': `Holder' suffix is reserved
NestedModule.ice:24: illegal identifier `APtr': `Ptr' suffix is reserved
NestedModule.ice:24: illegal identifier `BPrx': `Prx' suffix is reserved
NestedModule.ice:24: illegal identifier `CHelper': `Helper' suffix is reserved
NestedModule.ice:27: missing identifier: illegal empty identifier
NestedModule.ice:27: illegal identifier `Helper': `Helper' suffix is reserved
Copy link
Contributor

Choose a reason for hiding this comment

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

This will have to be updated accordingly if you implement my above suggestion.

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 find "illegal empty identifier" as a good way to say "a module name must start with a letter".

Copy link
Member Author

Choose a reason for hiding this comment

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

The message became illegal identifier: module identifiers cannot start with '::' prefix

@@ -483,7 +483,15 @@ Slice::checkIdentifier(const string& id)
name = id;
}

// Check that the identifier isn't empty.
if (name.empty())
Copy link
Member

Choose a reason for hiding this comment

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

Is it possible to reach this code?

If yes, please add a test.
If not, an assert would be more appropriate.

Copy link
Member Author

Choose a reason for hiding this comment

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

After some research, it should be impossible to hit.
So, I switched it to an assert.

I hit this by accident when I was using it to check modules, and saw that passing in "" gets a warning of "illegal trailing underscore"...... which is obviously not true (It's a fluke of how we check for trailing underscores).

Copy link
Member

@externl externl left a comment

Choose a reason for hiding this comment

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

LGTM

cpp/test/Slice/errorDetection/NestedModule.ice Outdated Show resolved Hide resolved
@InsertCreativityHere InsertCreativityHere merged commit 84d76e8 into zeroc-ice:main Apr 3, 2024
23 checks passed
InsertCreativityHere added a commit to InsertCreativityHere/compiler-comparison that referenced this pull request Jan 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants