aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse.cpp
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-08-19 22:34:22 +0000
committerDavid Robillard <d@drobilla.net>2010-08-19 22:34:22 +0000
commit594370a2a381545aea8d0631a86f422f84ee2792 (patch)
treebe71de4a2d9ec83d634c6978daa38c76428b58e7 /src/parse.cpp
parent60f4383ee1df7c326ac887b7c1750575c3becbb8 (diff)
downloadresp-594370a2a381545aea8d0631a86f422f84ee2792.tar.gz
resp-594370a2a381545aea8d0631a86f422f84ee2792.tar.bz2
resp-594370a2a381545aea8d0631a86f422f84ee2792.zip
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
Diffstat (limited to 'src/parse.cpp')
-rw-r--r--src/parse.cpp33
1 files changed, 23 insertions, 10 deletions
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<const ATuple*>();
if (tup) {
- if (tup->empty()) throw Error(exp->loc, "call to empty list");
- if (!tup->head()->to<const ATuple*>()) {
- MF mf = mac(*tup->head()->to<const ALexeme*>());
- const AST* expanded = (mf ? mf(*this, exp) : exp);
- const ATuple* expanded_tup = expanded->to<const ATuple*>();
- const PEnv::Handler* h = handler(true, *expanded_tup->head()->to<const ALexeme*>());
+ THROW_IF(tup->empty(), exp->loc, "Call to empty list");
+ const ALexeme* form = tup->head()->to<const ALexeme*>();
+ if (form) {
+ MF mf = mac(*form);
+ if (mf) {
+ exp = mf(*this, exp)->as<ATuple*>(); // Apply macro
+ tup = exp->to<const ATuple*>();
+ }
+ }
+ }
+
+ if (tup) {
+ THROW_IF(tup->empty(), exp->loc, "Call to empty list");
+ const ALexeme* form = tup->head()->to<const ALexeme*>();
+ 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<const ALexeme*>();
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<AIf>));
- penv.reg(true, "cons", PEnv::Handler(parseCall<ACons>));
penv.reg(true, ".", PEnv::Handler(parseCall<ADot>));
penv.reg(true, "def", PEnv::Handler(parseCall<ADef>));