diff options
Diffstat (limited to 'tuplr.hpp')
-rw-r--r-- | tuplr.hpp | 31 |
1 files changed, 27 insertions, 4 deletions
@@ -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])) { |