transcendental-lisp/src/main/kotlin/function/builtin/Set.kt
2018-11-18 08:42:51 -05:00

52 lines
1.3 KiB
Kotlin

package function.builtin
import function.ArgumentValidator
import function.FunctionNames
import function.LispFunction
import sexpression.Cons
import sexpression.SExpression
import sexpression.Symbol
import table.ExecutionContext
import table.FunctionTable.lookupFunction
import table.SymbolTable
@FunctionNames("SET")
class Set(name: String) : LispFunction() {
private val argumentValidator = ArgumentValidator(name).apply {
setExactNumberOfArguments(2)
setFirstArgumentExpectedType(Symbol::class.java)
}
override fun call(argumentList: Cons): SExpression {
argumentValidator.validate(argumentList)
val rest = argumentList.rest as Cons
val symbol = argumentList.first
val value = rest.first
val table = findScopeOfSymbol(symbol)
table[symbol.toString()] = value
return value
}
private fun findScopeOfSymbol(symbol: SExpression): SymbolTable {
var table: SymbolTable = ExecutionContext.scope
while (!isSymbolInTable(symbol, table) && !table.isGlobal())
table = table.parent!!
return table
}
private fun isSymbolInTable(symbol: SExpression, table: SymbolTable) =
table.contains(symbol.toString())
companion object {
fun set(argumentList: Cons) = lookupFunction("SET")!!.call(argumentList)
}
}