feat: add variable assignments

This commit is contained in:
2026-02-05 23:23:23 +01:00
parent 4e69a967b0
commit 059798e157
5 changed files with 43 additions and 5 deletions

View File

@@ -4,3 +4,7 @@ let var3 = false
let var4 = var3 let var4 = var3
var4 = var2 var4 = var2
var3 = null var3 = null
print(var1)
print(var2)
print(var3)
print(var4)

View File

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

View File

@@ -17,6 +17,10 @@ class Expr(ABC):
... ...
class Visitor(ABC, Generic[T]): class Visitor(ABC, Generic[T]):
@abstractmethod
def visit_assign_expr(self, expr: AssignExpr) -> T:
...
@abstractmethod @abstractmethod
def visit_binary_expr(self, expr: BinaryExpr) -> T: def visit_binary_expr(self, expr: BinaryExpr) -> T:
... ...
@@ -38,6 +42,15 @@ class Expr(ABC):
... ...
@dataclass(frozen=True)
class AssignExpr(Expr):
name: Token
value: Expr
def accept(self, visitor: Expr.Visitor[T]) -> T:
return visitor.visit_assign_expr(self)
@dataclass(frozen=True) @dataclass(frozen=True)
class BinaryExpr(Expr): class BinaryExpr(Expr):
left: Expr left: Expr

View File

@@ -1,6 +1,6 @@
from typing import Any from typing import Any
from src.ast.expr import LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, Expr, VariableExpr from src.ast.expr import LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, Expr, VariableExpr, AssignExpr
from src.ast.stmt import Stmt, PrintStmt, T, ExpressionStmt, LetStmt from src.ast.stmt import Stmt, PrintStmt, T, ExpressionStmt, LetStmt
from src.interpreter.error import PebbleRuntimeError from src.interpreter.error import PebbleRuntimeError
from src.pebble import Pebble from src.pebble import Pebble
@@ -21,6 +21,11 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
except IndexError: except IndexError:
raise PebbleRuntimeError(name, f"Undefined variable '{name.lexeme}'.") raise PebbleRuntimeError(name, f"Undefined variable '{name.lexeme}'.")
def assign(self, name: Token, value: Any):
if name.lexeme not in self.values:
raise PebbleRuntimeError(name, f"Undefined variable '{name.lexeme}'.")
self.values[name.lexeme] = value
def clear(self): def clear(self):
self.values = {} self.values = {}
@@ -41,6 +46,11 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
def execute(self, stmt: Stmt) -> None: def execute(self, stmt: Stmt) -> None:
stmt.accept(self) stmt.accept(self)
def visit_assign_expr(self, expr: AssignExpr) -> Any:
value: Any = self.evaluate(expr.value)
self.env.assign(expr.name, value)
return value
def visit_binary_expr(self, expr: BinaryExpr) -> Any: def visit_binary_expr(self, expr: BinaryExpr) -> Any:
left: Any = self.evaluate(expr.left) left: Any = self.evaluate(expr.left)
right: Any = self.evaluate(expr.right) right: Any = self.evaluate(expr.right)

View File

@@ -1,6 +1,6 @@
from typing import Optional from typing import Optional
from src.ast.expr import Expr, BinaryExpr, UnaryExpr, LiteralExpr, GroupingExpr, VariableExpr from src.ast.expr import Expr, BinaryExpr, UnaryExpr, LiteralExpr, GroupingExpr, VariableExpr, AssignExpr
from src.ast.stmt import Stmt, PrintStmt, ExpressionStmt, LetStmt from src.ast.stmt import Stmt, PrintStmt, ExpressionStmt, LetStmt
from src.parser.error import ParsingError from src.parser.error import ParsingError
from src.pebble import Pebble from src.pebble import Pebble
@@ -124,7 +124,18 @@ class Parser:
return ExpressionStmt(value) return ExpressionStmt(value)
def expression(self) -> Expr: def expression(self) -> Expr:
return self.equality() return self.assignment()
def assignment(self) -> Expr:
expr: Expr = self.equality()
if self.match(TokenType.EQUAL):
equals: Token = self.previous()
value: Expr = self.assignment()
if isinstance(expr, VariableExpr):
name: Token = expr.name
return AssignExpr(name, value)
self.error(equals, "Invalid assignment target.")
return expr
def equality(self) -> Expr: def equality(self) -> Expr:
expr: Expr = self.comparison() expr: Expr = self.comparison()