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
var4 = var2
var3 = null
print(var1)
print(var2)
print(var3)
print(var4)

View File

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

View File

@@ -17,6 +17,10 @@ class Expr(ABC):
...
class Visitor(ABC, Generic[T]):
@abstractmethod
def visit_assign_expr(self, expr: AssignExpr) -> T:
...
@abstractmethod
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)
class BinaryExpr(Expr):
left: Expr

View File

@@ -1,6 +1,6 @@
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.interpreter.error import PebbleRuntimeError
from src.pebble import Pebble
@@ -21,6 +21,11 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
except IndexError:
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):
self.values = {}
@@ -41,6 +46,11 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
def execute(self, stmt: Stmt) -> None:
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:
left: Any = self.evaluate(expr.left)
right: Any = self.evaluate(expr.right)

View File

@@ -1,6 +1,6 @@
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.parser.error import ParsingError
from src.pebble import Pebble
@@ -124,7 +124,18 @@ class Parser:
return ExpressionStmt(value)
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:
expr: Expr = self.comparison()