feat: add while loops

This commit is contained in:
2026-02-06 02:06:06 +01:00
parent 57eecb8a65
commit be1b03bb1f
5 changed files with 41 additions and 3 deletions

13
examples/10_while.peb Normal file
View File

@@ -0,0 +1,13 @@
let i = 0
let a = 1
let b = 1
print("Fibonacci")
while i < 10 {
print(a)
let c = a + b
a = b
b = c
i += 1
}

View File

@@ -13,7 +13,7 @@ def main():
123
"This is
another string" """
path: str = "examples/09_logical.peb"
path: str = "examples/10_while.peb"
with open(path, "r") as f:
source = f.read()
lexer: Lexer = Lexer()

View File

@@ -37,6 +37,10 @@ class Stmt(ABC):
def visit_let_stmt(self, stmt: LetStmt) -> T:
...
@abstractmethod
def visit_while_stmt(self, stmt: WhileStmt) -> T:
...
@dataclass(frozen=True)
class BlockStmt(Stmt):
@@ -79,3 +83,13 @@ class LetStmt(Stmt):
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_let_stmt(self)
@dataclass(frozen=True)
class WhileStmt(Stmt):
condition: Expr
body: Stmt
def accept(self, visitor: Stmt.Visitor[T]) -> T:
return visitor.visit_while_stmt(self)

View File

@@ -1,7 +1,7 @@
from typing import Any
from src.ast.expr import LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, Expr, VariableExpr, AssignExpr, LogicalExpr
from src.ast.stmt import Stmt, PrintStmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt
from src.ast.stmt import Stmt, PrintStmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt, WhileStmt
from src.interpreter.environment import Environment
from src.interpreter.error import PebbleRuntimeError
from src.pebble import Pebble
@@ -133,6 +133,10 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
value: Any = self.evaluate(stmt.expression)
print(value)
def visit_while_stmt(self, stmt: WhileStmt) -> None:
while self.is_truthy(self.evaluate(stmt.condition)):
self.execute(stmt.body)
def visit_let_stmt(self, stmt: LetStmt) -> None:
value: Any = None
if stmt.initializer is not None:

View File

@@ -1,7 +1,7 @@
from typing import Optional
from src.ast.expr import Expr, BinaryExpr, UnaryExpr, LiteralExpr, GroupingExpr, VariableExpr, AssignExpr, LogicalExpr
from src.ast.stmt import Stmt, PrintStmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt
from src.ast.stmt import Stmt, PrintStmt, ExpressionStmt, LetStmt, BlockStmt, IfStmt, WhileStmt
from src.parser.error import ParsingError
from src.pebble import Pebble
from src.token import Token, TokenType
@@ -111,6 +111,8 @@ class Parser:
return self.if_stmt()
if self.match(TokenType.PRINT):
return self.print_stmt()
if self.match(TokenType.WHILE):
return self.while_stmt()
if self.match(TokenType.LEFT_BRACE):
return self.block_stmt()
return self.expression_stmt()
@@ -130,6 +132,11 @@ class Parser:
self.expect_eol("Expected end of line after statement")
return PrintStmt(value)
def while_stmt(self) -> Stmt:
condition: Expr = self.expression()
body: Stmt = self.statement()
return WhileStmt(condition, body)
def block_stmt(self) -> Stmt:
statements: list[Stmt] = []
self.skip_newlines()