/// <summary> /// Tries to convert a CLR object to a MoonSharp value, using more in-depth analysis /// </summary> internal static R_VAL ObjectToValue(RubyState state, object obj) { R_VAL v = TryObjectToSimpleValue(script, obj); if (v != null) { return(v); } v = UserData.Create(obj); if (v != null) { return(v); } if (obj is Type) { v = UserData.CreateStatic(obj as Type); } // unregistered enums go as integers if (obj is Enum) { return(R_VAL.NewNumber( NumericConversions.TypeToDouble(Enum.GetUnderlyingType(obj.GetType()), obj))); } if (v != null) { return(v); } if (obj is Delegate) { return(R_VAL.NewCallback(CallbackFunction.FromDelegate(script, ( Delegate )obj))); } if (obj is MethodInfo) { MethodInfo mi = ( MethodInfo )obj; if (mi.IsStatic) { return(R_VAL.NewCallback(CallbackFunction.FromMethodInfo(script, mi))); } } if (obj is System.Collections.IList) { Table t = TableConversions.ConvertIListToTable(script, (System.Collections.IList)obj); return(R_VAL.NewTable(t)); } if (obj is System.Collections.IDictionary) { Table t = TableConversions.ConvertIDictionaryToTable(script, (System.Collections.IDictionary)obj); return(R_VAL.NewTable(t)); } var enumerator = EnumerationToValue(script, obj); if (enumerator != null) { return(enumerator); } throw ScriptRuntimeException.ConvertObjectFailed(obj); }
/// <summary> /// Converts a R_VAL to a CLR object of a specific type /// </summary> internal static object ValueToObjectOfType(RubyState state, R_VAL value, Type desiredType, object defaultValue, bool isOptional) { if (desiredType.IsByRef) { desiredType = desiredType.GetElementType(); } if (desiredType == typeof(R_VAL)) { return(value); } if (desiredType == typeof(object)) { return(ValueToObject(state, value)); } StringConversions.StringSubtype stringSubType = StringConversions.GetStringSubtype(desiredType); string str = null; Type nt = Nullable.GetUnderlyingType(desiredType); Type nullableType = null; if (nt != null) { nullableType = desiredType; desiredType = nt; } switch (value.tt) { case DataType.Void: if (isOptional) { return(defaultValue); } else if ((!desiredType.IsValueType) || (nullableType != null)) { return(null); } break; case DataType.Nil: if (Framework.Do.IsValueType(desiredType)) { if (nullableType != null) { return(null); } if (isOptional) { return(defaultValue); } } else { return(null); } break; case DataType.Boolean: if (desiredType == typeof(bool)) { return(value.Boolean); } if (stringSubType != StringConversions.StringSubtype.None) { str = value.Boolean.ToString(); } break; case DataType.Number: if (Framework.Do.IsEnum(desiredType)) { // number to enum conv Type underType = Enum.GetUnderlyingType(desiredType); return(NumericConversions.DoubleToType(underType, value.Number)); } if (NumericConversions.NumericTypes.Contains(desiredType)) { return(NumericConversions.DoubleToType(desiredType, value.Number)); } if (stringSubType != StringConversions.StringSubtype.None) { str = value.Number.ToString(); } break; case DataType.String: if (stringSubType != StringConversions.StringSubtype.None) { str = value.String; } break; case DataType.Function: if (desiredType == typeof(Closure)) { return(value.Function); } else if (desiredType == typeof(ScriptFunctionDelegate)) { return(value.Function.GetDelegate()); } break; case DataType.ClrFunction: if (desiredType == typeof(CallbackFunction)) { return(value.Callback); } else if (desiredType == typeof(Func <ScriptExecutionContext, CallbackArguments, R_VAL>)) { return(value.Callback.ClrCallback); } break; case DataType.UserData: if (value.UserData.Object != null) { var udObj = value.UserData.Object; var udDesc = value.UserData.Descriptor; if (udDesc.IsTypeCompatible(desiredType, udObj)) { return(udObj); } if (stringSubType != StringConversions.StringSubtype.None) { str = udDesc.AsString(udObj); } } break; case DataType.Table: if (desiredType == typeof(Table) || Framework.Do.IsAssignableFrom(desiredType, typeof(Table))) { return(value.Table); } else { object o = TableConversions.ConvertTableToType(value.Table, desiredType); if (o != null) { return(o); } } break; case DataType.Tuple: break; } if (stringSubType != StringConversions.StringSubtype.None && str != null) { return(StringConversions.ConvertString(stringSubType, str, desiredType, value.Type)); } throw ScriptRuntimeException.ConvertObjectFailed(value.Type, desiredType); }
/// <summary> /// Tries to convert a CLR object to a MoonSharp value, using "simple" logic. /// Does NOT throw on failure. /// </summary> internal static R_VAL TryObjectToSimpleValue(RubyState state, object obj) { if (obj == null) { return(R_VAL.NIL); } if (obj is R_VAL) { return(( R_VAL )obj); } Type t = obj.GetType(); if (obj is bool) { return(R_VAL.NewBoolean(( bool )obj)); } if (obj is string || obj is StringBuilder || obj is char) { return(R_VAL.NewString(obj.ToString())); } if (obj is Closure) { return(R_VAL.NewClosure(( Closure )obj)); } if (NumericConversions.NumericTypes.Contains(t)) { return(R_VAL.NewNumber(NumericConversions.TypeToDouble(t, obj))); } if (obj is Table) { return(R_VAL.NewTable(( Table )obj)); } if (obj is CallbackFunction) { return(R_VAL.NewCallback(( CallbackFunction )obj)); } if (obj is Delegate) { Delegate d = ( Delegate )obj; #if NETFX_CORE MethodInfo mi = d.GetMethodInfo(); #else MethodInfo mi = d.Method; #endif if (CallbackFunction.CheckCallbackSignature(mi, false)) { return(R_VAL.NewCallback((Func <ScriptExecutionContext, CallbackArguments, R_VAL>)d)); } } return(R_VAL.NIL); }
/// <summary> /// Converts a R_VAL to a CLR object [simple conversion] /// </summary> internal static object ValueToObject(RubyState state, R_VAL value) { if (R_VAL.IsNil(value)) { return(null); } switch (value.tt) { case mrb_vtype.MRB_TT_FALSE: return(false); case mrb_vtype.MRB_TT_TRUE: return(true); case mrb_vtype.MRB_TT_FIXNUM: return(( int )RubyDLL.mrb_fixnum(value)); case mrb_vtype.MRB_TT_SYMBOL: return(RubyDLL.mrb_symbol(value)); case mrb_vtype.MRB_TT_UNDEF: return(null); case mrb_vtype.MRB_TT_FLOAT: return(( float )RubyDLL.mrb_float(value)); case mrb_vtype.MRB_TT_STRING: return(value.ToString(state)); case mrb_vtype.MRB_TT_CPTR: return(RubyDLL.mrb_cptr(value)); case mrb_vtype.MRB_TT_OBJECT: case mrb_vtype.MRB_TT_CLASS: case mrb_vtype.MRB_TT_MODULE: case mrb_vtype.MRB_TT_ICLASS: case mrb_vtype.MRB_TT_SCLASS: case mrb_vtype.MRB_TT_PROC: case mrb_vtype.MRB_TT_RANGE: case mrb_vtype.MRB_TT_EXCEPTION: case mrb_vtype.MRB_TT_FILE: case mrb_vtype.MRB_TT_ENV: case mrb_vtype.MRB_TT_FIBER: case mrb_vtype.MRB_TT_ISTRUCT: case mrb_vtype.MRB_TT_BREAK: case mrb_vtype.MRB_TT_MAXDEFINE: return(RubyDLL.mrb_ptr(value)); case mrb_vtype.MRB_TT_ARRAY: case mrb_vtype.MRB_TT_HASH: // TODO: return(RubyDLL.mrb_ptr(value)); case mrb_vtype.MRB_TT_DATA: return(RubyDLL.IntPtrToObject(RubyDLL.mrb_data_get_ptr(state, value, RubyState.DATA_TYPE_PTR))); default: return(null); } }