diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | cs/core.cs | 37 | ||||
| -rw-r--r-- | cs/reader.cs | 8 | ||||
| -rw-r--r-- | cs/types.cs | 47 | ||||
| -rw-r--r-- | tests/stepA_more.mal | 12 |
5 files changed, 83 insertions, 23 deletions
@@ -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 @@ -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 |
