aboutsummaryrefslogtreecommitdiffstats
path: root/tuplr.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'tuplr.hpp')
-rw-r--r--tuplr.hpp31
1 files changed, 27 insertions, 4 deletions
diff --git a/tuplr.hpp b/tuplr.hpp
index d6ceb4c..081428d 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -65,6 +65,9 @@ struct Exp : public std::vector< Exp<Atom> > {
Atom atom;
};
+template<typename Atom>
+extern ostream& operator<<(ostream& out, const Exp<Atom>& exp);
+
/// Lexical Address
struct LAddr {
LAddr(unsigned u=0, unsigned o=0) : up(u), over(o) {}
@@ -315,7 +318,15 @@ struct ACall : public ATuple {
/// Definition special form, e.g. "(def x 2)"
struct ADefinition : public ACall {
ADefinition(const SExp& e, const ATuple& t) : ACall(e, t) {}
- ASymbol* sym() const { return at(1)->to<ASymbol*>(); }
+ ASymbol* sym() const {
+ ASymbol* sym = at(1)->to<ASymbol*>();
+ if (!sym) {
+ ATuple* tup = at(1)->to<ATuple*>();
+ if (tup && !tup->empty())
+ return tup->at(0)->to<ASymbol*>();
+ }
+ return sym;
+ }
void constrain(TEnv& tenv, Constraints& c) const;
void lift(CEnv& cenv);
CValue compile(CEnv& cenv);
@@ -366,10 +377,12 @@ struct ACdrCall : public ACall {
/// Parse Time Environment (really just a symbol table)
struct PEnv : private map<const string, ASymbol*> {
- typedef AST* (*PF)(PEnv&, const SExp&, void*); // Parse Function
+ typedef AST* (*PF)(PEnv&, const SExp&, void*); ///< Parse Function
+ typedef SExp (*MF)(PEnv&, const SExp&); ///< Macro Function
struct Handler { Handler(PF f, void* a=0) : func(f), arg(a) {} PF func; void* arg; };
map<const string, Handler> aHandlers; ///< Atom parse functions
map<const string, Handler> lHandlers; ///< List parse functions
+ map<const string, MF> macros; ///< Macro functions
void reg(bool list, const string& s, const Handler& h) {
(list ? lHandlers : aHandlers).insert(make_pair(sym(s)->str(), h));
}
@@ -378,6 +391,13 @@ struct PEnv : private map<const string, ASymbol*> {
map<string, Handler>::const_iterator i = handlers.find(s);
return (i != handlers.end()) ? &i->second : NULL;
}
+ void defmac(const string& s, const MF f) {
+ macros.insert(make_pair(s, f));
+ }
+ MF mac(const string& s) const {
+ map<string, MF>::const_iterator i = macros.find(s);
+ return (i != macros.end()) ? i->second : NULL;
+ }
ASymbol* sym(const string& s, Cursor c=Cursor()) {
const const_iterator i = find(s);
return ((i != end())
@@ -395,9 +415,12 @@ struct PEnv : private map<const string, ASymbol*> {
if (exp.type == SExp::LIST) {
if (exp.empty()) throw Error("call to empty list", exp.loc);
if (exp.front().type == SExp::ATOM) {
- const PEnv::Handler* h = handler(true, exp.front().atom);
+ MF mf = mac(exp.front().atom);
+ SExp expanded = (mf ? mf(*this, exp) : exp);
+
+ const PEnv::Handler* h = handler(true, expanded.front().atom);
if (h)
- return h->func(*this, exp, h->arg);
+ return h->func(*this, expanded, h->arg);
}
return new ACall(exp, parseTuple(exp)); // Parse as regular call
} else if (isdigit(exp.atom[0])) {