diff options
Diffstat (limited to 'tuplr.hpp')
-rw-r--r-- | tuplr.hpp | 58 |
1 files changed, 33 insertions, 25 deletions
@@ -31,6 +31,7 @@ typedef const void* CType; ///< Compiled type (opaque) typedef void* CFunction; ///< Compiled function (opaque) struct CEngine; ///< Backend data (opaque) +struct CArg; ///< Parser function argument (opaque) #define FOREACH(IT, i, c) for (IT i = (c).begin(); i != (c).end(); ++i) @@ -55,8 +56,6 @@ struct Error { Cursor loc; }; -struct CArg { CArg(int o=0, int a=0) : op(o), arg(a) {} int op; int arg; }; - template<typename Atom> struct Exp { // ::= Atom | (Exp*) Exp(Cursor c) : type(LIST), loc(c) {} @@ -245,7 +244,7 @@ struct ASTCall : public ASTTuple { /// Definition special form, e.g. "(def x 2)" struct ASTDefinition : public ASTCall { - ASTDefinition(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTDefinition(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; void lift(CEnv& cenv); CValue compile(CEnv& cenv); @@ -253,22 +252,22 @@ struct ASTDefinition : public ASTCall { /// Conditional special form, e.g. "(if cond thenexp elseexp)" struct ASTIf : public ASTCall { - ASTIf(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTIf(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); }; /// Primitive (builtin arithmetic function), e.g. "(+ 2 3)" struct ASTPrimitive : public ASTCall { - ASTPrimitive(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t), arg(ca) {} + ASTPrimitive(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t), arg(ca) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); - CArg arg; + CArg* arg; }; /// Cons special form, e.g. "(cons 1 2)" struct ASTConsCall : public ASTCall { - ASTConsCall(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTConsCall(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} AType* functionType(CEnv& cenv); void constrain(TEnv& tenv) const; void lift(CEnv& cenv); @@ -278,14 +277,14 @@ struct ASTConsCall : public ASTCall { /// Car special form, e.g. "(car p)" struct ASTCarCall : public ASTCall { - ASTCarCall(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTCarCall(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); }; /// Cdr special form, e.g. "(cdr p)" struct ASTCdrCall : public ASTCall { - ASTCdrCall(const SExp& e, const ASTTuple& t, CArg ca=CArg()) : ASTCall(e, t) {} + ASTCdrCall(const SExp& e, const ASTTuple& t, CArg* ca=0) : ASTCall(e, t) {} void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); }; @@ -297,15 +296,17 @@ struct ASTCdrCall : public ASTCall { // Parse Time Environment (symbol table) struct PEnv : private map<const string, ASTSymbol*> { - typedef AST* (*PF)(PEnv&, const SExp&, CArg); // Parse Function - struct Parser { Parser(PF f, CArg a=CArg()) : func(f), arg(a) {} PF func; CArg arg; }; - map<string, Parser> parsers; - void reg(const string& s, const Parser& p) { - parsers.insert(make_pair(sym(s)->str(), p)); + typedef AST* (*PF)(PEnv&, const SExp&, CArg*); // Parse Function + struct Handler { Handler(PF f, CArg* a=0) : func(f), arg(a) {} PF func; CArg* arg; }; + map<const string, Handler> aHandlers; ///< Atom parse functions + map<const string, Handler> lHandlers; ///< List parse functions + void reg(bool list, const string& s, const Handler& h) { + (list ? lHandlers : aHandlers).insert(make_pair(sym(s)->str(), h)); } - const Parser* parser(const string& s) const { - map<string, Parser>::const_iterator i = parsers.find(s); - return (i != parsers.end()) ? &i->second : NULL; + const Handler* handler(bool list, const string& s) const { + const map<const string, Handler>& handlers = list ? lHandlers : aHandlers; + map<string, Handler>::const_iterator i = handlers.find(s); + return (i != handlers.end()) ? &i->second : NULL; } ASTSymbol* sym(const string& s, Cursor c=Cursor()) { const const_iterator i = find(s); @@ -334,8 +335,8 @@ parseExpression(PEnv& penv, const SExp& exp) if (exp.type == SExp::LIST) { if (exp.list.empty()) throw Error("call to empty list", exp.loc); if (exp.list.front().type == SExp::ATOM) { - const PEnv::Parser* handler = penv.parser(exp.list.front().atom); - if (handler) // Dispatch to parse function + const PEnv::Handler* handler = penv.handler(true, exp.list.front().atom); + if (handler) // Dispatch to list parse function return handler->func(penv, exp, handler->arg); } return new ASTCall(exp, pmap(penv, exp.list)); // Parse as regular call @@ -344,23 +345,30 @@ parseExpression(PEnv& penv, const SExp& exp) return new ASTLiteral<int32_t>(strtol(exp.atom.c_str(), NULL, 10)); else return new ASTLiteral<float>(strtod(exp.atom.c_str(), NULL)); - } else if (exp.atom == "true") { - return new ASTLiteral<bool>(true); - } else if (exp.atom == "false") { - return new ASTLiteral<bool>(false); + } else { + const PEnv::Handler* handler = penv.handler(false, exp.atom); + if (handler) // Dispatch to atom parse function + return handler->func(penv, exp, handler->arg); } return penv.sym(exp.atom, exp.loc); } template<typename C> inline AST* -parseAST(PEnv& penv, const SExp& exp, CArg arg=CArg()) +parseCall(PEnv& penv, const SExp& exp, CArg* arg) { return new C(exp, pmap(penv, exp.list), arg); } +template<typename T> +inline AST* +parseLiteral(PEnv& penv, const SExp& exp, CArg* arg) +{ + return new ASTLiteral<T>(*reinterpret_cast<T*>(arg)); +} + inline AST* -parseFn(PEnv& penv, const SExp& exp, CArg arg) +parseFn(PEnv& penv, const SExp& exp, CArg* arg) { SExp::List::const_iterator a = exp.list.begin(); ++a; return new ASTClosure( |