public static bool MatchTypes( MondValueType[] mondTypes, Type[] clrTypes ) { if( mondTypes.Length != clrTypes.Length ) return false; return mondTypes.Zip( clrTypes, ( a, b ) => new { MondType = a, ClrType = b } ).All( x => MatchType( x.MondType, x.ClrType ) ); }
public static string GetName(this MondValueType type) { switch (type) { case MondValueType.Undefined: return("undefined"); case MondValueType.Null: return("null"); case MondValueType.True: case MondValueType.False: return("bool"); case MondValueType.Object: return("object"); case MondValueType.Array: return("array"); case MondValueType.Number: return("number"); case MondValueType.String: return("string"); case MondValueType.Function: return("function"); default: throw new NotSupportedException(); } }
public static bool MatchType( MondValueType mondType, Type clrType ) { if( clrType == typeof( MondValue ) ) return true; switch( mondType ) { case MondValueType.False: case MondValueType.True: return clrType == typeof( bool ); case MondValueType.String: return clrType == typeof( string ); case MondValueType.Number: return NumericTypes.Contains( clrType ) || clrType.IsEnum; case MondValueType.Null: case MondValueType.Undefined: return !clrType.IsValueType; case MondValueType.Function: return clrType == typeof( MulticastDelegate ) || clrType == typeof( Delegate ) || clrType.BaseType == typeof( MulticastDelegate ) || clrType.BaseType == typeof( Delegate ); case MondValueType.Object: throw new NotSupportedException( "Object type matching is not supported by this overload of MatchType" ); default: UnsupportedMondTypeError( mondType ); break; } return false; // we should never get here }
private static void Check(string method, MondValueType type, IList <MondValue> arguments, params MondValueType[] requiredTypes) { if (type != MondValueType.Object) { throw new MondRuntimeException("Object.{0}: must be called on an Object", method); } if (arguments.Count < requiredTypes.Length) { throw new MondRuntimeException("Object.{0}: must be called with {1} argument{2}", method, requiredTypes.Length, requiredTypes.Length == 1 ? "" : "s"); } for (var i = 0; i < requiredTypes.Length; i++) { if (requiredTypes[i] == MondValueType.Undefined) { continue; } if (arguments[i].Type != requiredTypes[i]) { throw new MondRuntimeException("Object.{0}: argument {1} must be of type {2}", method, i + 1, requiredTypes[i]); } } }
/// <summary> /// Construct a new MondValue. Should only be used for Object or Array. /// </summary> public MondValue(MondValueType type) : this() { Type = type; switch (type) { case MondValueType.Undefined: case MondValueType.Null: case MondValueType.True: case MondValueType.False: break; case MondValueType.Object: ObjectValue = new VirtualMachine.Object(); break; case MondValueType.Array: ArrayValue = new List <MondValue>(); break; default: throw new MondException("Incorrect MondValue constructor use"); } }
/// <summary> /// Construct a new MondValue. Should only be used for Object or Array. /// </summary> private MondValue(MondValueType type) { _type = type; _numberValue = 0; switch (type) { case MondValueType.Undefined: case MondValueType.Null: case MondValueType.True: case MondValueType.False: ObjectValue = null; ArrayValue = null; _stringValue = null; FunctionValue = null; break; case MondValueType.Object: ArrayValue = null; _stringValue = null; FunctionValue = null; ObjectValue = new VirtualMachine.Object(); break; case MondValueType.Array: ObjectValue = null; _stringValue = null; FunctionValue = null; ArrayValue = new List <MondValue>(); break; default: throw new MondException("Incorrect MondValue constructor use"); } }
/// <summary> /// Construct a new String MondValue with the specified value. /// </summary> private MondValue(string value) { if (ReferenceEquals(value, null)) { throw new ArgumentNullException(nameof(value)); } Type = MondValueType.String; _stringValue = value; }
/// <summary> /// Construct a new Array MondValue with the specified values. /// </summary> private MondValue(IEnumerable <MondValue> values) { if (ReferenceEquals(values, null)) { throw new ArgumentNullException(nameof(values)); } Type = MondValueType.Array; ArrayValue = new List <MondValue>(values); }
/// <summary> /// Construct a new Function MondValue with the specified value. /// </summary> private MondValue(MondFunction function) { if (ReferenceEquals(function, null)) { throw new ArgumentNullException(nameof(function)); } Type = MondValueType.Function; FunctionValue = new Closure(function); }
internal MondValue(Closure closure) { _type = MondValueType.Function; _numberValue = 0; ObjectValue = null; ArrayValue = null; _stringValue = null; FunctionValue = closure; }
/// <summary> /// Construct a new Number MondValue with the specified value. /// </summary> private MondValue(double value) { _type = MondValueType.Number; _numberValue = value; ObjectValue = null; ArrayValue = null; _stringValue = null; FunctionValue = null; }
private MondValue() { Type = MondValueType.Undefined; ObjectValue = null; ArrayValue = null; _numberValue = 0; _stringValue = null; FunctionValue = null; }
/// <summary> /// Construct a new Object MondValue with the specified values. /// </summary> public MondValue(IEnumerable <KeyValuePair <MondValue, MondValue> > values) { Type = MondValueType.Object; ObjectValue = new VirtualMachine.Object(); var obj = Object; foreach (var kvp in values) { obj.Add(kvp.Key, kvp.Value); } }
/// <summary> /// Construct a new Function MondValue with the specified value. Instance functions will /// bind themselves to their parent object when being retrieved. /// </summary> private MondValue(MondInstanceFunction function) { if (ReferenceEquals(function, null)) { throw new ArgumentNullException(nameof(function)); } _type = MondValueType.Function; _numberValue = 0; ObjectValue = null; ArrayValue = null; _stringValue = null; FunctionValue = new Closure(function); }
/// <summary> /// Construct a new String MondValue with the specified value. /// </summary> private MondValue(string value) { if (ReferenceEquals(value, null)) { throw new ArgumentNullException(nameof(value)); } _type = MondValueType.String; _numberValue = 0; _stringValue = value; ObjectValue = null; ArrayValue = null; FunctionValue = null; _stringValue = value; }
public static bool MatchType(MondValueType mondType, Type clrType) { if ((clrType == typeof(MondValue)) || (clrType == typeof(object))) { return(true); } var info = clrType.GetTypeInfo(); // ReSharper disable once SwitchStatementMissingSomeCases switch (mondType) { case MondValueType.False: case MondValueType.True: return(clrType == typeof(bool)); case MondValueType.String: return(clrType == typeof(string)); case MondValueType.Number: bool IsNumeric(Type type) => TypeConverter.NumericTypes.Contains(type) || type.GetTypeInfo().IsEnum; return(IsNumeric(clrType) || (clrType.IsConstructedGenericType && (clrType.GetGenericTypeDefinition() == typeof(Nullable <>)) && IsNumeric(clrType.GetGenericArguments()[0]))); case MondValueType.Null: case MondValueType.Undefined: return(!info.IsValueType || (clrType.IsConstructedGenericType && (clrType.GetGenericTypeDefinition() == typeof(Nullable <>)))); case MondValueType.Function: return(typeof(Delegate).IsAssignableFrom(clrType)); case MondValueType.Object: throw new NotSupportedException( "Object type matching is not supported by this overload of MatchType"); default: TypeConverter.UnsupportedMondTypeError(mondType); break; } return(false); // we should never get here }
/// <summary> /// Construct a new Number MondValue with the specified value. /// </summary> public MondValue(double value) : this() { Type = MondValueType.Number; _numberValue = value; }
internal MondValue(Closure closure) : this() { Type = MondValueType.Function; FunctionValue = closure; }
public static MondValue MarshalToMond( object value, MondValueType expectedType ) { if( !MatchType( expectedType, value.GetType() ) ) throw new ArgumentException( "Given value does not match expected type", "value" ); if( value is MondValue ) return (MondValue)value; switch( expectedType ) { case MondValueType.False: case MondValueType.True: return (bool)value; case MondValueType.Null: return MondValue.Null; case MondValueType.Undefined: return MondValue.Undefined; case MondValueType.String: return value.ToString(); case MondValueType.Number: return (double)Convert.ChangeType( value, typeof( double ) ); case MondValueType.Function: if( value is MulticastDelegate || value.GetType().BaseType == typeof( MulticastDelegate ) ) return MondObjectBinder.Bind( value as MulticastDelegate ); if( value is Delegate || value.GetType().BaseType == typeof( Delegate ) ) return MondObjectBinder.Bind( value as Delegate ); throw new NotSupportedException( "Unsupported delegate type" ); case MondValueType.Object: return MondObjectBinder.Bind( value.GetType(), value, null, MondBindingOptions.AutoLock ); default: UnsupportedMondTypeError( expectedType ); break; } return null; // we should never get here }
public static MondValue[] MarshalToMond( object[] values, MondValueType[] expectedTypes ) { if( !MatchTypes( expectedTypes, values.Select( v => v.GetType() ).ToArray() ) ) throw new ArgumentException( "Given values do not match expected types", "values" ); return values.Zip( expectedTypes, ( a, b ) => new { Value = a, ExpectedType = b } ).Select( x => MarshalToMond( x.Value, x.ExpectedType ) ).ToArray(); }
/// <summary> /// Construct a new Object MondValue and attach a MondState to it. Should be used if using metamethods. /// </summary> private MondValue(MondState state) { Type = MondValueType.Object; ObjectValue = new VirtualMachine.Object(); ObjectValue.State = state; }
/// <summary> /// Construct a new Number MondValue with the specified value. /// </summary> private MondValue(double value) { Type = MondValueType.Number; _numberValue = value; }
private static void UnsupportedMondTypeError( MondValueType type ) { throw new NotSupportedException( "Unsupported MondValueType '{0}'".With( type.GetName() ) ); }
private static void UnsupportedMondTypeError(MondValueType type) => throw new NotSupportedException( $"Unsupported MondValueType '{type.GetName()}'");
/// <summary> /// Construct a new String MondValue with the specified value. /// </summary> public MondValue(string value) : this() { Type = MondValueType.String; _stringValue = value; }
/// <summary> /// Construct a new Function MondValue with the specified value. Instance functions will /// bind themselves to their parent object when being retrieved. /// </summary> public MondValue(MondInstanceFunction function) : this() { Type = MondValueType.Function; FunctionValue = new Closure(function); }
public static MondValue MarshalToMond( object value, MondValueType expectedType, MondState state, MondBindingOptions options) { if (value == null) { return(MondValue.Null); } if (expectedType == MondValueType.Object) { if (state == null) { throw new ArgumentNullException( nameof(state), "Must have a valid MondState when binding an object"); } return(MondObjectBinder.Bind(value.GetType(), value, state, options)); } if (!TypeConverter.MatchType(expectedType, value.GetType())) { throw new ArgumentException("Given value does not match expected type", nameof(value)); } if (value is MondValue mond) { return(mond); } var type = value.GetType(); if (type.IsConstructedGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable <>))) { var innerType = type.GetGenericArguments()[0]; dynamic nullable = value; if (!TypeConverter.MatchType(expectedType, innerType) || (!nullable.HasValue && (expectedType != MondValueType.Null) && (expectedType != MondValueType.Undefined))) { throw new ArgumentException("Given value does not match expected type", nameof(value)); } value = nullable.Value; } // ReSharper disable once SwitchStatementMissingSomeCases switch (expectedType) { case MondValueType.False: case MondValueType.True: return((bool)value); case MondValueType.Null: return(MondValue.Null); case MondValueType.Undefined: return(MondValue.Undefined); case MondValueType.String: return(value.ToString()); case MondValueType.Number: return((double)Convert.ChangeType(value, typeof(double))); case MondValueType.Function: var info = value.GetType().GetTypeInfo(); if (value is MulticastDelegate || (info.BaseType == typeof(MulticastDelegate))) { return(MondObjectBinder.Bind(value as MulticastDelegate)); } if (value is Delegate || (info.BaseType == typeof(Delegate))) { return(MondObjectBinder.Bind(value as Delegate)); } throw new NotSupportedException("Unsupported delegate type"); case MondValueType.Object: return(MondObjectBinder.Bind(value.GetType(), value, null, MondBindingOptions.AutoLock)); default: TypeConverter.UnsupportedMondTypeError(expectedType); break; } return(null); // we should never get here }