/* Resp: A programming language * Copyright (C) 2008-2009 David Robillard * * 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 . */ /** @file * @brief REPL and eval */ #include #include #include #include "resp.hpp" using namespace std; static bool readParseType(CEnv& cenv, Cursor& cursor, istream& is, AST*& exp, AST*& ast) { try { exp = readExpression(cursor, is); } catch (Error e) { is.ignore(std::numeric_limits::max(), '\n'); // Skip REPL junk throw e; } if (exp->to() && exp->to()->empty()) return false; ast = cenv.penv.parse(exp); // Parse input Constraints c(cenv.tsubst); ast->constrain(cenv.tenv, c); // Constrain types const Subst subst = unify(c); // Solve type constraints for (Subst::const_iterator i = subst.begin(); i != subst.end(); ++i) { if (!cenv.tsubst.contains(i->first)) { // Substitution's LHS is a new variable cenv.tsubst.push_back(*i); // Add substitution to global type substitution Object::pool.addRoot(i->first); Object::pool.addRoot(i->second); } } //cout << "**** SUBST\n" << subst << "********" << endl; //cout << "**** CENV.SUBST\n" << cenv.tsubst << "********" << endl; //cenv.tsubst = Subst::compose(cenv.tsubst, subst); Object::pool.addRoot(ast); // Make parsed expression a GC root so it is not deleted return true; } static void callPrintCollect(CEnv& cenv, CFunc f, AST* result, const AType* resultT, bool execute) { if (execute) cenv.out << cenv.engine()->call(cenv, f, resultT); // Print type (if applicable) if (resultT->head()->str() != "Nothing") cenv.out << " : " << resultT << endl; Object::pool.collect(Object::pool.roots()); } /// Compile and evaluate code from @a is int eval(CEnv& cenv, const string& name, istream& is, bool execute) { AST* exp = NULL; AST* ast = NULL; list parsed; Cursor cursor(name); try { while (readParseType(cenv, cursor, is, exp, ast)) parsed.push_back(ast); /*for (list::const_iterator i = parsed.begin(); i != parsed.end(); ++i) pprint(cout, (*i)->cps(cenv.tenv, cenv.penv.sym("halt")));*/ CVal val = NULL; CFunc f = NULL; /* // De-poly all expressions Code concrete; for (list::iterator i = parsed.begin(); i != parsed.end(); ++i) { AST* c = (*i)->depoly(cenv, concrete); if (c) concrete.push_back(c); } if (cenv.args.find("-d") != cenv.args.end()) { cout << endl << ";;;; CONCRETE {" << endl << endl; for (Code::iterator i = concrete.begin(); i != concrete.end(); ++i) { cout << *i << endl; ADef* def = (*i)->to(); if (def) std::cout << " :: " << cenv.type(def->body()) << std::endl; cout << endl; } cout << ";;;; } CONCRETE" << endl << endl; } */ // Lift all expressions Code lifted; for (list::iterator i = parsed.begin(); i != parsed.end(); ++i) { AST* l = (*i)->lift(cenv, lifted); if (l) lifted.push_back(l); } if (cenv.args.find("-d") != cenv.args.end()) { cout << endl << ";;;; LIFTED {" << endl << endl; for (Code::iterator i = lifted.begin(); i != lifted.end(); ++i) { cout << *i << endl; ADef* def = (*i)->to(); if (def) std::cout << " :: " << cenv.type(def->body()) << std::endl; cout << endl; } cout << ";;;; } LIFTED" << endl << endl; } // Compile top-level (lifted) functions Code exprs; for (Code::iterator i = lifted.begin(); i != lifted.end(); ++i) { ADef* def = (*i)->to(); if (def && (*(def->begin() + 2))->to()) { val = def->compile(cenv); } else { exprs.push_back(*i); } } const AType* type = cenv.type(exprs.back()); const AType* fnT = tup(cursor, cenv.tenv.Fn, new AType(cursor), type, 0); // Create function for top-level of program f = cenv.engine()->startFunction(cenv, "main", new ATuple(cursor), fnT); // Compile expressions (other than function definitions) into it for (list::const_iterator i = exprs.begin(); i != exprs.end(); ++i) val = (*i)->compile(cenv); // Finish compilation cenv.engine()->finishFunction(cenv, f, val); if (cenv.args.find("-d") != cenv.args.end()) cenv.engine()->writeModule(cenv, cenv.out); // Call and print ast if (cenv.args.find("-S") == cenv.args.end()) callPrintCollect(cenv, f, ast, type, execute); } catch (Error& e) { cenv.err << e.what() << endl; return 1; } return 0; } /// Read Eval Print Loop int repl(CEnv& cenv) { AST* exp = NULL; AST* ast = NULL; const string replFnName = cenv.penv.gensymstr("_repl"); while (1) { cenv.out << "() "; cenv.out.flush(); Cursor cursor("(stdin)"); try { if (!readParseType(cenv, cursor, std::cin, exp, ast)) break; Code lifted; ast = ast->lift(cenv, lifted); const AType* type = cenv.type(ast); const AType* fnT = tup(cursor, cenv.tenv.Fn, new AType(cursor), type, 0); CFunc f = NULL; try { // Create function for this repl loop f = cenv.engine()->startFunction(cenv, replFnName, new ATuple(cursor), fnT); cenv.engine()->finishFunction(cenv, f, ast->compile(cenv)); callPrintCollect(cenv, f, ast, type, true); if (cenv.args.find("-d") != cenv.args.end()) cenv.engine()->writeModule(cenv, cenv.out); } catch (Error& e) { cenv.out << e.msg << endl; cenv.engine()->eraseFunction(cenv, f); } } catch (Error& e) { cenv.err << e.what() << endl; } } return 0; }