Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision | |||
creating:actions [2025/06/19 20:44] – Rewrite Interpreter code to use simplified action method ahelwer | creating:actions [2025/06/19 21:36] (current) – Finished probable final draft of actions tutorial ahelwer | ||
---|---|---|---|
Line 395: | Line 395: | ||
We can now generate all nondeterministic next states by calling '' | We can now generate all nondeterministic next states by calling '' | ||
+ | |||
+ | ===== The ENABLED Operator ===== | ||
+ | |||
+ | Now that we've written '' | ||
+ | An expression '' | ||
+ | So, as simple as a quick call to '' | ||
+ | Well, not quite - the '' | ||
+ | This means we need some extra ceremony to stash the current values of '' | ||
+ | Add the highlighted code to the '' | ||
+ | <code java [highlight_lines_extra=" | ||
+ | } case ENABLED: { | ||
+ | Map< | ||
+ | Set< | ||
+ | try { | ||
+ | clearNext(); | ||
+ | return !getNextStates(expr.operator, | ||
+ | } finally { | ||
+ | next = oldNext; | ||
+ | possibleNext = oldPossibleNext; | ||
+ | } | ||
+ | } case NOT: { | ||
+ | </ | ||
+ | |||
+ | This is a big milestone: we now have fully defined // | ||
+ | We aren't at the end yet, but it's well within sight. | ||
===== Error Checking ===== | ===== Error Checking ===== | ||
Line 462: | Line 487: | ||
Map<?, ?> function = (Map<?, ?> | Map<?, ?> function = (Map<?, ?> | ||
</ | </ | ||
+ | |||
+ | ===== Hooking Up the Interpreter ===== | ||
+ | |||
+ | It takes a bit of thought to consider how we should expose our new state-stepping capabilities through the REPL. | ||
+ | One decent approach is to hijack '' | ||
+ | For this, add the following code to the bottom of the '' | ||
+ | <code java [highlight_lines_extra=" | ||
+ | // Stop if there was a syntax error. | ||
+ | if (hadError) return; | ||
+ | |||
+ | if (replMode && statements.size() == 1 | ||
+ | && statements.get(0) instanceof Stmt.Print) { | ||
+ | tryStep((Stmt.Print)statements.get(0)); | ||
+ | } else { | ||
+ | interpreter.interpret(statements); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | This calls a method we'll define in '' | ||
+ | The '' | ||
+ | However, if '' | ||
+ | If this generates no new states, again treat '' | ||
+ | <code java> | ||
+ | private static void tryStep(Stmt.Print action) { | ||
+ | Object result = interpreter.executeBlock(action.expression, | ||
+ | if (!(result instanceof Boolean)) { | ||
+ | action.accept(interpreter); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | List< | ||
+ | interpreter.getNextStates(action.location, | ||
+ | if (nextStates.isEmpty()) { | ||
+ | action.accept(interpreter); | ||
+ | return; | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The '' | ||
+ | <code java [highlight_lines_extra=" | ||
+ | import java.util.List; | ||
+ | import java.util.Map; | ||
+ | |||
+ | public class TlaPlus { | ||
+ | </ | ||
+ | |||
+ | At this point all that remains is to handle the case of what happens when the '' | ||
+ | The REPL should choose one next state and make '' | ||
+ | <code java [highlight_lines_extra=" | ||
+ | List< | ||
+ | interpreter.getNextStates(action.location, | ||
+ | if (nextStates.isEmpty()) { | ||
+ | System.out.println(false); | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | Map< | ||
+ | interpreter.setNextState(nextState); | ||
+ | interpreter.step(action.location); | ||
+ | System.out.println(true); | ||
+ | System.out.println(nextState); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | We also print out '' | ||
+ | This called two methods; one, in '' | ||
+ | <code java> | ||
+ | void setNextState(Map< | ||
+ | this.next = next; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | The other, in '' | ||
+ | If there are multiple possible next states, the user is prompted to choose one: | ||
+ | <code java> | ||
+ | private static Map< | ||
+ | if (nextStates.size() == 1) { | ||
+ | return nextStates.get(0); | ||
+ | } else { | ||
+ | System.out.println(" | ||
+ | for (int i = 0; i < nextStates.size(); | ||
+ | System.out.println(i + ": " + nextStates.get(i)); | ||
+ | } | ||
+ | |||
+ | System.out.print("> | ||
+ | try (java.util.Scanner in = new java.util.Scanner(System.in)) { | ||
+ | return nextStates.get(in.nextInt()); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | And that's it! | ||
+ | You can now run the REPL and step through the state space! | ||
+ | Try entering expressions like the following: | ||
+ | - '' | ||
+ | - '' | ||
+ | - '' | ||
+ | |||
+ | This was a pivotal chapter; excellent work making it to the end. | ||
+ | You can find the expected state of the codebase in [[https:// | ||
+ | See you in the [[creating: | ||
+ | |||
+ | [[creating: | ||