예제 #1
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="rule"></param>
 /// <param name="validatedExpression"></param>
 public CastExpression(CoercionRule rule, IExpression validatedExpression)
     : this(validatedExpression.Location, CoercionKind.Implicit, rule.CastingType.Name, validatedExpression)
 {
     this.rule    = rule;
     SemanticType = rule.CastingType;
     Expression   = validatedExpression;
 }
예제 #2
0
        /// <summary>
        /// Validation: Checks whether the type really exists and whether the conversion is allowed.
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public CastExpression Validate(IValidationScope context)
        {
            var type = context.TypeSystem.GetTypeByName(CastTypeName)?.NativeType;

            if (type == null)
            {
                throw new LocateableException(Location, $"There is no type {CastTypeName}!");
            }
            Expression = Expression.Validate(context);
            rule       = context.TypeSystem.GetCoercionRule(Expression.SemanticType, type);
            if (rule == null)
            {
                throw new LocateableException(Location, $"Can not convert type into a '{CastTypeName}'.");
            }
            SemanticType = type;
            return(this);
        }
예제 #3
0
        /// <summary>
        /// Adds a new coercion rule. Trys to avoid cyclic implicit casts chains.
        /// </summary>
        /// <typeparam name="TOriginalType"></typeparam>
        /// <typeparam name="TCastingType"></typeparam>
        /// <param name="kind"></param>
        /// <param name="cast"></param>
        public void AddCoercionRule <TOriginalType, TCastingType>(CoercionKind kind, Func <TOriginalType, TCastingType> cast)
        {
            var original = typeof(TOriginalType);
            var casting  = typeof(TCastingType);

            if (GetTypeByNative(original) == null)
            {
                throw new UnknownTypeException(original);
            }
            if (GetTypeByNative(casting) == null)
            {
                throw new UnknownTypeException(casting);
            }
            var rule = new CoercionRule(kind, original, casting, a => cast((TOriginalType)a));

            if (allCoercionRules.TryGetEdge(original, casting, out TaggedEdge <Type, CoercionRule> existingEdge))
            {
                throw new InvalidOperationException("Such a rule does already exist!");
            }
            var edge = new TaggedEdge <System.Type, CoercionRule>(original, casting, rule);

            if (kind == CoercionKind.Implicit)
            {
                implicitCoercionRules.AddVertex(original);
                implicitCoercionRules.AddVertex(casting);
                implicitCoercionRules.AddEdge(edge);
                if (implicitCoercionRules.StronglyConnectedComponents(out IDictionary <Type, int> components) != implicitCoercionRules.Vertices.Count())
                {
                    implicitCoercionRules.RemoveEdge(edge);
                    throw new InvalidOperationException("This action would create an implicit conversion cycle!");
                }
            }
            allCoercionRules.AddVertex(original);
            allCoercionRules.AddVertex(casting);
            allCoercionRules.AddEdge(edge);
            Debug.WriteLine($"- added coercion rule from '{original.Name}' to '{casting.Name}'");
        }