diff options
Diffstat (limited to 'src/parse.cpp')
-rw-r--r-- | src/parse.cpp | 66 |
1 files changed, 37 insertions, 29 deletions
diff --git a/src/parse.cpp b/src/parse.cpp index 28279f9..066db76 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -23,13 +23,14 @@ using namespace std; -ATuple* +template<typename T> +T* parseTuple(PEnv& penv, const ATuple* e) { - ATuple* ret = new ATuple(e->loc); + List<T, AST> ret; FOREACHP(ATuple::const_iterator, i, e) - ret->push_back(penv.parse(*i)); - return ret; + ret.push_back(penv.parse(*i)); + return ret.head; } AST* @@ -57,10 +58,10 @@ PEnv::parse(const AST* exp) return h->func(*this, exp, h->arg); // Parse special form if (isupper(form->c_str()[0])) // Call constructor (any uppercase symbol) - return new ACons(parseTuple(*this, tup)); + return parseTuple<ACons>(*this, tup); } - return new ACall(parseTuple(*this, tup)); // Parse regular call + return parseTuple<ACall>(*this, tup); // Parse regular call } const ALexeme* lex = exp->to<const ALexeme*>(); @@ -92,29 +93,34 @@ macDef(PEnv& penv, const AST* exp) const ATuple* tup = exp->to<const ATuple*>(); 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<const ALexeme*>()) { + const AST* arg1 = *(++i); + THROW_IF(i == tup->end(), arg1->loc, "Unexpected end of `def' macro call"); + if (arg1->to<const ALexeme*>()) { return const_cast<AST*>(exp); } else { - const ATuple* pat = name->to<const ATuple*>(); - name = pat->head(); // (def (f x) y) => (def f (fn (x) y)) - ATuple* argsExp = new ATuple(exp->loc); + const ATuple* pat = arg1->to<const ATuple*>(); + + List<ATuple, AST> argsExp; ATuple::const_iterator j = pat->begin(); for (++j; j != pat->end(); ++j) - argsExp->push_back(*j); + argsExp.push_back(const_cast<AST*>(*j)); + argsExp.head->loc = exp->loc; const AST* body = *(++i); - ATuple* fnExp = new ATuple(body->loc); - fnExp->push_back(new ALexeme(exp->loc, "fn")); - fnExp->push_back(argsExp); + + List<ATuple, AST> fnExp; + fnExp.push_back(new ALexeme(exp->loc, "fn")); + fnExp.push_back(argsExp.head); for (; i != tup->end(); ++i) - fnExp->push_back(*i); - ATuple* ret = new ATuple(exp->loc); - ret->push_back(const_cast<AST*>(tup->head())); - ret->push_back(const_cast<AST*>(name)); - ret->push_back(fnExp); - return ret; + fnExp.push_back(const_cast<AST*>(*i)); + fnExp.head->loc = body->loc; + + List<ATuple, AST> ret; + ret.push_back(const_cast<AST*>(tup->head())); + ret.push_back(const_cast<AST*>(pat->head())); + ret.push_back(fnExp.head); + ret.head->loc = exp->loc; + return ret.head; } } @@ -127,7 +133,7 @@ template<typename C> inline AST* parseCall(PEnv& penv, const AST* exp, void* arg) { - return new C(parseTuple(penv, exp->to<const ATuple*>())); + return parseTuple<C>(penv, exp->to<const ATuple*>()); } template<typename T> @@ -143,19 +149,21 @@ parseFn(PEnv& penv, const AST* exp, void* arg) const ATuple* texp = exp->to<const ATuple*>(); ATuple::const_iterator a = texp->begin(); THROW_IF(++a == texp->end(), exp->loc, "Unexpected end of `fn' form"); - ATuple* prot = parseTuple(penv, (*a++)->to<const ATuple*>()); - AFn* ret = tup<AFn>(exp->loc, penv.sym("fn"), prot, 0); + ATuple* prot = parseTuple<ATuple>(penv, (*a++)->to<const ATuple*>()); + List<ATuple, AST> ret(new ATuple(penv.sym("fn"), NULL)); + ret.push_back(prot); while (a != texp->end()) - ret->push_back(penv.parse(*a++)); - return ret; + ret.push_back(penv.parse(*a++)); + ret.head->loc = exp->loc; + return new AFn(ret.head); } inline AST* parseQuote(PEnv& penv, const AST* exp, void* arg) { const ATuple* texp = exp->to<const ATuple*>(); - THROW_IF(texp->size() != 2, exp->loc, "`quote' requires exactly 1 argument"); - const AST* quotee = (*(texp->begin() + 1))->to<ALexeme*>(); + THROW_IF(texp->list_len() != 2, exp->loc, "`quote' requires exactly 1 argument"); + const ALexeme* quotee = texp->list_ref(1)->to<const ALexeme*>(); THROW_IF(!quotee, exp->loc, "`quote' argument is not a lexeme"); return new AQuote(texp); } |