internal static FuncDecl GetOrAddMemberAccessFunction(Context context, Environment environment, MemberInfo memberInfo)
{
FuncDecl memberFunc;
if (!environment.Members.TryGetValue(memberInfo, out memberFunc))
{
Sort memberTypeSort;
if (!environment.Types.TryGetValue(memberInfo.DeclaringType, out memberTypeSort))
{
throw new KeyNotFoundException(memberInfo.DeclaringType + " could not be found at environment.Types");
}
Sort memberReturnTypeEnumSort;
var propertyType = ((PropertyInfo)memberInfo).PropertyType;
if (propertyType == typeof(bool))
memberReturnTypeEnumSort = context.MkBoolSort();
else if (propertyType == typeof(int))
memberReturnTypeEnumSort = context.MkIntSort();
else if (propertyType == typeof(long))
memberReturnTypeEnumSort = context.MkRealSort();
else if (propertyType == typeof(string))
memberReturnTypeEnumSort = environment.PossibleStringValues;
else
{
if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
{
var listItemType = propertyType.GenericTypeArguments[0];
var listSort = context.MkSetSort(environment.Types[listItemType]);
memberReturnTypeEnumSort = listSort;
// TODO: add TryGetValue
environment.Types.Add(propertyType, listSort);
}
else if (propertyType.IsEnum)
{
EnumSort enumSort = context.MkEnumSort(propertyType.Name, Enum.GetNames(propertyType));
memberReturnTypeEnumSort = enumSort;
// TODO: add TryGetValue
environment.Types.Add(propertyType, enumSort);
}
else
{
// TODO throw exception if type is not supported
memberReturnTypeEnumSort = environment.Types[propertyType];
}
}
memberFunc = context.MkFuncDecl(memberInfo.Name, memberTypeSort, memberReturnTypeEnumSort);
environment.Members.Add(memberInfo, memberFunc);
}
return memberFunc;
}