diff --git a/src/jlox/interpreter.d b/src/jlox/interpreter.d index fd61716..d248eda 100644 --- a/src/jlox/interpreter.d +++ b/src/jlox/interpreter.d @@ -106,7 +106,7 @@ class Interpreter : Stmt.Visitor!void, Expr.Visitor!TValue { evaluate(stmt.expression); } void visit(Stmt.Function stmt){ - LoxFunction func = new LoxFunction(stmt); + LoxFunction func = new LoxFunction(stmt, environment); environment.define(stmt.name.lexeme, TValue.cal(func)); } void visit(Stmt.If stmt){ diff --git a/src/jlox/loxfunction.d b/src/jlox/loxfunction.d index 39a91ff..16c5878 100644 --- a/src/jlox/loxfunction.d +++ b/src/jlox/loxfunction.d @@ -10,11 +10,15 @@ import jlox.util; class LoxFunction : LoxCallable{ private Stmt.Function declaration; + private Environment closure; mixin defaultCtor; + invariant{ + assert(declaration && closure); + } int arity() => declaration.params.length.to!int; TValue call(Interpreter interpreter, TValue[] arguments){ - Environment environment = new Environment(interpreter.globals); + Environment environment = new Environment(closure); foreach(i; 0 .. declaration.params.length) environment.define(declaration.params[i].lexeme, arguments[i]); try{ diff --git a/test/all.d b/test/all.d index d22369c..5b79f0e 100755 --- a/test/all.d +++ b/test/all.d @@ -17,5 +17,6 @@ void main(){ } assert([ "./lox", "test/fib21.lox" ].execute.output == fib(6765)); assert([ "./lox", "test/fib10.lox" ].execute.output == fib(34)); + assert([ "./lox", "test/closure.lox" ].execute.output == "1\n2\n"); } diff --git a/test/closure.lox b/test/closure.lox new file mode 100644 index 0000000..170cdd0 --- /dev/null +++ b/test/closure.lox @@ -0,0 +1,13 @@ + +fun makeCounter(){ + var i = 0; + fun counter(){ + return i = i + 1; + } + return counter; +} + +var counter = makeCounter(); +print counter(); // "1". +print counter(); // "2". +