module jlox.loxfunction; import std.conv; import common.util; import jlox.token; import jlox.stmt; import jlox.interpreter; import jlox.environment; import jlox.loxinstance; class LoxFunction : LoxCallable{ private Stmt.Function declaration; private Environment closure; private const bool isInitialiser; mixin defaultCtor; invariant{ assert(declaration && closure); } LoxFunction bind(LoxInstance instance){ Environment environment = new Environment(closure); environment.define("this", instance); return new LoxFunction(declaration, environment, isInitialiser); } int arity() => declaration.params.length.to!int; LoxValue call(Interpreter interpreter, LoxValue[] arguments){ Environment environment = new Environment(closure); foreach(i; 0 .. declaration.params.length) environment.define(declaration.params[i].lexeme, arguments[i]); try{ interpreter.executeBlock(declaration.body, environment); } catch(Return returnValue){ if(isInitialiser) return closure.getAt(0, "this"); return cast(LoxValue)returnValue.value; } if(isInitialiser) return closure.getAt(0, "this"); return new LoxNil(); } override string toString() const => "function"; }