// Thanks, Douglas.
function object(o)
{
  function Construct() {}
  Construct.prototype = o;
  return new Construct();
}


SWYM =
{
	errors:""
}

SWYM.CountLines = function(str)
{
  var result = 1;
  for ( var i = 0; str[i] !== undefined; i++ )
  {
    if (str[i] === '\n' && str[i+1] !== undefined)
      result++;
  }
  return result;
}

SWYM.TextPosForLine = function(text, linenum)
{
  var curlinenum = 1;
  var linestart = 0;
  for( var i = 0; i < text.length; i++ )
  {
    if ( curlinenum >= linenum )
      return i;
    if ( text[i] === '\n' )
      curlinenum++;
  }
  return i;
}

SWYM.LineForTextPos = function(text, textpos)
{
  var result = 1;
  for ( var i = 0; i < textpos; i++ )
  {
    if (text[i] === '\n')
      result++;
  }
  return result;
}

SWYM.PosInLineForTextPos = function(text, textpos)
{
  var result = 1;
  for ( var i = 1; i <= textpos; i++ )
  {
    if (text[textpos-i] === '\n')
      return i;
  }
  return i;
}

SWYM.LogError = function(textpos, message)
{
  SWYM.errors += "Line "+SWYM.LineForTextPos(SWYM.source, textpos)+":"+SWYM.PosInLineForTextPos(SWYM.source, textpos)+" - "+message+"\n";
}

SWYM.ReportErrors = function(ErrorType, OutputSoFar)
{
  if ( SWYM.errors !== "" )
  {
    var numErrors = SWYM.CountLines(SWYM.errors);
    return "-- "+ErrorType+(numErrors>1? ("s ("+numErrors+")"): "")+" --\n" + SWYM.errors + (OutputSoFar?("\n\nOutput so far:\n"+OutputSoFar):"");
  }
}

SWYM.Eval = function(readsource)
{
	SWYM.errors = "";
	
	var tokenlist = SWYM.Tokenize(readsource);
	var result;
	
	result = SWYM.ReportErrors("Reading Error");
	if ( result ) return result;
	
	//temp
//	return tokenlist;
//	alert("tokens: "+tokenlist);
	
	var parsetree = SWYM.Parse(tokenlist);

	result = SWYM.ReportErrors("Parsing Error");
	if ( result ) return result;
	
//	return parsetree;
//	alert("parsed: "+parsetree);

	var executable = SWYM.Compile(parsetree);

	result = SWYM.ReportErrors("Compiling Error");
	if ( result ) return result;

	SWYM.Exec(executable);

	result = SWYM.ReportErrors("Runtime Error");
	if ( result ) return result;

    var output = SWYM.GetOutput();
	
/*	var parsetree = Compile(tokenlist);
	
	result = ReportErrors("Compiling Error");
	if ( result ) return result;
	
	var bakedlist = {};
	parsetree.bakeToList(bakedlist);
//	var bakedtree = parsetree.bake();
	
	result = ReportErrors("Baking Error");
	if ( result ) return result;
	
	PrintedOutput = "";
	var output = RunSequence(globalscope, bakedlist.next);
	
	//var output = bakedtree.eval();
	if ( PrintedOutput !== "" )
	{
		output = PrintedOutput;// + "\n\n -- result: " + output;
	}
	else
	{
		output = "<no output>";
	}
	
	result = ReportErrors("Runtime Error", output);
	if ( result ) return result;
	*/
	return output;
}