#include "stdafx.h"
#include "StormAssert.h"

namespace storm {

	AssertError::AssertError(Str *file, Nat line, MAYBE(Str *) expr, MAYBE(Str *) message)
		: file(file), line(line), expr(expr), msg(message) {
		saveTrace();
	}

	AssertError::AssertError(SrcPos pos, MAYBE(Str *) expr, MAYBE(Str *) message)
		: pos(pos), expr(expr), msg(message) {
		saveTrace();
	}

	void AssertError::message(StrBuf *to) const {
			*to << S("Assertion failed");
		if (msg) {
			*to << S(": ") << msg;
			if (expr) {
				*to << S(" (") << expr << S(")");
			}
		} else if (expr) {
			*to << S(": ") << expr;
		}

		if (file) {
			*to << S("\n") << file << S("(") << line << S(")");
		} else if (pos != SrcPos()) {
			*to << S("\n@") << pos << S(": here");
		}
	}

	void stormDebugAssert(const wchar *file, Nat line, const wchar *expr) {
		stormDebugAssert(file, line, expr, (const wchar *)null);
	}

	void stormDebugAssert(const wchar *file, Nat line, const wchar *expr, const wchar *message) {
		Engine *e = runtime::someEngineUnsafe();
		if (e) {
			Str *stormFile = new (*e) Str(file);
			Str *stormExpr = expr ? new (*e) Str(expr) : null;
			Str *stormMessage = message ? new (*e) Str(message) : null;
			throw new (*e) AssertError(stormFile, line, stormExpr, stormMessage);
		}

		if (expr == null)
			expr = S("");
		if (message == null)
			message = S("");
		throw AssertionException(String(file), line, String(expr), String(message));
	}

	void stormDebugAssert(const wchar *file, Nat line, const wchar *expr, const std::wstring &message) {
		Engine *e = runtime::someEngineUnsafe();
		if (e) {
			Str *stormFile = new (*e) Str(file);
			Str *stormExpr = expr ? new (*e) Str(expr) : null;
			Str *stormMessage = new (*e) Str(message.c_str());
			throw new (*e) AssertError(stormFile, line, stormExpr, stormMessage);
		}

		if (expr == null)
			expr = S("");
		throw AssertionException(String(file), line, String(expr), message);
	}

	void stormDebugAssert(const wchar *file, Nat line, const wchar *expr, Str *message) {
		if (!message) {
			stormDebugAssert(file, line, expr);
		} else {
			Engine &e = message->engine();
			Str *stormFile = new (e) Str(file);
			Str *stormExpr = expr ? new (e) Str(expr) : null;
			throw new (e) AssertError(stormFile, line, stormExpr, message);
		}
	}

}
