157 lines
5.0 KiB
Kotlin
157 lines
5.0 KiB
Kotlin
package table
|
|
|
|
import error.CriticalLispException
|
|
import function.FunctionNames
|
|
import function.LispFunction
|
|
import function.builtin.APPLY
|
|
import function.builtin.EVAL
|
|
import function.builtin.Exit
|
|
import function.builtin.FUNCALL
|
|
import function.builtin.FUSE
|
|
import function.builtin.GENSYM
|
|
import function.builtin.LOAD
|
|
import function.builtin.PRINT
|
|
import function.builtin.SET
|
|
import function.builtin.SYMBOLS
|
|
import function.builtin.SYMBOL_FUNCTION
|
|
import function.builtin.cons.APPEND
|
|
import function.builtin.cons.CONS
|
|
import function.builtin.cons.FIRST
|
|
import function.builtin.cons.LENGTH
|
|
import function.builtin.cons.LIST
|
|
import function.builtin.cons.REST
|
|
import function.builtin.math.DIVIDE
|
|
import function.builtin.math.MINUS
|
|
import function.builtin.math.MODULO
|
|
import function.builtin.math.MULTIPLY
|
|
import function.builtin.math.PLUS
|
|
import function.builtin.math.REMAINDER
|
|
import function.builtin.predicate.ATOM
|
|
import function.builtin.predicate.EQ
|
|
import function.builtin.predicate.EQUAL
|
|
import function.builtin.predicate.GENSYM_EQUAL
|
|
import function.builtin.predicate.LISTP
|
|
import function.builtin.predicate.NULL
|
|
import function.builtin.predicate.NUMERIC_GREATER
|
|
import function.builtin.predicate.NUMERIC_LESS
|
|
import function.builtin.predicate.NumericEqual
|
|
import function.builtin.special.AND
|
|
import function.builtin.special.CASE
|
|
import function.builtin.special.COND
|
|
import function.builtin.special.DEFINE_SPECIAL
|
|
import function.builtin.special.DEFMACRO
|
|
import function.builtin.special.DEFUN
|
|
import function.builtin.special.IF
|
|
import function.builtin.special.LET
|
|
import function.builtin.special.LET_STAR
|
|
import function.builtin.special.Lambda
|
|
import function.builtin.special.OR
|
|
import function.builtin.special.PROGN
|
|
import function.builtin.special.QUOTE
|
|
import function.builtin.special.RECUR
|
|
import function.builtin.special.SETQ
|
|
|
|
object FunctionTable {
|
|
|
|
private val allBuiltIns = setOf(
|
|
AND::class.java,
|
|
APPEND::class.java,
|
|
APPLY::class.java,
|
|
ATOM::class.java,
|
|
CASE::class.java,
|
|
COND::class.java,
|
|
CONS::class.java,
|
|
DEFINE_SPECIAL::class.java,
|
|
DEFMACRO::class.java,
|
|
DEFUN::class.java,
|
|
DIVIDE::class.java,
|
|
EQ::class.java,
|
|
EQUAL::class.java,
|
|
NumericEqual::class.java,
|
|
EVAL::class.java,
|
|
Exit::class.java,
|
|
FIRST::class.java,
|
|
FUNCALL::class.java,
|
|
FUSE::class.java,
|
|
GENSYM::class.java,
|
|
GENSYM_EQUAL::class.java,
|
|
NUMERIC_GREATER::class.java,
|
|
IF::class.java,
|
|
Lambda::class.java,
|
|
LENGTH::class.java,
|
|
NUMERIC_LESS::class.java,
|
|
LET::class.java,
|
|
LET_STAR::class.java,
|
|
LIST::class.java,
|
|
LISTP::class.java,
|
|
LOAD::class.java,
|
|
MINUS::class.java,
|
|
MODULO::class.java,
|
|
MULTIPLY::class.java,
|
|
NULL::class.java,
|
|
OR::class.java,
|
|
PLUS::class.java,
|
|
PRINT::class.java,
|
|
PROGN::class.java,
|
|
QUOTE::class.java,
|
|
RECUR::class.java,
|
|
REMAINDER::class.java,
|
|
REST::class.java,
|
|
SET::class.java,
|
|
SETQ::class.java,
|
|
SYMBOL_FUNCTION::class.java,
|
|
SYMBOLS::class.java)
|
|
|
|
private val table = mutableMapOf<String, LispFunction>()
|
|
|
|
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'"
|
|
}
|
|
}
|