using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Upsilon.BaseTypes.Number; using Upsilon.BaseTypes.ScriptTypeInterfaces; using Upsilon.BoundTypes; using Upsilon.Evaluator; using Upsilon.Text; namespace Upsilon.BaseTypes.UserData { internal class DictionaryUserData : ScriptType, IUserData, ILengthType, IIterable { public IDictionary Dictionary { get; } private string BoundTypeName { get; } public DictionaryUserData(IDictionary dictionary) { Dictionary = dictionary; var type = dictionary.GetType(); var generics = type.GetGenericArguments(); if (generics.Length == 2) { var keyType = generics[0]; var valueType = generics[1]; var boundKeyType = BoundTypeHandler.GetTypeName(keyType); var boundValueType = BoundTypeHandler.GetTypeName(valueType); var boundKey = boundKeyType == null ? new UndefinedUserDataTypeContainer(keyType) : new TypeContainer(boundKeyType); var boundValue = boundValueType == null ? new UndefinedUserDataTypeContainer(valueType) : new TypeContainer(boundValueType); Type = new CompositeTypeContainer(new[] {boundKey, boundValue}.ToImmutableArray()); } else { BoundTypeName = BoundTypeHandler.GetTypeName(type); Type = BoundTypeName == null ? new UndefinedUserDataTypeContainer(type) : new TypeContainer(BoundTypeName); } } public ScriptType Get(Diagnostics diagnostics, TextSpan span, ScriptType index, EvaluationScope scope) { var key = index.ToCSharpObject(); if (Dictionary.Contains(key)) { return Dictionary[key].ToScriptType(); } //TODO: log error return new ScriptNull(); } public void Set(Diagnostics diagnostics, TextSpan span, ScriptType index, ScriptType value) { var key = index.ToCSharpObject(); if (Dictionary.Contains(key)) { Dictionary[key] = value.ToCSharpObject(); } else { Dictionary.Add(key, value.ToCSharpObject()); } } public override TypeContainer Type { get; } public override object ToCSharpObject() { return Dictionary; } public override System.Type GetCSharpType() { return Dictionary.GetType(); } public ScriptNumberLong Length() { return new ScriptNumberLong(Dictionary.Count); } protected bool Equals(DictionaryUserData other) { return Dictionary.Equals(other.Dictionary); } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (ReferenceEquals(this, obj)) return true; if (obj.GetType() == Dictionary.GetType()) { return Dictionary.Equals(obj); } if (obj.GetType() != this.GetType()) return false; return Equals((DictionaryUserData) obj); } public ScriptType GetValueFromIndex(ScriptType index) { return Dictionary[index.ToCSharpObject()].ToScriptType(); } public IEnumerator GetScriptEnumerator() { return (from object key in Dictionary.Keys select key.ToScriptType()).GetEnumerator(); } } }