/**
 * Authors: k.inaba
 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/)
 *
 * Read-Eval-Print-Loop
 */
module polemy.repl;
import polemy.failure;
import polemy.layer;
import polemy.eval;
import polemy.runtime;
import polemy.value;
import polemy.valueconv;
import std.stdio;
import std.string;
import std.cstream;

enum VersionNoMajor = 0; /// Version Number
enum VersionNoMinor = 1; /// Version Number
enum VersionNoRev   = 0; /// Version Number

/// Read-Eval-Print-Loop

class REPL
{
	/// Load the prelude environment
	this(string[] args)
	{
		ev = new Evaluator;
		ev.globalContext.set("argv", ValueLayer, d2polemy(args));
		enrollRuntimeLibrary(ev);
	}

	/// Print the version number etc.
	void greet()
	{
		writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNoMinor, VersionNoRev);
	}

	/// Run one file on the global scope
	void runFile(string filename)
	{
		ev.evalFile(filename);
	}

	/// Repeat the singleInteraction
	void replLoop()
	{
		while( singleInteraction() ) {}
	}

	/// Read one line from stdin, and do some reaction
	bool singleInteraction()
	{
		writef(">> ", lineno);
		string line = readln();
		if( line.startsWith("exit") || line.startsWith("quit") || din.eof() )
			return false;
		try {
			if( tryRun(line) )
				writeln(lastVal);
		} catch(Throwable e) {
			writeln(e);
		}
		return true;
	}

private:
	Evaluator ev;
	Table ctx;
	string buf;
	Value  lastVal;
	int lineno = 1;
	int nextlineno = 1;

	bool tryRun( string s )
	{
		scope(failure)
			{ buf = ""; lineno = nextlineno; }

		buf ~= s;
		nextlineno ++;
		try 
			{ lastVal = ev.evalString(buf, "<REPL>", lineno); }
		catch( UnexpectedEOF )
			{ return false; } // wait
		buf = "";
		lineno = nextlineno;
		return true;
	}
}
