///// <summary>
///// Gets value determining whether <paramref name="totype"/> type can be assigned from <paramref name="fromtype"/>.
///// </summary>
///// <param name="totype">Type mask which we check whether is assignable from <paramref name="fromtype"/>.</param>
///// <param name="fromtype">Type mask we check whether is equal or is a subclass of <paramref name="totype"/>.</param>
///// <param name="ctx">Type context for resolving class names from type mask.</param>
///// <param name="model">Helper object which caches class inheritance.</param>
///// <remarks>
///// Gets <c>true</c>, if <paramref name="totype"/> is equal to or is a base type of <paramref name="fromtype"/>.
///// Gets <c>False</c> for <c>void</c> type masks.
///// </remarks>
//public static bool IsAssignableFrom(this TypeRefMask totype, TypeRefMask fromtype, TypeRefContext/*!*/ctx, ISemanticModel/*!*/model)
//{
// Debug.Assert(ctx != null);
// Debug.Assert(model != null);
// if ((totype & fromtype & ~(ulong)TypeRefMask.FlagsMask) != 0)
// return true; // types are equal (or at least one of them is Any Type)
// // object <-> unspecified object instance
// if ((ctx.IsObject(totype) && ctx.IsObject(fromtype)) &&
// (ctx.IsAnObject(totype) || ctx.IsAnObject(fromtype)))
// return true;
// if (IsImplicitConversion(fromtype, totype, ctx, model))
// return true;
// // cut off object types (primitive types do not have subclasses)
// var selfObjs = ctx.GetObjectTypes(totype);
// if (selfObjs.Count == 0)
// return false; // self mask does not represent a class
// var typeObjs = ctx.GetObjectTypes(fromtype);
// if (typeObjs.Count == 0)
// return false; // type mask does not represent a class
// // build inheritance graph and check whether any type from self is a base of anything in type
// if (selfObjs.Count == 1 && typeObjs.Count == 1)
// return model.IsAssignableFrom(selfObjs[0].QualifiedName, typeObjs[0].QualifiedName);
// //
// return model.IsAssignableFrom(selfObjs.Select(t => t.QualifiedName), typeObjs.Select(t => t.QualifiedName));
//}
///// <summary>
///// Determines whether there is an implicit conversion from one type to another.
///// </summary>
//private static bool IsImplicitConversion(TypeRefMask fromtype, TypeRefMask totype, TypeRefContext/*!*/ctx, ISemanticModel/*!*/model)
//{
// // TODO: optimize bit operations
// //
// if (ctx.IsArray(totype) && ctx.IsArray(fromtype))
// {
// // both types are arrays, type may be more specific (int[]) and self just ([])
// // TODO: check whether their element types are assignable,
// // avoid infinite recursion!
// return true;
// }
// // any callable -> "callable"
// if (ctx.IsLambda(totype) && IsCallable(fromtype, ctx, model))
// return true;
// //// allowed conversions
// // int <-> bool
// //if (ctx.IsInteger(totype) && ctx.IsBoolean(fromtype)) // int -> bool
// // return true;
// // int <-> double
// if (ctx.IsNumber(fromtype) && ctx.IsNumber(totype)) // TODO: maybe settings for strict number type check
// return true;
// if (ctx.IsString(totype) && IsConversionToString(fromtype, ctx, model))
// return true;
// //
// if (ctx.IsNull(fromtype) && ctx.IsNullable(totype))
// return true; // NULL can be assigned to any nullable
// //
// return false;
//}
///// <summary>
///// Determines whether given type can be converted to string without warning.
///// </summary>
//internal static bool IsConversionToString(TypeRefMask fromtype, TypeRefContext/*!*/ctx, ISemanticModel/*!*/model)
//{
// // primitive -> string
// if (ctx.IsPrimitiveType(fromtype))
// return true;
// // object with __toString() -> string
// if (ctx.IsObject(fromtype) && ctx.GetObjectTypes(fromtype).Any(tref => model.GetClass(tref.QualifiedName).HasMethod(NameUtils.SpecialNames.__toString, model)))
// return true;
// //
// return false;
//}
/// <summary>
/// Checks whether given type may be callable.
/// </summary>
internal static bool IsCallable(TypeRefContext /*!*/ ctx, TypeRefMask type)
{
if (type.IsAnyType || type.IsRef ||
ctx.IsLambda(type) || ctx.IsAString(type) || ctx.IsArray(type) || ctx.IsObject(type))
{
return(true);
}
//// type has "__invoke" method
//if (type.IsSingleType) // just optimization
//{
// var tref = ctx.GetObjectTypes(type).FirstOrDefault();
// if (tref != null)
// {
// var node = model.GetClass(tref.QualifiedName);
// // type has __invoke method or is assignable from Closure
// if (node.HasMethod(NameUtils.SpecialNames.__invoke, model) || model.IsAssignableFrom(NameUtils.SpecialNames.Closure, node))
// return true;
// }
//}
return(false);
}