using System;
using MoonSharp.Interpreter.Interop;
using MoonSharp.Interpreter.Interop.BasicDescriptors;
namespace MoonSharp.Interpreter
{
///
/// Exception for all runtime errors. In addition to constructors, it offers a lot of static methods
/// generating more "standard" Lua errors.
///
#if !(PCL || ((!UNITY_EDITOR) && (ENABLE_DOTNET)) || NETFX_CORE)
[Serializable]
#endif
public class ScriptRuntimeException : InterpreterException
{
///
/// Initializes a new instance of the class.
///
/// The ex.
public ScriptRuntimeException(Exception ex)
: base(ex)
{
}
///
/// Initializes a new instance of the class.
///
/// The ex.
public ScriptRuntimeException(ScriptRuntimeException ex)
: base(ex, ex.DecoratedMessage)
{
this.DecoratedMessage = Message;
this.DoNotDecorateMessage = true;
}
///
/// Initializes a new instance of the class.
///
/// The message that describes the error.
public ScriptRuntimeException(string message)
: base(message)
{
}
///
/// Initializes a new instance of the class.
///
/// The format.
/// The arguments.
public ScriptRuntimeException(string format, params object[] args)
: base(format, args)
{
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an arithmetic operation was attempted on non-numbers
///
/// The left operand.
/// The right operand (or null).
/// The exception to be raised.
/// If both are numbers
public static ScriptRuntimeException ArithmeticOnNonNumber(DynValue l, DynValue r = null)
{
if (l.Type != DataType.Number && l.Type != DataType.String)
return new ScriptRuntimeException("attempt to perform arithmetic on a {0} value", l.Type.ToLuaTypeString());
else if (r != null && r.Type != DataType.Number && r.Type != DataType.String)
return new ScriptRuntimeException("attempt to perform arithmetic on a {0} value", r.Type.ToLuaTypeString());
else if (l.Type == DataType.String || (r != null && r.Type == DataType.String))
return new ScriptRuntimeException("attempt to perform arithmetic on a string value");
else
throw new InternalErrorException("ArithmeticOnNonNumber - both are numbers");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a concat operation was attempted on non-strings
///
/// The left operand.
/// The right operand.
/// The exception to be raised.
/// If both are numbers or strings
public static ScriptRuntimeException ConcatOnNonString(DynValue l, DynValue r)
{
if (l.Type != DataType.Number && l.Type != DataType.String)
return new ScriptRuntimeException("attempt to concatenate a {0} value", l.Type.ToLuaTypeString());
else if (r != null && r.Type != DataType.Number && r.Type != DataType.String)
return new ScriptRuntimeException("attempt to concatenate a {0} value", r.Type.ToLuaTypeString());
else
throw new InternalErrorException("ConcatOnNonString - both are numbers/strings");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a len operator was applied on an invalid operand
///
/// The operand.
/// The exception to be raised.
public static ScriptRuntimeException LenOnInvalidType(DynValue r)
{
return new ScriptRuntimeException("attempt to get length of a {0} value", r.Type.ToLuaTypeString());
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a comparison operator was applied on an invalid combination of operand types
///
/// The left operand.
/// The right operand.
/// The exception to be raised.
public static ScriptRuntimeException CompareInvalidType(DynValue l, DynValue r)
{
if (l.Type.ToLuaTypeString() == r.Type.ToLuaTypeString())
return new ScriptRuntimeException("attempt to compare two {0} values", l.Type.ToLuaTypeString());
else
return new ScriptRuntimeException("attempt to compare {0} with {1}", l.Type.ToLuaTypeString(), r.Type.ToLuaTypeString());
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a function was called with a bad argument
///
/// The argument number (0-based).
/// Name of the function generating this error.
/// The error message.
/// The exception to be raised.
public static ScriptRuntimeException BadArgument(int argNum, string funcName, string message)
{
return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2})", argNum + 1, funcName, message);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a function was called with a bad userdata argument
///
/// The argument number (0-based).
/// Name of the function generating this error.
/// The expected System.Type.
/// The object which was used.
/// True if nils were allowed in this call.
///
/// The exception to be raised.
///
public static ScriptRuntimeException BadArgumentUserData(int argNum, string funcName, Type expected, object got, bool allowNil)
{
return new ScriptRuntimeException("bad argument #{0} to '{1}' (userdata<{2}>{3} expected, got {4})",
argNum + 1,
funcName,
expected.Name,
allowNil ? "nil or " : "",
got != null ? "userdata<" + got.GetType().Name + ">" : "null"
);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a function was called with a bad argument
///
/// The argument number (0-based).
/// Name of the function generating this error.
/// The expected data type.
/// The data type received.
/// True if nils were allowed in this call.
///
/// The exception to be raised.
///
public static ScriptRuntimeException BadArgument(int argNum, string funcName, DataType expected, DataType got, bool allowNil)
{
return BadArgument(argNum, funcName, expected.ToErrorTypeString(), got.ToErrorTypeString(), allowNil);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a function was called with a bad argument
///
/// The argument number (0-based).
/// Name of the function generating this error.
/// The expected type description.
/// The description of the type received.
/// True if nils were allowed in this call.
///
/// The exception to be raised.
///
public static ScriptRuntimeException BadArgument(int argNum, string funcName, string expected, string got, bool allowNil)
{
return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2}{3} expected, got {4})",
argNum + 1, funcName, allowNil ? "nil or " : "", expected, got);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a function was called with no value when a value was required.
///
/// This function creates a message like "bad argument #xxx to 'yyy' (zzz expected, got no value)"
/// while creates a message like "bad argument #xxx to 'yyy' (value expected)"
///
/// The argument number (0-based).
/// Name of the function generating this error.
/// The expected data type.
///
/// The exception to be raised.
///
public static ScriptRuntimeException BadArgumentNoValue(int argNum, string funcName, DataType expected)
{
return new ScriptRuntimeException("bad argument #{0} to '{1}' ({2} expected, got no value)",
argNum + 1, funcName, expected.ToErrorTypeString());
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an out of range index was specified
///
/// The argument number (0-based).
/// Name of the function generating this error.
///
/// The exception to be raised.
///
public static ScriptRuntimeException BadArgumentIndexOutOfRange(string funcName, int argNum)
{
return new ScriptRuntimeException("bad argument #{0} to '{1}' (index out of range)", argNum + 1, funcName);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a function was called with a negative number when a positive one was expected.
///
/// The argument number (0-based).
/// Name of the function generating this error.
///
/// The exception to be raised.
///
public static ScriptRuntimeException BadArgumentNoNegativeNumbers(int argNum, string funcName)
{
return new ScriptRuntimeException("bad argument #{0} to '{1}' (not a non-negative number in proper range)",
argNum + 1, funcName);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a function was called with no value when a value was required.
/// This function creates a message like "bad argument #xxx to 'yyy' (value expected)"
/// while creates a message like "bad argument #xxx to 'yyy' (zzz expected, got no value)"
///
/// The argument number (0-based).
/// Name of the function generating this error.
///
/// The exception to be raised.
///
public static ScriptRuntimeException BadArgumentValueExpected(int argNum, string funcName)
{
return new ScriptRuntimeException("bad argument #{0} to '{1}' (value expected)",
argNum + 1, funcName);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an invalid attempt to index the specified object was made
///
/// The object.
///
/// The exception to be raised.
///
public static ScriptRuntimeException IndexType(DynValue obj)
{
return new ScriptRuntimeException("attempt to index a {0} value", obj.Type.ToLuaTypeString());
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a loop was detected when performing __index over metatables.
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException LoopInIndex()
{
return new ScriptRuntimeException("loop in gettable");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a loop was detected when performing __newindex over metatables.
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException LoopInNewIndex()
{
return new ScriptRuntimeException("loop in settable");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a loop was detected when performing __call over metatables.
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException LoopInCall()
{
return new ScriptRuntimeException("loop in call");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a table indexing operation used nil as the key.
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException TableIndexIsNil()
{
return new ScriptRuntimeException("table index is nil");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a table indexing operation used a NaN as the key.
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException TableIndexIsNaN()
{
return new ScriptRuntimeException("table index is NaN");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a conversion to number failed.
///
///
/// Selects the correct error message:
/// 0 - "value must be a number"
/// 1 - "'for' initial value must be a number"
/// 2 - "'for' step must be a number"
/// 3 - "'for' limit must be a number"
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException ConvertToNumberFailed(int stage)
{
switch (stage)
{
case 1:
return new ScriptRuntimeException("'for' initial value must be a number");
case 2:
return new ScriptRuntimeException("'for' step must be a number");
case 3:
return new ScriptRuntimeException("'for' limit must be a number");
default:
return new ScriptRuntimeException("value must be a number");
}
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a conversion of a CLR type to a Lua type has failed.
///
/// The object which could not be converted.
///
/// The exception to be raised.
///
public static ScriptRuntimeException ConvertObjectFailed(object obj)
{
return new ScriptRuntimeException("cannot convert clr type {0}", obj.GetType());
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a conversion of a Lua type to a CLR type has failed.
///
/// The Lua type.
///
/// The exception to be raised.
///
public static ScriptRuntimeException ConvertObjectFailed(DataType t)
{
return new ScriptRuntimeException("cannot convert a {0} to a clr type", t.ToString().ToLowerInvariant());
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a constrained conversion of a Lua type to a CLR type has failed.
///
/// The Lua type.
/// The expected CLR type.
///
/// The exception to be raised.
///
public static ScriptRuntimeException ConvertObjectFailed(DataType t, Type t2)
{
return new ScriptRuntimeException("cannot convert a {0} to a clr type {1}", t.ToString().ToLowerInvariant(), t2.FullName);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// a userdata of a specific CLR type was expected and a non-userdata type was passed.
///
/// The Lua type.
/// The expected CLR type.
///
/// The exception to be raised.
///
public static ScriptRuntimeException UserDataArgumentTypeMismatch(DataType t, Type clrType)
{
return new ScriptRuntimeException("cannot find a conversion from a MoonSharp {0} to a clr {1}", t.ToString().ToLowerInvariant(), clrType.FullName);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an attempt to index an invalid member of a userdata was done.
///
/// The name of the userdata type.
/// The field name.
///
/// The exception to be raised.
///
public static ScriptRuntimeException UserDataMissingField(string typename, string fieldname)
{
return new ScriptRuntimeException("cannot access field {0} of userdata<{1}>", fieldname, typename);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an attempt resume a coroutine in an invalid state was done.
///
/// The state of the coroutine.
///
/// The exception to be raised.
///
public static ScriptRuntimeException CannotResumeNotSuspended(CoroutineState state)
{
if (state == CoroutineState.Dead)
return new ScriptRuntimeException("cannot resume dead coroutine");
else
return new ScriptRuntimeException("cannot resume non-suspended coroutine");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an attempt to yield across a CLR boundary was made.
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException CannotYield()
{
return new ScriptRuntimeException("attempt to yield across a CLR-call boundary");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an attempt to yield from the main coroutine was made.
///
///
/// The exception to be raised.
///
public static ScriptRuntimeException CannotYieldMain()
{
return new ScriptRuntimeException("attempt to yield from outside a coroutine");
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an attempt to call a non-function was made
///
/// The lua non-function data type.
/// The debug text to aid location (appears as "near 'xxx'").
///
public static ScriptRuntimeException AttemptToCallNonFunc(DataType type, string debugText = null)
{
string functype = type.ToErrorTypeString();
if (debugText != null)
return new ScriptRuntimeException("attempt to call a {0} value near '{1}'", functype, debugText);
else
return new ScriptRuntimeException("attempt to call a {0} value", functype);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an attempt to access a non-static member from a static userdata was made
///
/// The member descriptor.
public static ScriptRuntimeException AccessInstanceMemberOnStatics(IMemberDescriptor desc)
{
return new ScriptRuntimeException("attempt to access instance member {0} from a static userdata", desc.Name);
}
///
/// Creates a ScriptRuntimeException with a predefined error message specifying that
/// an attempt to access a non-static member from a static userdata was made
///
/// The type descriptor.
/// The member descriptor.
///
public static ScriptRuntimeException AccessInstanceMemberOnStatics(IUserDataDescriptor typeDescr, IMemberDescriptor desc)
{
return new ScriptRuntimeException("attempt to access instance member {0}.{1} from a static userdata", typeDescr.Name, desc.Name);
}
///
/// Rethrows this instance if
///
///
public override void Rethrow()
{
if (Script.GlobalOptions.RethrowExceptionNested)
throw new ScriptRuntimeException(this);
}
}
}