aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--cs/core.cs37
-rw-r--r--cs/reader.cs8
-rw-r--r--cs/types.cs47
-rw-r--r--tests/stepA_more.mal12
5 files changed, 83 insertions, 23 deletions
diff --git a/Makefile b/Makefile
index bea1604..8ea60de 100644
--- a/Makefile
+++ b/Makefile
@@ -22,7 +22,7 @@ step8 = step8_macros
step9 = step9_interop
stepA = stepA_more
-EXCLUDE_TESTS = test^make^step5 test^mal^step0 test^mal^step5 test^mal^step9 test^java^step9
+EXCLUDE_TESTS = test^make^step5 test^mal^step0 test^mal^step5 test^mal^step9 test^java^step9 test^cs^step9
#
# Utility functions
diff --git a/cs/core.cs b/cs/core.cs
index f762075..f8bd7ff 100644
--- a/cs/core.cs
+++ b/cs/core.cs
@@ -8,6 +8,7 @@ using MalString = Mal.types.MalString;
using MalList = Mal.types.MalList;
using MalVector = Mal.types.MalVector;
using MalHashMap = Mal.types.MalHashMap;
+using MalAtom = Mal.types.MalAtom;
using MalFunction = Mal.types.MalFunction;
namespace Mal {
@@ -189,6 +190,34 @@ namespace Mal {
});
+ // Metadata functions
+ static MalFunction meta = new MalFunction(
+ a => a[0].getMeta());
+
+ static MalFunction with_meta = new MalFunction(
+ a => ((MalVal)a[0]).copy().setMeta(a[1]));
+
+
+ // Atom functions
+ static MalFunction atom_Q = new MalFunction(
+ a => a[0] is MalAtom ? True : False);
+
+ static MalFunction deref = new MalFunction(
+ a => ((MalAtom)a[0]).getValue());
+
+ static MalFunction reset_BANG = new MalFunction(
+ a => ((MalAtom)a[0]).setValue(a[1]));
+
+ static MalFunction swap_BANG = new MalFunction(
+ a => {
+ MalAtom atm = (MalAtom)a[0];
+ MalFunction f = (MalFunction)a[1];
+ var new_lst = new List<MalVal>();
+ new_lst.Add(atm.getValue());
+ new_lst.AddRange(((MalList)a.slice(2)).getValue());
+ return atm.setValue(f.apply(new MalList(new_lst)));
+ });
+
static public Dictionary<string, MalVal> ns =
@@ -237,6 +266,14 @@ namespace Mal {
{"conj", conj},
{"apply", apply},
{"map", map},
+
+ {"with-meta", with_meta},
+ {"meta", meta},
+ {"atom", new MalFunction(a => new MalAtom(a[0]))},
+ {"atom?", atom_Q},
+ {"deref", deref},
+ {"reset!", reset_BANG},
+ {"swap!", swap_BANG},
};
}
}
diff --git a/cs/reader.cs b/cs/reader.cs
index a8d09c6..8ab53da 100644
--- a/cs/reader.cs
+++ b/cs/reader.cs
@@ -125,6 +125,14 @@ namespace Mal {
rdr.next();
return new MalList(new MalSymbol("splice-unquote"),
read_form(rdr));
+ case "^": rdr.next();
+ MalVal meta = read_form(rdr);
+ return new MalList(new MalSymbol("with-meta"),
+ read_form(rdr),
+ meta);
+ case "@": rdr.next();
+ return new MalList(new MalSymbol("deref"),
+ read_form(rdr));
case "(": form = read_list(rdr, new MalList(), '(' , ')'); break;
case ")": throw new ParseError("unexpected ')'");
diff --git a/cs/types.cs b/cs/types.cs
index 642da7a..34985ad 100644
--- a/cs/types.cs
+++ b/cs/types.cs
@@ -65,17 +65,24 @@ namespace Mal {
public abstract class MalVal {
+ MalVal meta = Nil;
+ public virtual MalVal copy() {
+ return (MalVal)this.MemberwiseClone();
+ }
+
// Default is just to call regular toString()
public virtual string ToString(bool print_readably) {
return this.ToString();
}
+ public MalVal getMeta() { return meta; }
+ public MalVal setMeta(MalVal m) { meta = m; return this; }
public virtual bool list_Q() { return false; }
}
public class MalConstant : MalVal {
string value;
public MalConstant(string name) { value = name; }
- public MalConstant copy() { return this; }
+ public new MalConstant copy() { return this; }
public override string ToString() {
return value;
@@ -92,7 +99,7 @@ namespace Mal {
public class MalInteger : MalVal {
int value;
public MalInteger(int v) { value = v; }
- public MalInteger copy() { return this; }
+ public new MalInteger copy() { return this; }
public int getValue() { return value; }
public override string ToString() {
@@ -130,7 +137,7 @@ namespace Mal {
public class MalSymbol : MalVal {
string value;
public MalSymbol(string v) { value = v; }
- public MalSymbol copy() { return this; }
+ public new MalSymbol copy() { return this; }
public string getName() { return value; }
public override string ToString() {
@@ -144,7 +151,7 @@ namespace Mal {
public class MalString : MalVal {
string value;
public MalString(string v) { value = v; }
- public MalString copy() { return this; }
+ public new MalString copy() { return this; }
public string getValue() { return value; }
public override string ToString() {
@@ -177,10 +184,6 @@ namespace Mal {
conj_BANG(mvs);
}
- public MalList copy() {
- return (MalList)this.MemberwiseClone();
- }
-
public List<MalVal> getValue() { return value; }
public override bool list_Q() { return true; }
@@ -232,15 +235,6 @@ namespace Mal {
start = "[";
end = "]";
}
- /*
- public MalVector(MalVal[] mvs) : base(mvs.ToArray()) {
- start = "[";
- end = "]";
- }
- */
- public new MalVector copy() {
- return (MalVector)this.MemberwiseClone();
- }
public override bool list_Q() { return false; }
@@ -259,7 +253,7 @@ namespace Mal {
value = new Dictionary<String, MalVal>();
assoc_BANG(lst);
}
- public MalHashMap copy() {
+ public new MalHashMap copy() {
var new_self = (MalHashMap)this.MemberwiseClone();
new_self.value = new Dictionary<string, MalVal>(value);
return new_self;
@@ -289,6 +283,20 @@ namespace Mal {
}
}
+ public class MalAtom : MalVal {
+ MalVal value;
+ public MalAtom(MalVal value) { this.value = value; }
+ //public MalAtom copy() { return new MalAtom(value); }
+ public MalVal getValue() { return value; }
+ public MalVal setValue(MalVal value) { return this.value = value; }
+ public override string ToString() {
+ return "(atom " + printer._pr_str(value, true) + ")";
+ }
+ public override string ToString(Boolean print_readably) {
+ return "(atom " + printer._pr_str(value, print_readably) + ")";
+ }
+ }
+
public class MalFunction : MalVal {
Func<MalList, MalVal> fn = null;
MalVal ast = null;
@@ -305,9 +313,6 @@ namespace Mal {
this.env = env;
this.fparams = fparams;
}
- public MalFunction copy() {
- return (MalFunction)this.MemberwiseClone();
- }
public override string ToString() {
if (ast != null) {
diff --git a/tests/stepA_more.mal b/tests/stepA_more.mal
index abca165..456a092 100644
--- a/tests/stepA_more.mal
+++ b/tests/stepA_more.mal
@@ -249,6 +249,13 @@
(meta f-wm)
;=>{"abc" 1}
+(meta (with-meta f-wm "new_meta"))
+;=>"new_meta"
+
+(meta f-wm)
+;=>{"abc" 1}
+
+
(def! f-wm2 ^{"abc" 1} (fn* [a] (+ 1 a)))
(meta f-wm2)
;=>{"abc" 1}
@@ -289,8 +296,11 @@
(swap! a (fn* (a) (* 2 a)))
;=>12
+(swap! a (fn* (a b) (* a b)) 10)
+;=>120
+
(swap! a + 3)
-;=>15
+;=>123
;;
;; Testing read-str and eval