aboutsummaryrefslogtreecommitdiffstats
path: root/src/constrain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/constrain.cpp')
-rw-r--r--src/constrain.cpp33
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