#pragma once enum class ErrorCode { Success, OutOfMemory, IndexOutOfRange, TypeMismatch, ReadError, UnterminatedStringLiteral, InvalidNumericLiteral, NotImplemented, InvalidSymbol, MalformedList, KeyError, EndOfProgram, CompilationError, ArgumentCountMismatch, IOError, Interrupt, AssertionFailed, DivisionByZero, SyntaxError, }; class Value; template class Result; const char* errname(ErrorCode errcode); void seterr(const char* err); const char* geterr(void); const Value& geterrobj(void); Result seterrobj(const Value&); void reseterrobj(); #define STRINGIZE_NESTED(A) #A #define STRINGIZE(A) STRINGIZE_NESTED(A) #define ERROR(code) \ (({ \ reseterrobj(); \ seterr("Error " STRINGIZE(code) " at " __FILE__ ":" STRINGIZE(__LINE__)); \ ErrorCode::code; \ })) #define ERROR_FMT(code, ...) \ (({ \ auto name = TRY(Symbol::create(errname(ErrorCode::code))); \ auto message = TRY(build_string(__VA_ARGS__)); \ auto err = Value(TRY(Error::create(name, message))); \ TRY(seterrobj(err)); \ seterr("Error " STRINGIZE(code) " at " __FILE__ ":" STRINGIZE(__LINE__)); \ ErrorCode::code; \ }))