Esempio n. 1
0
        private static MondValue JsonValueProperty(MondValue key, MondValue value)
        {
            var property = MondValue.Object();

            property["name"]      = key.ToString();
            property["nameType"]  = key.Type.GetName();
            property["value"]     = value.ToString();
            property["valueType"] = value.Type.GetName();
            return(property);
        }
Esempio n. 2
0
        public static bool MatchType( MondValue value, Type type )
        {
            if( type == typeof( char ) )
                return value.Type == MondValueType.String && value.ToString().Length == 1;

            if( value.Type == MondValueType.Object )
                return value.UserData != null && type.IsAssignableFrom( value.UserData.GetType() );

            return MatchType( value.Type, type );
        }
Esempio n. 3
0
        public static bool MatchType(MondValue value, Type type)
        {
            if (type == typeof(char))
            {
                return((value.Type == MondValueType.String) && (value.ToString().Length == 1));
            }

            if (value.Type == MondValueType.Object)
            {
                return((type == typeof(MondValue)) ||
                       ((value.UserData != null) && type.IsInstanceOfType(value.UserData)));
            }

            return(TypeConverter.MatchType(value.Type, type));
        }
Esempio n. 4
0
        public static string Format([MondInstance] MondValue instance, params MondValue[] arguments)
        {
            var values = arguments.Select <MondValue, object>(x =>
            {
                // System.String.Format has certain format specifiers
                // that are valid for integers but not floats
                // (ex. String.Format( "{0:x2}", 1.23f ); throws FormatException
                // So we treat all whole numbers as integers, everything else
                // remains unchanged.
                if (x.Type == MondValueType.Number)
                {
                    if (x % 1.0 == 0.0)
                    {
                        return((int)x);
                    }

                    return((double)x);
                }

                return(x.ToString());
            }).ToArray();

            return(string.Format(instance.ToString(), values));
        }
Esempio n. 5
0
        public static object MarshalToClr( MondValue value, Type expectedType, MondState state )
        {
            if( !MatchType( value, expectedType ) )
                throw new ArgumentException( "Given value does not match expected type", "value" );

            if( expectedType == typeof( MondValue ) )
                return value;

            switch( value.Type )
            {
                case MondValueType.False:
                case MondValueType.True:
                    return (bool)value;

                case MondValueType.Null:
                case MondValueType.Undefined:
                    return null;

                case MondValueType.String:
                    var str = value.ToString();
                    if( expectedType == typeof( char ) )
                    {
                        if( str.Length != 1 )
                            throw new ArgumentException( "Value cannot be converted to char", "value" );

                        return str[0];
                    }

                    return str;

                case MondValueType.Number:
                    if( expectedType.IsEnum )
                    {
                        var underlying = Enum.GetUnderlyingType( expectedType );
                        var rawValue = Convert.ChangeType( (double)value, underlying );
                        var valueName = Enum.GetName( expectedType, rawValue );

                        return Enum.Parse( expectedType, valueName );
                    }

                    return Convert.ChangeType( (double)value, expectedType );

                case MondValueType.Object:
                    return value.UserData;

                case MondValueType.Function:
                    Func<object[], object> shim = delegate( object[] args )
                    {
                        var result = null as MondValue;

                        if( args == null )
                            result = state.Call( value );
                        else
                        {
                            var mondTypes = ToMondTypes( args.Select( a => a.GetType() ).ToArray() );
                            var mondValues = MarshalToMond( args, mondTypes );
                            result = state.Call( value, mondValues );
                        }

                        var clrType = ToClrType( result );
                        return MarshalToClr( result, clrType, state );
                    };

                    return shim;

                default:
                    UnsupportedMondTypeError( value.Type );
                    break;
            }

            return null; // we should never get here
        }
Esempio n. 6
0
 public static string ToString([MondInstance] MondValue instance)
 {
     return(instance.ToString());
 }
Esempio n. 7
0
 private static MondValue ToString(MondState state, MondValue instance, params MondValue[] args)
 {
     return(instance.ToString());
 }
Esempio n. 8
0
        public static object MarshalToClr(
            MondValue value,
            Type expectedType,
            MondState state,
            MondBindingOptions options)
        {
            if (!TypeConverter.MatchType(value, expectedType))
            {
                throw new ArgumentException("Given value does not match expected type", nameof(value));
            }

            if (expectedType == typeof(MondValue))
            {
                return(value);
            }

            // ReSharper disable once SwitchStatementMissingSomeCases
            switch (value.Type)
            {
            case MondValueType.False:
            case MondValueType.True: return((bool)value);

            case MondValueType.Null:
            case MondValueType.Undefined:
                if (!expectedType.GetTypeInfo().IsValueType)
                {
                    return(null);
                }

                if (expectedType.IsConstructedGenericType &&
                    (expectedType.GetGenericTypeDefinition() == typeof(Nullable <>)))
                {
                    return(Activator.CreateInstance(expectedType));
                }

                throw new InvalidOperationException(
                          $"Cannot bind {value.Type.GetName()} value to " +
                          $"{expectedType.FullName} because it is a value type");

            case MondValueType.String:
                var str = value.ToString();
                if (expectedType != typeof(char))
                {
                    return(str);
                }

                if (str.Length != 1)
                {
                    throw new ArgumentException("Value cannot be converted to char", nameof(value));
                }

                return(str[0]);

            case MondValueType.Number:
                if (expectedType.IsConstructedGenericType &&
                    (expectedType.GetGenericTypeDefinition() == typeof(Nullable <>)))
                {
                    var innerType = expectedType.GetGenericArguments()[0];
                    var converted = Convert.ChangeType((double)value, innerType);
                    return(Activator.CreateInstance(expectedType, converted));
                }

                if (!expectedType.GetTypeInfo().IsEnum)
                {
                    return(Convert.ChangeType((double)value, expectedType));
                }

                var underlying = Enum.GetUnderlyingType(expectedType);
                var rawValue   = Convert.ChangeType((double)value, underlying);
                var valueName  = Enum.GetName(expectedType, rawValue);

                // ReSharper disable once AssignNullToNotNullAttribute
                return(Enum.Parse(expectedType, valueName));

            case MondValueType.Object: return(value.UserData);

            case MondValueType.Function:

                object Shim(object[] args)
                {
                    MondValue result;

                    if ((args == null) || (args.Length == 0))
                    {
                        result = state.Call(value);
                    }
                    else
                    {
                        var mondTypes = TypeConverter.ToMondTypes(
                            args.Select(a => a.GetType()).ToArray());
                        var mondValues = TypeConverter.MarshalToMond(args, mondTypes, state, options);
                        result = state.Call(value, mondValues);
                    }

                    if ((result.Type == MondValueType.Null) || (result.Type == MondValueType.Undefined))
                    {
                        return(null);
                    }

                    var clrType = TypeConverter.ToClrType(result);

                    return(TypeConverter.MarshalToClr(result, clrType, state, options));
                }

                if (!typeof(Delegate).IsAssignableFrom(expectedType))
                {
                    return((Func <object[], object>)Shim);
                }

                var invoke       = expectedType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance);
                var parameters   = invoke.GetParameters().Select(p => p.ParameterType).ToArray();
                var delegateType = invoke.ReturnType == typeof(void)
                        ? Expression.GetActionType(parameters)
                        : Expression.GetFuncType(parameters.Concat(invoke.ReturnType).ToArray());

                var shim = (Func <object[], object>)Shim;

                var paramsExpr = parameters.Select(Expression.Parameter).ToArray();
                // ReSharper disable once CoVariantArrayConversion
                var paramsArr  = Expression.NewArrayInit(typeof(object), paramsExpr);
                var invokeExpr = Expression.Call(
                    Expression.Constant(shim.Target),
                    shim.GetMethodInfo(),
                    paramsArr);

                // ReSharper disable once TooWideLocalVariableScope
                BlockExpression body;
                if (invoke.ReturnType == typeof(void))
                {
                    body = Expression.Block(invokeExpr);
                }
                else
                {
                    var castExpr = Expression.Convert(invokeExpr, invoke.ReturnType);
                    body = Expression.Block(castExpr);
                }

                var method = typeof(Expression)
                             .GetMethods(BindingFlags.Public | BindingFlags.Static)
                             .Where(m => m.Name == "Lambda")
                             .First(m => m.IsGenericMethodDefinition);

                var lambda = method.MakeGenericMethod(delegateType);
                return(((LambdaExpression)lambda.Invoke(null, new object[] { body, paramsExpr })).Compile());

            default:
                TypeConverter.UnsupportedMondTypeError(value.Type);
                break;
            }

            return(null); // we should never get here
        }