|
9 | 9 |
|
10 | 10 | LiquidJava is an additional type checker for Java, based on **liquid types** and **typestates**, which provides additional safety guarantees to Java programs through **refinements** at compile time. |
11 | 11 |
|
12 | | -**Example:** |
| 12 | +### Refinements |
| 13 | + |
| 14 | +To refine a variable, field, parameter or return value, use the `@Refinement` annotation with a predicate as an argument. The predicate must be a boolean expression that uses the name of the variable being refined (or `_`) to refer to its value. |
13 | 15 |
|
14 | 16 | ```java |
15 | 17 | @Refinement("a > 0") |
16 | | -int a = 3; // okay |
17 | | -a = -8; // type error! |
| 18 | +int a = 3; |
| 19 | +a = -8; // Refinement Error |
| 20 | + |
| 21 | + |
| 22 | +@Refinement("_ >= low && _ <= high") |
| 23 | +public static int midpoint( |
| 24 | + @Refinement("_ <= high") int low, |
| 25 | + int high |
| 26 | +) { |
| 27 | + return low + (high - low) / 2; |
| 28 | +} |
| 29 | + |
| 30 | +midpoint(5, 10); |
| 31 | +midpoint(10, 5); // Refinement Error |
18 | 32 | ``` |
19 | 33 |
|
20 | | -This project contains the LiquidJava verifier and its API, as well as some examples for testing. |
| 34 | +### State Refinements |
21 | 35 |
|
22 | | -You can find out more about LiquidJava in the following resources: |
| 36 | +LiquidJava also supports object state modeling via typestates, which allows enforcing protocols on objects using the `@StateSet` and `@StateRefinement` annotations. The `@StateSet` annotation defines the possible states of an object, while the `@StateRefinement` annotation specifies the allowed transitions between states for each method. The `@ExternalRefinementsFor` annotation is used to specify an external class for which the refinements are being defined. |
23 | 37 |
|
24 | | -* [LiquidJava Website](https://liquid-java.github.io) |
25 | | -* [VS Code Extension (Marketplace)](https://marketplace.visualstudio.com/items?itemName=AlcidesFonseca.liquid-java) |
26 | | -* [VS Code Extension (Source Code)](https://github.com/liquid-java/vscode-liquidjava) |
27 | | -* [LiquidJava Examples](https://github.com/liquid-java/liquidjava-examples) |
28 | | -* [LiquidJava External Libraries Examples](https://github.com/liquid-java/liquid-java-external-libs) |
29 | | -<!-- * [Formalization of LiquidJava](https://github.com/liquid-java/liquidjava-formalization) - not opensource yet --> |
| 38 | +```java |
| 39 | +@ExternalRefinementsFor("java.net.Socket") |
| 40 | +@StateSet({"unconnected", "bound", "connected", "closed"}) |
| 41 | +public interface SocketRefinements { |
| 42 | + @StateRefinement(to="unconnected(this)") |
| 43 | + public void Socket(); |
| 44 | + |
| 45 | + @StateRefinement(from="unconnected(this)", to="bound(this)") |
| 46 | + public void bind(SocketAddress add); |
| 47 | + |
| 48 | + @StateRefinement(from="bound(this)", to="connected(this)") |
| 49 | + public void connect(SocketAddress add); |
| 50 | + |
| 51 | + @StateRefinement(from="connected(this)") |
| 52 | + public void sendUrgentData(int n); |
| 53 | + |
| 54 | + @StateRefinement(from="!closed(this)", to="closed(this)") |
| 55 | + public void close(); |
| 56 | +} |
| 57 | + |
| 58 | +Socket socket = new Socket(); |
| 59 | +socket.bind(new InetSocketAddress("localhost", 8080)); |
| 60 | +socket.sendUrgentData(1); // State Refinement Error |
| 61 | +socket.close(); |
| 62 | +``` |
| 63 | + |
| 64 | +### Ghosts |
| 65 | + |
| 66 | +Finally, LiquidJava also provides ghost variables that are used to track additional information about the program state with the `@Ghost` annotation. These are also updated through the `@StateRefinement` annotation. |
| 67 | + |
| 68 | +```java |
| 69 | +@ExternalRefinementsFor("java.util.Stack") |
| 70 | +@Ghost("int size") |
| 71 | +public interface StackRefinements<E> { |
| 72 | + @StateRefinement(to="size(this) == 0") |
| 73 | + public void Stack(); |
| 74 | + |
| 75 | + @StateRefinement(to="size(this) == size(old(this)) + 1") |
| 76 | + public E push(E elem); |
| 77 | + |
| 78 | + @StateRefinement(from="size(this) > 0", to="size(this) == size(old(this)) - 1") |
| 79 | + public E pop(); |
| 80 | + |
| 81 | + @StateRefinement(from="size(this) > 0") |
| 82 | + public E peek(); |
| 83 | +} |
| 84 | + |
| 85 | +Stack<Integer> stack = new Stack<>(); |
| 86 | +stack.push(1); |
| 87 | +stack.pop(); |
| 88 | +stack.pop(); // State Refinement Error |
| 89 | +``` |
30 | 90 |
|
31 | 91 | ## Getting Started |
32 | 92 |
|
@@ -134,11 +194,21 @@ Tests with no expectation must produce no diagnostics. |
134 | 194 | * **liquidjava-api**: Includes the annotations that can be introduced in the Java programs to add the refinements |
135 | 195 | * **liquidjava-example**: Includes some examples and the test suite used for testing the verifier |
136 | 196 | * **liquidjava-verifier**: Includes the implementation of the verifier. Its main packages are: |
137 | | - * `api`: Includes the `CommandLineLauncher` that runs the verification on a given class or in the `currentlyTesting` directory if no argument is given |
138 | | - * `ast`: Represents the Abstract Syntax Tree (AST) of the Refinements Language (RJ) |
139 | | - * `errors`: Package for reporting the errors |
140 | | - * `processor`: Package that handles the type checking |
141 | | - * `rj_language`: Handles the parsing of the refinement strings to an AST |
142 | | - * `smt`: Package that handles the translation to the SMT solver and the processing of the results the SMT solver produces |
143 | | - * `utils`: Includes useful methods for all the previous packages |
144 | | - * `test/java/liquidjava/api/tests`: Contains the `TestExamples` class used for running the test suite |
| 197 | + * `api`: Includes the `CommandLineLauncher`, which verifies one or more specified files or directories |
| 198 | + * `diagnostics`: Reports verification errors and warnings |
| 199 | + * `processor`: Handles the type checking |
| 200 | + * `rj_language`: Parses refinement strings and contains the Refinements Language (RJ) AST |
| 201 | + * `smt`: Translates verification conditions to the SMT solver and processes its results |
| 202 | + * `utils`: Provides shared utility classes |
| 203 | + |
| 204 | +## References |
| 205 | + |
| 206 | +You can find out more about LiquidJava in the following resources: |
| 207 | + |
| 208 | +* [LiquidJava Website](https://liquid-java.github.io) |
| 209 | +* [VS Code Extension (Marketplace)](https://marketplace.visualstudio.com/items?itemName=AlcidesFonseca.liquid-java) |
| 210 | +* [VS Code Extension (Source Code)](https://github.com/liquid-java/vscode-liquidjava) |
| 211 | +* [LiquidJava Examples](https://github.com/liquid-java/liquidjava-examples) |
| 212 | +* [LiquidJava External Libraries Examples](https://github.com/liquid-java/liquid-java-external-libs) |
| 213 | +* [LiquidJava MCP](https://github.com/liquid-java/liquidjava-mcp) |
| 214 | +<!-- * [Formalization of LiquidJava](https://github.com/liquid-java/liquidjava-formalization) - not opensource yet --> |
0 commit comments