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.")))); }
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)); }
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)); }
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)))); } }
public static Symbol FromString(string sexpr) { return(SymbolParser.ParseSymbol(sexpr)); }
public override string ToString() { return(SymbolParser.UnparseSymbol(this)); }