You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+25-7Lines changed: 25 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -110,9 +110,15 @@ This class simulates a simple bank account with two methods: `deposit` and `with
110
110
111
111
> Replace the `"true"` refinements with the appropriate ones to ensure the correct behavior of both methods.
112
112
113
-
For example, we want to ensure that the `balance` and `amount` parameters of both methods are equal or greater than zero and greater than zero, respectively. Also, we want to ensure the correct implementation of both methods — they must return the updated balance after the deposit or withdrawal operations. This also tells the typechecker what the expected output is, allowing it to verify the correctness of the following operations.
113
+
- The `balance` parameter of both methods should be non-negative.
114
+
- The `amount` parameter of the `deposit` method should be greater than zero.
115
+
- The `amount` parameter of the `withdraw` method should be greater than zero and less than or equal to the `balance`.
116
+
- The return value of the `deposit` method should be equal to the sum of `balance` and `amount`.
117
+
- The return value of the `withdraw` method should be equal to the difference between `balance` and `amount`.
114
118
115
-
With the correct refinements in place, LiquidJava will report an error in the `withdraw` method call, since it tries to withdraw more money than it was deposited. If we instead try to withdraw `10` or less, no error will be reported.
119
+
With the correct refinements in place, LiquidJava will report an error in the `withdraw` method call, since it tries to withdraw more money than it was deposited.
120
+
121
+
> Modify the `withdraw` method call to withdraw `10` or less to fix the error.
116
122
117
123
However, notice that we are repeating the same refinement twice in the `balance` parameter of both methods. For this, we can use a refinement aliases to define commonly used refinements and avoid repetition.
118
124
@@ -150,7 +156,14 @@ For example, we want to ensure that the `pause` method can only be called when t
150
156
151
157

152
158
153
-
With the correct implementation, LiquidJava will report an error in line 30, since we are trying to resume playback when the player is stopped.
159
+
If you get stuck, here are some **hints**:
160
+
161
+
- Follow the diagram carefully
162
+
- For each edge in the diagram, identify the method that causes that transition and the source and target states
163
+
- If a method is allowed from multiple source states, use the `||` operator to combine them
164
+
- Don't forget the `(this)` after each state name, since states are always associated with an object instance
165
+
166
+
With the correct implementation, LiquidJava will report an error in line 30, since we are trying to resume playback when the player is stopped. Fix the error before proceeding.
154
167
155
168
### 3. External Refinements
156
169
@@ -166,7 +179,6 @@ Here, we refine the `Socket` class through state refinements, with the possible
166
179
167
180
Here, we see a simple usage of the `Socket` class. If you comment out the line 9 containing with the `bind` method call, LiquidJava will report an error in the `connect` method call, since it violates the state refinement specified for the `Socket` class! Notice that when using the `Socket` class, we don't need to deal with any refinement annotations, since they are already specified in the external refinement interface.
168
181
169
-
170
182
#### Exercise
171
183
172
184
Let's refine another external class.
@@ -177,8 +189,7 @@ We want to ensure that the `lock` method can only be called in the `unlocked` st
With the correct implementation, LiquidJava will report an error in line 10 of [ReentrantLockExample.java](./src/main/java/com/tutorial/part3/exercise/ReentrantLockExample.java), since we are trying to unlock a lock that is not locked.
181
-
192
+
With the correct implementation, LiquidJava will report an error in line 10 of [ReentrantLockExample.java](./src/main/java/com/tutorial/part3/exercise/ReentrantLockExample.java), since we are trying to unlock a lock that is not locked. Remember to fix the error before moving on.
182
193
183
194
### 4. Ghost Variables
184
195
@@ -196,10 +207,17 @@ Here, we can see a simple usage of the refined `ArrayList` class. If you uncomme
196
207
197
208
#### Exercise
198
209
199
-
Let's do the same but for the `Stack` class. You may find it useful to look at the previous example for reference.
210
+
Let's do the same but for the `Stack` class.
200
211
201
212
> Open [StackRefinements.java](./src/main/java/com/tutorial/part4/exercise/StackRefinements.java). Your task is to refine the `Stack` class by replacing the `"true"` refinements with the appropriate ones to ensure the correct behavior of the `push`, `pop` and `peek` methods, using the `count` ghost variable to keep track of the number of elements in the stack, and not allow incorrect uses of these methods — popping or peeking from an empty stack.
202
213
214
+
If you get stuck, here are some **hints**:
215
+
216
+
- You may find it useful to look at the previous example for reference
217
+
- The predicates must be boolean expressions
218
+
- You should use the `old` keyword to refer to the previous state of the object
219
+
- You should use the `count` ghost variable in all refinements
220
+
203
221
With the correct implementation, LiquidJava will report an error in line 11 of [StackExample.java](./src/main/java/com/tutorial/part4/exercise/StackExample.java), since we are trying to pop an element of the stack when it is empty.
0 commit comments