﻿/**
 * Authors: k.inaba
 * License: NYSL 0.9982 http://www.kmonos.net/nysl/
 *
 * Error Information for Polemy Programming Language
 */
module polemy.failure;
import polemy._common;

/// Represents a position in source codes

class LexPosition_t
{
	immutable string filename; /// name of the source file
	immutable int    lineno;   /// 1-origin
	immutable int    column;   /// 1-origin

	mixin SimpleClass;
	override string toString() const
	{
		return sprintf!("%s:%d:%d")(filename, lineno, column);
	}

	static LexPosition dummy;
	static this(){ dummy = new LexPosition("<unnamed>",0,0); }
}

/// Represents a position in source codes

alias immutable(LexPosition_t) LexPosition;

unittest
{
	auto p = new LexPosition("hello.cpp", 123, 45);

	assert_eq( p.filename, "hello.cpp" );
	assert_eq( p.lineno, 123 );
	assert_eq( p.column, 45 );
	assert_eq( text(p), "hello.cpp:123:45" );

	assert( !__traits(compiles, new LexPosition) );
	assert( !__traits(compiles, p.filename="foo") );
	assert( !__traits(compiles, p.lineno  =789) );
	assert( !__traits(compiles, p.column  =222) );

	auto q = new LexPosition("hello.cpp", 123, 46);
	assert_lt( p, q );
	assert_ne( p, q );
}

/*mixin*/
template ExceptionWithPosition()
{
	LexPosition pos;
	this( LexPosition pos, string msg, string file=null, size_t line=0, Throwable next=null )
	{
		if(pos is null)
			super(sprintf!("[??] %s")(msg), file, line, next);
		else
			super(sprintf!("[%s] %s")(pos, msg), file, line, next);
		this.pos = pos;
	}
}

class UnexpectedEOF : Exception { mixin ExceptionWithPosition; } /// EOF during lexing/parsing
class LexException : Exception { mixin ExceptionWithPosition; } /// Lexer errors
class ParseException : Exception { mixin ExceptionWithPosition; } /// Parser errors
class RuntimeException : Exception { mixin ExceptionWithPosition; } /// Evaluator errors
