From 0faa00e9dfd221016ad26b5629617949fcce4676 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Thu, 30 Sep 2010 12:45:47 +0000 Subject: Preliminary work on algebraic data types and run-time typing. git-svn-id: http://svn.drobilla.net/resp/resp@270 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/constrain.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 5 deletions(-) (limited to 'src/constrain.cpp') diff --git a/src/constrain.cpp b/src/constrain.cpp index e5a8dc4..ef8e3bf 100644 --- a/src/constrain.cpp +++ b/src/constrain.cpp @@ -184,16 +184,85 @@ AIf::constrain(TEnv& tenv, Constraints& c) const throw(Error) } } +void +AMatch::constrain(TEnv& tenv, Constraints& c) const throw(Error) +{ + THROW_IF(size() < 5, loc, "`match' requires at least 4 arguments"); + const AST* matchee = (*(begin() + 1)); + const AType* retT = tenv.var(); + const AType* matcheeT = NULL;// = tup(loc, tenv.U, 0); + matchee->constrain(tenv, c); + for (const_iterator i = begin() + 2; i != end();) { + const AST* exp = *i++; + const ATuple* pattern = exp->to(); + THROW_IF(!pattern, exp->loc, "pattern expression expected"); + const ASymbol* name = (*pattern->begin())->to(); + THROW_IF(!name, (*pattern->begin())->loc, "pattern does not start with a symbol"); + + const AType* consT = *tenv.ref(name); + + if (!matcheeT) { + const AType* headT = consT->head()->as(); + matcheeT = tup(loc, const_cast(headT), 0); + } + + THROW_IF(i == end(), pattern->loc, "missing pattern body"); + const AST* body = *i++; + body->constrain(tenv, c); + c.constrain(tenv, body, retT); + } + c.constrain(tenv, this, retT); + c.constrain(tenv, matchee, matcheeT); +} + +void +ADefType::constrain(TEnv& tenv, Constraints& c) const throw(Error) +{ + THROW_IF(size() < 3, loc, "`def-type' requires at least 2 arguments"); + const_iterator i = begin() + 1; + const ATuple* prot = (*i)->to(); + THROW_IF(!prot, (*i)->loc, "first argument of `def-type' is not a tuple"); + const ASymbol* sym = (*prot->begin())->as(); + THROW_IF(!sym, (*prot->begin())->loc, "type name is not a symbol"); + THROW_IF(tenv.ref(sym), loc, "type redefinition"); + AType* type = tup(loc, tenv.U, 0); + for (const_iterator i = begin() + 2; i != end(); ++i) { + const ATuple* exp = (*i)->as(); + const ASymbol* tag = (*exp->begin())->as(); + AType* consT = new AType(exp->loc, AType::EXPR); + consT->push_back(new AType(const_cast(sym), AType::NAME)); + for (ATuple::const_iterator i = exp->begin(); i != exp->end(); ++i) { + const ASymbol* sym = (*i)->to(); + THROW_IF(!sym, (*i)->loc, "type expression element is not a symbol"); + consT->push_back(new AType(const_cast(sym), AType::NAME)); + } + type->push_back(consT); + tenv.def(tag, consT); + } + tenv.def(sym, type); +} + void ACons::constrain(TEnv& tenv, Constraints& c) const throw(Error) { - ASymbol* sym = (*begin())->as(); - AType* type = tup(loc, new AType(sym), 0); - for (const_iterator i = begin() + 1; i != end(); ++i) { + const ASymbol* sym = (*begin())->as(); + const AType* type = NULL; + + for (const_iterator i = begin() + 1; i != end(); ++i) (*i)->constrain(tenv, c); - type->push_back(const_cast(tenv.var(*i))); - } + if (sym->cppstr == "Tup") { + AType* tupT = tup(loc, tenv.Tup, 0); + for (const_iterator i = begin() + 1; i != end(); ++i) { + tupT->push_back(const_cast(tenv.var(*i))); + } + type = tupT; + } else { + const AType** consTRef = tenv.ref(sym); + THROW_IF(!consTRef, loc, (format("call to undefined constructor `%1%'") % sym->cppstr).str()); + const AType* consT = *consTRef; + type = tup(loc, const_cast(consT->head()->as()), 0); + } c.constrain(tenv, this, type); } -- cgit v1.2.1