aboutsummaryrefslogtreecommitdiffstats
path: root/src/constrain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/constrain.cpp')
-rw-r--r--src/constrain.cpp115
1 files changed, 61 insertions, 54 deletions
diff --git a/src/constrain.cpp b/src/constrain.cpp
index 8d16218..0383f20 100644
--- a/src/constrain.cpp
+++ b/src/constrain.cpp
@@ -22,35 +22,12 @@
#include <set>
#include "resp.hpp"
-#define CONSTRAIN_LITERAL(CT, NAME) \
-template<> void \
-ALiteral<CT>::constrain(TEnv& tenv, Constraints& c) const throw(Error) { \
- c.constrain(tenv, this, tenv.named(NAME)); \
-}
-
-// Literal template instantiations
-CONSTRAIN_LITERAL(int32_t, "Int")
-CONSTRAIN_LITERAL(float, "Float")
-CONSTRAIN_LITERAL(bool, "Bool")
-
-void
-AString::constrain(TEnv& tenv, Constraints& c) const throw(Error)
-{
- c.constrain(tenv, this, tenv.named("String"));
-}
-
-void
-ALexeme::constrain(TEnv& tenv, Constraints& c) const throw(Error)
-{
- c.constrain(tenv, this, tenv.named("Lexeme"));
-}
-
-void
-ASymbol::constrain(TEnv& tenv, Constraints& c) const throw(Error)
+static void
+constrain_symbol(TEnv& tenv, Constraints& c, const ASymbol* sym) throw(Error)
{
- const AType** ref = tenv.ref(this);
- THROW_IF(!ref, loc, (format("undefined symbol `%1%'") % cppstr).str());
- c.constrain(tenv, this, *ref);
+ const AType** ref = tenv.ref(sym);
+ THROW_IF(!ref, sym->loc, (format("undefined symbol `%1%'") % sym->cppstr).str());
+ c.constrain(tenv, sym, *ref);
}
static void
@@ -80,7 +57,7 @@ constrain_fn(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
// Add internal definitions to environment frame
for (++i; i != call->end(); ++i) {
- const AST* exp = *i;
+ const AST* exp = *i;
const ATuple* call = exp->to<const ATuple*>();
if (call && is_form(call, "def")) {
const ASymbol* sym = call->list_ref(1)->as<const ASymbol*>();
@@ -96,7 +73,7 @@ constrain_fn(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
const AST* exp = NULL;
for (i = call->iter_at(2); i != call->end(); ++i) {
exp = *i;
- exp->constrain(tenv, c);
+ resp_constrain(tenv, c, exp);
}
const AType* bodyT = tenv.var(exp);
@@ -118,7 +95,7 @@ constrain_def(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
const AType* tvar = tenv.var(body);
tenv.def(sym, tvar);
- body->constrain(tenv, c);
+ resp_constrain(tenv, c, body);
c.constrain(tenv, sym, tvar);
c.constrain(tenv, call, tenv.named("Nothing"));
}
@@ -158,7 +135,7 @@ constrain_match(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
const AST* matchee = call->list_ref(1);
const AType* retT = tenv.var();
const AType* matcheeT = NULL;// = tup<AType>(loc, tenv.U, 0);
- matchee->constrain(tenv, c);
+ resp_constrain(tenv, c, matchee);
for (ATuple::const_iterator i = call->iter_at(2); i != call->end();) {
const AST* exp = *i++;
const ATuple* pattern = exp->to<const ATuple*>();
@@ -175,7 +152,7 @@ constrain_match(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
THROW_IF(i == call->end(), pattern->loc, "missing pattern body");
const AST* body = *i++;
- body->constrain(tenv, c);
+ resp_constrain(tenv, c, body);
c.constrain(tenv, body, retT);
}
c.constrain(tenv, call, retT);
@@ -188,7 +165,7 @@ constrain_if(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
THROW_IF(call->list_len() < 4, call->loc, "`if' requires at least 3 arguments");
THROW_IF(call->list_len() % 2 != 0, call->loc, "`if' missing final else clause");
for (ATuple::const_iterator i = call->iter_at(1); i != call->end(); ++i)
- (*i)->constrain(tenv, c);
+ resp_constrain(tenv, c, *i);
const AType* retT = tenv.var(call);
for (ATuple::const_iterator i = call->iter_at(1); true; ++i) {
ATuple::const_iterator next = i;
@@ -211,7 +188,7 @@ constrain_cons(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
const AType* type = NULL;
for (ATuple::const_iterator i = call->iter_at(1); i != call->end(); ++i)
- (*i)->constrain(tenv, c);
+ resp_constrain(tenv, c, *i);
if (sym->cppstr == "Tup") {
TList tupT(new AType(tenv.Tup, NULL, call->loc));
@@ -237,7 +214,7 @@ constrain_dot(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
const AST* obj = *++i;
const ALiteral<int32_t>* idx = (*++i)->to<const ALiteral<int32_t>*>();
THROW_IF(!idx, call->loc, "the 2nd argument to `.' must be a literal integer");
- obj->constrain(tenv, c);
+ resp_constrain(tenv, c, obj);
const AType* retT = tenv.var(call);
c.constrain(tenv, call, retT);
@@ -254,7 +231,7 @@ static void
constrain_quote(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
{
c.constrain(tenv, call, tenv.named("Quote"));
- call->list_ref(1)->constrain(tenv, c);
+ resp_constrain(tenv, c, call->list_ref(1));
}
static void
@@ -263,7 +240,7 @@ constrain_call(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
const AST* const head = call->head();
for (ATuple::const_iterator i = call->begin(); i != call->end(); ++i)
- (*i)->constrain(tenv, c);
+ resp_constrain(tenv, c, *i);
const AType* fnType = tenv.var(head);
if (fnType->kind != AType::VAR) {
@@ -305,7 +282,7 @@ constrain_primitive(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
ATuple::const_iterator i = call->begin();
for (++i; i != call->end(); ++i)
- (*i)->constrain(tenv, c);
+ resp_constrain(tenv, c, *i);
i = call->begin();
@@ -342,34 +319,64 @@ constrain_primitive(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error)
}
}
-void
-ATuple::constrain(TEnv& tenv, Constraints& c) const throw(Error)
+static void
+constrain_tuple(TEnv& tenv, Constraints& c, const ATuple* tup) throw(Error)
{
- const ASymbol* const sym = head()->to<const ASymbol*>();
+ const ASymbol* const sym = tup->head()->to<const ASymbol*>();
if (!sym) {
- constrain_call(tenv, c, this);
+ constrain_call(tenv, c, tup);
return;
}
const std::string form = sym->cppstr;
- if (is_primitive(tenv.penv, this))
- constrain_primitive(tenv, c, this);
+ if (is_primitive(tenv.penv, tup))
+ constrain_primitive(tenv, c, tup);
else if (form == "fn")
- constrain_fn(tenv, c, this);
+ constrain_fn(tenv, c, tup);
else if (form == "def")
- constrain_def(tenv, c, this);
+ constrain_def(tenv, c, tup);
else if (form == "def-type")
- constrain_def_type(tenv, c, this);
+ constrain_def_type(tenv, c, tup);
else if (form == "match")
- constrain_match(tenv, c, this);
+ constrain_match(tenv, c, tup);
else if (form == "if")
- constrain_if(tenv, c, this);
+ constrain_if(tenv, c, tup);
else if (form == "cons" || isupper(form[0]))
- constrain_cons(tenv, c, this);
+ constrain_cons(tenv, c, tup);
else if (form == ".")
- constrain_dot(tenv, c, this);
+ constrain_dot(tenv, c, tup);
else if (form == "quote")
- constrain_quote(tenv, c, this);
+ constrain_quote(tenv, c, tup);
else
- constrain_call(tenv, c, this);
+ constrain_call(tenv, c, tup);
+}
+
+void
+resp_constrain(TEnv& tenv, Constraints& c, const AST* ast) throw(Error)
+{
+ switch (ast->tag()) {
+ case T_UNKNOWN:
+ break;
+ case T_BOOL:
+ c.constrain(tenv, ast, tenv.named("Bool"));
+ break;
+ case T_FLOAT:
+ c.constrain(tenv, ast, tenv.named("Float"));
+ break;
+ case T_INT32:
+ c.constrain(tenv, ast, tenv.named("Int"));
+ break;
+ case T_LEXEME:
+ c.constrain(tenv, ast, tenv.named("Lexeme"));
+ break;
+ case T_STRING:
+ c.constrain(tenv, ast, tenv.named("String"));
+ break;
+ case T_SYMBOL:
+ constrain_symbol(tenv, c, ast->as<const ASymbol*>());
+ break;
+ case T_TUPLE:
+ constrain_tuple(tenv, c, ast->as<const ATuple*>());
+ break;
+ }
}