diff options
Diffstat (limited to 'src/simplify.cpp')
-rw-r--r-- | src/simplify.cpp | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/src/simplify.cpp b/src/simplify.cpp new file mode 100644 index 0000000..31eb83a --- /dev/null +++ b/src/simplify.cpp @@ -0,0 +1,94 @@ +/* Resp: A programming language + * Copyright (C) 2008-2009 David Robillard <dave@drobilla.net> + * + * Resp is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Resp is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Resp. If not, see <http://www.gnu.org/licenses/>. + */ + +/** @file + * @brief Simplify (reduce to simpler forms, e.g. match => if) + */ + +#include <string> + +#include "resp.hpp" + +using namespace std; + +static const AST* +simplify_match(CEnv& cenv, const ATuple* match) throw() +{ + List<ATuple, const AST> copy(match->loc, cenv.penv.sym("let"), NULL); + List<ATuple, const AST> copyVars; + + const ASymbol* tsym = cenv.penv.gensym("_matchT"); + + List<ATuple, const AST> tval; + tval.push_back(cenv.penv.sym(".")); + tval.push_back(resp_simplify(cenv, match->list_ref(1))); + tval.push_back(new ALiteral<int32_t>(T_INT32, 0, Cursor())); + + copyVars.push_back(tsym); + copyVars.push_back(tval); + copy.push_back(copyVars); + + List<ATuple, const AST> copyIf; + copyIf.push_back(cenv.penv.sym("if")); + for (ATuple::const_iterator i = match->iter_at(2); i != match->end();) { + const ATuple* pat = (*i++)->as_tuple(); + const AST* body = *i++; + + List<ATuple, const AST> cond; + cond.push_back(cenv.penv.sym("__tag_is")); + cond.push_back(tsym); + cond.push_back(pat->head()); + + copyIf.push_back(cond); + copyIf.push_back(resp_simplify(cenv, body)); + } + copyIf.push_back(cenv.penv.sym("__unreachable")); + copy.push_back(copyIf); + + cenv.setTypeSameAs(copyIf, match); + cenv.setTypeSameAs(copy, match); + + return copy; +} + +static const AST* +simplify_list(CEnv& cenv, const ATuple* call) throw() +{ + List<ATuple, const AST> copy; + for (ATuple::const_iterator i = call->begin(); i != call->end(); ++i) + copy.push_back(resp_simplify(cenv, *i)); + + cenv.setTypeSameAs(copy.head, call); + + return copy; +} + +const AST* +resp_simplify(CEnv& cenv, const AST* ast) throw() +{ + const ATuple* const list = ast->to_tuple(); + if (!list) + return ast; + + const ASymbol* const sym = list->head()->to_symbol(); + const std::string form = sym ? sym->sym() : ""; + + if (form == "match") + return simplify_match(cenv, list); + else + return simplify_list(cenv, list); +} |