/* 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; /// Compile and evaluate code from @a is int eval(CEnv& cenv, const string& name, istream& is, bool execute) { AST* result = NULL; AType* resultType = NULL; list< pair > exprs; Cursor cursor(name); try { while (true) { AST* exp = readExpression(cursor, is); if (exp->to() && exp->to()->empty()) break; result = cenv.penv.parse(exp); // Parse input Constraints c; result->constrain(cenv.tenv, c); // Constrain types cenv.tsubst = Subst::compose(cenv.tsubst, unify(c)); // Solve type constraints resultType = cenv.type(result); result->lift(cenv); // Lift functions exprs.push_back(make_pair(exp, result)); // Add definitions as GC roots if (result->to()) cenv.lock(result); // 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); } } // Print CPS form CValue val = NULL; /*for (list< pair >::const_iterator i = exprs.begin(); i != exprs.end(); ++i) { cout << "; CPS" << endl; pprint(cout, i->second->cps(cenv.tenv, cenv.penv.sym("cont"))); }*/ if (resultType->concrete()) { // Create function for top-level of program CFunction f = cenv.engine()->startFunction(cenv, "main", resultType, ATuple(cursor)); // Compile all expressions into it for (list< pair >::const_iterator i = exprs.begin(); i != exprs.end(); ++i) val = cenv.compile(i->second); // Finish compilation cenv.engine()->finishFunction(cenv, f, resultType, val); // Call it if (execute) cenv.out << cenv.engine()->call(cenv, f, resultType); } if (execute) cenv.out << " : " << resultType << endl; Object::pool.collect(Object::pool.roots()); if (cenv.args.find("-d") != cenv.args.end()) cenv.engine()->writeModule(cenv, cenv.out); } catch (Error& e) { cenv.err << e.what() << endl; return 1; } return 0; } /// Read Eval Print Loop int repl(CEnv& cenv) { while (1) { cenv.out << "() "; cenv.out.flush(); Cursor cursor("(stdin)"); try { AST* exp = readExpression(cursor, std::cin); if (exp->to() && exp->to()->empty()) break; AST* body = cenv.penv.parse(exp); // Parse input Constraints c; body->constrain(cenv.tenv, c); // Constrain types Subst oldSubst = cenv.tsubst; cenv.tsubst = Subst::compose(cenv.tsubst, unify(c)); // Solve type constraints AType* bodyT = cenv.type(body); THROW_IF(!bodyT, cursor, "call to untyped body") body->lift(cenv); CFunction f = NULL; try { // Create anonymous function to insert code into f = cenv.engine()->startFunction(cenv, cenv.penv.gensymstr("_repl"), bodyT, ATuple(cursor)); CValue retVal = cenv.compile(body); cenv.engine()->finishFunction(cenv, f, bodyT, retVal); cenv.out << cenv.engine()->call(cenv, f, bodyT); } catch (Error& e) { ADef* def = body->to(); if (def) cenv.out << def->sym(); else cenv.out << "?"; cenv.engine()->eraseFunction(cenv, f); } if (bodyT->at(0)->to()->cppstr != "Nothing") cenv.out << " : " << cenv.type(body) << endl; // Add definitions as GC roots if (body->to()) cenv.lock(body); Object::pool.collect(Object::pool.roots()); cenv.tsubst = oldSubst; if (cenv.args.find("-d") != cenv.args.end()) cenv.engine()->writeModule(cenv, cenv.out); } catch (Error& e) { cenv.err << e.what() << endl; } } return 0; }