From 7f188ed14c6a98a27c41b51399131493e2217f04 Mon Sep 17 00:00:00 2001 From: LordBaryhobal Date: Fri, 6 Feb 2026 14:17:27 +0100 Subject: [PATCH] feat: add basic closures --- examples/14_closure.peb | 17 +++++++++++++++++ main.py | 2 +- src/core/function.py | 5 +++-- src/interpreter/interpreter.py | 2 +- 4 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 examples/14_closure.peb diff --git a/examples/14_closure.peb b/examples/14_closure.peb new file mode 100644 index 0000000..d0e6e4f --- /dev/null +++ b/examples/14_closure.peb @@ -0,0 +1,17 @@ +fun make_counter() { + let i = 0 + fun count() { + i += 1 + return i + } + return count +} + +let counter = make_counter() + +print(counter) + +print(counter()) +counter() +counter() +print(counter()) \ No newline at end of file diff --git a/main.py b/main.py index e68794b..3320c0b 100644 --- a/main.py +++ b/main.py @@ -7,7 +7,7 @@ from src.token import Token def main(): - path: str = "examples/13_return.peb" + path: str = "examples/14_closure.peb" source: str = "" with open(path, "r") as f: source = f.read() diff --git a/src/core/function.py b/src/core/function.py index 594cd08..929d269 100644 --- a/src/core/function.py +++ b/src/core/function.py @@ -12,14 +12,15 @@ if TYPE_CHECKING: class PebbleFunction(PebbleCallable): - def __init__(self, declaration: FunctionStmt): + def __init__(self, declaration: FunctionStmt, closure: Environment): self.declaration: FunctionStmt = declaration + self.closure: Environment = closure def arity(self) -> int: return len(self.declaration.params) def call(self, interpreter: Interpreter, arguments: list[Any]) -> Any: - env: Environment = Environment(interpreter.global_env) + env: Environment = Environment(self.closure) for i, param in enumerate(self.declaration.params): env.define(param.lexeme, arguments[i]) diff --git a/src/interpreter/interpreter.py b/src/interpreter/interpreter.py index 771750b..d685242 100644 --- a/src/interpreter/interpreter.py +++ b/src/interpreter/interpreter.py @@ -146,7 +146,7 @@ class Interpreter(Expr.Visitor[Any], Stmt.Visitor[None]): self.evaluate(stmt.expression) def visit_function_stmt(self, stmt: FunctionStmt) -> None: - function: PebbleFunction = PebbleFunction(stmt) + function: PebbleFunction = PebbleFunction(stmt, self.env) self.env.define(stmt.name.lexeme, function) def visit_if_stmt(self, stmt: IfStmt) -> None: