From 8ec662aa4e6c7443cfca82e3085f71c5f944ec1a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 4 Jul 2009 01:06:07 +0000 Subject: Safer Exp. git-svn-id: http://svn.drobilla.net/resp/tuplr@179 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/tuplr.hpp | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'src/tuplr.hpp') diff --git a/src/tuplr.hpp b/src/tuplr.hpp index 5deff71..aaa0867 100644 --- a/src/tuplr.hpp +++ b/src/tuplr.hpp @@ -64,21 +64,30 @@ struct Error { /// Expression ::= Atom | (Expression*) template struct Exp : private std::vector< Exp > { - Exp(Cursor c) : type(LIST), loc(c) {} - Exp(Cursor c, const Atom& a) : type(ATOM), loc(c), atom(a) {} + Exp(Cursor c) : type(LIST), loc(c) {} + Exp(Cursor c, const Atom& a) : type(ATOM), loc(c), _atom(a) {} - void push_back(const Exp& exp) { vector< Exp >::push_back(exp); } + enum { ATOM, LIST } type; - bool empty() const { return vector< Exp >::empty(); } - const Exp& front() const { return vector< Exp >::front(); } + inline const Atom& atom() const { assert(type == ATOM); return _atom; } - typedef typename vector< Exp >::const_iterator const_iterator; - const_iterator begin() const { return vector< Exp >::begin(); } - const_iterator end() const { return vector< Exp >::end(); } +private: + typedef std::vector< Exp > ListImpl; - enum { ATOM, LIST } type; - Cursor loc; - Atom atom; +public: + void push_back(const Exp& exp) { assert(type == LIST); ListImpl::push_back(exp); } + + bool empty() const { assert(type == LIST); return ListImpl::empty(); } + const Exp& front() const { assert(type == LIST); return ListImpl::front(); } + + typedef typename ListImpl::const_iterator const_iterator; + const_iterator begin() const { assert(type == LIST); return ListImpl::begin(); } + const_iterator end() const { assert(type == LIST); return ListImpl::end(); } + + Cursor loc; + +private: + Atom _atom; }; template @@ -527,25 +536,25 @@ struct PEnv : private map { if (exp.type == SExp::LIST) { if (exp.empty()) throw Error(exp.loc, "call to empty list"); if (exp.front().type == SExp::ATOM) { - MF mf = mac(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); + const PEnv::Handler* h = handler(true, expanded.front().atom()); if (h) return h->func(*this, expanded, h->arg); } return new ACall(exp, parseTuple(exp)); // Parse as regular call - } else if (isdigit(exp.atom[0])) { - if (exp.atom.find('.') == string::npos) - return new ALiteral(strtol(exp.atom.c_str(), NULL, 10), exp.loc); + } else if (isdigit(exp.atom()[0])) { + if (exp.atom().find('.') == string::npos) + return new ALiteral(strtol(exp.atom().c_str(), NULL, 10), exp.loc); else - return new ALiteral(strtod(exp.atom.c_str(), NULL), exp.loc); + return new ALiteral(strtod(exp.atom().c_str(), NULL), exp.loc); } else { - const PEnv::Handler* h = handler(false, exp.atom); + const PEnv::Handler* h = handler(false, exp.atom()); if (h) return h->func(*this, exp, h->arg); } - return sym(exp.atom, exp.loc); + return sym(exp.atom(), exp.loc); } unsigned symID; }; -- cgit v1.2.1