Пример #1
0
            // writers

            public void WriteItem(object value)
            {
                if (value == null)
                {
                    WriteMarker(Marker.Null);
                }
                else
                {
                    var type = value.GetType();

                    if (Int29Types.Contains(type))
                    {
                        WriteInt29(Convert.ToInt32(value));
                    }
                    else if (NumberTypes.Contains(type))
                    {
                        WriteDouble(Convert.ToDouble(value));
                    }
                    else if (Writers.TryGetValue(type, out var writer))
                    {
                        writer(this, value);
                    }
                    else
                    {
                        DispatchGenericWrite(value);
                    }
                }
            }
Пример #2
0
        internal static ReturnConverter MakeReturnConversion(Type returnType)
        {
            if (returnType == typeof(void))
            {
                return((e, s, o) => MondValue.Undefined);
            }

            if (returnType == typeof(MondValue))
            {
                return((e, s, o) => ReferenceEquals(o, null) ? MondValue.Null : (MondValue)o);
            }

            if (returnType == typeof(string))
            {
                return((e, s, o) => ReferenceEquals(o, null) ? MondValue.Null : (MondValue)(string)o);
            }

            if (returnType == typeof(bool))
            {
                return((e, s, o) => (bool)o);
            }

            if (NumberTypes.Contains(returnType))
            {
                return((e, s, o) => Convert.ToDouble(o));
            }

            var classAttrib = returnType.Attribute <MondClassAttribute>();

            if (classAttrib != null && classAttrib.AllowReturn)
            {
                var className = classAttrib.Name ?? returnType.Name;

                return((e, s, o) =>
                {
                    var prototype = s.FindPrototype(className);
                    if (prototype == null)
                    {
                        throw new MondRuntimeException(e + string.Format(BindingError.PrototypeNotFound, className));
                    }

                    var obj = new MondValue(s);
                    obj.Prototype = prototype;
                    obj.UserData = o;
                    return obj;
                });
            }

            throw new MondBindingException(BindingError.UnsupportedReturnType, returnType);
        }
Пример #3
0
        // MondValue -> T
        internal static Func <Expression, Expression> MakeParameterConversion(Type parameterType)
        {
            if (BasicTypes.Contains(parameterType))
            {
                return(e => Expression.Convert(e, parameterType));
            }

            if (NumberTypes.Contains(parameterType))
            {
                return(e => Expression.Convert(Expression.Convert(e, typeof(double)), parameterType));
            }

            return(null);
        }
Пример #4
0
            void WriteItemInternal(object value)
            {
                var type = value.GetType();

                if (NumberTypes.Contains(type))
                {
                    WriteNumber(Convert.ToDouble(value));
                }
                else if (Writers.TryGetValue(type, out var write))
                {
                    write(this, value);
                }
                else
                {
                    DispatchGenericWrite(value);
                }
            }
Пример #5
0
        // T -> MondValue
        internal static ReturnConverter MakeReturnConversion(Type returnType)
        {
            if (returnType == typeof(void))
            {
                return((e, s, v) => throw new MondBindingException("Expression binder should not use void return conversion"));
            }

            if (returnType == typeof(MondValue))
            {
                return((e, s, v) => Expression.Coalesce(v, Expression.Constant(MondValue.Null)));
            }

            if (returnType == typeof(string))
            {
                return((e, s, v) =>
                {
                    var tempVar = Expression.Variable(typeof(string));

                    var tempVarIsNull = Expression.ReferenceEqual(tempVar, Expression.Constant(null));
                    var tempVarAsValue = Expression.Convert(tempVar, typeof(MondValue));

                    var block = Expression.Block(
                        new[] { tempVar },
                        Expression.Assign(tempVar, v),
                        Expression.Condition(tempVarIsNull, Expression.Constant(MondValue.Null), tempVarAsValue)
                        );

                    return block;
                });
            }

            if (BasicTypes.Contains(returnType))
            {
                return((e, s, v) => Expression.Convert(v, typeof(MondValue)));
            }

            if (NumberTypes.Contains(returnType))
            {
                return((e, s, v) => Expression.Convert(Expression.Convert(v, typeof(double)), typeof(MondValue)));
            }

            var classAttrib = returnType.Attribute <MondClassAttribute>();

            if (classAttrib != null && classAttrib.AllowReturn)
            {
                var objInitializerType = typeof(IEnumerable <KeyValuePair <MondValue, MondValue> >);
                var valueFactory       = typeof(MondValue).GetMethod("Object", new[] { typeof(MondState), objInitializerType });
                if (valueFactory == null)
                {
                    throw new Exception("Could not find MondValue.Object method");
                }

                var findPrototype = typeof(MondState).GetMethod("FindPrototype");
                if (findPrototype == null)
                {
                    throw new Exception("Could not find FindPrototype method");
                }

                var className = classAttrib.Name ?? returnType.Name;

                return((e, s, v) =>
                {
                    var prototype = Expression.Variable(typeof(MondValue));
                    var obj = Expression.Variable(typeof(MondValue));

                    var throwMsg = Expression.Constant(e + string.Format(BindingError.PrototypeNotFound, className));
                    var throwExpr = Expression.Throw(Expression.New(RuntimeExceptionConstructor, throwMsg));

                    return Expression.Block(
                        new [] { prototype, obj },
                        Expression.Assign(prototype, Expression.Call(s, findPrototype, Expression.Constant(className))),
                        Expression.IfThen(Expression.ReferenceEqual(prototype, Expression.Constant(null)), throwExpr),
                        Expression.Assign(obj, Expression.Call(valueFactory, s, Expression.Constant(null, objInitializerType))),
                        Expression.Assign(Expression.PropertyOrField(obj, "Prototype"), prototype),
                        Expression.Assign(Expression.PropertyOrField(obj, "UserData"), v),
                        obj
                        );
                });
            }

            throw new MondBindingException(BindingError.UnsupportedReturnType, returnType);
        }