From 0dcf8dd26c9356ec5683450eb51e26f621096828 Mon Sep 17 00:00:00 2001 From: Olivier Abrivard Date: Thu, 5 Sep 2024 10:18:00 +0200 Subject: [PATCH] Add native functions --- src/main/fr/celticinfo/lox/AstPrinter.kt | 4 +++ src/main/fr/celticinfo/lox/Interpreter.kt | 19 +++++++++++- src/main/fr/celticinfo/loxext/RpnPrinter.kt | 4 +++ src/test/fr/celticinfo/lox/InterpreterTest.kt | 29 +++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/main/fr/celticinfo/lox/AstPrinter.kt b/src/main/fr/celticinfo/lox/AstPrinter.kt index 203f173..99464f4 100644 --- a/src/main/fr/celticinfo/lox/AstPrinter.kt +++ b/src/main/fr/celticinfo/lox/AstPrinter.kt @@ -5,6 +5,10 @@ class AstPrinter : ExprVisitor { return expr.accept(this) } + override fun visitCall(expr: Call): String { + return parenthesize("call", expr.callee, *expr.arguments.toTypedArray()) + } + override fun visitAssign(expr: Assign): String { return parenthesize("=", expr) } diff --git a/src/main/fr/celticinfo/lox/Interpreter.kt b/src/main/fr/celticinfo/lox/Interpreter.kt index c85efc7..0c81f1f 100644 --- a/src/main/fr/celticinfo/lox/Interpreter.kt +++ b/src/main/fr/celticinfo/lox/Interpreter.kt @@ -3,7 +3,24 @@ package fr.celticinfo.lox import fr.celticinfo.lox.TokenType.* class Interpreter: ExprVisitor, StmtVisitor{ - private var environment = Environment() + private var globals = Environment() + private var environment = globals + + constructor() { + globals.define("clock", object : LoxCallable { + override fun arity(): Int { + return 0 + } + + override fun call(interpreter: Interpreter, arguments: List): Any? { + return System.currentTimeMillis().toDouble() / 1000.0 + } + + override fun toString(): String { + return "" + } + }) + } fun interpret(statements: List) { try { diff --git a/src/main/fr/celticinfo/loxext/RpnPrinter.kt b/src/main/fr/celticinfo/loxext/RpnPrinter.kt index 76040c6..533b523 100644 --- a/src/main/fr/celticinfo/loxext/RpnPrinter.kt +++ b/src/main/fr/celticinfo/loxext/RpnPrinter.kt @@ -7,6 +7,10 @@ class RpnPrinter : ExprVisitor { return expr.accept(this) } + override fun visitCall(expr: Call): String { + return stack("call", expr.callee, *expr.arguments.toTypedArray()) + } + override fun visitAssign(expr: Assign): String { return stack("=", expr) } diff --git a/src/test/fr/celticinfo/lox/InterpreterTest.kt b/src/test/fr/celticinfo/lox/InterpreterTest.kt index 2924e83..d945373 100644 --- a/src/test/fr/celticinfo/lox/InterpreterTest.kt +++ b/src/test/fr/celticinfo/lox/InterpreterTest.kt @@ -1,6 +1,7 @@ package fr.celticinfo.lox import fr.celticinfo.loxext.RpnPrinter +import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.assertDoesNotThrow import java.io.ByteArrayOutputStream import java.io.PrintStream @@ -358,4 +359,32 @@ for (var b = 1; a < 10000; b = temp + b) { System.setOut(standardOut) } } + + @Test + fun `Clock native function should return a valid timestamp`() { + val standardOut = System.out + val outputStreamCaptor = ByteArrayOutputStream() + + System.setOut(PrintStream(outputStreamCaptor)) + + try { + val code = """ +print clock(); + """.trimIndent() + val scanner = Scanner(code) + val tokens = scanner.scanTokens() + val parser = Parser(tokens) + val statements = parser.parse() + Assertions.assertEquals(1, statements.size) + + Interpreter().interpret(statements) + val output = outputStreamCaptor.toString().trim() + val timestamp = output.toDoubleOrNull() + Assertions.assertNotNull(timestamp) + Assertions.assertTrue(timestamp!! >= 0) + } finally { + System.setOut(standardOut) + } + } + } \ No newline at end of file