Clean up logic of object interpretation in PDT interpreter.

This commit is contained in:
2023-04-07 12:21:20 +08:00
parent 1fc5ea8ac6
commit 6cb36a7064
3 changed files with 40 additions and 54 deletions

View File

@@ -28,6 +28,10 @@ namespace Cryville.Common.Collections.Generic {
if (_pairList != null) _pairList.CopyTo(array, index); if (_pairList != null) _pairList.CopyTo(array, index);
else _dictionary.CopyTo(array, index); else _dictionary.CopyTo(array, index);
} }
public static bool IsPairCollection(Type type) {
return typeof(IPairList<TKey, TValue>).IsAssignableFrom(type) || typeof(IDictionary<TKey, TValue>).IsAssignableFrom(type);
}
} }
internal class PairCollectionDebugView<TKey, TValue> { internal class PairCollectionDebugView<TKey, TValue> {
readonly PairCollection<TKey, TValue> _self; readonly PairCollection<TKey, TValue> _self;

View File

@@ -29,6 +29,10 @@ namespace Cryville.Common.Collections {
if (_pairList != null) _pairList.CopyTo(array, index); if (_pairList != null) _pairList.CopyTo(array, index);
else _dictionary.CopyTo(array, index); else _dictionary.CopyTo(array, index);
} }
public static bool IsPairCollection(Type type) {
return typeof(IPairList).IsAssignableFrom(type) || typeof(IDictionary).IsAssignableFrom(type);
}
} }
internal class PairCollectionDebugView { internal class PairCollectionDebugView {
readonly PairCollection _self; readonly PairCollection _self;

View File

@@ -229,7 +229,7 @@ namespace Cryville.Common.Pdt {
} }
object InterpretObject(Type type) { object InterpretObject(Type type) {
var result = ReflectionHelper.InvokeEmptyConstructor(type); var result = ReflectionHelper.InvokeEmptyConstructor(type);
bool dictflag = typeof(IDictionary).IsAssignableFrom(type); bool pcflag = PairCollection.IsPairCollection(type);
while (true) { while (true) {
try { ws(); } try { ws(); }
catch (IndexOutOfRangeException) { return result; } catch (IndexOutOfRangeException) { return result; }
@@ -241,18 +241,33 @@ namespace Cryville.Common.Pdt {
char c = GetChar(); char c = GetChar();
switch (c) { switch (c) {
case '{': case '{':
if (dictflag) { InterpretObjectInternal<ElementListAttribute>(pcflag, type, pkey, result, type => InterpretObject(type));
break;
case ':':
case ';':
var exp = c == ';' ? _emptyexp : GetExp();
InterpretObjectInternal<PropertyListAttribute>(pcflag, type, pkey, result, type => _binder.ChangeType(exp, type, null));
break;
default:
throw new InvalidOperationException("Internal error: Invalid key interpretation");
}
}
}
void InterpretObjectInternal<T>(bool pcflag, Type type, object pkey, object result, Func<Type, object> vfunc) where T : Attribute {
if (pcflag) {
using (var collection = new PairCollection(result)) {
var ktype = type.GetGenericArguments()[0]; var ktype = type.GetGenericArguments()[0];
var ptype = type.GetGenericArguments()[1]; var ptype = type.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null); object key = _binder.ChangeType(pkey, ktype, null);
object value = InterpretObject(ptype); object value = vfunc(ptype);
((IDictionary)result).Add(key, value); collection.Add(key, value);
}
} }
else { else {
MemberInfo prop = null; MemberInfo prop = null;
bool flag = false; bool flag = false;
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey); if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<ElementListAttribute>(type, out prop); if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<T>(type, out prop);
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey)); if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
Type ptype = ReflectionHelper.GetMemberType(prop); Type ptype = ReflectionHelper.GetMemberType(prop);
if (flag) { if (flag) {
@@ -260,48 +275,11 @@ namespace Cryville.Common.Pdt {
var ktype = ptype.GetGenericArguments()[0]; var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1]; var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null); object key = _binder.ChangeType(pkey, ktype, null);
object value = InterpretObject(vtype); object value = vfunc(vtype);
collection.Add(key, value); collection.Add(key, value);
} }
} }
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype)); else ReflectionHelper.SetValue(prop, result, vfunc(ptype), _binder);
}
break;
case ':':
case ';':
var exp = c == ';' ? _emptyexp : GetExp();
if (dictflag) {
var ktype = type.GetGenericArguments()[0];
var vtype = type.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = _binder.ChangeType(exp, vtype, null);
((IDictionary)result).Add(key, value);
}
else {
MemberInfo prop = null;
bool flag = false;
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<PropertyListAttribute>(type, out prop);
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
var ptype = ReflectionHelper.GetMemberType(prop);
if (flag) {
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
var ktype = ptype.GetGenericArguments()[0];
var vtype = ptype.GetGenericArguments()[1];
object key = _binder.ChangeType(pkey, ktype, null);
object value = _binder.ChangeType(exp, vtype, null);
collection.Add(key, value);
}
}
else {
object value = _binder.ChangeType(exp, ptype, null);
ReflectionHelper.SetValue(prop, result, value, _binder);
}
}
break;
default:
throw new InvalidOperationException("Internal error: Invalid key interpretation");
}
} }
} }
/// <summary> /// <summary>