creating:statements

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
creating:statements [2025/04/19 19:47] – Use internal wiki links, add link to code repo ahelwercreating:statements [2025/06/13 20:13] (current) – Removed PrintStream parameter from Interpreter constructor ahelwer
Line 71: Line 71:
  
 Add ''Stmt'' to the list of interfaces implemented by the ''Interpreter'' class: Add ''Stmt'' to the list of interfaces implemented by the ''Interpreter'' class:
- 
 <code java [highlight_lines_extra="2"]> <code java [highlight_lines_extra="2"]>
 class Interpreter implements Expr.Visitor<Object>, class Interpreter implements Expr.Visitor<Object>,
Line 79: Line 78:
  
 Now add a visitor method for the ''Stmt.Print'' class, after ''evaluate()'' in the ''Interpreter'' class. Now add a visitor method for the ''Stmt.Print'' class, after ''evaluate()'' in the ''Interpreter'' class.
-This is identical to the book except for one thing, which we will change to improve the testability of our interpreter: +This is identical to the book: 
- +<code java>
-<code java [highlight_lines_extra="4"]>+
   @Override   @Override
   public Void visitPrintStmt(Stmt.Print stmt) {   public Void visitPrintStmt(Stmt.Print stmt) {
     Object value = evaluate(stmt.expression);     Object value = evaluate(stmt.expression);
-    out.println(stringify(value));+    System.out.println(stringify(value));
     return null;     return null;
-  } 
-</code> 
- 
-Instead of printing directly to ''System.out'', we add a ''[[https://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html|PrintStream]]'' field to the ''Interpreter'' class called ''out''. 
-''System.out'' implements the ''PrintStream'' interface, but so do other things, and if we want to write unit tests for this class it helps to be able to intercept its output. 
-Add a constructor for the ''Interpreter'' class along with the field; also add a ''replMode'' parameter, although don't make use of it just yet: 
- 
-<code java [highlight_lines_extra="3,5,6,7"]> 
-class Interpreter implements Expr.Visitor<Object>, 
-                             Stmt.Visitor<Void> { 
-  private final PrintStream out; 
- 
-  public Interpreter(PrintStream out, boolean replMode) { 
-    this.out = out; 
   }   }
 </code> </code>
Line 106: Line 90:
 Same as the book, modify the old ''interpret()'' method to accept a list of statements. Same as the book, modify the old ''interpret()'' method to accept a list of statements.
 The changed method is identical to the book except for using ''TlaPlus'' instead of ''Lox'': The changed method is identical to the book except for using ''TlaPlus'' instead of ''Lox'':
- 
 <code java [highlight_lines_extra="7"]> <code java [highlight_lines_extra="7"]>
   void interpret(List<Stmt> statements) {   void interpret(List<Stmt> statements) {
Line 120: Line 103:
  
 Also add the ''execute()'' helper method to the ''Interpreter'' class: Also add the ''execute()'' helper method to the ''Interpreter'' class:
- 
 <code java> <code java>
   private void execute(Stmt stmt) {   private void execute(Stmt stmt) {
Line 127: Line 109:
 </code> </code>
  
-At the top of ''Interpreter.java'', import the classes we're now using: +At the top of ''Interpreter.java'', add an import for the ''List'' class that is now being used by ''interpret()''
- +<code java [highlight_lines_extra="5"]>
-<code java [highlight_lines_extra="5,6"]>+
 package tla; package tla;
  
Line 135: Line 116:
 import java.util.HashSet; import java.util.HashSet;
 import java.util.List; import java.util.List;
-import java.io.PrintStream; 
 </code> </code>
  
Line 154: Line 134:
 </code> </code>
  
-Then replace the call to the interpreter with this: +Still in ''run()'', replace the call to the interpreter with this:
 <code java [highlight_lines_extra="3"]> <code java [highlight_lines_extra="3"]>
     if (hadError) return;     if (hadError) return;
Line 176: Line 155:
 <code java [highlight_lines_extra="2,4"]> <code java [highlight_lines_extra="2,4"]>
   private static void runFile(String path) throws IOException {   private static void runFile(String path) throws IOException {
-    interpreter = new Interpreter(System.out, false);+    interpreter = new Interpreter(false);
     byte[] bytes = Files.readAllBytes(Paths.get(path));     byte[] bytes = Files.readAllBytes(Paths.get(path));
     run(new String(bytes, StandardCharsets.UTF_8), false);     run(new String(bytes, StandardCharsets.UTF_8), false);
Line 185: Line 164:
 <code java [highlight_lines_extra="2,10"]> <code java [highlight_lines_extra="2,10"]>
   private static void runPrompt() throws IOException {   private static void runPrompt() throws IOException {
-    interpreter = new Interpreter(System.out, true);+    interpreter = new Interpreter(true);
     InputStreamReader input = new InputStreamReader(System.in);     InputStreamReader input = new InputStreamReader(System.in);
     BufferedReader reader = new BufferedReader(input);     BufferedReader reader = new BufferedReader(input);
Line 196: Line 175:
       hadError = false;       hadError = false;
     }     }
 +  }
 +</code>
 +
 +We just used an ''Interpreter'' constructor accepting a parameter indicating whether we're operating in REPL mode.
 +Write that constructor now, although don't yet do anything with the parameter:
 +<code Java>
 +  public Interpreter(boolean replMode) {
 +
   }   }
 </code> </code>
Line 386: Line 373:
  
 Now add an ''Environment'' instance as a field of your ''Interpreter'' class; here's where we make use of the ''replMode'' constructor parameter we added up above: Now add an ''Environment'' instance as a field of your ''Interpreter'' class; here's where we make use of the ''replMode'' constructor parameter we added up above:
- +<code java [highlight_lines_extra="3,6"]>
-<code java [highlight_lines_extra="3,7"]>+
 class Interpreter implements Expr.Visitor<Object>, class Interpreter implements Expr.Visitor<Object>,
                              Stmt.Visitor<Void> {                              Stmt.Visitor<Void> {
   private Environment environment;   private Environment environment;
-  private final PrintStream out; 
  
-  public Interpreter(PrintStream out, boolean replMode) {+  public Interpreter(boolean replMode) {
     this.environment = new Environment(replMode);     this.environment = new Environment(replMode);
-    this.out = out; 
   }   }
 </code> </code>
  
-Now add a visitor method in the ''Interpreter'' class for the ''Expr.Variable'' class, which retrieves the value of the variable from the environment: +Add a visitor method in the ''Interpreter'' class for the ''Expr.Variable'' class, which retrieves the value of the variable from the environment:
 <code java> <code java>
   @Override   @Override
Line 407: Line 390:
   }   }
 </code> </code>
- 
  
 ====== Section 8.4: Assignment ====== ====== Section 8.4: Assignment ======
Line 463: Line 445:
  
 Next up, our greatest parsing challenge yet: [[creating:jlists|conjunction & disjunction lists]]! Next up, our greatest parsing challenge yet: [[creating:jlists|conjunction & disjunction lists]]!
-If your code got out of sync during this tutorial, you can find a snapshot of its expected state in [[https://github.com/tlaplus-community/tlaplus-creator/tree/main/5-statements|this repo directory]].+If your code got out of sync during this tutorial, you can find a snapshot of its expected state in [[https://github.com/tlaplus/devkit/tree/main/5-statements|this repo directory]].
  
 ====== Section 8.5: Challenges ====== ====== Section 8.5: Challenges ======
  
-  - Write some unit tests for your interpreter. Use a ''[[https://docs.oracle.com/javase/8/docs/api/java/io/ByteArrayOutputStream.html|ByteArrayOutputStream]]'' instance as parameter to the ''PrintStream'' constructor, then pass your ''PrintStream'' instance into the ''Interpreter'' class to capture its output.+  - Write some unit tests for your interpreter. Capture the ''System.out'' output; use the ''[[https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#setOut-java.io.PrintStream-|System.setOut()]]'' method with a ''[[https://docs.oracle.com/javase/8/docs/api/java/io/PrintStream.html|PrintStream]]'' instance constructed using a ''[[https://docs.oracle.com/javase/8/docs/api/java/io/ByteArrayOutputStream.html|ByteArrayOutputStream]]''.
   - The ''isAtOpDefStart()'' and ''operatorDefinition()'' methods have some duplicated logic that will only grow more involved when we add operator parameter support. Can you find a way to factor out this logic into a single method?   - The ''isAtOpDefStart()'' and ''operatorDefinition()'' methods have some duplicated logic that will only grow more involved when we add operator parameter support. Can you find a way to factor out this logic into a single method?
  
 [[creating:evaluation|< Previous Page]] | [[creating:start#table_of_contents|Table of Contents]] | [[creating:jlists|Next Page >]] [[creating:evaluation|< Previous Page]] | [[creating:start#table_of_contents|Table of Contents]] | [[creating:jlists|Next Page >]]
  
  • creating/statements.txt
  • Last modified: 2025/06/13 20:13
  • by ahelwer