diff options
Diffstat (limited to 'src/simplify.cpp')
-rw-r--r-- | src/simplify.cpp | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/src/simplify.cpp b/src/simplify.cpp index 35178ac..b797057 100644 --- a/src/simplify.cpp +++ b/src/simplify.cpp @@ -56,19 +56,16 @@ simplify_if(CEnv& cenv, const ATuple* aif) throw() 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"); - + // 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<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())); + tval.push_back(new ALiteral<int32_t>(T_INT32, -1, Cursor())); + + const ASymbol* tsym = cenv.penv.gensym("_matchT"); - copyVars.push_back(tsym); - copyVars.push_back(tval); - copy.push_back(copyVars); + List<ATuple, const AST> def(match->loc, cenv.penv.sym("def"), tsym, tval.head, NULL); List<ATuple, const AST> copyIf; copyIf.push_back(cenv.penv.sym("if")); @@ -86,6 +83,10 @@ simplify_match(CEnv& cenv, const ATuple* match) throw() } copyIf.push_back(cenv.penv.sym("__unreachable")); cenv.setTypeSameAs(copyIf, match); + + List<ATuple, const AST> copy; + copy.push_back(cenv.penv.sym("do")); + copy.push_back(def); copy.push_back(simplify_if(cenv, copyIf)); cenv.setTypeSameAs(copy, match); @@ -104,6 +105,39 @@ simplify_list(CEnv& cenv, const ATuple* call) throw() return copy; } +static const AST* +simplify_let(CEnv& cenv, const ATuple* call) throw() +{ + const ATuple* vars = call->list_ref(1)->to_tuple(); + + List<ATuple, const AST> fn(Cursor(), cenv.penv.sym("fn"), NULL); + + List<ATuple, const AST> fnProt; + List<ATuple, const AST> fnArgs; + List<AType, const AType> fnProtT; + for (ATuple::const_iterator i = vars->begin(); i != vars->end();) { + const ASymbol* sym = (*i++)->to_symbol(); + const AST* val = (*i++); + fnProt.push_back(sym); + fnArgs.push_back(resp_simplify(cenv, val)); + fnProtT.push_back(cenv.type(val)); + } + + fn.push_back(fnProt.head); + fn.push_back(resp_simplify(cenv, call->list_ref(2))); + + List<AType, const AType> fnT; + fnT.push_back(cenv.tenv.Fn); + fnT.push_back(fnProtT); + fnT.push_back(cenv.type(call->list_ref(2))); + cenv.setType(fn, fnT); + + ATuple* copy = new ATuple(fn, fnArgs, call->loc); + cenv.setTypeSameAs(copy, call); + + return copy; +} + const AST* resp_simplify(CEnv& cenv, const AST* ast) throw() { @@ -118,6 +152,8 @@ resp_simplify(CEnv& cenv, const AST* ast) throw() return simplify_match(cenv, list); else if (form == "if") return simplify_if(cenv, list); + else if (form == "let") + return simplify_let(cenv, list); else return simplify_list(cenv, list); } |