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 typing import Any
|
||||||
|
|
||||||
from src.ast.expr import LiteralExpr, GroupingExpr, UnaryExpr, BinaryExpr, Expr, VariableExpr, AssignExpr
|
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.interpreter.error import PebbleRuntimeError
|
||||||
from src.pebble import Pebble
|
from src.pebble import Pebble
|
||||||
from src.token import TokenType, Token
|
from src.token import TokenType, Token
|
||||||
|
|
||||||
|
|
||||||
class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]):
|
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):
|
def __init__(self):
|
||||||
self.env: Interpreter.Environment = Interpreter.Environment()
|
self.env: Environment = Environment()
|
||||||
|
|
||||||
def interpret(self, statements: list[Stmt]) -> None:
|
def interpret(self, statements: list[Stmt]) -> None:
|
||||||
self.env.clear()
|
self.env.clear()
|
||||||
|
|||||||
Reference in New Issue
Block a user