Implemented step 8 (macros)
[jackhill/mal.git] / kotlin / src / mal / types.kt
1 package mal
2
3 import java.util.*
4
5 open class MalException(message: String) : Exception(message) { }
6 class MalContinue() : MalException("continue") { }
7 class MalReaderException(message: String) : MalException(message) { }
8 class MalPrinterException(message: String) : MalException(message) { }
9
10 interface MalType {
11 }
12
13 open class MalConstant(val value: String) : MalType {
14 override fun equals(other: Any?): Boolean = other is MalConstant && value.equals(other.value)
15 }
16
17 class MalInteger(val value: Int) : MalType {
18 operator fun plus(a: MalInteger): MalInteger = MalInteger(value + a.value)
19 operator fun minus(a: MalInteger): MalInteger = MalInteger(value - a.value)
20 operator fun times(a: MalInteger): MalInteger = MalInteger(value * a.value)
21 operator fun div(a: MalInteger): MalInteger = MalInteger(value / a.value)
22 operator fun compareTo(a: MalInteger): Int = value.compareTo(a.value)
23
24 override fun equals(other: Any?): Boolean = other is MalInteger && value.equals(other.value)
25 }
26
27 class MalSymbol(val value: String) : MalType {
28 override fun equals(other: Any?): Boolean = other is MalSymbol && value.equals(other.value)
29 }
30
31 open class MalString(value: String) : MalConstant(value)
32
33 class MalKeyword(value: String) : MalString("\u029E" + value)
34
35 interface ILambda : MalType {
36 fun apply(seq: ISeq): MalType
37 }
38
39 open class MalFunction(val lambda: (ISeq) -> MalType) : MalType, ILambda {
40 var is_macro: Boolean = false
41
42 override fun apply(seq: ISeq): MalType = lambda(seq)
43 }
44
45 class MalFnFunction(val ast: MalType, val params: Sequence<MalSymbol>, val env: Env, lambda: (ISeq) -> MalType) : MalFunction(lambda)
46
47 interface ISeq : MalType {
48 fun seq(): Sequence<MalType>
49 fun first(): MalType
50 fun rest(): ISeq
51 fun nth(n: Int): MalType
52 fun slice(fromIndex: Int, toIndex: Int): ISeq
53 }
54
55 interface IMutableSeq : ISeq {
56 fun conj_BANG(form: MalType)
57 }
58
59 class MalSequence(val elements : Sequence<MalType>) : MalType, ISeq {
60 override fun seq(): Sequence<MalType> = elements
61 override fun first(): MalType = elements.first()
62 override fun rest(): ISeq = MalSequence(elements.drop(1))
63 override fun nth(n: Int): MalType = elements.elementAt(n)
64
65 override fun slice(fromIndex: Int, toIndex: Int): MalList =
66 MalList(elements.toLinkedList().subList(fromIndex, toIndex))
67 }
68
69 class MalList(val elements: MutableList<MalType>) : MalType, IMutableSeq {
70 constructor() : this(LinkedList<MalType>())
71 constructor(s: ISeq) : this(s.seq().toLinkedList())
72
73 override fun seq(): Sequence<MalType> = elements.asSequence()
74 override fun first(): MalType = elements.first()
75 override fun rest(): ISeq = MalSequence(elements.drop(1).asSequence())
76 override fun nth(n: Int): MalType = elements.elementAt(n)
77
78 override fun conj_BANG(form: MalType) {
79 elements.add(form)
80 }
81
82 override fun equals(other: Any?): Boolean =
83 (other is ISeq)
84 && elements.size == other.seq().count() // TODO optimize counting?
85 && elements.asSequence().zip(other.seq()).all({ it -> it.first == it.second })
86
87 override fun slice(fromIndex: Int, toIndex: Int): MalList =
88 MalList(elements.subList(fromIndex, toIndex))
89 }
90
91 class MalVector(val elements: MutableList<MalType>) : MalType, IMutableSeq {
92 constructor() : this(ArrayList<MalType>())
93 constructor(s: ISeq) : this(s.seq().toArrayList())
94
95 override fun seq(): Sequence<MalType> = elements.asSequence()
96 override fun first(): MalType = elements.first()
97 override fun rest(): ISeq = MalSequence(elements.drop(1).asSequence())
98 override fun nth(n: Int): MalType = elements.elementAt(n)
99
100 override fun conj_BANG(form: MalType) {
101 elements.add(form)
102 }
103
104 override fun equals(other: Any?): Boolean =
105 (other is ISeq)
106 && elements.size == other.seq().count() // TODO optimize counting?
107 && elements.asSequence().zip(other.seq()).all({ it -> it.first == it.second })
108
109 override fun slice(fromIndex: Int, toIndex: Int): MalVector =
110 MalVector(elements.subList(fromIndex, toIndex))
111 }
112
113 class MalHashMap : MalType {
114 val elements = HashMap<MalString, MalType>()
115
116 fun assoc_BANG(key: MalString, value: MalType) = elements.put(key, value)
117 }
118
119 // TODO add truthiness checking
120 val NIL = MalConstant("nil")
121 val TRUE = MalConstant("true")
122 val FALSE = MalConstant("false")