feat(interpreter): add enclosing environment parameter
This commit is contained in:
34
src/interpreter/environment.py
Normal file
34
src/interpreter/environment.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Optional
|
||||
|
||||
from src.interpreter.error import PebbleRuntimeError
|
||||
from src.token import Token
|
||||
|
||||
|
||||
class Environment:
|
||||
def __init__(self, enclosing: Optional[Environment] = None):
|
||||
self.enclosing: Optional[Environment] = enclosing
|
||||
self.values: dict[str, Any] = {}
|
||||
|
||||
def define(self, name: str, value: Any):
|
||||
self.values[name] = value
|
||||
|
||||
def get(self, name: Token) -> Any:
|
||||
try:
|
||||
return self.values[name.lexeme]
|
||||
except IndexError:
|
||||
if self.enclosing is not None:
|
||||
return self.enclosing.get(name)
|
||||
raise PebbleRuntimeError(name, f"Undefined variable '{name.lexeme}'.")
|
||||
|
||||
def assign(self, name: Token, value: Any):
|
||||
if name.lexeme not in self.values:
|
||||
if self.enclosing is not None:
|
||||
self.enclosing.assign(name, value)
|
||||
return
|
||||
raise PebbleRuntimeError(name, f"Undefined variable '{name.lexeme}'.")
|
||||
self.values[name.lexeme] = value
|
||||
|
||||
def clear(self):
|
||||
self.values = {}
|
||||
@@ -1,36 +1,16 @@
|
||||
from typing import Any
|
||||
|
||||
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, ExpressionStmt, LetStmt
|
||||
from src.interpreter.environment import Environment
|
||||
from src.interpreter.error import PebbleRuntimeError
|
||||
from src.pebble import Pebble
|
||||
from src.token import TokenType, Token
|
||||
|
||||
|
||||
class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
|
||||
class Environment:
|
||||
def __init__(self):
|
||||
self.values: dict[str, Any] = {}
|
||||
|
||||
def define(self, name: str, value: Any):
|
||||
self.values[name] = value
|
||||
|
||||
def get(self, name: Token) -> Any:
|
||||
try:
|
||||
return self.values[name.lexeme]
|
||||
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 = {}
|
||||
|
||||
def __init__(self):
|
||||
self.env: Interpreter.Environment = Interpreter.Environment()
|
||||
self.env: Environment = Environment()
|
||||
|
||||
def interpret(self, statements: list[Stmt]) -> None:
|
||||
self.env.clear()
|
||||
|
||||
Reference in New Issue
Block a user