Clean up data structure code
This commit is contained in:
parent
cb0e8a1d15
commit
8a970b6797
|
@ -9,14 +9,13 @@ import java.io.FileInputStream
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
object LispInterpreterBuilder {
|
object LispInterpreterBuilder {
|
||||||
|
|
||||||
private var inputName = ""
|
private var inputName = ""
|
||||||
private var isInteractive = true
|
private var isInteractive = true
|
||||||
private var isFileBased = false
|
private var isFileBased = false
|
||||||
private var languageFiles = ArrayList<LanguageFile>()
|
private var languageFiles = mutableListOf<LanguageFile>()
|
||||||
private var inputStream: InputStream? = null
|
private var inputStream: InputStream? = null
|
||||||
private var outputStream: PrintStream? = null
|
private var outputStream: PrintStream? = null
|
||||||
private var errorOutputStream: PrintStream? = null
|
private var errorOutputStream: PrintStream? = null
|
||||||
|
@ -36,7 +35,7 @@ object LispInterpreterBuilder {
|
||||||
inputName = ""
|
inputName = ""
|
||||||
isInteractive = true
|
isInteractive = true
|
||||||
isFileBased = false
|
isFileBased = false
|
||||||
languageFiles = ArrayList()
|
languageFiles = mutableListOf()
|
||||||
inputStream = null
|
inputStream = null
|
||||||
outputStream = null
|
outputStream = null
|
||||||
errorOutputStream = null
|
errorOutputStream = null
|
||||||
|
@ -74,7 +73,7 @@ object LispInterpreterBuilder {
|
||||||
|
|
||||||
fun setLanguageFileNames(vararg languageFiles: String) {
|
fun setLanguageFileNames(vararg languageFiles: String) {
|
||||||
val classLoader = javaClass.classLoader
|
val classLoader = javaClass.classLoader
|
||||||
this.languageFiles = ArrayList()
|
this.languageFiles = mutableListOf()
|
||||||
|
|
||||||
for (fileName in languageFiles)
|
for (fileName in languageFiles)
|
||||||
this.languageFiles.add(LanguageFile(classLoader.getResourceAsStream(fileName), fileName))
|
this.languageFiles.add(LanguageFile(classLoader.getResourceAsStream(fileName), fileName))
|
||||||
|
|
|
@ -11,7 +11,6 @@ import util.Characters.NEWLINE
|
||||||
import util.Characters.isIdentifierCharacter
|
import util.Characters.isIdentifierCharacter
|
||||||
import util.Characters.isNumberPrefix
|
import util.Characters.isNumberPrefix
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.lang.Character.isWhitespace
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a stream of bytes into a stream of Lisp tokens.
|
* Converts a stream of bytes into a stream of Lisp tokens.
|
||||||
|
@ -28,7 +27,7 @@ class LispScanner(inputStream: InputStream, fileName: String) {
|
||||||
val currentCharacter = c.toChar()
|
val currentCharacter = c.toChar()
|
||||||
positionTracker.incrementColumn()
|
positionTracker.incrementColumn()
|
||||||
|
|
||||||
if (!isWhitespace(currentCharacter))
|
if (!currentCharacter.isWhitespace())
|
||||||
return createTokenFromCharacter(currentCharacter)
|
return createTokenFromCharacter(currentCharacter)
|
||||||
else if (currentCharacter == NEWLINE)
|
else if (currentCharacter == NEWLINE)
|
||||||
positionTracker.incrementLine()
|
positionTracker.incrementLine()
|
||||||
|
|
|
@ -50,63 +50,61 @@ import function.builtin.special.PROGN
|
||||||
import function.builtin.special.QUOTE
|
import function.builtin.special.QUOTE
|
||||||
import function.builtin.special.RECUR
|
import function.builtin.special.RECUR
|
||||||
import function.builtin.special.SETQ
|
import function.builtin.special.SETQ
|
||||||
import java.util.HashMap
|
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
object FunctionTable {
|
object FunctionTable {
|
||||||
|
|
||||||
private var table = HashMap<String, LispFunction>()
|
private val allBuiltIns = setOf(
|
||||||
private val allBuiltIns = HashSet<Class<out LispFunction>>()
|
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 {
|
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(NumericEqual::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)
|
initializeFunctionTable(allBuiltIns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,11 @@ import sexpression.Cons
|
||||||
import sexpression.Nil.NIL
|
import sexpression.Nil.NIL
|
||||||
import sexpression.SExpression
|
import sexpression.SExpression
|
||||||
import sexpression.Symbol
|
import sexpression.Symbol
|
||||||
import java.util.HashMap
|
|
||||||
import java.util.TreeMap
|
|
||||||
import kotlin.collections.Map.Entry
|
import kotlin.collections.Map.Entry
|
||||||
|
|
||||||
open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? = NullSymbolTable) : Iterable<SymbolTable> {
|
open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? = NullSymbolTable) : Iterable<SymbolTable> {
|
||||||
|
|
||||||
private val table: HashMap<String, SExpression> = HashMap()
|
private val table = mutableMapOf<String, SExpression>()
|
||||||
|
|
||||||
override fun iterator(): Iterator<SymbolTable> = SymbolTableIterator(this)
|
override fun iterator(): Iterator<SymbolTable> = SymbolTableIterator(this)
|
||||||
operator fun contains(symbolName: String) = symbolName in table
|
operator fun contains(symbolName: String) = symbolName in table
|
||||||
|
@ -27,7 +25,7 @@ open class SymbolTable @JvmOverloads constructor(open val parent: SymbolTable? =
|
||||||
fun toList(): Cons {
|
fun toList(): Cons {
|
||||||
var context: Cons = NIL
|
var context: Cons = NIL
|
||||||
|
|
||||||
for (binding in TreeMap(table).entries)
|
for (binding in table.toSortedMap().entries)
|
||||||
context = append(context, makeList(makeSymbolValuePair(binding)))
|
context = append(context, makeList(makeSymbolValuePair(binding)))
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package util
|
package util
|
||||||
|
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
object Characters {
|
object Characters {
|
||||||
|
|
||||||
const val EOF = -1
|
const val EOF = -1
|
||||||
|
@ -24,24 +22,21 @@ object Characters {
|
||||||
const val UNICODE_ESCAPE = '\u001B'
|
const val UNICODE_ESCAPE = '\u001B'
|
||||||
const val UNICODE_NULL = '\u0000'
|
const val UNICODE_NULL = '\u0000'
|
||||||
|
|
||||||
private val illegalIdentifierCharacters = HashSet<Char>()
|
private val illegalIdentifierCharacters =
|
||||||
|
setOf(AT_SIGN,
|
||||||
|
BACKQUOTE,
|
||||||
|
BACKSLASH,
|
||||||
|
COMMA,
|
||||||
|
DOUBLE_QUOTE,
|
||||||
|
HASH,
|
||||||
|
LEFT_PARENTHESIS,
|
||||||
|
LEFT_SQUARE_BRACKET,
|
||||||
|
PERIOD,
|
||||||
|
RIGHT_PARENTHESIS,
|
||||||
|
RIGHT_SQUARE_BRACKET,
|
||||||
|
SEMICOLON,
|
||||||
|
SINGLE_QUOTE)
|
||||||
|
|
||||||
init {
|
fun isIdentifierCharacter(c: Char) = !c.isWhitespace() && !illegalIdentifierCharacters.contains(c)
|
||||||
illegalIdentifierCharacters.add(AT_SIGN)
|
|
||||||
illegalIdentifierCharacters.add(BACKQUOTE)
|
|
||||||
illegalIdentifierCharacters.add(BACKSLASH)
|
|
||||||
illegalIdentifierCharacters.add(COMMA)
|
|
||||||
illegalIdentifierCharacters.add(DOUBLE_QUOTE)
|
|
||||||
illegalIdentifierCharacters.add(HASH)
|
|
||||||
illegalIdentifierCharacters.add(LEFT_PARENTHESIS)
|
|
||||||
illegalIdentifierCharacters.add(LEFT_SQUARE_BRACKET)
|
|
||||||
illegalIdentifierCharacters.add(PERIOD)
|
|
||||||
illegalIdentifierCharacters.add(RIGHT_PARENTHESIS)
|
|
||||||
illegalIdentifierCharacters.add(RIGHT_SQUARE_BRACKET)
|
|
||||||
illegalIdentifierCharacters.add(SEMICOLON)
|
|
||||||
illegalIdentifierCharacters.add(SINGLE_QUOTE)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isIdentifierCharacter(c: Char) = !Character.isWhitespace(c) && !illegalIdentifierCharacters.contains(c)
|
|
||||||
fun isNumberPrefix(c: Char) = c == DASH || c == PLUS
|
fun isNumberPrefix(c: Char) = c == DASH || c == PLUS
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.TestInstance
|
import org.junit.jupiter.api.TestInstance
|
||||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
@TestInstance(PER_CLASS)
|
@TestInstance(PER_CLASS)
|
||||||
class RuntimeEnvironmentTest {
|
class RuntimeEnvironmentTest {
|
||||||
|
@ -17,7 +16,7 @@ class RuntimeEnvironmentTest {
|
||||||
private const val TERMINATED_EXCEPTIONALLY = "TERMINATED_EXCEPTIONALLY"
|
private const val TERMINATED_EXCEPTIONALLY = "TERMINATED_EXCEPTIONALLY"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val indicatorSet: MutableSet<String> = HashSet()
|
private val indicatorSet = mutableSetOf<String>()
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.junit.jupiter.api.BeforeEach
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
class ErrorManagerTest {
|
class ErrorManagerTest {
|
||||||
|
|
||||||
|
@ -19,7 +18,7 @@ class ErrorManagerTest {
|
||||||
private const val MESSAGE = "message"
|
private const val MESSAGE = "message"
|
||||||
}
|
}
|
||||||
|
|
||||||
private val indicatorSet: MutableSet<String> = HashSet()
|
private val indicatorSet = mutableSetOf<String>()
|
||||||
private val errorOutputStream: ByteArrayOutputStream = ByteArrayOutputStream()
|
private val errorOutputStream: ByteArrayOutputStream = ByteArrayOutputStream()
|
||||||
private val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
|
private val outputStream: ByteArrayOutputStream = ByteArrayOutputStream()
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.junit.jupiter.api.TestInstance
|
||||||
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS
|
||||||
import testutil.SymbolAndFunctionCleaner
|
import testutil.SymbolAndFunctionCleaner
|
||||||
import testutil.TestUtilities.evaluateString
|
import testutil.TestUtilities.evaluateString
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
@TestInstance(PER_CLASS)
|
@TestInstance(PER_CLASS)
|
||||||
class ExitTest : SymbolAndFunctionCleaner() {
|
class ExitTest : SymbolAndFunctionCleaner() {
|
||||||
|
@ -18,7 +17,7 @@ class ExitTest : SymbolAndFunctionCleaner() {
|
||||||
private const val TERMINATED = "terminated"
|
private const val TERMINATED = "terminated"
|
||||||
}
|
}
|
||||||
|
|
||||||
private var indicatorSet = HashSet<String>()
|
private val indicatorSet = mutableSetOf<String>()
|
||||||
|
|
||||||
private fun assertTerminated() {
|
private fun assertTerminated() {
|
||||||
assertThat(indicatorSet.contains(TERMINATED)).isTrue()
|
assertThat(indicatorSet.contains(TERMINATED)).isTrue()
|
||||||
|
|
|
@ -11,7 +11,6 @@ import org.junit.Test
|
||||||
import testutil.TestUtilities.createInputStreamFromString
|
import testutil.TestUtilities.createInputStreamFromString
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
class LispInterpreterTest {
|
class LispInterpreterTest {
|
||||||
|
|
||||||
|
@ -20,9 +19,9 @@ class LispInterpreterTest {
|
||||||
private val FILE = LispInterpreterTest::class.java.getResource("file.lisp").file
|
private val FILE = LispInterpreterTest::class.java.getResource("file.lisp").file
|
||||||
}
|
}
|
||||||
|
|
||||||
private var indicatorSet = HashSet<String>()
|
private val indicatorSet = mutableSetOf<String>()
|
||||||
private var outputStream = ByteArrayOutputStream()
|
private val outputStream = ByteArrayOutputStream()
|
||||||
private var errorOutputStream = ByteArrayOutputStream()
|
private val errorOutputStream = ByteArrayOutputStream()
|
||||||
|
|
||||||
private fun setCommonFeatures() {
|
private fun setCommonFeatures() {
|
||||||
LispInterpreterBuilder.setOutput(PrintStream(outputStream))
|
LispInterpreterBuilder.setOutput(PrintStream(outputStream))
|
||||||
|
|
|
@ -20,7 +20,6 @@ import token.QuotedString
|
||||||
import token.RightParenthesis
|
import token.RightParenthesis
|
||||||
import token.Token
|
import token.Token
|
||||||
import token.TokenFactory.BadCharacterException
|
import token.TokenFactory.BadCharacterException
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
class LispScannerTypeTest {
|
class LispScannerTypeTest {
|
||||||
|
|
||||||
|
@ -38,7 +37,7 @@ class LispScannerTypeTest {
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
expectedTypes = ArrayList()
|
expectedTypes = mutableListOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -20,7 +20,6 @@ import table.FunctionTable.defineFunction
|
||||||
import table.FunctionTable.isAlreadyDefined
|
import table.FunctionTable.isAlreadyDefined
|
||||||
import table.FunctionTable.lookupFunction
|
import table.FunctionTable.lookupFunction
|
||||||
import table.FunctionTable.resetFunctionTable
|
import table.FunctionTable.resetFunctionTable
|
||||||
import java.util.HashSet
|
|
||||||
|
|
||||||
@TestInstance(PER_CLASS)
|
@TestInstance(PER_CLASS)
|
||||||
class FunctionTableTest {
|
class FunctionTableTest {
|
||||||
|
@ -101,8 +100,7 @@ class FunctionTableTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `reset function table with custom built-ins`() {
|
fun `reset function table with custom built-ins`() {
|
||||||
val goodBuiltIns = HashSet<Class<out LispFunction>>()
|
val goodBuiltIns = setOf(GoodFunction::class.java)
|
||||||
goodBuiltIns.add(GoodFunction::class.java)
|
|
||||||
|
|
||||||
resetFunctionTable(goodBuiltIns)
|
resetFunctionTable(goodBuiltIns)
|
||||||
|
|
||||||
|
@ -112,8 +110,7 @@ class FunctionTableTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `unable to initialize a built-in function`() {
|
fun `unable to initialize a built-in function`() {
|
||||||
val badBuiltIns = HashSet<Class<out LispFunction>>()
|
val badBuiltIns = setOf(BadFunction::class.java)
|
||||||
badBuiltIns.add(BadFunction::class.java)
|
|
||||||
|
|
||||||
assertThrows(LispFunctionInstantiationException::class.java) { resetFunctionTable(badBuiltIns) }
|
assertThrows(LispFunctionInstantiationException::class.java) { resetFunctionTable(badBuiltIns) }
|
||||||
}
|
}
|
||||||
|
@ -128,8 +125,7 @@ class FunctionTableTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `built-in without a name doesn't throw an exception`() {
|
fun `built-in without a name doesn't throw an exception`() {
|
||||||
val namelessBuiltins = HashSet<Class<out LispFunction>>()
|
val namelessBuiltins = setOf(UglyFunction::class.java)
|
||||||
namelessBuiltins.add(UglyFunction::class.java)
|
|
||||||
|
|
||||||
resetFunctionTable(namelessBuiltins)
|
resetFunctionTable(namelessBuiltins)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue