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

Resolve ambiguity in export least predicate #3291

Merged
merged 144 commits into from
Dec 29, 2022
Merged

Conversation

davidcok
Copy link
Collaborator

Fixes #3288

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

davidcok and others added 30 commits January 29, 2021 12:41
@davidcok davidcok enabled auto-merge (squash) December 29, 2022 20:38
[ ExportId<out exportId> ]
[ IF(IsIdentifier(la.kind) || la.kind==_digits) ExportId<out exportId> // If the next token is 'least' or 'greatest' use it as the export id,
// not the beginning of a subsequent extreme predicate declaration
(. if (startToken.line != exportId.line) errors.Warning(exportId, "the id for the export declaration is on a different line than the 'export' keyword -- this looks suspicious or confusing");
Copy link
Member

Choose a reason for hiding this comment

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

I'm puzzled about that. I've seen people writing

  export
    name
    provides X
    reveals Y

which seems adequate.

I think the error message could be more appropriate - but I don't have a strong opinion, your warning is already great - if the token before the start of a predicate on the same line was "least" or "greatest" and this predicate itself is not "least" or "greatest".
That way, export names could be on a different line.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest that if the input includes export least predicate, then we should given an error if least and predicate are on the same line (not if export and least are on different lines).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

OK. Now there is a warning if the token is least or greatest, it is in a export declaration, the next token is 'predicate', and 'predicate' is on the same line as 'least or 'greatest'.

Or, Rustan, did you really mean 'error' instead of 'warn ing' in your comment?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry, I meant warning. Good fix.

@@ -2445,6 +2449,9 @@ FunctionDecl<DeclModifierData dmod, out Function/*!*/ f>
MethodFunctionName<out id>
(
[ GenericParameters<typeArgs, false> ]
[ KType<ref kType>
(. SemErr(t, "a formal [ ] declaration is only allowed for least and greatest predicates"); .)
Copy link
Member

Choose a reason for hiding this comment

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

Great proactive error reporting

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks

@@ -453,6 +453,25 @@ in `B` nor as `Z.a` in C would be valid, because `a` is not in `Z`.
The default export set is important in the resolution of qualified
names, as described in [Section 4.8](#sec-name-resolution).

There are a few unusual cases to be noted:
- an export set can be completely empty, as in `export Nothing`
- an anonymous export set can be completely empty, as in `export`
Copy link
Member

Choose a reason for hiding this comment

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

Is this a way to make the module entirely private? If so, you could mention it.

Copy link
Collaborator

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 term "anonymous export set". It does have a name, even if you don't give the name explicitly. (This is unlike a constructor in a class, which can indeed be anonymous.) If you omit the name of the export set, the name of the export set defaults to the name of the module. Therefore, "eponymous export set" is more appropriate.

For example, consider

module Module {
  export
    provides F
  export Friends extends Module
    provides G

  function F(): int
  function G(): int
}

Here, the Friends export set extends the eponymous export set. Here, it is important that the first export set does have a name.

A client can use any of these import declarations:

import Module
import Module`Module
import Module`Friends

where the first two mean the same thing. (Each one of these three introduces the local name Module, so if a client wants to use more than one of these imports, the client needs to provide an explicit local name.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Reworded

In this case the `least` (or `greatest`) is the identifier naming the export set.
Consequently, `export least predicate[nat]() { true }` is illegal because `[nat]` cannot be part of a non-extreme predicate.
Also, it is not possible to declare an anonymous, empty export set immediately prior to a declaration of an extreme predicate,
because the `least` or `greatest` is parsed as the export set identifier. The workaround for this situation is to reorder the declarations.
Copy link
Collaborator

Choose a reason for hiding this comment

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

I just thought of a better or more natural workaround: Don't omit the name of the eponymous export set, but instead give its name explicitly. That is, change export to export M if this declaration is placed inside a module named M. (Alright, you still have to reorder the declarations inside the module if your module happens to be called least.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Revised accordingly.

@davidcok davidcok merged commit 26e8a78 into dafny-lang:master Dec 29, 2022
@davidcok davidcok deleted the cok-3288 branch December 30, 2022 00:03
RustanLeino added a commit that referenced this pull request Dec 30, 2022
This PR is a follow-up to PR
#3291, making a few small
corrections.

<small>By submitting this pull request, I confirm that my contribution
is made under the terms of the [MIT
license](https://github.com/dafny-lang/dafny/blob/master/LICENSE.txt).</small>
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.

Resolve ambiguity with 'export least predicate ...'
3 participants