diff options
Diffstat (limited to 'src/constrain.cpp')
-rw-r--r-- | src/constrain.cpp | 115 |
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; + } } |