public TemplateParameterSymbol(TemplateParameter tpn, ISemantic typeOrValue, ISyntaxRegion paramIdentifier = null) : base(tpn != null ? tpn.Representation : null, AbstractType.Get(typeOrValue), paramIdentifier) { this.Parameter = tpn; this.ParameterValue = typeOrValue as ISymbolValue; }
/// <summary> /// Checks results for implicit type convertability /// </summary> public static bool IsImplicitlyConvertible(ISemantic resultToCheck, AbstractType targetType, ResolutionContext ctxt = null) { var resToCheck = AbstractType.Get(resultToCheck); bool isVariable = resToCheck is MemberSymbol; // Initially remove aliases from results var _r = DResolver.StripMemberSymbols(resToCheck); if (_r == null) { return(IsEqual(resToCheck, targetType)); } resToCheck = _r; targetType = DResolver.StripAliasSymbol(targetType); if (targetType is DSymbol) { var tpn = ((DSymbol)targetType).Definition as TemplateParameter.Node; if (tpn != null) { var par = tpn.Parent as DNode; if (par != null && par.TemplateParameters != null) { var dedParam = new DeducedTypeDictionary(par); return(new TemplateParameterDeduction(dedParam, ctxt).Handle(tpn.TemplateParameter, resToCheck)); } } } _r = DResolver.StripMemberSymbols(targetType); if (_r == null) { return(false); } targetType = _r; if (resToCheck is PrimitiveType && targetType is PrimitiveType) { var sr1 = (PrimitiveType)resToCheck; var sr2 = (PrimitiveType)targetType; if (sr1.TypeToken == sr2.TypeToken /*&& sr1.Modifier == sr2.Modifier*/) { return(true); } switch (sr2.TypeToken) { case DTokens.Int: return(sr1.TypeToken == DTokens.Uint); case DTokens.Uint: return(sr1.TypeToken == DTokens.Int); //TODO: Further types that can be converted into each other implicitly } } else if (resToCheck is UserDefinedType && targetType is UserDefinedType) { return(IsImplicitlyConvertible((UserDefinedType)resToCheck, (UserDefinedType)targetType)); } else if (resToCheck is DelegateType && targetType is DelegateType) { return(IsEqual(resToCheck, targetType)); //TODO: Can non-equal delegates be converted into each other? } else if (resToCheck is ArrayType && targetType is ArrayType) { var ar1 = (ArrayType)resToCheck; var ar2 = (ArrayType)targetType; // Key as well as value types must be matching! var ar1_n = ar1.KeyType == null; var ar2_n = ar2.KeyType == null; if (ar1_n != ar2_n) { return(false); } if (ar1_n || IsImplicitlyConvertible(ar1.KeyType, ar2.KeyType, ctxt)) { return(IsImplicitlyConvertible(ar1.Base, ar2.Base, ctxt)); } } else if (resToCheck is DTuple && targetType is DTuple) { var tup1 = resToCheck as DTuple; var tup2 = resToCheck as DTuple; //TODO return(true); } /*else if (resultToCheck is ExpressionValueResult && targetType is ExpressionValue) * { * return ((ExpressionValueResult)resultToCheck).Value.Equals(((ExpressionValueResult)targetType).Value); * }*/ // http://dlang.org/type.html //TODO: Pointer to non-pointer / vice-versa checkability? -- Can it really be done implicitly? else if (!isVariable && resToCheck is ArrayType && targetType is PointerType && ((targetType = (targetType as PointerType).Base) is PrimitiveType) && DTokens.CharTypes[(targetType as PrimitiveType).TypeToken]) { return((resultToCheck as ArrayType).IsString); } return(false); }