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