diff options
Diffstat (limited to 'src/compile.cpp')
-rw-r--r-- | src/compile.cpp | 156 |
1 files changed, 78 insertions, 78 deletions
diff --git a/src/compile.cpp b/src/compile.cpp index 127a981..a696836 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -34,63 +34,27 @@ compile_symbol(CEnv& cenv, const ASymbol* sym) throw() } static CVal -compile_fn(CEnv& cenv, const ATuple* fn) throw() -{ - assert(!cenv.currentFn); - - const AType* type = cenv.type(fn); - CFunc f = cenv.findImpl(fn, type); - if (f) - return f; - - // Write function declaration and push stack frame - f = cenv.engine()->startFn(cenv, cenv.name(fn), fn->prot(), type); - cenv.engine()->pushFnArgs(cenv, fn->prot(), type, f); - cenv.currentFn = f; - - // Write function body - CVal retVal = NULL; - for (ATuple::const_iterator i = fn->iter_at(2); i != fn->end(); ++i) - retVal = resp_compile(cenv, *i); - - // Write function conclusion and pop stack frame - cenv.engine()->finishFn(cenv, f, retVal); - cenv.pop(); - cenv.currentFn = NULL; - - cenv.vals.def(cenv.penv.sym(cenv.name(fn)), f); - cenv.addImpl(fn, f); - return f; -} - -static CVal -compile_type(CEnv& cenv, const AType* type) throw() +compile_cons(CEnv& cenv, const ATuple* cons) throw() { - const ASymbol* sym = type->head()->as_symbol(); - CVal* existing = cenv.vals.ref(sym); - if (existing) { - return *existing; - } else { - CVal compiled = cenv.engine()->compileString( - cenv, (string("__T_") + type->head()->str()).c_str()); - cenv.vals.def(sym, compiled); - return compiled; + AType* type = new AType(cons->head()->as_symbol(), NULL, Cursor()); + TList tlist(type); + vector<CVal> fields; + for (ATuple::const_iterator i = cons->iter_at(1); i != cons->end(); ++i) { + tlist.push_back(cenv.type(*i)); + fields.push_back(resp_compile(cenv, *i)); } + return cenv.engine()->compileCons(cenv, type, resp_compile(cenv, type), fields); } static CVal -compile_call(CEnv& cenv, const ATuple* call) throw() +compile_dot(CEnv& cenv, const ATuple* dot) throw() { - CFunc f = resp_compile(cenv, call->head()); - - if (!f) - f = cenv.currentFn; // Recursive call (callee defined as a stub) - - vector<CVal> args; - for (ATuple::const_iterator e = call->iter_at(1); e != call->end(); ++e) - args.push_back(resp_compile(cenv, *e)); - - return cenv.engine()->compileCall(cenv, f, cenv.type(call->head()), args); + ATuple::const_iterator i = dot->begin(); + const AST* tup = *++i; + const ALiteral<int32_t>* index = (ALiteral<int32_t>*)(*++i); + assert(index->tag() == T_INT32); + CVal tupVal = resp_compile(cenv, tup); + return cenv.engine()->compileDot(cenv, tupVal, index->val + 1); // + 1 to skip RTTI } static CVal @@ -110,27 +74,33 @@ compile_def(CEnv& cenv, const ATuple* def) throw() } static CVal -compile_cons(CEnv& cenv, const ATuple* cons) throw() +compile_fn(CEnv& cenv, const ATuple* fn) throw() { - AType* type = new AType(cons->head()->as_symbol(), NULL, Cursor()); - TList tlist(type); - vector<CVal> fields; - for (ATuple::const_iterator i = cons->iter_at(1); i != cons->end(); ++i) { - tlist.push_back(cenv.type(*i)); - fields.push_back(resp_compile(cenv, *i)); - } - return cenv.engine()->compileCons(cenv, type, resp_compile(cenv, type), fields); -} + assert(!cenv.currentFn); + + const AType* type = cenv.type(fn); + CFunc f = cenv.findImpl(fn, type); + if (f) + return f; -static CVal -compile_dot(CEnv& cenv, const ATuple* dot) throw() -{ - ATuple::const_iterator i = dot->begin(); - const AST* tup = *++i; - const ALiteral<int32_t>* index = (ALiteral<int32_t>*)(*++i); - assert(index->tag() == T_INT32); - CVal tupVal = resp_compile(cenv, tup); - return cenv.engine()->compileDot(cenv, tupVal, index->val + 1); // + 1 to skip RTTI + // Write function declaration and push stack frame + f = cenv.engine()->startFn(cenv, cenv.name(fn), fn->prot(), type); + cenv.engine()->pushFnArgs(cenv, fn->prot(), type, f); + cenv.currentFn = f; + + // Write function body + CVal retVal = NULL; + for (ATuple::const_iterator i = fn->iter_at(2); i != fn->end(); ++i) + retVal = resp_compile(cenv, *i); + + // Write function conclusion and pop stack frame + cenv.engine()->finishFn(cenv, f, retVal); + cenv.pop(); + cenv.currentFn = NULL; + + cenv.vals.def(cenv.penv.sym(cenv.name(fn)), f); + cenv.addImpl(fn, f); + return f; } static CVal @@ -173,6 +143,36 @@ compile_match(CEnv& cenv, const ATuple* match) throw() return cenv.engine()->compileIfEnd(cenv, state, NULL, type); } +static CVal +compile_type(CEnv& cenv, const AType* type) throw() +{ + const ASymbol* sym = type->head()->as_symbol(); + CVal* existing = cenv.vals.ref(sym); + if (existing) { + return *existing; + } else { + CVal compiled = cenv.engine()->compileString( + cenv, (string("__T_") + type->head()->str()).c_str()); + cenv.vals.def(sym, compiled); + return compiled; + } +} + +static CVal +compile_call(CEnv& cenv, const ATuple* call) throw() +{ + CFunc f = resp_compile(cenv, call->head()); + + if (!f) + f = cenv.currentFn; // Recursive call (callee defined as a stub) + + vector<CVal> args; + for (ATuple::const_iterator e = call->iter_at(1); e != call->end(); ++e) + args.push_back(resp_compile(cenv, *e)); + + return cenv.engine()->compileCall(cenv, f, cenv.type(call->head()), args); +} + CVal resp_compile(CEnv& cenv, const AST* ast) throw() { @@ -196,20 +196,20 @@ resp_compile(CEnv& cenv, const AST* ast) throw() const std::string form = sym ? sym->sym() : ""; if (is_primitive(cenv.penv, call)) return cenv.engine()->compilePrimitive(cenv, ast->as_tuple()); - else if (form == "fn") - return compile_fn(cenv, call); - else if (form == "def") - return compile_def(cenv, call); - else if (form == "if") - return compile_if(cenv, call); else if (form == "cons" || isupper(form[0])) return compile_cons(cenv, call); else if (form == ".") return compile_dot(cenv, call); + else if (form == "def") + return compile_def(cenv, call); + else if (form == "def-type") + return NULL; // FIXME + else if (form == "fn") + return compile_fn(cenv, call); + else if (form == "if") + return compile_if(cenv, call); else if (form == "match") return compile_match(cenv, call); - else if (form == "def-type") - return NULL; else return compile_call(cenv, call); } |