summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TestOutput.xml2
-rw-r--r--src/bind/AutoBinder.kt79
-rw-r--r--test/res/scratch.lisp2
-rw-r--r--test/src/TestLisp.kt8
4 files changed, 49 insertions, 42 deletions
diff --git a/TestOutput.xml b/TestOutput.xml
index aaef8ea..f935a7d 100644
--- a/TestOutput.xml
+++ b/TestOutput.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" ?><testsuites><testsuite name="Test" tests="0" skipped="0" failures="0" errors="0" timestamp="2023-08-21T04:12:42"><properties></properties><system-out><![CDATA[Hello, World, here is an atom: :iamanatom
+<?xml version="1.0" ?><testsuites><testsuite name="Test" tests="0" skipped="0" failures="0" errors="0" timestamp="2023-08-21T04:26:56"><properties></properties><system-out><![CDATA[Hello, World, here is an atom: :iamanatom
:myfunworks
:atom
a :test
diff --git a/src/bind/AutoBinder.kt b/src/bind/AutoBinder.kt
index 83d5d86..53a4ebb 100644
--- a/src/bind/AutoBinder.kt
+++ b/src/bind/AutoBinder.kt
@@ -8,74 +8,80 @@ import java.lang.reflect.Parameter
class AutoBinder {
- private fun mapLispData(parameter: Parameter): ((Iterator<LispData>, ErrorReporter) -> Any)? {
- if (LispData::class.java.isAssignableFrom(parameter.type)) return { a, b -> parameter.type.cast(a.next()) }
+ private fun mapLispData(parameter: Parameter): ((() -> LispData, () -> LispAst, ErrorReporter) -> Any)? {
+ if (LispData::class.java.isAssignableFrom(parameter.type)) return { a, b, c -> parameter.type.cast(a()) }
return null
}
- private fun mapErrorReporter(parameter: Parameter): ((Iterator<LispData>, ErrorReporter) -> Any)? {
- if (ErrorReporter::class.java.isAssignableFrom(parameter.type)) return { a, b -> b }
+ private fun mapErrorReporter(parameter: Parameter): ((() -> LispData, () -> LispAst, ErrorReporter) -> Any)? {
+ if (ErrorReporter::class.java.isAssignableFrom(parameter.type)) return { a, b, c -> c }
return null
}
- private fun mapString(parameter: Parameter): ((Iterator<LispData>, ErrorReporter) -> Any?)? {
- if (String::class.java == parameter.type) return { a, b ->
- when (val x = a.next()) {
+ private fun mapString(parameter: Parameter): ((() -> LispData, () -> LispAst, ErrorReporter) -> Any?)? {
+ if (String::class.java == parameter.type) return { a, b, c ->
+ when (val x = a()) {
is LispData.LispString -> x.string
is LispData.Atom -> x.label
- else -> null.also { b.reportError("Could not coerce $x to string") }
+ else -> null.also { c.reportError("Could not coerce $x to string") }
}
}
return null
}
- private fun mapBoolean(parameter: Parameter): ((Iterator<LispData>, ErrorReporter) -> Any?)? {
- if (Boolean::class.java.isAssignableFrom(parameter.type)) return { a, b ->
- val x = a.next()
+ private fun mapBoolean(parameter: Parameter): ((() -> LispData, () -> LispAst, ErrorReporter) -> Any?)? {
+ if (Boolean::class.java.isAssignableFrom(parameter.type)) return { a, b, c ->
+ val x = a()
val y = CoreBindings.isTruthy(x)
if (y == null) {
- b.reportError("Could not coerce $x to a boolean")
+ c.reportError("Could not coerce $x to a boolean")
}
y
}
return null
}
- private fun mapNumber(parameter: Parameter): ((Iterator<LispData>, ErrorReporter) -> Any?)? {
- if (Double::class.java.isAssignableFrom(parameter.type)) return { a, b ->
- when (val x = a.next()) {
+ private fun mapAST(parameter: Parameter): ((() -> LispData, () -> LispAst, ErrorReporter) -> Any?)? {
+ if (LispAst::class.java.isAssignableFrom(parameter.type)) return { a, b, c -> parameter.type.cast(b()) }
+ return null
+ }
+
+ private fun mapNumber(parameter: Parameter): ((() -> LispData, () -> LispAst, ErrorReporter) -> Any?)? {
+ if (Double::class.java.isAssignableFrom(parameter.type)) return { a, b, c ->
+ when (val x = a()) {
is LispData.LispNumber -> x.value
- else -> null.also { b.reportError("Could not coerce $x to number") }
+ else -> null.also { c.reportError("Could not coerce $x to number") }
}
}
- if (Float::class.java.isAssignableFrom(parameter.type)) return { a, b ->
- when (val x = a.next()) {
+ if (Float::class.java.isAssignableFrom(parameter.type)) return { a, b, c ->
+ when (val x = a()) {
is LispData.LispNumber -> x.value.toFloat()
- else -> null.also { b.reportError("Could not coerce $x to number") }
+ else -> null.also { c.reportError("Could not coerce $x to number") }
}
}
- if (Int::class.java.isAssignableFrom(parameter.type)) return { a, b ->
- when (val x = a.next()) {
+ if (Int::class.java.isAssignableFrom(parameter.type)) return { a, b, c ->
+ when (val x = a()) {
is LispData.LispNumber -> x.value.toInt()
- else -> null.also { b.reportError("Could not coerce $x to number") }
+ else -> null.also { c.reportError("Could not coerce $x to number") }
}
}
- if (Long::class.java.isAssignableFrom(parameter.type)) return { a, b ->
- when (val x = a.next()) {
+ if (Long::class.java.isAssignableFrom(parameter.type)) return { a, b, c ->
+ when (val x = a()) {
is LispData.LispNumber -> x.value.toLong()
- else -> null.also { b.reportError("Could not coerce $x to number") }
+ else -> null.also { c.reportError("Could not coerce $x to number") }
}
}
return null
}
- val objectMappers = mutableListOf<((Parameter) -> (((Iterator<LispData>, ErrorReporter) -> Any?)?))>(
+ val objectMappers = mutableListOf<((Parameter) -> (((() -> LispData, () -> LispAst, ErrorReporter) -> Any?)?))>(
::mapLispData,
::mapErrorReporter,
::mapNumber,
::mapString,
::mapBoolean,
+ ::mapAST,
)
@@ -101,19 +107,22 @@ class AutoBinder {
objectMappers.firstNotNullOfOrNull { it.invoke(param) }
?: error("Could not find object mapper for parameter $param")
}
- return LispData.externalCall(name) { args, fReportError ->
+ return LispData.externalRawCall(name) { context: LispExecutionContext, callsite: LispAst.LispNode, stackFrame: StackFrame, args: List<LispAst.LispNode> ->
+ val e = object : ErrorReporter {
+ override fun reportError(string: String): LispData {
+ return stackFrame.reportError(string, callsite)
+ }
+ }
try {
val iterator = args.iterator()
- val e = object : ErrorReporter {
- override fun reportError(string: String): LispData {
- return fReportError(string)
- }
+ val p = objectMappers.map {
+ it.invoke({ context.resolveValue(stackFrame, iterator.next()) }, { iterator.next() }, e)
+ ?: return@externalRawCall LispData.LispNil
}
- val p = objectMappers.map { it.invoke(iterator, e) ?: return@externalCall LispData.LispNil }
- if (iterator.hasNext()) return@externalCall fReportError("Too many arguments")
+ if (iterator.hasNext()) return@externalRawCall e.reportError("Too many arguments")
mh.invokeWithArguments(p) as LispData
- } catch (e: Exception) {
- fReportError("$name threw an exception: $e")
+ } catch (x: Exception) {
+ e.reportError("$name threw an exception", x)
}
}
}
diff --git a/test/res/scratch.lisp b/test/res/scratch.lisp
index 667f903..00517a8 100644
--- a/test/res/scratch.lisp
+++ b/test/res/scratch.lisp
@@ -25,4 +25,4 @@
(debuglog "============")
(debuglog "Running tests")
-(debuglog "This should be 1.0" (funny-method 1.1 "test" false)) \ No newline at end of file
+(debuglog "This should be 1.0" (funny-method 1.1 "test" false (test 1 2 3 4 /))) \ No newline at end of file
diff --git a/test/src/TestLisp.kt b/test/src/TestLisp.kt
index 205bea2..5f56d68 100644
--- a/test/src/TestLisp.kt
+++ b/test/src/TestLisp.kt
@@ -1,7 +1,4 @@
-import moe.nea.lisp.LispData
-import moe.nea.lisp.LispExecutionContext
-import moe.nea.lisp.LispParser
-import moe.nea.lisp.TestResultFormatter
+import moe.nea.lisp.*
import moe.nea.lisp.bind.AutoBinder
import moe.nea.lisp.bind.LispBinding
import java.io.File
@@ -12,9 +9,10 @@ object T
object TestBindings {
@LispBinding("funny-method")
- fun funnyMethod(arg: Int, test: String, boolean: Boolean): LispData {
+ fun funnyMethod(arg: Int, test: String, boolean: Boolean, ast: LispAst): LispData {
if (boolean)
println("From java: $test")
+ println(ast.toSource())
return LispData.LispNumber(arg.toDouble())
}