/**
 * Authors: k.inaba
 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/)
 *
 * Entry point for Polemy interpreter.
 */
module main;
import std.stdio;
import std.algorithm;
import std.array;
import polemy.value;
import polemy.failure;
import polemy.layer;
import polemy.parse;
import polemy.ast;
import polemy.eval;

enum VersionNoMajor = 0;
enum VersionNoMinor = 1;
enum VersionNoRev   = 0;

/// Read-Eval-Print-Loop

class REPL
{
Evaluator ev;
	/// Load the prelude environment
	this()
	{
		ev = new Evaluator;
	}

	/// 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") )
			return false;
		try {
			if( tryRun(line) )
				writeln(lastVal);
		} catch(Throwable e) {
			writeln(e);
		}
		return true;
	}

private:
	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;
	}
}

/// Advance args[] to point the argument list fed to the script.
/// Returns the name of the source file to run, or returns "" if
/// no filename was given. Also, returns to libs[] the list of
/// library source to load.

string parseArgv(ref string[] args, out string[] libs)
{
	args.popFront();

	while( !args.empty && args.front=="-l" ) {
		args.popFront();
		if( !args.empty ) {
			libs ~= args.front();
			args.popFront();
		}
	}

	if( args.empty )
		return "";
	else {
		scope(exit) args.popFront;
		return args.front;
	}
}

/// Entry point.

void main( string[] args )
{
	string[] libs;
	string   src = parseArgv(args, libs);

	auto r = new REPL;
	if( src.empty )
		r.greet();
	foreach(lb; libs)
		r.runFile(lb);
	if( src.empty )
		r.replLoop();
	else
		r.runFile(src);
}
