mirror of
https://github.com/kanaka/mal.git
synced 2024-11-10 12:47:45 +03:00
Finished metadata
This commit is contained in:
parent
700862df46
commit
8337e32c1c
@ -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()) }))
|
||||
)
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user