/**
 * Authors: k.inaba
 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/
 *
 * Entry point for Polemy interpreter.
 */

import std.stdio;
import std.algorithm;
import polemy.value;
import polemy.lex;
import polemy.parse;
import polemy.ast;
import polemy.eval;

/// Tenuki Read-Eval-Print-Loop
class REPL
{
	Table ctx;
	string buf;
	Value  lastVal;
	int lineno = 1;
	int nextlineno = 1;
	this() { ctx = createGlobalContext(); }
	this(string filename) {
		ctx = createGlobalContext();
		eval(parseFile(filename), ctx, false, "@v");
	}

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

		buf ~= s;
		nextlineno ++;
		try 
			{ lastVal = eval(parseString(buf, "<REPL>", lineno), ctx, false, "@v"); }
		catch( UnexpectedEOF )
			{ return false; } // wait
		buf = "";
		lineno = nextlineno;
		return true;
	}

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

/// Entry point. If args.length==1, invoke REPL.
/// If args.length==3 && args[1]=="-l" read args[2] and invoke REPL.
/// Otherwise interpret the argument as a filename.
void main( string[] args )
{
	if( args.length <= 1 )
	{
		writeln("Welcome to Polemy 0.1.0");
		for(auto r = new REPL; r.singleInteraction();) {}
	}
	else if( args.length>=3 && args[1]=="-l" )
	{
		writeln("Welcome to Polemy 0.1.0");
		for(auto r = new REPL(args[2]); r.singleInteraction();) {}
	}
	else
	{
		evalFile(args[1]);
	}
}
