Skip to content

JmlLexer w/o expr mode #3572

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

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

JmlLexer w/o expr mode #3572

wants to merge 13 commits into from

Conversation

wadoon
Copy link
Member

@wadoon wadoon commented Feb 27, 2025

Intended Change

Make JMLLexer more straightforward to understand by eliminating the two modes (aka contract/expr or outer/inner).

Type of pull request

  • Refactoring (behaviour should not change or only minimally change)

Ensuring quality

  • I have tested the feature as follows: unit-tests

Breaking Changes

  • Identifier that clashes with JML keywords need to be quoted now.

@wadoon wadoon force-pushed the weigl/lexerwomodes branch 2 times, most recently from 178b07a to fa9ab56 Compare February 27, 2025 12:08
@wadoon wadoon force-pushed the weigl/lexerwomodes branch from 6a9e8c0 to 7380131 Compare March 3, 2025 00:19
@wadoon
Copy link
Member Author

wadoon commented Mar 3, 2025

I just re-noticed how bad the JML language design is.

  /*@ model_behavior
        accessible<heap> fpLock();
        accessible<permissions> fpPerm();
  ...

The previous JML contract could mean:

  • A model contract with the two accessible clauses.
  • An empty model contract, and the definition of the method fpLock returning an instance of accessible<heap>. Followed by a second method definition.

@wadoon wadoon force-pushed the weigl/lexerwomodes branch from 7380131 to 552f739 Compare March 3, 2025 23:27
@mattulbrich
Copy link
Member

An empty model contract, and the definition of the method fpLock returning an instance of accessible<heap>. Followed by a second method definition.

Would that not require the keyword model before the method declaration? There are no method declarations in comments without model (or possibly ghost one day).

@wadoon
Copy link
Member Author

wadoon commented Mar 4, 2025

Would that not require the keyword model before the method declaration? There are no method declarations in comments without model (or possibly ghost one day).

model is a modifier, and therefore admissible currently. This should be valid lexically:

//@ model model model(model model model) { return model; }

A model method, named model, getting a model instance (named model), and returning it.
It should be rejected because model is not a valid identifier for parameters (currently not in KeY bit in the jmlparser), but ghost is valid on parameters (if your plans are accepted):

//@ model model model(ghost ghost ghost) { return ghost; }

@wadoon wadoon self-assigned this Mar 5, 2025
@wadoon
Copy link
Member Author

wadoon commented Mar 15, 2025

Discussed solutions:

  1. Introduce two parser rules for identifier: one for relaxed identifier (Java identifier + JML keywords) and one for strict identifiers (Java identifier only).

    Use strict identifiers in ambiguous positions. Nobody needs to declare a model method which collides with a JML name.

    This does not work as names in Java can collide with JML names. You can then never declare a model method return the class invariant.

  2. Introduction of backticks to quote JML keywords.

  3. Remove ghost and model from the list of modifiers.

    Following is valid in JML //@ ghost public ensures invariant;,
    ghost switches the lexer mode, and public is still a keyword signaling a modifier in the expr (inner) mode. In contrast, //@ ghost helper ensures invariant; would throw an exception, although helper is a modifier, because the lexer mode switch forces to emit helper as an identifier.

    The JML syntax is normally <modifier> <construct keyword> .... The construct keywords are keywords that force a specific JML construct, like invariant, initially, and normal_behavior.

    This is not true for model methods or field declaration. We promote ghost/model from an arbitrary modifier to construct-keyword that introduces ghost or model elements.

    Hence, ghost public int x will be invalid, as invariant public int x is invalid.

@wadoon wadoon force-pushed the weigl/lexerwomodes branch from 552f739 to 525a5b2 Compare March 15, 2025 02:40
@wadoon
Copy link
Member Author

wadoon commented Mar 15, 2025

Backtick-escaping is added. Following is valid:

//@ model `model` `model`(`ghost` `ghost`) { return `ghost`; }

@mattulbrich
Copy link
Member

Thanks! I'd like to keep this open for discussion for a moment.

I must admit that apart from technical necessity, model `model` `ensures`; reads a lot better than blindly using model/ensures as identifiers here.

This very backticking mechanism is used in mysql, Kotlin and Scala; so we are in good company.

@wadoon wadoon force-pushed the weigl/lexerwomodes branch from ac785f9 to 266c230 Compare April 2, 2025 20:51
@wadoon wadoon force-pushed the weigl/lexerwomodes branch from 266c230 to 42aced2 Compare April 15, 2025 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants