Example #1
0
        private TemplateTranslation overridden(IReadOnlyList <TemplateParameter> parameters, IEnumerable <IEntityInstance> arguments)
        {
            var dict = Later.Create(() => this.table.ToDictionary(it => it.Key, it => it.Value));
            int i    = -1;

            foreach (IEntityInstance arg in arguments)
            {
                ++i;

                TemplateParameter key = parameters[i];
                if (!object.ReferenceEquals(this.table[key], arg))
                {
                    dict.Value[key] = arg;
                }
            }

            if (dict.HasValue)
            {
                return(new TemplateTranslation(this.parametersProvider, dict.Value));
            }
            else
            {
                return(this);
            }
        }
Example #2
0
        public ConstraintMatch ArgumentMatchesParameterConstraints(ComputationContext ctx, EntityInstance closedTemplate,
                                                                   TemplateParameter param)
        {
            foreach (IEntityInstance arg in this.elements)
            {
                ConstraintMatch match = arg.ArgumentMatchesParameterConstraints(ctx, closedTemplate, param);
                if (match != ConstraintMatch.Yes)
                {
                    return(match);
                }
            }

            return(ConstraintMatch.Yes);
        }
Example #3
0
        public bool ValidateTypeVariance(ComputationContext ctx, IOwnedNode placement, VarianceMode typeNamePosition)
        {
            // Programming in Scala, 2nd ed, p. 399 (all errors are mine)

            TypeDefinition typedef = this.TargetType;

            if (typedef.IsTemplateParameter)
            {
                TemplateParameter  param    = typedef.TemplateParameter;
                TemplateDefinition template = param.EnclosingScope <TemplateDefinition>();
                if (placement.EnclosingScopesToRoot().Contains(template))
                {
                    bool covariant_in_immutable = param.Variance == VarianceMode.Out &&
                                                  (template.IsFunction() || template.CastType().InstanceOf.MutabilityOfType(ctx) == TypeMutability.ConstAsSource);

                    // don't report errors for covariant types which are used in immutable template types
                    if (!covariant_in_immutable &&
                        typeNamePosition.PositionCollides(param.Variance))
                    {
                        return(false);
                    }
                }
            }
            else
            {
                for (int i = 0; i < typedef.Name.Parameters.Count; ++i)
                {
                    if (!this.TemplateArguments[i].ValidateTypeVariance(ctx,
                                                                        placement,
                                                                        typeNamePosition.Flipped(typedef.Name.Parameters[i].Variance)))
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
Example #4
0
 public bool Translate(TemplateParameter templateParameter, out IEntityInstance instanceArgument)
 {
     return(this.table.TryGetValue(templateParameter, out instanceArgument) && instanceArgument != null);
 }
Example #5
0
        public ConstraintMatch ArgumentMatchesParameterConstraints(ComputationContext ctx, EntityInstance closedTemplate,
                                                                   TemplateParameter param)
        {
            if (this.TargetsTemplateParameter && this.TemplateParameterTarget == param)
            {
                return(ConstraintMatch.Yes);
            }

            TypeMutability arg_mutability = this.SurfaceMutabilityOfType(ctx);

            if (param.Constraint.Modifier.HasConst &&
                arg_mutability != TypeMutability.ForceConst && arg_mutability != TypeMutability.ConstAsSource)
            {
                return(ConstraintMatch.MutabilityViolation);
            }
            else if (param.Constraint.Modifier.HasMutable && arg_mutability != TypeMutability.ForceMutable)
            {
                return(ConstraintMatch.MutabilityViolation);
            }
            else if (param.Constraint.Modifier.HasReassignable && !arg_mutability.HasFlag(TypeMutability.Reassignable))
            {
                return(ConstraintMatch.AssignabilityViolation);
            }

            // 'inherits' part of constraint
            foreach (EntityInstance constraint_inherits in param.Constraint.TranslateInherits(closedTemplate))
            {
                TypeMatch match = TypeMatcher.Matches(ctx, this, constraint_inherits,
                                                      TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: true));
                if (match.IsMismatch())
                {
                    return(ConstraintMatch.InheritsViolation);
                }
            }

            {
                VirtualTable vtable = EntityInstanceExtension.BuildDuckVirtualTable(ctx, this, param.AssociatedType.InstanceOf,
                                                                                    allowPartial: false);
                if (vtable == null)
                {
                    return(ConstraintMatch.MissingFunction);
                }
            }


            // 'base-of' part of constraint
            IEnumerable <IEntityInstance> arg_bases = (this.TargetsTemplateParameter
                ? this.TargetType.TemplateParameter.Constraint.TranslateBaseOf(closedTemplate)
                : Enumerable.Empty <EntityInstance>()
                                                       )
                                                      .Concat(this);

            foreach (EntityInstance constraint_base in param.Constraint.TranslateBaseOf(closedTemplate))
            {
                if (!arg_bases.Any(it => !constraint_base.MatchesTarget(ctx, it, TypeMatching.Create(ctx.Env.Options.InterfaceDuckTyping, allowSlicing: true))
                                   .IsMismatch()))
                {
                    return(ConstraintMatch.BaseViolation);
                }
            }

            return(ConstraintMatch.Yes);
        }