diff options
Diffstat (limited to 'src/constrain.cpp')
-rw-r--r-- | src/constrain.cpp | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/src/constrain.cpp b/src/constrain.cpp index c4a08ec..047a5b0 100644 --- a/src/constrain.cpp +++ b/src/constrain.cpp @@ -199,6 +199,37 @@ constrain_if(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) } static void +constrain_let(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) +{ + THROW_IF(call->list_len() < 3, call->loc, "`let' requires at least 2 arguments"); + const ATuple* vars = call->list_ref(1)->to_tuple(); + THROW_IF(!vars, call->list_ref(1)->loc, "first argument of `let' is not a list"); + + TEnv::Frame frame; + for (ATuple::const_iterator i = vars->begin(); i != vars->end(); ++i) { + const ASymbol* sym = (*i)->to_symbol(); + THROW_IF(!sym, (*i)->loc, "`let' binding name is not a symbol"); + ATuple::const_iterator val = ++i; + THROW_IF(val == vars->end(), sym->loc, "`let' variable missing value"); + + resp_constrain(tenv, c, *val); + const AType* tvar = tenv.var(*val); + frame.push_back(make_pair(sym->sym(), tvar)); + c.constrain(tenv, sym, tvar); + //c.constrain(tenv, *val, tvar); + } + + tenv.push(frame); + + for (ATuple::const_iterator i = call->iter_at(2); i != call->end(); ++i) + resp_constrain(tenv, c, *i); + + c.constrain(tenv, call, tenv.var(call->list_last())); + + tenv.pop(); +} + +static void constrain_match(TEnv& tenv, Constraints& c, const ATuple* call) throw(Error) { THROW_IF(call->list_len() < 5, call->loc, "`match' requires at least 4 arguments"); @@ -338,6 +369,8 @@ constrain_list(TEnv& tenv, Constraints& c, const ATuple* tup) throw(Error) constrain_fn(tenv, c, tup); else if (form == "if") constrain_if(tenv, c, tup); + else if (form == "let") + constrain_let(tenv, c, tup); else if (form == "match") constrain_match(tenv, c, tup); else |