/* Tuplr: A programming language * Copyright (C) 2008-2009 David Robillard * * Tuplr 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. * * Tuplr 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 Tuplr. If not, see . */ /** @file * @brief REPL and eval */ #include #include #include #include "tuplr.hpp" using namespace std; static bool readParseTypeLift(CEnv& cenv, Cursor& cursor, istream& is, AST*& exp, AST*& ast, AType*& type) { exp = readExpression(cursor, is); if (exp->to() && exp->to()->empty()) return false; ast = cenv.penv.parse(exp); // Parse input Constraints c; ast->constrain(cenv.tenv, c); // Constrain types cenv.tsubst = Subst::compose(cenv.tsubst, unify(c)); // Solve type constraints // Add types in type substition as GC roots for (Subst::iterator i = cenv.tsubst.begin(); i != cenv.tsubst.end(); ++i) { Object::pool.addRoot(i->first); Object::pool.addRoot(i->second); } type = cenv.type(ast); THROW_IF(!type, cursor, "call to untyped body"); ast->lift(cenv); // Lift functions return true; } static void callPrintCollect(CEnv& cenv, CFunc f, AST* result, 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()); if (cenv.args.find("-d") != cenv.args.end()) cenv.engine()->writeModule(cenv, cenv.out); } /// Compile and evaluate code from @a is int eval(CEnv& cenv, const string& name, istream& is, bool execute) { AST* exp = NULL; AST* ast = NULL; AType* type = NULL; list< pair > exprs; Cursor cursor(name); try { while (readParseTypeLift(cenv, cursor, is, exp, ast, type)) exprs.push_back(make_pair(exp, ast)); //for (list< pair >::const_iterator i = exprs.begin(); i != exprs.end(); ++i) // pprint(cout, i->second->cps(cenv.tenv, cenv.penv.sym("cont"))); CVal val = NULL; CFunc f = NULL; if (type->concrete()) { // Create function for top-level of program f = cenv.engine()->startFunction(cenv, "main", type, ATuple(cursor)); // Compile all expressions into it for (list< pair >::const_iterator i = exprs.begin(); i != exprs.end(); ++i) val = i->second->compile(cenv); // Finish compilation cenv.engine()->finishFunction(cenv, f, type, val); } // Call and print ast 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; AType* type = NULL; const string replFnName = cenv.penv.gensymstr("_repl"); while (1) { cenv.out << "() "; cenv.out.flush(); Cursor cursor("(stdin)"); try { if (!readParseTypeLift(cenv, cursor, std::cin, exp, ast, type)) break; CFunc f = NULL; try { // Create function for this repl loop f = cenv.engine()->startFunction(cenv, replFnName, type, ATuple(cursor)); cenv.engine()->finishFunction(cenv, f, type, ast->compile(cenv)); callPrintCollect(cenv, f, ast, type, true); } catch (Error& e) { cenv.out << e.msg << endl; cenv.engine()->eraseFunction(cenv, f); } } catch (Error& e) { cenv.err << e.what() << endl; } } return 0; }