diff --git a/src/main/fr/celticinfo/lox/Interpreter.kt b/src/main/fr/celticinfo/lox/Interpreter.kt index 0c81f1f..a7590ea 100644 --- a/src/main/fr/celticinfo/lox/Interpreter.kt +++ b/src/main/fr/celticinfo/lox/Interpreter.kt @@ -3,7 +3,7 @@ package fr.celticinfo.lox import fr.celticinfo.lox.TokenType.* class Interpreter: ExprVisitor, StmtVisitor{ - private var globals = Environment() + var globals = Environment() private var environment = globals constructor() { @@ -41,7 +41,7 @@ class Interpreter: ExprVisitor, StmtVisitor{ executeBlock(stmt.statements, Environment(environment)) } - private fun executeBlock(statements: List, environment: Environment) { + fun executeBlock(statements: List, environment: Environment) { val previous = this.environment try { this.environment = environment @@ -61,6 +61,11 @@ class Interpreter: ExprVisitor, StmtVisitor{ evaluate(stmt.expression) } + override fun visitFunction(stmt: Function) { + val function = LoxFunction(stmt) + environment.define(stmt.name.lexeme, function) + } + override fun visitIf(stmt: If) { if (isTruthy(evaluate(stmt.condition))) { execute(stmt.thenBranch) diff --git a/src/main/fr/celticinfo/lox/LoxFunction.kt b/src/main/fr/celticinfo/lox/LoxFunction.kt new file mode 100644 index 0000000..bd8b081 --- /dev/null +++ b/src/main/fr/celticinfo/lox/LoxFunction.kt @@ -0,0 +1,27 @@ +package fr.celticinfo.lox + +class LoxFunction : LoxCallable { + private val declaration: Function + + constructor(declaration: Function) { + this.declaration = declaration + } + + override fun call(interpreter: Interpreter, arguments: List): Any? { + val environment = Environment(interpreter.globals) + for (i in declaration.params.indices) { + environment.define(declaration.params[i].lexeme, arguments[i]) + } + interpreter.executeBlock(declaration.body, environment) + return null + } + + override fun arity(): Int { + return declaration.params.size + } + + override fun toString(): String { + return "" + } + +} \ No newline at end of file diff --git a/src/test/fr/celticinfo/lox/InterpreterTest.kt b/src/test/fr/celticinfo/lox/InterpreterTest.kt index d945373..cdb2e27 100644 --- a/src/test/fr/celticinfo/lox/InterpreterTest.kt +++ b/src/test/fr/celticinfo/lox/InterpreterTest.kt @@ -387,4 +387,32 @@ print clock(); } } + @Test + fun `Function should work`() { + val standardOut = System.out + val outputStreamCaptor = ByteArrayOutputStream() + + System.setOut(PrintStream(outputStreamCaptor)) + + try { + val code = """ +fun sayHi(first, last) { + print "Hi, " + first + " " + last + "!"; +} + +sayHi("Dear", "Reader"); + """ + val scanner = Scanner(code) + val tokens = scanner.scanTokens() + val parser = Parser(tokens) + val statements = parser.parse() + assertEquals(2, statements.size) + + Interpreter().interpret(statements) + val output = outputStreamCaptor.toString().trim() + assertEquals("Hi, Dear Reader!", output) + } finally { + System.setOut(standardOut) + } + } } \ No newline at end of file