From 2eda11ca28589991471ff3251cccc2471424770e Mon Sep 17 00:00:00 2001 From: David Robillard Date: Wed, 29 Dec 2010 22:50:20 +0000 Subject: Destructuring (i.e. working `match'). git-svn-id: http://svn.drobilla.net/resp/resp@374 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- src/simplify.cpp | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) (limited to 'src/simplify.cpp') diff --git a/src/simplify.cpp b/src/simplify.cpp index c5b2566..d6188ad 100644 --- a/src/simplify.cpp +++ b/src/simplify.cpp @@ -56,12 +56,12 @@ simplify_if(CEnv& cenv, const ATuple* aif) throw() static const AST* simplify_match(CEnv& cenv, const ATuple* match) throw() { + const AST* const obj = resp_simplify(cenv, match->list_ref(1)); + // Dot expression to get tag. Note index is -1 to compensate for the lift phase // which adds 1 to skip the RTTI, which we don't want here (FIXME: ick...) - List tval; - tval.push_back(cenv.penv.sym(".")); - tval.push_back(resp_simplify(cenv, match->list_ref(1))); - tval.push_back(new ALiteral(T_INT32, -1, Cursor())); + const AST* index = new ALiteral(T_INT32, -1, Cursor()); + List tval(Cursor(), cenv.penv.sym("."), obj, index, 0); const ASymbol* tsym = cenv.penv.gensym("__tag"); @@ -78,11 +78,47 @@ simplify_match(CEnv& cenv, const ATuple* match) throw() const_cast(consTag)->tag(T_LITSYM); cenv.setType(consTag, cenv.tenv.named("Symbol")); + const ATuple* texp = cenv.tenv.named(consTag->sym())->as_tuple(); + + // Append condition for this case List cond(Cursor(), cenv.penv.sym("="), tsym, consTag, 0); cenv.setType(cond, cenv.tenv.named("Bool")); - copyIf.push_back(cond); - copyIf.push_back(resp_simplify(cenv, body)); + + // If constructor has no variables, append body and continue + // (don't generate pointless fn) + if (texp->list_len() == 2) { + copyIf.push_back(body); + continue; + } + + // Build fn for the body of this case + const ASymbol* osym = cenv.penv.gensym("__obj"); + const ATuple* prot = new ATuple(osym, 0, Cursor()); + const ATuple* protT = new ATuple(texp->rst(), 0, Cursor()); + + List fn(Cursor(), cenv.penv.sym("fn"), prot, 0); + int idx = 0; + ATuple::const_iterator ti = texp->iter_at(2); + for (ATuple::const_iterator j = pat->iter_at(1); j != pat->end(); ++j, ++ti, ++idx) { + const AST* index = new ALiteral(T_INT32, idx, Cursor()); + const AST* dot = tup(Cursor(), cenv.penv.sym("."), osym, index, 0); + const AST* def = tup(Cursor(), cenv.penv.sym("def"), *j, dot); + fn.push_back(def); + } + + fn.push_back(resp_simplify(cenv, body)); + + List fnT(Cursor(), cenv.tenv.Fn, protT, cenv.type(match), 0); + assert(fnT.head->list_ref(1)); + cenv.setType(fn, fnT); + + const ATuple* cast = tup(Cursor(), cenv.penv.sym("cast"), obj, 0); + cenv.setType(cast, texp->rst()); + + List call(Cursor(), fn, cast, 0); + cenv.setTypeSameAs(call, match); + copyIf.push_back(call); } copyIf.push_back(cenv.penv.sym("__unreachable")); cenv.setTypeSameAs(copyIf, match); -- cgit v1.2.1