if-ELSE!!!!
This commit is contained in:
		
							parent
							
								
									19c9409ccd
								
							
						
					
					
						commit
						6e0b8f950d
					
				
					 8 changed files with 50 additions and 11 deletions
				
			
		|  | @ -1,4 +1,4 @@ | ||||||
| package ch.fritteli.gombaila.domain.common; | package ch.fritteli.gombaila.domain.common; | ||||||
| 
 | 
 | ||||||
| public sealed interface NodeStmt extends Node permits NodeStmtAssign, NodeStmtExit, NodeStmtIf, NodeStmtLet, NodeStmtPrint, NodeStmtScope { | public sealed interface NodeStmt extends Node permits NodeStmtAssign, NodeStmtExit, NodeStmtIf, NodeStmtIfElse, NodeStmtLet, NodeStmtPrint, NodeStmtScope { | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,6 +2,5 @@ package ch.fritteli.gombaila.domain.common; | ||||||
| 
 | 
 | ||||||
| import org.jetbrains.annotations.NotNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public record NodeStmtIf(@NotNull NodeExpr expr, @NotNull NodeStmtScope scope) implements NodeStmt { | public record NodeStmtIf(@NotNull NodeExpr expr, @NotNull NodeStmtScope ifScope) implements NodeStmt { | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | package ch.fritteli.gombaila.domain.common; | ||||||
|  | 
 | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
|  | public record NodeStmtIfElse(@NotNull NodeExpr expr, @NotNull NodeStmtScope ifScope, | ||||||
|  |                              @NotNull NodeStmtScope elseScope) implements NodeStmt { | ||||||
|  | } | ||||||
|  | @ -26,7 +26,8 @@ public enum TokenType { | ||||||
|     IDENTIFIER, |     IDENTIFIER, | ||||||
|     // the rest |     // the rest | ||||||
|     WHITESPACE, |     WHITESPACE, | ||||||
|     IF; |     IF, | ||||||
|  |     ELSE; | ||||||
| 
 | 
 | ||||||
|     public boolean isBinaryOperator() { |     public boolean isBinaryOperator() { | ||||||
|         return switch (this) { |         return switch (this) { | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ import ch.fritteli.gombaila.domain.common.NodeStmt; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtAssign; | import ch.fritteli.gombaila.domain.common.NodeStmtAssign; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtExit; | import ch.fritteli.gombaila.domain.common.NodeStmtExit; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtIf; | import ch.fritteli.gombaila.domain.common.NodeStmtIf; | ||||||
|  | import ch.fritteli.gombaila.domain.common.NodeStmtIfElse; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtLet; | import ch.fritteli.gombaila.domain.common.NodeStmtLet; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtPrint; | import ch.fritteli.gombaila.domain.common.NodeStmtPrint; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtScope; | import ch.fritteli.gombaila.domain.common.NodeStmtScope; | ||||||
|  | @ -27,6 +28,7 @@ final class StmtVisitor { | ||||||
|             case final NodeStmtPrint stmtPrint -> visit(stmtPrint); |             case final NodeStmtPrint stmtPrint -> visit(stmtPrint); | ||||||
|             case final NodeStmtScope stmtScope -> visit(stmtScope); |             case final NodeStmtScope stmtScope -> visit(stmtScope); | ||||||
|             case final NodeStmtIf stmtIf -> visit(stmtIf); |             case final NodeStmtIf stmtIf -> visit(stmtIf); | ||||||
|  |             case final NodeStmtIfElse stmtIfElse -> visit(stmtIfElse); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -96,9 +98,30 @@ final class StmtVisitor { | ||||||
|                 "skip to %s if condition is not met".formatted(label), |                 "skip to %s if condition is not met".formatted(label), | ||||||
|                 "jz", label |                 "jz", label | ||||||
|         ); |         ); | ||||||
|         this.visit(stmt.scope()); |         this.visit(stmt.ifScope()); | ||||||
|         this.generator.printer.label(label); |         this.generator.printer.label(label); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|  |     private void visit(@NotNull final NodeStmtIfElse stmt) { | ||||||
|  |         final String afterIfLabel = this.createNextLabel(); | ||||||
|  |         final String afterElseLabel = this.createNextLabel(); | ||||||
|  |         this.generator.generateExpr(stmt.expr()); | ||||||
|  |         this.generator.pop("rax"); | ||||||
|  |         this.generator.printer.commentedLine("test the condition", | ||||||
|  |                 "test", "rax, rax"); | ||||||
|  |         this.generator.printer.commentedLine( | ||||||
|  |                 "skip to %s (else) if condition is not met".formatted(afterIfLabel), | ||||||
|  |                 "jz", afterIfLabel | ||||||
|  |         ); | ||||||
|  |         this.visit(stmt.ifScope()); | ||||||
|  |         this.generator.printer.commentedLine( | ||||||
|  |                 "skip to %s to skip the else".formatted(afterElseLabel), | ||||||
|  |                 "jmp", | ||||||
|  |                 afterElseLabel | ||||||
|  |         ); | ||||||
|  |         this.generator.printer.label(afterIfLabel); | ||||||
|  |         this.visit(stmt.elseScope()); | ||||||
|  |         this.generator.printer.label(afterElseLabel); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private String createNextLabel() { |     private String createNextLabel() { | ||||||
|  |  | ||||||
|  | @ -80,6 +80,7 @@ public class Lexer { | ||||||
|             case "let" -> this.appendToken(new Token(TokenType.LET, line, column)); |             case "let" -> this.appendToken(new Token(TokenType.LET, line, column)); | ||||||
|             case "print" -> this.appendToken(new Token(TokenType.PRINT, line, column)); |             case "print" -> this.appendToken(new Token(TokenType.PRINT, line, column)); | ||||||
|             case "if" -> this.appendToken(new Token(TokenType.IF, line, column)); |             case "if" -> this.appendToken(new Token(TokenType.IF, line, column)); | ||||||
|  |             case "else" -> this.appendToken(new Token(TokenType.ELSE, line, column)); | ||||||
|             case final String value -> |             case final String value -> | ||||||
|                     this.appendToken(new Token(TokenType.IDENTIFIER, Option.of(value), line, column)); |                     this.appendToken(new Token(TokenType.IDENTIFIER, Option.of(value), line, column)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -15,6 +15,7 @@ import ch.fritteli.gombaila.domain.common.NodeStmt; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtAssign; | import ch.fritteli.gombaila.domain.common.NodeStmtAssign; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtExit; | import ch.fritteli.gombaila.domain.common.NodeStmtExit; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtIf; | import ch.fritteli.gombaila.domain.common.NodeStmtIf; | ||||||
|  | import ch.fritteli.gombaila.domain.common.NodeStmtIfElse; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtLet; | import ch.fritteli.gombaila.domain.common.NodeStmtLet; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtPrint; | import ch.fritteli.gombaila.domain.common.NodeStmtPrint; | ||||||
| import ch.fritteli.gombaila.domain.common.NodeStmtScope; | import ch.fritteli.gombaila.domain.common.NodeStmtScope; | ||||||
|  | @ -65,9 +66,14 @@ public class Parser { | ||||||
|             this.assertAndConsumeNextTokenType(TokenType.OPEN_PAREN); |             this.assertAndConsumeNextTokenType(TokenType.OPEN_PAREN); | ||||||
|             final NodeExpr expr = this.parseExpr(1); |             final NodeExpr expr = this.parseExpr(1); | ||||||
|             this.assertAndConsumeNextTokenType(TokenType.CLOSE_PAREN); |             this.assertAndConsumeNextTokenType(TokenType.CLOSE_PAREN); | ||||||
|             final NodeStmtScope scope = this.parseScope(); |             final NodeStmtScope ifScope = this.parseScope(); | ||||||
|  |             // there /could/ be an else, so let's check that | ||||||
|  |             if (this.checkNextTokenTypeConsuming(TokenType.ELSE)) { | ||||||
|  |                 final NodeStmtScope elseScope = this.parseScope(); | ||||||
|  |                 return new NodeStmtIfElse(expr, ifScope, elseScope); | ||||||
|  |             } | ||||||
|             // NB: We do NOT expect a SEMI here, so we return directly. |             // NB: We do NOT expect a SEMI here, so we return directly. | ||||||
|             return new NodeStmtIf(expr, scope); |             return new NodeStmtIf(expr, ifScope); | ||||||
|         } else if (this.checkNextTokenType(TokenType.IDENTIFIER)) { |         } else if (this.checkNextTokenType(TokenType.IDENTIFIER)) { | ||||||
|             result = this.parseStmtAssign(); |             result = this.parseStmtAssign(); | ||||||
|         } else { |         } else { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,7 @@ | ||||||
| let x = (10 - 2 * 3) / 2; | let x = 1; | ||||||
| if (x-2) { | if (x) { | ||||||
|     exit (69); |     x = 99; | ||||||
|  | } else { | ||||||
|  |     x = 12; | ||||||
| } | } | ||||||
| exit(1); | exit(x); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue