aboutsummaryrefslogtreecommitdiffstats
path: root/src/parse.cpp
diff options
context:
space:
mode:
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>));