package table import function.builtin.cons.APPEND.append import function.builtin.cons.LIST.makeList import sexpression.Cons import sexpression.Nil.NIL import sexpression.SExpression import sexpression.Symbol import java.util.HashMap import java.util.TreeMap import kotlin.collections.Map.Entry open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? = NullSymbolTable) : Iterable { val isGlobal: Boolean get() = parent === NullSymbolTable private val table: HashMap = HashMap() private val sortedBindings: Set> get() = TreeMap(table).entries override fun iterator(): Iterator = SymbolTableIterator(this) operator fun contains(symbolName: String) = table.containsKey(symbolName) operator fun get(symbolName: String) = table[symbolName] operator fun set(symbolName: String, value: SExpression) { table[symbolName] = value } fun toList(): Cons { var context: Cons = NIL for (binding in sortedBindings) context = append(context, makeList(makeSymbolValuePair(binding))) return context } private fun makeSymbolValuePair(binding: Entry) = Cons(Symbol(binding.key), makeList(binding.value)) object NullSymbolTable : SymbolTable(null) { override val parent: SymbolTable get() = this } private class SymbolTableIterator(private var symbolTable: SymbolTable) : AbstractIterator() { override fun computeNext() { when (symbolTable) { is NullSymbolTable -> done() else -> { setNext(symbolTable) symbolTable = symbolTable.parent ?: NullSymbolTable } } } } }