160 lines
5.7 KiB
Kotlin
160 lines
5.7 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_EQUAL
|
|
import function.builtin.predicate.NUMERIC_GREATER
|
|
import function.builtin.predicate.NUMERIC_LESS
|
|
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.LAMBDA
|
|
import function.builtin.special.LET
|
|
import function.builtin.special.LET_STAR
|
|
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
|
|
import java.text.MessageFormat.format
|
|
import java.util.HashMap
|
|
import java.util.HashSet
|
|
|
|
object FunctionTable {
|
|
|
|
private var table: MutableMap<String, LispFunction> = HashMap()
|
|
private val allBuiltIns = HashSet<Class<out LispFunction>>()
|
|
|
|
init {
|
|
allBuiltIns.add(AND::class.java)
|
|
allBuiltIns.add(APPEND::class.java)
|
|
allBuiltIns.add(APPLY::class.java)
|
|
allBuiltIns.add(ATOM::class.java)
|
|
allBuiltIns.add(CASE::class.java)
|
|
allBuiltIns.add(COND::class.java)
|
|
allBuiltIns.add(CONS::class.java)
|
|
allBuiltIns.add(DEFINE_SPECIAL::class.java)
|
|
allBuiltIns.add(DEFMACRO::class.java)
|
|
allBuiltIns.add(DEFUN::class.java)
|
|
allBuiltIns.add(DIVIDE::class.java)
|
|
allBuiltIns.add(EQ::class.java)
|
|
allBuiltIns.add(EQUAL::class.java)
|
|
allBuiltIns.add(NUMERIC_EQUAL::class.java)
|
|
allBuiltIns.add(EVAL::class.java)
|
|
allBuiltIns.add(EXIT::class.java)
|
|
allBuiltIns.add(FIRST::class.java)
|
|
allBuiltIns.add(FUNCALL::class.java)
|
|
allBuiltIns.add(FUSE::class.java)
|
|
allBuiltIns.add(GENSYM::class.java)
|
|
allBuiltIns.add(GENSYM_EQUAL::class.java)
|
|
allBuiltIns.add(NUMERIC_GREATER::class.java)
|
|
allBuiltIns.add(IF::class.java)
|
|
allBuiltIns.add(LAMBDA::class.java)
|
|
allBuiltIns.add(LENGTH::class.java)
|
|
allBuiltIns.add(NUMERIC_LESS::class.java)
|
|
allBuiltIns.add(LET::class.java)
|
|
allBuiltIns.add(LET_STAR::class.java)
|
|
allBuiltIns.add(LIST::class.java)
|
|
allBuiltIns.add(LISTP::class.java)
|
|
allBuiltIns.add(LOAD::class.java)
|
|
allBuiltIns.add(MINUS::class.java)
|
|
allBuiltIns.add(MODULO::class.java)
|
|
allBuiltIns.add(MULTIPLY::class.java)
|
|
allBuiltIns.add(NULL::class.java)
|
|
allBuiltIns.add(OR::class.java)
|
|
allBuiltIns.add(PLUS::class.java)
|
|
allBuiltIns.add(PRINT::class.java)
|
|
allBuiltIns.add(PROGN::class.java)
|
|
allBuiltIns.add(QUOTE::class.java)
|
|
allBuiltIns.add(RECUR::class.java)
|
|
allBuiltIns.add(REMAINDER::class.java)
|
|
allBuiltIns.add(REST::class.java)
|
|
allBuiltIns.add(SET::class.java)
|
|
allBuiltIns.add(SETQ::class.java)
|
|
allBuiltIns.add(SYMBOL_FUNCTION::class.java)
|
|
allBuiltIns.add(SYMBOLS::class.java)
|
|
|
|
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<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() = format("Could not create an instance of ''{0}''", functionName)
|
|
}
|
|
}
|