From 594370a2a381545aea8d0631a86f422f84ee2792 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 19 Aug 2010 22:34:22 +0000 Subject: Generalise `cons': a call to any symbol beginning with an uppercase character (i.e. a type symbol), e.g. (Thing 2), is a call to a type constructor which creates a Tup containing the arguments, with the symbol as the first element in the type expression, e.g. (Thing 2) has type (Thing Int) and compiles to a tuple containing a single Int. The type constructor `Tup' can be used as a `cons' replacement to construct generic tuples. git-svn-id: http://svn.drobilla.net/resp/resp@264 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/parse.cpp | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src/parse.cpp') diff --git a/src/parse.cpp b/src/parse.cpp index 3184f8a..7482039 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -37,18 +37,32 @@ PEnv::parse(const AST* exp) { const ATuple* tup = exp->to(); if (tup) { - if (tup->empty()) throw Error(exp->loc, "call to empty list"); - if (!tup->head()->to()) { - MF mf = mac(*tup->head()->to()); - const AST* expanded = (mf ? mf(*this, exp) : exp); - const ATuple* expanded_tup = expanded->to(); - const PEnv::Handler* h = handler(true, *expanded_tup->head()->to()); + THROW_IF(tup->empty(), exp->loc, "Call to empty list"); + const ALexeme* form = tup->head()->to(); + if (form) { + MF mf = mac(*form); + if (mf) { + exp = mf(*this, exp)->as(); // Apply macro + tup = exp->to(); + } + } + } + + if (tup) { + THROW_IF(tup->empty(), exp->loc, "Call to empty list"); + const ALexeme* form = tup->head()->to(); + if (form) { + const PEnv::Handler* h = handler(true, *form); if (h) - return h->func(*this, expanded, h->arg); + 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)); } - ATuple* parsed_tup = parseTuple(*this, tup); - return new ACall(parsed_tup); // Parse as regular call + + return new ACall(parseTuple(*this, tup)); // Parse regular call } + const ALexeme* lex = exp->to(); assert(lex); if (isdigit((*lex)[0])) { @@ -177,7 +191,6 @@ initLang(PEnv& penv, TEnv& tenv) penv.reg(true, "fn", PEnv::Handler(parseFn)); penv.reg(true, "quote", PEnv::Handler(parseQuote)); penv.reg(true, "if", PEnv::Handler(parseCall)); - penv.reg(true, "cons", PEnv::Handler(parseCall)); penv.reg(true, ".", PEnv::Handler(parseCall)); penv.reg(true, "def", PEnv::Handler(parseCall)); -- cgit v1.2.1