From 7164809b051050fb4f4877793b9739b6177bcab1 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 4 Jul 2009 05:02:09 +0000 Subject: Ditch Exp type and use AST even at lex time. git-svn-id: http://svn.drobilla.net/resp/tuplr@182 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/cps.cpp | 2 +- src/lex.cpp | 26 ++++++++-------- src/parse.cpp | 69 ++++++++++++++++++++++------------------- src/pprint.cpp | 4 +++ src/repl.cpp | 12 +++---- src/tuplr.cpp | 2 +- src/tuplr.hpp | 98 ++++++++++++++++++++++------------------------------------ 7 files changed, 99 insertions(+), 114 deletions(-) diff --git a/src/cps.cpp b/src/cps.cpp index 75b771f..b8b6b62 100644 --- a/src/cps.cpp +++ b/src/cps.cpp @@ -33,7 +33,7 @@ AST::cps(TEnv& tenv, AST* cont) AST* AFn::cps(TEnv& tenv, AST* cont) { - ATuple* copyProt = new ATuple(prot()->loc, *prot()); + ATuple* copyProt = new ATuple(*prot()); ASymbol* contArg = tenv.penv.gensym("_k"); copyProt->push_back(contArg); AFn* copy = tup(loc, tenv.penv.sym("fn"), copyProt, 0); diff --git a/src/lex.cpp b/src/lex.cpp index bfdd9c1..b5c89e9 100644 --- a/src/lex.cpp +++ b/src/lex.cpp @@ -16,7 +16,7 @@ */ /** @file - * @brief Lexing (build a SExp from a string) + * @brief Lexing (build an unparsed textual AST from a string) */ #include @@ -36,19 +36,19 @@ readChar(Cursor& cur, istream& in) } /// Read an expression from @a in -SExp +AST* readExpression(Cursor& cur, istream& in) { -#define PUSH(s, t) { if (t != "") { s.top().push_back(SExp(loc, new AString(loc, t))); t = ""; } } -#define YIELD(s, t) { if (s.empty()) { return SExp(loc, new AString(loc, t)); } else PUSH(s, t) } - stack stk; - string tok; - Cursor loc; // start of tok +#define PUSH(s, t) { if (t != "") { s.top()->push_back(new AString(loc, t)); t = ""; } } +#define YIELD(s, t) { if (s.empty()) { return new AString(loc, t); } else PUSH(s, t) } + stack stk; + string tok; + Cursor loc; // start of tok while (int c = readChar(cur, in)) { switch (c) { case EOF: THROW_IF(!stk.empty(), cur, "unexpected end of file") - return SExp(cur); + return new ATuple(cur); case ';': while ((c = readChar(cur, in)) != '\n') {} case '\n': case ' ': case '\t': @@ -60,7 +60,7 @@ readExpression(Cursor& cur, istream& in) YIELD(stk, tok + '"'); break; case '(': - stk.push(SExp(cur)); + stk.push(new ATuple(cur)); break; case ')': switch (stk.size()) { @@ -71,9 +71,9 @@ readExpression(Cursor& cur, istream& in) return stk.top(); default: PUSH(stk, tok); - SExp l = stk.top(); + ATuple* l = stk.top(); stk.pop(); - stk.top().push_back(l); + stk.top()->push_back(l); } break; case '#': @@ -87,9 +87,9 @@ readExpression(Cursor& cur, istream& in) } } switch (stk.size()) { - case 0: return SExp(loc, new AString(loc, tok)); + case 0: return new AString(loc, tok); case 1: return stk.top(); default: throw Error(cur, "missing `)'"); } - return SExp(cur); + return new ATuple(cur); } diff --git a/src/parse.cpp b/src/parse.cpp index a065e64..1f16bfe 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -16,7 +16,7 @@ */ /** @file - * @brief Parsing (build an AST from a SExp) + * @brief Parsing (build a code AST from a textual AST) */ #include "tuplr.hpp" @@ -28,31 +28,34 @@ using namespace std; * Macro Functions * ***************************************************************************/ -inline SExp -macDef(PEnv& penv, const SExp& exp) +inline AST* +macDef(PEnv& penv, const AST* exp) { - SExp::const_iterator i = exp.begin(); - THROW_IF(i == exp.end(), exp.loc, "Unexpected end of `def' macro call"); - const SExp& name = *(++i); - THROW_IF(i == exp.end(), name.loc, "Unexpected end of `def' macro call"); - if (name.type == SExp::ATOM) { - return exp; + const ATuple* tup = exp->to(); + ATuple::const_iterator i = tup->begin(); + THROW_IF(i == tup->end(), tup->loc, "Unexpected end of `def' macro call"); + const AST* name = *(++i); + THROW_IF(i == tup->end(), name->loc, "Unexpected end of `def' macro call"); + if (name->to()) { + return const_cast(exp); } else { + const ATuple* pat = name->to(); + name = pat->at(0); // (def (f x) y) => (def f (fn (x) y)) - SExp argsExp(exp.loc); - SExp::const_iterator j = name.begin(); - for (++j; j != name.end(); ++j) - argsExp.push_back(*j); - const SExp& body = *(++i); - SExp fnExp(body.loc); - fnExp.push_back(SExp(body.loc, new AString(body.loc, "fn"))); - fnExp.push_back(argsExp); - for (; i != exp.end(); ++i) - fnExp.push_back(*i); - SExp ret(exp.loc); - ret.push_back(exp.front()); - ret.push_back(name.front()); - ret.push_back(fnExp); + ATuple* argsExp = new ATuple(exp->loc); + ATuple::const_iterator j = pat->begin(); + for (++j; j != pat->end(); ++j) + argsExp->push_back(*j); + const AST* body = *(++i); + ATuple* fnExp = new ATuple(body->loc); + fnExp->push_back(new AString(exp->loc, "fn")); + fnExp->push_back(argsExp); + for (; i != tup->end(); ++i) + fnExp->push_back(*i); + ATuple* ret = new ATuple(exp->loc); + ret->push_back(const_cast(tup->front())); + ret->push_back(const_cast(name)); + ret->push_back(fnExp); return ret; } } @@ -64,25 +67,27 @@ macDef(PEnv& penv, const SExp& exp) template inline AST* -parseCall(PEnv& penv, const SExp& exp, void* arg) +parseCall(PEnv& penv, const AST* exp, void* arg) { - return new C(exp, penv.parseTuple(exp)); + return new C(penv.parseTuple(exp->to())); } template inline AST* -parseLiteral(PEnv& penv, const SExp& exp, void* arg) +parseLiteral(PEnv& penv, const AST* exp, void* arg) { - return new ALiteral(*reinterpret_cast(arg), exp.loc); + return new ALiteral(*reinterpret_cast(arg), exp->loc); } inline AST* -parseFn(PEnv& penv, const SExp& exp, void* arg) +parseFn(PEnv& penv, const AST* exp, void* arg) { - SExp::const_iterator a = exp.begin(); - THROW_IF(++a == exp.end(), exp.loc, "Unexpected end of `fn' form"); - AFn* ret = tup(exp.loc, penv.sym("fn"), new ATuple(penv.parseTuple(*a++)), 0); - while (a != exp.end()) + const ATuple* texp = exp->to(); + ATuple::const_iterator a = texp->begin(); + THROW_IF(++a == texp->end(), exp->loc, "Unexpected end of `fn' form"); + ATuple* prot = penv.parseTuple((*a++)->to()); + AFn* ret = tup(exp->loc, penv.sym("fn"), prot, 0); + while (a != texp->end()) ret->push_back(penv.parse(*a++)); return ret; } diff --git a/src/pprint.cpp b/src/pprint.cpp index cb507b1..ddbd403 100644 --- a/src/pprint.cpp +++ b/src/pprint.cpp @@ -36,6 +36,10 @@ operator<<(ostream& out, const AST* ast) if (blit) return out << (blit->val ? "#t" : "#f"); + const AString* str = ast->to(); + if (str) + return out << *str; + const ASymbol* sym = ast->to(); if (sym) return out << sym->cppstr; diff --git a/src/repl.cpp b/src/repl.cpp index 1ec1834..bca6037 100644 --- a/src/repl.cpp +++ b/src/repl.cpp @@ -32,12 +32,12 @@ eval(CEnv& cenv, const string& name, istream& is) { AST* result = NULL; AType* resultType = NULL; - list< pair > exprs; + list< pair > exprs; Cursor cursor(name); try { while (true) { - SExp exp = readExpression(cursor, is); - if (exp.type == SExp::LIST && exp.empty()) + AST* exp = readExpression(cursor, is); + if (exp->to() && exp->to()->empty()) break; result = cenv.penv.parse(exp); // Parse input @@ -71,7 +71,7 @@ eval(CEnv& cenv, const string& name, istream& is) CFunction f = cenv.engine()->startFunction(cenv, "main", resultType, ATuple(cursor)); // Compile all expressions into it - for (list< pair >::const_iterator i = exprs.begin(); i != exprs.end(); ++i) + for (list< pair >::const_iterator i = exprs.begin(); i != exprs.end(); ++i) val = cenv.compile(i->second); // Finish and call it @@ -102,8 +102,8 @@ repl(CEnv& cenv) Cursor cursor("(stdin)"); try { - SExp exp = readExpression(cursor, std::cin); - if (exp.type == SExp::LIST && exp.empty()) + AST* exp = readExpression(cursor, std::cin); + if (exp->to() && exp->to()->empty()) break; AST* body = cenv.penv.parse(exp); // Parse input diff --git a/src/tuplr.cpp b/src/tuplr.cpp index e9bcae9..f8cc246 100644 --- a/src/tuplr.cpp +++ b/src/tuplr.cpp @@ -92,7 +92,7 @@ main(int argc, char** argv) ifstream is(files.front().c_str()); if (is.good()) { Cursor loc; - SExp exp = readExpression(loc, is); + AST* exp = readExpression(loc, is); AST* ast = penv.parse(exp); pprint(cout, ast); } diff --git a/src/tuplr.hpp b/src/tuplr.hpp index 087ce77..54d7098 100644 --- a/src/tuplr.hpp +++ b/src/tuplr.hpp @@ -62,37 +62,6 @@ struct Error { string msg; }; -/// Expression ::= Atom | (Expression*) -template -struct Exp { - typedef std::vector< Exp > Vec; - - Exp(Cursor c) : type(LIST), loc(c), _vec(new Vec()) {} - Exp(Cursor c, const Atom& a) : type(ATOM), loc(c), _atom(a) {} - - enum { ATOM, LIST } type; - - inline const Atom& atom() const { assert(type == ATOM); return _atom; } - - void push_back(const Exp& exp) { assert(type == LIST); _vec->push_back(exp); } - - bool empty() const { assert(type == LIST); return _vec->empty(); } - const Exp& front() const { assert(type == LIST); return _vec->front(); } - - typedef typename Vec::const_iterator const_iterator; - const_iterator begin() const { assert(type == LIST); return _vec->begin(); } - const_iterator end() const { assert(type == LIST); return _vec->end(); } - - Cursor loc; - -private: - Atom _atom; - Vec* _vec; -}; - -template -extern ostream& operator<<(ostream& out, const Exp& exp); - /// Lexical Address struct LAddr { LAddr(unsigned u=0, unsigned o=0) : up(u), over(o) {} @@ -143,10 +112,9 @@ struct Env : public list< vector< pair > > { * Lexer: Text (istream) -> S-Expressions (SExp) * ***************************************************************************/ -class AString; -typedef Exp SExp; ///< Textual S-Expression +class AST; +AST* readExpression(Cursor& cur, std::istream& in); -SExp readExpression(Cursor& cur, std::istream& in); /*************************************************************************** @@ -290,9 +258,9 @@ private: /// Tuple (heterogeneous sequence of fixed length), e.g. "(a b c)" struct ATuple : public AST { ATuple(Cursor c) : AST(c), _len(0), _vec(0) {} - ATuple(Cursor c, const ATuple& t) : AST(c), _len(t._len) { + ATuple(const ATuple& exp) : AST(exp.loc), _len(exp._len) { _vec = (AST**)malloc(sizeof(AST*) * _len); - memcpy(_vec, t._vec, sizeof(AST*) * _len); + memcpy(_vec, exp._vec, sizeof(AST*) * _len); } ATuple(Cursor c, AST* ast, va_list args) : AST(c), _len(0), _vec(0) { if (!ast) return; @@ -306,6 +274,7 @@ struct ATuple : public AST { newvec[_len++] = ast; _vec = newvec; } + const AST* front() const { assert(_len > 0); return _vec[0]; } const AST* at(size_t i) const { assert(i < _len); return _vec[i]; } AST*& at(size_t i) { assert(i < _len); return _vec[i]; } size_t size() const { return _len; } @@ -456,7 +425,7 @@ struct AFn : public ATuple { /// Function call/application, e.g. "(func arg1 arg2)" struct ACall : public ATuple { - ACall(const SExp& e, const ATuple& t) : ATuple(e.loc, t) {} + ACall(const ATuple* exp) : ATuple(*exp) {} ACall(Cursor c, AST* ast, va_list args) : ATuple(c, ast, args) {} void constrain(TEnv& tenv, Constraints& c) const; AST* cps(TEnv& tenv, AST* cont); @@ -466,7 +435,7 @@ struct ACall : public ATuple { /// Definition special form, e.g. "(def x 2)" struct ADef : public ACall { - ADef(const SExp& e, const ATuple& t) : ACall(e, t) {} + ADef(const ATuple* exp) : ACall(exp) {} ADef(Cursor c, AST* ast, va_list args) : ACall(c, ast, args) {} const ASymbol* sym() const { const ASymbol* sym = at(1)->to(); @@ -485,7 +454,7 @@ struct ADef : public ACall { /// Conditional special form, e.g. "(if cond thenexp elseexp)" struct AIf : public ACall { - AIf(const SExp& e, const ATuple& t) : ACall(e, t) {} + AIf(const ATuple* exp) : ACall(exp) {} AIf(Cursor c, AST* ast, va_list args) : ACall(c, ast, args) {} void constrain(TEnv& tenv, Constraints& c) const; AST* cps(TEnv& tenv, AST* cont); @@ -494,7 +463,7 @@ struct AIf : public ACall { /// Primitive (builtin arithmetic function), e.g. "(+ 2 3)" struct APrimitive : public ACall { - APrimitive(const SExp& e, const ATuple& t) : ACall(e, t) {} + APrimitive(const ATuple* exp) : ACall(exp) {} bool value() const { ATuple::const_iterator i = begin(); for (++i; i != end(); ++i) @@ -515,8 +484,8 @@ struct APrimitive : public ACall { /// Parse Time Environment (really just a symbol table) struct PEnv : private map { PEnv() : symID(0) {} - typedef AST* (*PF)(PEnv&, const SExp&, void*); ///< Parse Function - typedef SExp (*MF)(PEnv&, const SExp&); ///< Macro Function + typedef AST* (*PF)(PEnv&, const AST*, void*); ///< Parse Function + typedef AST* (*MF)(PEnv&, const AST*); ///< Macro Function struct Handler { Handler(PF f, void* a=0) : func(f), arg(a) {} PF func; void* arg; }; map aHandlers; ///< Atom parse functions map lHandlers; ///< List parse functions @@ -548,36 +517,43 @@ struct PEnv : private map { return sym; } } - ATuple parseTuple(const SExp& e) { - ATuple ret(e.loc); - FOREACH(SExp::const_iterator, i, e) - ret.push_back(parse(*i)); + ATuple* parseTuple(const ATuple* e) { + ATuple* ret = new ATuple(e->loc); + FOREACH(ATuple::const_iterator, i, *e) + ret->push_back(parse(*i)); return ret; } - AST* parse(const SExp& exp) { - 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()); - SExp expanded = (mf ? mf(*this, exp) : exp); - - const PEnv::Handler* h = handler(true, *expanded.front().atom()); + AST* parse(const AST* exp) { + const ATuple* tup = exp->to(); + if (tup) { + if (tup->empty()) throw Error(exp->loc, "call to empty list"); + if (!tup->front()->to()) { + const AString* str = tup->front()->to(); + assert(str); + MF mf = mac(*str); + const AST* expanded = (mf ? mf(*this, exp) : exp); + const ATuple* expanded_tup = expanded->to(); + const PEnv::Handler* h = handler(true, *expanded_tup->front()->to()); 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])) { - const std::string& s = *exp.atom(); + ATuple* parsed_tup = parseTuple(tup); // FIXME: leak + return new ACall(parsed_tup); // Parse as regular call + } + const AString* str = exp->to(); + assert(str); + if (isdigit((*str)[0])) { + const std::string& s = *str; if (s.find('.') == string::npos) - return new ALiteral(strtol(s.c_str(), NULL, 10), exp.loc); + return new ALiteral(strtol(s.c_str(), NULL, 10), exp->loc); else - return new ALiteral(strtod(s.c_str(), NULL), exp.loc); + return new ALiteral(strtod(s.c_str(), NULL), exp->loc); } else { - const PEnv::Handler* h = handler(false, *exp.atom()); + const PEnv::Handler* h = handler(false, *str); if (h) return h->func(*this, exp, h->arg); } - return sym(*exp.atom(), exp.loc); + return sym(*exp->to(), exp->loc); } unsigned symID; }; -- cgit v1.2.1