예제 #1
0
        public TypeMatch TemplateMatchesInput(ComputationContext ctx, EntityInstance input,
                                              VarianceMode variance, TypeMatching matching)
        {
            // todo: this is correct but it is just a hack really, because we should check constraints
            // and if they are compatible we should return match
            if (input.TargetsTemplateParameter && this.TargetsTemplateParameter &&
                !input.TargetTemplate.Constraints.Any() && !this.TargetTemplate.Constraints.Any())
            {
                return(TypeMatch.Same);
            }

            matching.Position = matching.Position.Flipped(variance);
            switch (matching.Position)
            {
            case VarianceMode.None:
                return(this.IsExactlySame(input, jokerMatchesAll: true) ? TypeMatch.Same : TypeMatch.No);

            case VarianceMode.In:
                return(TypeMatcher.Matches(ctx, this, input, matching));

            case VarianceMode.Out:
                return(TypeMatcher.Matches(ctx, input, this, matching));
            }

            throw new NotImplementedException();
        }
예제 #2
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);
        }
예제 #3
0
 public TypeMatch MatchesInput(ComputationContext ctx, EntityInstance input, TypeMatching matching)
 {
     return(TypeMatcher.Matches(ctx, input, this, matching));
 }