2 using System
.Collections
.Generic
;
10 public class MalThrowable
: Exception
{
11 public MalThrowable() : base() { }
12 public MalThrowable(string msg
) : base(msg
) { }
14 public class MalError
: MalThrowable
{
15 public MalError(string msg
) :base(msg
) { }
17 public class MalContinue
: MalThrowable { }
19 // Thrown by throw function
20 public class MalException
: MalThrowable
{
23 public MalException(MalVal
value) {
26 public MalException(string value) :base(value) {
27 this.value = new MalString(value);
29 public MalVal
getValue() { return value; }
36 public static bool _equal_Q(MalVal a
, MalVal b
) {
37 Type ota
= a
.GetType(), otb
= b
.GetType();
39 (a
is MalList
&& b
is MalList
))) {
43 return ((MalInt
)a
).getValue() ==
44 ((MalInt
)b
).getValue();
45 } else if (a
is MalSymbol
) {
46 return ((MalSymbol
)a
).getName() ==
47 ((MalSymbol
)b
).getName();
48 } else if (a
is MalString
) {
49 return ((MalString
)a
).getValue() ==
50 ((MalString
)b
).getValue();
51 } else if (a
is MalList
) {
52 if (((MalList
)a
).size() != ((MalList
)b
).size()) {
55 for (int i
=0; i
<((MalList
)a
).size(); i
++) {
56 if (! _equal_Q(((MalList
)a
)[i
], ((MalList
)b
)[i
])) {
61 } else if (a
is MalHashMap
) {
62 var akeys
= ((MalHashMap
)a
).getValue().Keys
;
63 var bkeys
= ((MalHashMap
)b
).getValue().Keys
;
64 if (akeys
.Count
!= bkeys
.Count
) {
67 foreach (var k
in akeys
) {
68 if (!_equal_Q(((MalHashMap
)a
).getValue()[k
],
69 ((MalHashMap
)b
).getValue()[k
])) {
81 public abstract class MalVal
{
83 public virtual MalVal
copy() {
84 return (MalVal
)this.MemberwiseClone();
87 // Default is just to call regular toString()
88 public virtual string ToString(bool print_readably
) {
89 return this.ToString();
91 public MalVal
getMeta() { return meta; }
92 public MalVal
setMeta(MalVal m
) { meta = m; return this; }
93 public virtual bool list_Q() { return false; }
96 public class MalConstant
: MalVal
{
98 public MalConstant(string name
) { value = name; }
99 public new MalConstant
copy() { return this; }
101 public override string ToString() {
104 public override string ToString(bool print_readably
) {
109 static public MalConstant Nil
= new MalConstant("nil");
110 static public MalConstant True
= new MalConstant("true");
111 static public MalConstant False
= new MalConstant("false");
113 public class MalInt
: MalVal
{
115 public MalInt(Int64 v
) { value = v; }
116 public new MalInt
copy() { return this; }
118 public Int64
getValue() { return value; }
119 public override string ToString() {
120 return value.ToString();
122 public override string ToString(bool print_readably
) {
123 return value.ToString();
125 public static MalConstant
operator <(MalInt a
, MalInt b
) {
126 return a
.getValue() < b
.getValue() ? True
: False
;
128 public static MalConstant
operator <=(MalInt a
, MalInt b
) {
129 return a
.getValue() <= b
.getValue() ? True
: False
;
131 public static MalConstant
operator >(MalInt a
, MalInt b
) {
132 return a
.getValue() > b
.getValue() ? True
: False
;
134 public static MalConstant
operator >=(MalInt a
, MalInt b
) {
135 return a
.getValue() >= b
.getValue() ? True
: False
;
137 public static MalInt
operator +(MalInt a
, MalInt b
) {
138 return new MalInt(a
.getValue() + b
.getValue());
140 public static MalInt
operator -(MalInt a
, MalInt b
) {
141 return new MalInt(a
.getValue() - b
.getValue());
143 public static MalInt
operator *(MalInt a
, MalInt b
) {
144 return new MalInt(a
.getValue() * b
.getValue());
146 public static MalInt
operator /(MalInt a
, MalInt b
) {
147 return new MalInt(a
.getValue() / b
.getValue());
151 public class MalSymbol
: MalVal
{
153 public MalSymbol(string v
) { value = v; }
154 public MalSymbol(MalString v
) { value = v.getValue(); }
155 public new MalSymbol
copy() { return this; }
157 public string getName() { return value; }
158 public override string ToString() {
161 public override string ToString(bool print_readably
) {
166 public class MalString
: MalVal
{
168 public MalString(string v
) { value = v; }
169 public new MalString
copy() { return this; }
171 public string getValue() { return value; }
172 public override string ToString() {
173 return "\"" + value + "\"";
175 public override string ToString(bool print_readably
) {
176 if (value.Length
> 0 && value[0] == '\u029e') {
177 return ":" + value.Substring(1);
178 } else if (print_readably
) {
179 return "\"" + value.Replace("\\", "\\\\")
180 .Replace("\"", "\\\"")
181 .Replace("\n", "\\n") + "\"";
190 public class MalList
: MalVal
{
191 public string start
= "(", end
= ")";
194 value = new List
<MalVal
>();
196 public MalList(List
<MalVal
> val
) {
199 public MalList(params MalVal
[] mvs
) {
200 value = new List
<MalVal
>();
204 public List
<MalVal
> getValue() { return value; }
205 public override bool list_Q() { return true; }
207 public override string ToString() {
208 return start
+ printer
.join(value, " ", true) + end
;
210 public override string ToString(bool print_readably
) {
211 return start
+ printer
.join(value, " ", print_readably
) + end
;
214 public MalList
conj_BANG(params MalVal
[] mvs
) {
215 for (int i
= 0; i
< mvs
.Length
; i
++) {
221 public int size() { return value.Count; }
222 public MalVal
nth(int idx
) {
223 return value.Count
> idx
? value[idx
] : Nil
;
225 public MalVal
this[int idx
] {
226 get { return value.Count > idx ? value[idx] : Nil; }
228 public MalList
rest() {
230 return new MalList(value.GetRange(1, value.Count
-1));
232 return new MalList();
235 public virtual MalList
slice(int start
) {
236 return new MalList(value.GetRange(start
, value.Count
-start
));
238 public virtual MalList
slice(int start
, int end
) {
239 return new MalList(value.GetRange(start
, end
-start
));
244 public class MalVector
: MalList
{
245 // Same implementation except for instantiation methods
246 public MalVector() :base() {
250 public MalVector(List
<MalVal
> val
)
256 public override bool list_Q() { return false; }
258 public override MalList
slice(int start
, int end
) {
259 var val
= this.getValue();
260 return new MalVector(val
.GetRange(start
, val
.Count
-start
));
264 public class MalHashMap
: MalVal
{
265 Dictionary
<string, MalVal
> value;
266 public MalHashMap(Dictionary
<string, MalVal
> val
) {
269 public MalHashMap(MalList lst
) {
270 value = new Dictionary
<String
, MalVal
>();
273 public new MalHashMap
copy() {
274 var new_self
= (MalHashMap
)this.MemberwiseClone();
275 new_self
.value = new Dictionary
<string, MalVal
>(value);
279 public Dictionary
<string, MalVal
> getValue() { return value; }
281 public override string ToString() {
282 return "{" + printer.join(value, " ", true) + "}";
284 public override string ToString(bool print_readably
) {
285 return "{" + printer.join(value, " ", print_readably) + "}";
288 public MalHashMap
assoc_BANG(MalList lst
) {
289 for (int i
=0; i
<lst
.size(); i
+=2) {
290 value[((MalString
)lst
[i
]).getValue()] = lst
[i
+1];
295 public MalHashMap
dissoc_BANG(MalList lst
) {
296 for (int i
=0; i
<lst
.size(); i
++) {
297 value.Remove(((MalString
)lst
[i
]).getValue());
303 public class MalAtom
: MalVal
{
305 public MalAtom(MalVal
value) { this.value = value; }
306 //public MalAtom copy() { return new MalAtom(value); }
307 public MalVal
getValue() { return value; }
308 public MalVal
setValue(MalVal
value) { return this.value = value; }
309 public override string ToString() {
310 return "(atom " + printer
._pr_str(value, true) + ")";
312 public override string ToString(Boolean print_readably
) {
313 return "(atom " + printer
._pr_str(value, print_readably
) + ")";
317 public class MalFunc
: MalVal
{
318 Func
<MalList
, MalVal
> fn
= null;
320 Mal
.env
.Env env
= null;
323 public MalFunc(Func
<MalList
, MalVal
> fn
) {
326 public MalFunc(MalVal ast
, Mal
.env
.Env env
, MalList fparams
,
327 Func
<MalList
, MalVal
> fn
) {
331 this.fparams
= fparams
;
334 public override string ToString() {
336 return "<fn* " + Mal
.printer
._pr_str(fparams
,true) +
337 " " + Mal
.printer
._pr_str(ast
, true) + ">";
339 return "<builtin_function " + fn
.ToString() + ">";
343 public MalVal
apply(MalList args
) {
347 public MalVal
getAst() { return ast; }
348 public Mal
.env
.Env
getEnv() { return env; }
349 public MalList
getFParams() { return fparams; }
350 public Mal
.env
.Env
genEnv(MalList args
) {
351 return new Mal
.env
.Env(env
, fparams
, args
);
353 public bool isMacro() { return macro; }
354 public void setMacro() { macro = true; }