aboutsummaryrefslogtreecommitdiffstats
path: root/tuplr.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2009-06-18 20:22:10 +0000
committerDavid Robillard <d@drobilla.net>2009-06-18 20:22:10 +0000
commit545b524bda45f2087ac92cf58f6eaa78499332cf (patch)
tree71043cffd2b64da7420d2840a6be666b9fef037a /tuplr.cpp
parent4e34e229beb12164ea49b1121785dc71eb7c3566 (diff)
downloadresp-545b524bda45f2087ac92cf58f6eaa78499332cf.tar.gz
resp-545b524bda45f2087ac92cf58f6eaa78499332cf.tar.bz2
resp-545b524bda45f2087ac92cf58f6eaa78499332cf.zip
Primitive internal macro system (for implementing sugar).
(def (f x) ...) sugar. git-svn-id: http://svn.drobilla.net/resp/tuplr@119 ad02d1e2-f140-0410-9f75-f8b11f17cedd
Diffstat (limited to 'tuplr.cpp')
-rw-r--r--tuplr.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/tuplr.cpp b/tuplr.cpp
index 6e0571e..c13b9bc 100644
--- a/tuplr.cpp
+++ b/tuplr.cpp
@@ -28,6 +28,24 @@ using boost::format;
Funcs AConsCall::funcs;
+template<typename Atom>
+ostream&
+operator<<(ostream& out, const Exp<Atom>& exp)
+{
+ switch (exp.type) {
+ case Exp<Atom>::ATOM:
+ out << exp.atom;
+ break;
+ case Exp<Atom>::LIST:
+ out << "(";
+ for (size_t i = 0; i != exp.size(); ++i)
+ out << exp.at(i) << ((i != exp.size() - 1) ? " " : "");
+ out << ")";
+ break;
+ }
+ return out;
+}
+
/***************************************************************************
* Lexer *
***************************************************************************/
@@ -103,6 +121,34 @@ readExpression(Cursor& cur, istream& in)
/***************************************************************************
+ * Macro Functions *
+ ***************************************************************************/
+
+inline SExp
+macDef(PEnv& penv, const SExp& exp)
+{
+ if (exp.size() != 3) throw Error("`def' requires exactly 2 arguments", exp.loc);
+ if (exp.at(1).type == SExp::ATOM) {
+ return exp;
+ } else {
+ // (def (f x) y) => (def f (fn (x) y))
+ SExp argsExp(exp.loc);
+ for (size_t i = 1; i < exp.at(1).size(); ++i)
+ argsExp.push_back(exp.at(1).at(i));
+ SExp fnExp(exp.at(2).loc);
+ fnExp.push_back(SExp(exp.at(2).loc, "fn"));
+ fnExp.push_back(argsExp);
+ fnExp.push_back(exp.at(2));
+ SExp ret(exp.loc);
+ ret.push_back(exp.at(0));
+ ret.push_back(exp.at(1).at(0));
+ ret.push_back(fnExp);
+ return ret;
+ }
+}
+
+
+/***************************************************************************
* Parser Functions *
***************************************************************************/
@@ -153,6 +199,9 @@ initLang(PEnv& penv, TEnv& tenv)
penv.reg(false, "#t", PEnv::Handler(parseLiteral<bool>, &trueVal));
penv.reg(false, "#f", PEnv::Handler(parseLiteral<bool>, &falseVal));
+ // Macros
+ penv.defmac("def", macDef);
+
// Special forms
penv.reg(true, "fn", PEnv::Handler(parseFn));
penv.reg(true, "if", PEnv::Handler(parseCall<AIf>));