aboutsummaryrefslogtreecommitdiffstats
path: root/tuplr.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'tuplr.hpp')
-rw-r--r--tuplr.hpp58
1 files changed, 33 insertions, 25 deletions
diff --git a/tuplr.hpp b/tuplr.hpp
index d769982..ba4f9a9 100644
--- a/tuplr.hpp
+++ b/tuplr.hpp
@@ -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(