예제 #1
0
        private static object FromSymbol(Type destType, Symbol symbol)
        {
            // desymbolize .NET primitive
            if (destType.IsPrimitive)
            {
                return(symbol.Match(
                           atom => TypeDescriptor.GetConverter(destType).ConvertFromString(atom),
                           number => TypeDescriptor.GetConverter(destType).ConvertFromString(number),
                           str => TypeDescriptor.GetConverter(destType).ConvertFromString(str),
                           quote => Expression <object> .Throw <ConversionException>(),
                           symbols => Expression <object> .Throw <ConversionException>()));
            }

            // desymbolize string
            if (destType == typeof(string))
            {
                return(symbol.Match(
                           atom => SymbolParser.IsExplicit(atom) ? atom.Substring(1, atom.Length - 2) : atom,
                           number => number,
                           str => str,
                           quote => Expression <object> .Throw <ConversionException>(),
                           symbols => Expression <object> .Throw <ConversionException>()));
            }

            // desymbolize Symbol (no tranformation)
            if (destType == typeof(Symbol))
            {
                return(symbol);
            }

            // desymbolize user-defined type
            var typeConverterOpt = destType.TryGetCustomTypeConverter();

            if (typeConverterOpt != null)
            {
                if (typeConverterOpt.CanConvertFrom(typeof(Symbol)))
                {
                    return(typeConverterOpt.ConvertFrom(symbol));
                }
                throw new ConversionException("Expected ability to convert from Symbol for custom type converter '" + typeConverterOpt.GetType().Name + "'.");
            }

            // desymbolize vanilla .NET type
            return(symbol.Match(
                       atom => TypeDescriptor.GetConverter(destType).ConvertFromString(atom),
                       number => TypeDescriptor.GetConverter(destType).ConvertFromString(number),
                       str => TypeDescriptor.GetConverter(destType).ConvertFromString(str),
                       quote => Expression <object> .Throw(new ConversionException("Expected atom, number, or string for vanilla .NET type.")),
                       symbols => Expression <object> .Throw(new ConversionException("Expected atom, number, or string for vanilla .NET type."))));
        }
예제 #2
0
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            var sourceType = value.GetType();

            if (sourceType == pointType)
            {
                return(value);
            }
            if (sourceType == typeof(string))
            {
                return(ConvertFrom(context, culture, Symbol.FromString((string)value)));
            }
            if (sourceType == typeof(Symbol))
            {
                var symbol = (Symbol)value;
                try
                {
                    var symbols = symbol.AsSymbols;
                    var fields  = symbols
                                  .Select((fieldSymbol, index) => {
                        var fieldName      = "Item" + (index + 1);
                        var fieldProperty  = pointType.GetProperty(fieldName, BindingFlags.Public | BindingFlags.Instance);
                        var fieldConverter = new SymbolicConverter(fieldProperty.PropertyType);
                        var fieldValue     = fieldSymbol.Match(
                            atom => fieldConverter.ConvertFromString(atom),
                            number => fieldConverter.ConvertFromString(number),
                            str => fieldConverter.ConvertFromString(SymbolParser.Explicitize(str)),
                            _ => fieldSymbol,
                            _ => fieldConverter.ConvertFrom(fieldSymbol));
                        return(fieldValue);
                    })
                                  .ToArray();
                    return(Activator.CreateInstance(pointType, fields));
                }
                catch (Exception exn)
                {
                    throw new ArgumentException($"Invalid form '{symbol}' for {value.GetType().FullName}. Required form is '[Value ...]'.", exn);
                }
            }
            return(base.ConvertFrom(context, culture, value));
        }
예제 #3
0
파일: Union.cs 프로젝트: bryanedds/Sigma
        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            var sourceType = value.GetType();

            if (sourceType == pointType)
            {
                return(value);
            }
            if (sourceType == typeof(string))
            {
                return(ConvertFrom(context, culture, Symbol.FromString((string)value)));
            }
            if (sourceType == typeof(Symbol))
            {
                var symbol = (Symbol)value;
                try
                {
                    var fields        = symbol.AsSymbols;
                    var tagField      = pointType.GetField(nameof(Union <bool, bool> .Tag));
                    var tagConverter  = new SymbolicConverter(tagField.FieldType);
                    var tag           = (Enum)tagConverter.ConvertFromString(fields[0].AsAtom);
                    var dataField     = pointType.GetField(nameof(Union <bool, bool> .Data));
                    var dataConverter = new SymbolicConverter(tag.TryGetAttributeOfType <UnionAttribute>().TryThen(attr => attr.Type) ?? dataField.FieldType);
                    var data          = fields[1].Match(
                        atom => dataConverter.ConvertFromString(atom),
                        number => dataConverter.ConvertFromString(number),
                        str => dataConverter.ConvertFromString(SymbolParser.Explicitize(str)),
                        _ => fields[1],
                        _ => dataConverter.ConvertFrom(fields[1]));
                    return(Activator.CreateInstance(pointType, new object[] { tag, data }));
                }
                catch (Exception exn)
                {
                    throw new ArgumentException($"Invalid form '{symbol}' for {value.GetType().FullName}. Required form is '[Enum Value]'.", exn);
                }
            }
            return(base.ConvertFrom(context, culture, value));
        }
예제 #4
0
        private static Symbol ToSymbol(Type sourceType, object source)
        {
            var typeConverterOpt = sourceType.TryGetCustomTypeConverter();

            if (typeConverterOpt != null)
            {
                // symbolize user-defined type
                if (!typeConverterOpt.CanConvertTo(typeof(Symbol)))
                {
                    throw new ConversionException("Cannot convert type '" + source.GetType().Name + "' to Symbol.");
                }
                else
                {
                    return((Symbol)typeConverterOpt.ConvertTo(source, typeof(Symbol)));
                }
            }
            else
            {
                // symbolize .NET primitive
                if (sourceType.IsPrimitive)
                {
                    var converted = (string)TypeDescriptor.GetConverter(sourceType).ConvertTo(source, typeof(string));
                    if (sourceType == typeof(bool))
                    {
                        return(new Symbol(converted));
                    }
                    if (sourceType == typeof(char))
                    {
                        return(new Symbol(new StringSpecifier(converted)));
                    }
                    return(new Symbol(new NumberSpecifier(converted)));
                }

                // symbolize string
                if (sourceType == typeof(string))
                {
                    var sourceStr = source.ToString();
                    if (SymbolParser.IsNumber(sourceStr))
                    {
                        return(new Symbol(new NumberSpecifier(sourceStr)));
                    }
                    if (SymbolParser.ShouldBeExplicit(sourceStr))
                    {
                        return(new Symbol(new StringSpecifier(sourceStr)));
                    }
                    return(new Symbol(sourceStr));
                }

                // symbolize Symbol (no transformation)
                if (sourceType == typeof(Symbol))
                {
                    return((Symbol)source);
                }

                // symbolize vanilla .NET type...
                var typeConverter = TypeDescriptor.GetConverter(sourceType);

                // HACK: we do not want to use this converter here as it strips the time when converting to string!
                if (typeConverter is DateTimeConverter)
                {
                    return(new Symbol(new StringSpecifier(source.ToString())));
                }

                if (typeConverter.CanConvertTo(typeof(Symbol)))
                {
                    return((Symbol)typeConverter.ConvertTo(source, typeof(Symbol)));
                }

                return(new Symbol((string)typeConverter.ConvertTo(source, typeof(string))));
            }
        }
예제 #5
0
 public static Symbol FromString(string sexpr)
 {
     return(SymbolParser.ParseSymbol(sexpr));
 }
예제 #6
0
 public override string ToString()
 {
     return(SymbolParser.UnparseSymbol(this));
 }