transcendental-lisp/src/main/kotlin/table/FunctionTable.kt
Mike Cifelli 5f2ecf79c6 Switch to ClassGraph for annotation reflection
Some maven dependencies were updated and alternative method of
building an uberjar was added (currently commented out), since
the shade plugin displays a warning for the module-info in
ClassGraph.
2018-10-21 08:33:22 -04:00

75 lines
2.3 KiB
Kotlin

package table
import error.CriticalLispException
import function.FunctionNames
import function.LispFunction
import io.github.classgraph.ClassGraph
object FunctionTable {
private val table = mutableMapOf<String, LispFunction>()
private val classGraph = ClassGraph()
.disableJarScanning()
.enableClassInfo()
.enableAnnotationInfo()
.whitelistPackages("function.builtin")
private val allBuiltIns = with(classGraph.scan()) {
getClassesWithAnnotation(FunctionNames::class.qualifiedName)
.map { it.loadClass() }
.filterIsInstance<Class<out LispFunction>>()
.toSet()
}
init {
initializeFunctionTable(allBuiltIns)
}
private fun initializeFunctionTable(builtIns: Set<Class<out LispFunction>>) {
table.clear()
for (function in builtIns)
addBuiltInFunctionToTable(function)
}
private fun addBuiltInFunctionToTable(function: Class<out LispFunction>) {
val functionNames = function.getAnnotation(FunctionNames::class.java)
if (functionNames != null)
addAllFunctionNamesToTable(function, functionNames.value)
}
private fun addAllFunctionNamesToTable(function: Class<out LispFunction>, names: Array<out String>) {
for (name in names)
table[name] = createInstance(function, name)
}
private fun createInstance(function: Class<out LispFunction>, name: String) = try {
function.getConstructor(String::class.java).newInstance(name)
} catch (e: Exception) {
throw LispFunctionInstantiationException(function.name)
}
fun lookupFunction(functionName: String) = table[functionName]
fun isAlreadyDefined(functionName: String) = table.containsKey(functionName)
fun defineFunction(functionName: String, function: LispFunction) {
table[functionName] = function
}
fun resetFunctionTable() {
initializeFunctionTable(allBuiltIns)
}
internal fun resetFunctionTable(builtIns: Set<Class<out LispFunction>>) {
initializeFunctionTable(builtIns)
}
class LispFunctionInstantiationException(private val functionName: String) : CriticalLispException() {
override val message: String
get() = "Could not create an instance of '$functionName'"
}
}