Add function objects

main
Olivier Abrivard 1 year ago
parent f24f8729e0
commit 20033fd74a

@ -3,7 +3,7 @@ package fr.celticinfo.lox
import fr.celticinfo.lox.TokenType.*
class Interpreter: ExprVisitor<Any?>, StmtVisitor<Unit>{
private var globals = Environment()
var globals = Environment()
private var environment = globals
constructor() {
@ -41,7 +41,7 @@ class Interpreter: ExprVisitor<Any?>, StmtVisitor<Unit>{
executeBlock(stmt.statements, Environment(environment))
}
private fun executeBlock(statements: List<Stmt?>, environment: Environment) {
fun executeBlock(statements: List<Stmt?>, environment: Environment) {
val previous = this.environment
try {
this.environment = environment
@ -61,6 +61,11 @@ class Interpreter: ExprVisitor<Any?>, StmtVisitor<Unit>{
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)

@ -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?>): 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 "<fn ${declaration.name.lexeme}>"
}
}

@ -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)
}
}
}
Loading…
Cancel
Save