Upsilon/Upsilon/BaseTypes/UserData/DictionaryUserData.cs

112 lines
3.7 KiB
C#

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<ScriptType> GetScriptEnumerator()
{
return (from object key in Dictionary.Keys
select key.ToScriptType()).GetEnumerator();
}
}
}