Artifact 2827b7df74d1df197a586b61058e49f4d15b4a5b
/**
* 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
alias immutable(LexPosition_t) LexPosition;
/// 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("<nowhere>",0,0); }
}
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 )
{
string fullmsg = pos is null ? sprintf!("\n[??] %s")(msg)
: sprintf!("\n[%s] %s")(pos, msg);
for(int i=0; i<callstack_pos.length || i<callstack_msg.length; ++i)
{
LexPosition p = (i<callstack_pos.length ? callstack_pos[i] : null);
string m = (i<callstack_msg.length ? callstack_msg[i] : null);
fullmsg ~= p is null ? sprintf!("\n[??] %s")(m)
: sprintf!("\n[%s] %s")(p, m);
}
super(fullmsg, file, line, next);
this.pos = pos;
}
this( string msg, string file=null, size_t line=0, Throwable next=null )
{
this(null, msg, file, line, next);
}
}
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
/// Per-thread call stack management.
/// This scoped class's ctor&dtor maintain the callstack.
/// TODO: make it "per-evaluator" !!!!!!!!!!!
scope class PushCallStack
{
this(LexPosition pos, string msg) { callstackEnterFunction(pos,msg); }
~this() { callstackLeaveFunction(); }
}
LexPosition[] callstack_pos;
string[] callstack_msg;
private void callstackEnterFunction(LexPosition pos, string msg)
{
callstack_pos ~= pos;
callstack_msg ~= msg;
}
private void callstackLeaveFunction()
{
callstack_pos.length -= 1;
callstack_msg.length -= 1;
}