1
1
mirror of https://github.com/kanaka/mal.git synced 2024-11-10 12:47:45 +03:00

Finished atoms and readline

This commit is contained in:
Javier Fernandez-Ivern 2015-10-26 14:02:30 -05:00
parent 8337e32c1c
commit a779c814b9
6 changed files with 59 additions and 5 deletions

View File

@ -163,7 +163,46 @@ val ns = hashMapOf(
Pair(MalSymbol("sequential?"), MalFunction({ a: ISeq -> if (a.nth(0) is ISeq) TRUE else FALSE })),
Pair(MalSymbol("meta"), MalFunction({ a: ISeq -> a.first().metadata })),
Pair(MalSymbol("conj"), MalFunction({ a: ISeq -> (a.first() as ISeq).conj(a.rest()) }))
Pair(MalSymbol("conj"), MalFunction({ a: ISeq -> (a.first() as ISeq).conj(a.rest()) })),
Pair(MalSymbol("deref"), MalFunction({ a: ISeq -> (a.first() as MalAtom).value })),
Pair(MalSymbol("reset!"), MalFunction({ a: ISeq ->
val atom = (a.nth(0) as MalAtom)
val value = a.nth(1)
atom.value = value
value
})),
Pair(MalSymbol("swap!"), MalFunction({ a: ISeq ->
val atom = (a.nth(0) as MalAtom)
val function = a.nth(1) as MalFunction
// TODO reuse code from apply?
val params = MalList()
params.conj_BANG(atom.value)
a.seq().drop(2).forEach({ it ->
if (it is ISeq) {
it.seq().forEach({ x -> params.conj_BANG(x) })
} else {
params.conj_BANG(it)
}
})
val value = function.apply(params)
atom.value = value
value
})),
Pair(MalSymbol("readline"), MalFunction({ a: ISeq ->
val prompt = a.first() as MalString
try {
MalString(readline(prompt.value))
} catch (e: java.io.IOException) {
throw MalException(e.message)
} catch (e: EofException) {
NIL
}
}))
)
fun pairwiseEquals(s: ISeq): MalConstant =

View File

@ -25,6 +25,8 @@ fun pr_str(malType: MalType, print_readably: Boolean = false): String =
pr_str(malType.elements, "[", "]", print_readably)
} else if (malType is MalHashMap) {
malType.elements.map({ it -> pr_str(it, print_readably) }).joinToString(" ", "{", "}")
} else if (malType is MalAtom) {
"(atom " + pr_str(malType.value, print_readably) + ")"
} else {
throw MalPrinterException("Unrecognized MalType: " + malType)
}

View File

@ -47,6 +47,7 @@ fun read_form(reader: Reader): MalType =
"~" -> read_shorthand(reader, "unquote")
"~@" -> read_shorthand(reader, "splice-unquote")
"^" -> read_with_meta(reader)
"@" -> read_shorthand(reader, "deref")
else -> read_atom(reader)
}

View File

@ -1,6 +1,8 @@
package mal
fun readline(prompt: String): String? {
class EofException : Exception("EOF")
fun readline(prompt: String): String {
print(prompt)
return readLine()
return readLine() ?: throw EofException()
}

View File

@ -72,6 +72,8 @@ fun eval(_ast: MalType, _env: Env): MalType {
val obj = eval(ast.nth(1), env)
val metadata = eval(ast.nth(2), env)
return obj.with_meta(metadata)
} else if (first is MalSymbol && first.value == "atom") {
return MalAtom(eval(ast.nth(1), env))
} else {
val evaluated = eval_ast(ast, env) as ISeq
val firstEval = evaluated.first()
@ -173,10 +175,11 @@ fun main(args: Array<String>) {
}
while (true) {
val input = readline("user> ") ?: break
val input = readline("user> ")
try {
println(rep(input, repl_env))
} catch (e: EofException) {
break
} catch (e: MalContinue) {
} catch (e: MalException) {
println("Error: " + e.message)

View File

@ -235,6 +235,13 @@ class MalHashMap() : MalType {
}
}
class MalAtom(var value: MalType) : MalType {
override var metadata: MalType = NIL
override fun with_meta(meta: MalType): MalType = throw UnsupportedOperationException()
}
// TODO add truthiness checking
val NIL = MalConstant("nil")
val TRUE = MalConstant("true")