Skip to content

Commit 723ae56

Browse files
committed
Add Hints
1 parent d8f5eaf commit 723ae56

File tree

1 file changed

+25
-7
lines changed

1 file changed

+25
-7
lines changed

README.md

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,15 @@ This class simulates a simple bank account with two methods: `deposit` and `with
110110

111111
> Replace the `"true"` refinements with the appropriate ones to ensure the correct behavior of both methods.
112112
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`.
114118

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.
116122
117123
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.
118124

@@ -150,7 +156,14 @@ For example, we want to ensure that the `pause` method can only be called when t
150156

151157
![Media Player DFA](./images/media_player_dfa.png)
152158

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.
154167

155168
### 3. External Refinements
156169

@@ -166,7 +179,6 @@ Here, we refine the `Socket` class through state refinements, with the possible
166179
167180
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.
168181

169-
170182
#### Exercise
171183

172184
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
177189

178190
![ReentrantLock DFA](./images/reentrant_lock_dfa.png)
179191

180-
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.
182193

183194
### 4. Ghost Variables
184195

@@ -196,10 +207,17 @@ Here, we can see a simple usage of the refined `ArrayList` class. If you uncomme
196207

197208
#### Exercise
198209

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.
200211

201212
> 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.
202213
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+
203221
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.
204222

205223
---

0 commit comments

Comments
 (0)