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

Finished metadata

This commit is contained in:
Javier Fernandez-Ivern 2015-10-26 13:31:36 -05:00
parent 700862df46
commit 8337e32c1c
3 changed files with 105 additions and 11 deletions

View File

@ -162,7 +162,7 @@ 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() as? MalFunction)?.metadata ?: NIL })),
Pair(MalSymbol("meta"), MalFunction({ a: ISeq -> a.first().metadata })),
Pair(MalSymbol("conj"), MalFunction({ a: ISeq -> (a.first() as ISeq).conj(a.rest()) }))
)

View File

@ -69,9 +69,9 @@ fun eval(_ast: MalType, _env: Env): MalType {
return eval(catchBody, catchEnv)
}
} else if (first is MalSymbol && first.value == "with-meta") {
val function = eval(ast.nth(1), env) as MalFunction
function.metadata = eval(ast.nth(2), env)
return function
val obj = eval(ast.nth(1), env)
val metadata = eval(ast.nth(2), env)
return obj.with_meta(metadata)
} else {
val evaluated = eval_ast(ast, env) as ISeq
val firstEval = evaluated.first()

View File

@ -3,22 +3,46 @@ package mal
import java.util.*
// TODO clean up exception hierarchy
open class MalException(message: String?) : Exception(message), MalType { }
open class MalException(message: String?) : Exception(message), MalType {
override var metadata: MalType = NIL
override fun with_meta(meta: MalType): MalType {
val exception = MalException(message)
exception.metadata = meta
return exception
}
}
class MalContinue() : MalException("continue") { }
class MalReaderException(message: String) : MalException(message) { }
class MalPrinterException(message: String) : MalException(message) { }
class MalCoreException(message: String, val value: MalType) : MalException(message) // TODO rename
class MalCoreException(message: String, val value: MalType) : MalException(message) { // TODO rename
override fun with_meta(meta: MalType): MalType {
val exception = MalCoreException(message as String, value)
exception.metadata = meta
return exception
}
}
interface MalType {
var metadata: MalType // TODO make immutable
fun with_meta(meta: MalType): MalType
}
open class MalConstant(val value: String) : MalType {
override var metadata: MalType = NIL
override fun equals(other: Any?): Boolean = other is MalConstant && value.equals(other.value)
override fun hashCode(): Int = value.hashCode()
override fun with_meta(meta: MalType): MalType {
val obj = MalConstant(value)
obj.metadata = meta
return obj
}
}
class MalInteger(val value: Int) : MalType {
override var metadata: MalType = NIL
operator fun plus(a: MalInteger): MalInteger = MalInteger(value + a.value)
operator fun minus(a: MalInteger): MalInteger = MalInteger(value - a.value)
operator fun times(a: MalInteger): MalInteger = MalInteger(value * a.value)
@ -26,15 +50,41 @@ class MalInteger(val value: Int) : MalType {
operator fun compareTo(a: MalInteger): Int = value.compareTo(a.value)
override fun equals(other: Any?): Boolean = other is MalInteger && value.equals(other.value)
override fun with_meta(meta: MalType): MalType {
val obj = MalInteger(value)
obj.metadata = meta
return obj
}
}
class MalSymbol(val value: String) : MalType {
override var metadata: MalType = NIL
override fun equals(other: Any?): Boolean = other is MalSymbol && value.equals(other.value)
override fun with_meta(meta: MalType): MalType {
val obj = MalSymbol(value)
obj.metadata = meta
return obj
}
}
open class MalString(value: String) : MalConstant(value)
open class MalString(value: String) : MalConstant(value) {
override fun with_meta(meta: MalType): MalType {
val obj = MalString(value)
obj.metadata = meta
return obj
}
}
class MalKeyword(value: String) : MalString("\u029E" + value)
class MalKeyword(value: String) : MalString("\u029E" + value) {
override fun with_meta(meta: MalType): MalType {
val obj = MalKeyword(value)
obj.metadata = meta
return obj
}
}
interface ILambda : MalType {
fun apply(seq: ISeq): MalType
@ -43,12 +93,24 @@ interface ILambda : MalType {
open class MalFunction(val lambda: (ISeq) -> MalType) : MalType, ILambda {
// TODO make this stuff immutable?
var is_macro: Boolean = false
var metadata: MalType = NIL
override var metadata: MalType = NIL
override fun apply(seq: ISeq): MalType = lambda(seq)
override fun with_meta(meta: MalType): MalType {
val obj = MalFunction(lambda)
obj.metadata = meta
return obj
}
}
class MalFnFunction(val ast: MalType, val params: Sequence<MalSymbol>, val env: Env, lambda: (ISeq) -> MalType) : MalFunction(lambda)
class MalFnFunction(val ast: MalType, val params: Sequence<MalSymbol>, val env: Env, lambda: (ISeq) -> MalType) : MalFunction(lambda) {
override fun with_meta(meta: MalType): MalType {
val obj = MalFnFunction(ast, params, env, lambda)
obj.metadata = meta
return obj
}
}
interface ISeq : MalType {
fun seq(): Sequence<MalType>
@ -65,6 +127,8 @@ interface IMutableSeq : ISeq {
}
class MalSequence(val elements : Sequence<MalType>) : MalType, ISeq {
override var metadata: MalType = NIL
override fun seq(): Sequence<MalType> = elements
override fun first(): MalType = elements.first()
override fun rest(): ISeq = MalSequence(elements.drop(1))
@ -74,9 +138,17 @@ class MalSequence(val elements : Sequence<MalType>) : MalType, ISeq {
MalList(elements.toLinkedList().subList(fromIndex, toIndex))
override fun conj(s: ISeq): ISeq = MalList(elements.toLinkedList()).conj(s)
override fun with_meta(meta: MalType): MalType {
val obj = MalSequence(elements)
obj.metadata = meta
return obj
}
}
class MalList(val elements: MutableList<MalType>) : MalType, IMutableSeq {
override var metadata: MalType = NIL
constructor() : this(LinkedList<MalType>())
constructor(s: ISeq) : this(s.seq().toLinkedList())
@ -102,9 +174,17 @@ class MalList(val elements: MutableList<MalType>) : MalType, IMutableSeq {
s.seq().forEach({ it -> list.addFirst(it) })
return MalList(list)
}
override fun with_meta(meta: MalType): MalType {
val obj = MalList(elements)
obj.metadata = meta
return obj
}
}
class MalVector(val elements: MutableList<MalType>) : MalType, IMutableSeq {
override var metadata: MalType = NIL
constructor() : this(ArrayList<MalType>())
constructor(s: ISeq) : this(s.seq().toArrayList())
@ -126,9 +206,17 @@ class MalVector(val elements: MutableList<MalType>) : MalType, IMutableSeq {
MalVector(elements.subList(fromIndex, toIndex))
override fun conj(s: ISeq): ISeq = MalVector(elements.plus(s.seq()).toArrayList())
override fun with_meta(meta: MalType): MalType {
val obj = MalVector(elements)
obj.metadata = meta
return obj
}
}
class MalHashMap() : MalType {
override var metadata: MalType = NIL
val elements = HashMap<MalString, MalType>()
constructor(other: MalHashMap) : this() {
@ -139,6 +227,12 @@ class MalHashMap() : MalType {
fun dissoc_BANG(key: MalString) {
elements.remove(key)
}
override fun with_meta(meta: MalType): MalType {
val obj = MalHashMap(this)
obj.metadata = meta
return obj
}
}
// TODO add truthiness checking