feat: add variable assignments
This commit is contained in:
@@ -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)
|
||||||
2
main.py
2
main.py
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
Reference in New Issue
Block a user