Пример #1
0
        private static bool strictTemplateMatches(ComputationContext ctx, EntityInstance input, EntityInstance target,
                                                  TypeMatching matching,
                                                  out TypeMatch failMatch)
        {
            if (input.Target != target.Target)
            {
                failMatch = TypeMatch.No;
                return(false);
            }

            TemplateDefinition template = target.TargetTemplate;

            for (int i = 0; i < template.Name.Arity; ++i)
            {
                failMatch = input.TemplateArguments[i].TemplateMatchesTarget(ctx,
                                                                             target.TemplateArguments[i],
                                                                             template.Name.Parameters[i].Variance,
                                                                             matching);

                if (!failMatch.Passed)
                {
                    return(false);
                }
            }

            failMatch = TypeMatch.Same;
            return(true);
        }
Пример #2
0
        private static bool templateMatches(ComputationContext ctx, EntityInstance input,
                                            EntityInstance target, TypeMatching matching,
                                            out TypeMatch failMatch)
        {
            if (input.IsJoker || target.IsJoker)
            {
                failMatch = TypeMatch.Same;
                return(true);
            }

            bool matches = strictTemplateMatches(ctx, input, target, matching, out failMatch);

            TypeDefinition target_type = target.TargetType;

            if (matches || (!(matching.DuckTyping && target_type.IsInterface) && !target_type.IsProtocol))
            {
                return(matches);
            }

            VirtualTable vtable = EntityInstanceExtension.BuildDuckVirtualTable(ctx, input, target, allowPartial: false);

            if (vtable == null)
            {
                return(false);
            }
            else
            {
                failMatch = TypeMatch.Same;
                return(true);
            }
        }
Пример #3
0
        public TypeInheritance TranslateThrough(ComputationContext ctx, EntityInstance closedTemplate)
        {
            IEnumerable <TypeDefinition> traits = closedTemplate.AvailableTraits(ctx);

            IEnumerable <EntityInstance> minimal_parents = this.MinimalParentsWithoutObject
                                                           .Concat(traits.SelectMany(it => it.Inheritance.MinimalParentsWithoutObject))
                                                           .Select(it => it.TranslateThrough(closedTemplate))
                                                           .Distinct(EntityInstance.Comparer);

            var dict = new Dictionary <EntityInstance, int>(EntityInstance.Comparer);

            foreach (TypeAncestor ancestor in this.OrderedTypeAncestorsIncludingObject
                     .Concat(traits.SelectMany(it => it.Inheritance.OrderedTypeAncestorsIncludingObject))
                     .Select(it => it.TranslateThrough(closedTemplate)))
            {
                if (dict.TryGetValue(ancestor.AncestorInstance, out int dist))
                {
                    dict[ancestor.AncestorInstance] = Math.Min(dist, ancestor.Distance);
                }
                else
                {
                    dict.Add(ancestor.AncestorInstance, ancestor.Distance);
                }
            }

            return(new TypeInheritance(this.objectType,
                                       minimal_parents,
                                       completeAncestors: dict.Select(it => new TypeAncestor(it.Key, it.Value))));
        }
Пример #4
0
        public static TypeMatch inversedTypeMatching(ComputationContext ctx, EntityInstance input, IEnumerable <TypeAncestor> targets,
                                                     TypeMatching matching)
        {
            if (!targets.Any())
            {
                return(TypeMatch.No);
            }

            EntityInstance target = targets.First().AncestorInstance;

            TypeMutability target_mutability = target.MutabilityOfType(ctx);

            foreach (TypeAncestor inherited_target in targets)
            {
                // please note that unlike normal type matching we reversed the types, in enum you can
                // pass base type as descendant!
                if (matchTypes(ctx, target_mutability, target.Lifetime, inherited_target.AncestorInstance,
                               input, matching, inherited_target.Distance,
                               out TypeMatch match))
                {
                    return(match);
                }
            }

            return(TypeMatch.No);
        }
Пример #5
0
        // please remember we have to allow specialization of the function
        // template types (T and V) are not distinct
        // template type (T) and concrete type (String) are (!) distinct (specialization)
        // two concrete types (String and Object) are distinct (here is the example of specialization as well)
        public bool IsOverloadDistinctFrom(IEntityInstance other)
        {
            EntityInstance other_entity = other as EntityInstance;

            if (other_entity == null)
            {
                return(other.IsOverloadDistinctFrom(this));
            }
            else if ((this.TargetsTemplateParameter && other_entity.TargetsTemplateParameter) || this.IsIdentical(other_entity))
            {
                return(false);
            }
            else if (this.Target != other_entity.Target)
            {
                return(true);
            }

            for (int i = 0; i < this.TemplateArguments.Count; ++i)
            {
                if (this.TemplateArguments[i].IsOverloadDistinctFrom(other_entity.TemplateArguments[i]))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #6
0
        public override TypeMatch MatchesInput(ComputationContext ctx, EntityInstance input, TypeMatching matching)
        {
            TypeMatch match = TypeMatch.No;

            foreach (IEntityInstance target in this.elements)
            {
                TypeMatch m = target.MatchesInput(ctx, input, matching);
                if (m == TypeMatch.Same || m == TypeMatch.Substitute)
                {
                    return(m);
                }
                else if (m == TypeMatch.InConversion ||
                         m == TypeMatch.AutoDereference ||
                         m == TypeMatch.ImplicitReference ||
                         m == TypeMatch.OutConversion)
                {
                    match = m;
                }
                else if (!m.IsMismatch())
                {
                    throw new NotImplementedException();
                }
            }

            return(match);
        }
Пример #7
0
        internal static CallResolution Create(ComputationContext ctx,
                                              IEnumerable <TemplateArgument> templateArguments,
                                              IFunctionArgumentsProvider argumentsProvider,
                                              CallContext callContext,
                                              EntityInstance targetFunctionInstance)
        {
            // at this point we target true function (any function-like object is converted to closure already)
            if (!targetFunctionInstance.Target.IsFunction())
            {
                throw new Exception("Internal error");
            }

            List <int> arg_param_mapping = createArgParamMapping(targetFunctionInstance,
                                                                 callContext.MetaThisArgument, argumentsProvider.UserArguments);

            if (arg_param_mapping == null)
            {
                return(null);
            }

            var result = new CallResolution(ctx, templateArguments, argumentsProvider,
                                            callContext,
                                            targetFunctionInstance,
                                            arg_param_mapping,
                                            out bool success);

            if (success)
            {
                return(result);
            }
            else
            {
                return(null);
            }
        }
Пример #8
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();
        }
Пример #9
0
        private static EntityInstance selectFromLowestCommonAncestorPool(ComputationContext ctx, EntityInstance type,
                                                                         HashSet <EntityInstance> pool)
        {
            if (type == null)
            {
                return(null);
            }

            if (pool.Contains(type))
            {
                return(type);
            }

            EntityInstance implementation_parent = type.Inheritance(ctx).GetTypeImplementationParent();
            // prefer LCA as implementation
            EntityInstance via_implementation = selectFromLowestCommonAncestorPool(ctx, implementation_parent, pool);

            if (via_implementation != null)
            {
                return(via_implementation);
            }

            foreach (EntityInstance interface_parent in type.Inheritance(ctx).MinimalParentsIncludingObject
                     .Where(it => it != implementation_parent))
            {
                EntityInstance via_interface = selectFromLowestCommonAncestorPool(ctx, interface_parent, pool);
                if (via_interface != null)
                {
                    return(via_interface);
                }
            }

            return(null);
        }
Пример #10
0
        public IEntityInstance Evaluated(ComputationContext ctx)
        {
            if (this.Evaluation == null)
            {
                IEntityInstance eval;
                if (!this.IsJoker && this.Target is TemplateDefinition)
                {
                    eval = this.TargetTemplate.Evaluation.Components;
                }
                else
                {
                    eval = this.Target.Evaluated(ctx, EvaluationCall.AdHocCrossJump);
                }

                this.Evaluation = eval.TranslateThrough(this);
                if (this.Evaluation.IsJoker)
                {
                    this.Aggregate = Environment.JokerInstance;
                }
                else
                {
                    EntityInstance aggregate = this.Target.Evaluation.Aggregate;
                    this.Aggregate = aggregate.TranslateThrough(this);
                }
            }

            return(this.Evaluation);
        }
Пример #11
0
        private static bool matchTypes(ComputationContext ctx, TypeMutability inputMutability,
                                       Lifetime inputLifetime,
                                       EntityInstance input, EntityInstance target,
                                       TypeMatching matching, int distance, out TypeMatch match)
        {
            bool is_matched = templateMatches(ctx, input, target, matching, out TypeMatch fail_match);

            if (!is_matched)
            {
                match = fail_match;
                return(false);
            }

            // we cannot shove mutable type in disguise as immutable one, consider such scenario
            // user could create const wrapper over "*Object" (this is immutable type) and then create its instance
            // passing some mutable instance, wrapper would be still immutable despite the fact it holds mutable data
            // this would be disastrous when working concurrently (see more in Documentation/Mutability)

            bool mutability_matches;

            {
                TypeMutability target_mutability = target.MutabilityOfType(ctx);
                // cheapest part to compute
                mutability_matches = MutabilityMatches(ctx.Env.Options, inputMutability, target_mutability);

                // fixing mutability mismatch
                if (!mutability_matches
                    &&
                    (matching.ForcedIgnoreMutability
                     // in case when we have two value types in hand mutability does not matter, because we copy
                     // instances and they are separate beings afterwards
                     || (!matching.MutabilityCheckRequestByData &&
                         input.TargetType.IsValueType(ctx) && target.TargetType.IsValueType(ctx))))
                {
                    mutability_matches = true;
                }
            }

            if (!mutability_matches)
            {
                match = TypeMatch.Mismatched(mutability: true);
                return(true);
            }
            else if (matching.LifetimeCheck && matching.TargetLifetime.Outlives(matching.InputLifetime))
            {
                match = TypeMatch.Lifetime;
                return(true);
            }
            else if (distance == 0 && input.Target == target.Target)
            {
                match = TypeMatch.Same;
                return(true);
            }
            else
            {
                match = TypeMatch.Substituted(distance);
                return(true);
            }
        }
Пример #12
0
            internal void AddDuckVirtualTable(ComputationContext ctx, EntityInstance target, VirtualTable vtable)
            {
                if (vtable == null)
                {
                    throw new Exception("Internal error");
                }

                this.duckVirtualTables.Add(target.core, vtable);
            }
Пример #13
0
        internal static EntityInstance CreateUnregistered(RuntimeCore core, IEntity target,
                                                          TemplateTranslation translation,
                                                          TypeMutability overrideMutability,
                                                          Lifetime lifetime)
        {
            var instance = new EntityInstance(core, target, translation, overrideMutability, lifetime);

            return(instance);
        }
Пример #14
0
        public bool IsExactlySame(INameReference other, EntityInstance translationTemplate, bool jokerMatchesAll)
        {
            if (!jokerMatchesAll)
            {
                return(this == other);
            }

            return(hasSymmetricRelation(other, (a, b) => a.IsExactlySame(b, translationTemplate, jokerMatchesAll)));
        }
Пример #15
0
        public EvaluationInfo(IEntityInstance components, EntityInstance merged)
        {
            if (components == null || merged == null)
            {
                throw new ArgumentNullException();
            }

            this.Components = components;
            this.Aggregate  = merged;
        }
Пример #16
0
        public bool IsStrictDescendantOf(ComputationContext ctx, EntityInstance ancestor)
        {
            foreach (IEntityInstance instance in this.elements)
            {
                if (!instance.IsStrictDescendantOf(ctx, ancestor))
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #17
0
        public static NameReference Create(TypeMutability overrideMutability, IExpression prefix, string name,
                                           IEnumerable <INameReference> arguments, EntityInstance target, bool isLocal)
        {
            var result = new NameReference(overrideMutability, prefix, BrowseMode.None, null, name,
                                           arguments?.Select(it => new TemplateArgument(it)),
                                           ExpressionReadMode.ReadRequired, isRoot: false);

            if (target != null)
            {
                result.Binding.Set(new[] { new BindingMatch(target, isLocal) });
            }
            return(result);
        }
Пример #18
0
        public static TemplateTranslation Create(EntityInstance instance, IEntityInstance argument)
        {
            if (instance.Target.Name.Parameters.Count != 1)
            {
                throw new ArgumentException();
            }

            Dictionary <TemplateParameter, IEntityInstance> dict
                = instance.Translation.table.ToDictionary(it => it.Key, it => it.Value);

            dict[instance.Target.Name.Parameters[0]] = argument;

            return(new TemplateTranslation(instance.Target, dict));
        }
Пример #19
0
        private CallResolution(ComputationContext ctx,
                               IEnumerable <TemplateArgument> templateArguments,
                               IFunctionArgumentsProvider argumentsProvider,
                               CallContext callContext,
                               EntityInstance targetFunctionInstance,
                               List <int> argParamMapping,
                               out bool success)
        {
            success = true;

            this.MetaThisArgument       = callContext.MetaThisArgument;
            this.TargetFunctionInstance = targetFunctionInstance;
            this.argumentsProvider      = argumentsProvider;

            if (this.IsExtendedCall)
            {
                this.ExtensionsArguments = new[] { this.MetaThisArgument }
            }
Пример #20
0
            internal static ParameterType Create(ComputationContext ctx,
                                                 FunctionParameter param,
                                                 IEntityInstance objectInstance,
                                                 EntityInstance targetFunctionInstance)
            {
                IEntityInstance elem_instance = translateFunctionElement(param.ElementTypeName.Evaluation.Components,
                                                                         objectInstance, targetFunctionInstance);

                IEntityInstance type_instance = translateFunctionElement(param.TypeName.Evaluation.Components,
                                                                         objectInstance, targetFunctionInstance);

                Lifetime param_lifetime = param.Evaluation.Aggregate.Lifetime;

                elem_instance = elem_instance.Rebuild(ctx, param_lifetime, deep: false);
                type_instance = type_instance.Rebuild(ctx, param_lifetime, deep: false);

                return(new ParameterType(elementTypeInstance: elem_instance, typeInstance: type_instance));
            }
Пример #21
0
        public IEntityInstance TranslateThrough(ref bool translated, TemplateTranslation translation)
        {
            // consider:
            // Coll<T,A> implements IColl<A>
            // and then you have Coll<Int,String> (closedTemplate) -- so how does IColl looks now?
            // IColl<String> (since A maps to String)
            // and we compute it here
            // or let's say we have type Foo<T> and one of its methods returns T
            // then we have instance Foo<String> (closedTemplate), what T is then? (String)

            if (translation == null || translation == TemplateTranslation.Empty)
            {
                return(this);
            }

            if (this.TargetsTemplateParameter)
            {
                if (translation.Translate(this.TemplateParameterTarget, out IEntityInstance trans))
                {
                    if (!this.IsIdentical(trans))
                    {
                        translated = true;
                    }

                    return(trans);
                }

                return(this);
            }
            else
            {
                TemplateTranslation combo_translation = TemplateTranslation.Translated(this.Translation, translation, ref translated);

                EntityInstance result = this.Target.GetInstance(this.OverrideMutability, combo_translation, this.Lifetime);

                return(result);
            }
        }
Пример #22
0
        public override TypeMatch MatchesInput(ComputationContext ctx, EntityInstance input, TypeMatching matching)
        {
            TypeMatch match = TypeMatch.No;

            foreach (IEntityInstance target in this.elements)
            {
                TypeMatch m = target.MatchesInput(ctx, input, matching);
                if (m.IsMismatch())
                {
                    return(m);
                }
                else if (match.IsMismatch())
                {
                    match = m;
                }
                else if (match != m)
                {
                    return(TypeMatch.No);
                }
            }

            return(match);
        }
Пример #23
0
        protected EntityInstance createAggregate(ComputationContext ctx, bool hasReference, bool hasPointer,
                                                 IEnumerable <EntityInstance> dereferencedInstances, IEnumerable <FunctionDefinition> members,
                                                 bool partialVirtualTables)
        {
            this.aggregate = TypeBuilder.Create(AutoName.Instance.CreateNew("Aggregate"))
                             .With(members)
                             .SetModifier(EntityModifier.Protocol);
            aggregate.AttachTo(this);
            this.aggregate.Evaluated(ctx, EvaluationCall.AdHocCrossJump);

            EntityInstance aggregate_instance = this.aggregate.InstanceOf;

            foreach (EntityInstance instance in dereferencedInstances)
            {
                EntityInstanceExtension.BuildDuckVirtualTable(ctx, instance, aggregate_instance, allowPartial: partialVirtualTables);
            }

            if (hasReference || hasPointer)
            {
                aggregate_instance = ctx.Env.Reference(aggregate_instance, TypeMutability.None, viaPointer: hasPointer);
            }

            return(aggregate_instance);
        }
Пример #24
0
        public static ConstraintMatch ArgumentsMatchConstraintsOf(ComputationContext ctx, EntityInstance closedTemplate)
        {
            if (closedTemplate == null || closedTemplate.IsJoker)
            {
                return(ConstraintMatch.Yes);
            }

            return(ArgumentsMatchConstraintsOf(ctx, closedTemplate.Target.Name.Parameters, closedTemplate));
        }
Пример #25
0
        public static ConstraintMatch ArgumentsMatchConstraintsOf(ComputationContext ctx,
                                                                  IEnumerable <TemplateParameter> templateParameters, EntityInstance closedTemplate)
        {
            if (templateParameters.Count() != closedTemplate.TemplateArguments.Count)
            {
                return(ConstraintMatch.UndefinedTemplateArguments);
            }

            foreach (Tuple <TemplateParameter, IEntityInstance> param_arg in templateParameters
                     .SyncZip(closedTemplate.TemplateArguments))
            {
                ConstraintMatch match = param_arg.Item2.ArgumentMatchesParameterConstraints(ctx, closedTemplate, param_arg.Item1);
                if (match != ConstraintMatch.Yes)
                {
                    return(match);
                }
            }

            return(ConstraintMatch.Yes);
        }
Пример #26
0
 public static bool TryGetSingleType(this INameReference @this, out NameReference nameReference, out EntityInstance typeInstance)
 {
     nameReference = @this as NameReference;
     if (nameReference == null)
     {
         typeInstance = null;
         return(false);
     }
     else
     {
         typeInstance = nameReference.Evaluation.Components.Cast <EntityInstance>();
         return(true);
     }
 }
Пример #27
0
 public IEnumerable <EntityInstance> TranslateBaseOf(EntityInstance closedTemplate)
 {
     return(BaseOfNames.Select(it => it.Binding.Match.Instance)
            .Select(it => it.TranslateThrough(closedTemplate)));
 }
Пример #28
0
        protected override void compute(ComputationContext ctx)
        {
            IEntityInstance eval = EntityInstanceUnion.Create(Elements.Select(it => it.Evaluation.Components));

            // we need to get common members

            bool has_reference                = false;
            bool has_pointer                  = false;
            var  dereferenced_instances       = new List <EntityInstance>();
            List <FunctionDefinition> members = null;

            foreach (EntityInstance ____instance in this.Elements.Select(it => it.Evaluation.Aggregate))
            {
                if (ctx.Env.DereferencedOnce(____instance, out IEntityInstance __instance, out bool via_pointer))
                {
                    if (via_pointer)
                    {
                        has_pointer = true;
                    }
                    else
                    {
                        has_reference = true;
                    }
                }

                EntityInstance instance = __instance.Cast <EntityInstance>();

                dereferenced_instances.Add(instance);

                if (members == null)
                {
                    members = instance.TargetType.NestedFunctions
                              .Where(f => !f.IsAnyConstructor() && f.Parameters.All(it => !it.IsOptional))
                              .ToList();
                }
                else
                {
                    foreach (FunctionDefinition m in members.ToArray())
                    {
                        bool found = false;
                        foreach (FunctionDefinition func in instance.TargetType.NestedFunctions)
                        {
                            // todo: maybe some day handle optionals
                            if (func.IsAnyConstructor() || func.Parameters.Any(it => it.IsOptional))
                            {
                                continue;
                            }

                            if (FunctionDefinitionExtension.IsSame(ctx, m, func, instance))
                            {
                                found = true;
                                break;
                            }
                        }

                        if (!found)
                        {
                            members.Remove(m);
                        }
                    }
                }
            }

            EntityInstance aggregate_instance = createAggregate(ctx, has_reference, has_pointer,
                                                                dereferenced_instances, members, partialVirtualTables: false);

            this.Evaluation = new EvaluationInfo(eval, aggregate_instance);
        }
Пример #29
0
        public static TypeMatch Matches(ComputationContext ctx, EntityInstance input, EntityInstance target, TypeMatching matching)
        {
            if (input.IsJoker || target.IsJoker)
            {
                return(TypeMatch.Same);
            }

            if (!target.Target.IsType() || !input.Target.IsType())
            {
                return(TypeMatch.No);
            }

            if (input.Lifetime.IsAttached)
            {
                matching = matching.WithLifetimeCheck(true, input.Lifetime, target.Lifetime);
            }


            {
                IEnumerable <FunctionDefinition> in_conv = target.TargetType.ImplicitInConverters().StoreReadOnly();
                bool conv_slicing_sub = input.TargetType.AllowSlicedSubstitution;
                foreach (FunctionDefinition func in in_conv)
                {
                    IEntityInstance conv_type = func.Parameters.Single().TypeName.Evaluated(ctx, EvaluationCall.AdHocCrossJump).TranslateThrough(target);
                    if (target.IsIdentical(conv_type)) // preventing circular conversion check
                    {
                        continue;
                    }

                    TypeMatch m = input.MatchesTarget(ctx, conv_type, matching.WithSlicing(conv_slicing_sub));
                    if (m == TypeMatch.Same || m == TypeMatch.Substitute)
                    {
                        return(TypeMatch.InConversion);
                    }
                }
            }


            if (ctx.Env.IsReferenceOfType(target))
            {
                if (ctx.Env.IsPointerLikeOfType(input))
                {
                    // note, that we could have reference to pointer in case of the target, we have to unpack both
                    // to the level of the value types
                    int target_dereferences = ctx.Env.Dereference(target, out IEntityInstance inner_target_type);
                    int input_dereferences  = ctx.Env.Dereference(input, out IEntityInstance inner_input_type);

                    TypeMatch m = inner_input_type.MatchesTarget(ctx, inner_target_type, matching
                                                                 .WithSlicing(true)
                                                                 .WithMutabilityCheckRequest(true)
                                                                 .WithLifetimeCheck(true, ctx.Env.IsReferenceOfType(input) ? input.Lifetime : Lifetime.Timeless, target.Lifetime));
                    if (target_dereferences > input_dereferences && !m.IsMismatch())
                    {
                        m |= TypeMatch.ImplicitReference;
                    }
                    return(m);
                }
                else
                {
                    ctx.Env.Dereferenced(target, out IEntityInstance inner_target_type);

                    TypeMatch m = input.MatchesTarget(ctx, inner_target_type, matching
                                                      .WithSlicing(true)
                                                      .WithMutabilityCheckRequest(true)
                                                      .WithLifetimeCheck(true, input.Lifetime, target.Lifetime));
                    if (m == TypeMatch.Same || m == TypeMatch.Substitute)
                    {
                        return(m | TypeMatch.ImplicitReference);
                    }
                    else
                    {
                        return(m);
                    }
                }
            }
            // automatic dereferencing pointers
            else if (ctx.Env.IsPointerLikeOfType(input))
            {
                int input_dereferences;
                {
                    input_dereferences = ctx.Env.Dereference(input, out IEntityInstance dummy);
                }

                // we check if we have more refs/ptrs in input than in target
                if (input_dereferences > (ctx.Env.IsPointerOfType(target) ? 1 : 0))
                {
                    ctx.Env.DereferencedOnce(input, out IEntityInstance inner_input_type, out bool dummy);

                    TypeMatch m = inner_input_type.MatchesTarget(ctx, target, matching.WithSlicing(true));
                    if (m.Passed)
                    {
                        return(m | TypeMatch.AutoDereference);
                    }
                }
                else
                {
                    matching = matching.WithMutabilityCheckRequest(true)
                    ;
                }
            }

            if (ctx.Env.IsReferenceOfType(input) && ctx.Env.IsPointerOfType(target))
            {
                // note, that we could have reference to pointer in case of the target, we have to unpack both
                // to the level of the value types
                ctx.Env.DereferencedOnce(target, out IEntityInstance inner_target_type, out bool dummy1);
                ctx.Env.DereferencedOnce(input, out IEntityInstance inner_input_type, out bool dummy2);

                TypeMatch m = inner_input_type.MatchesTarget(ctx, inner_target_type, matching
                                                             .WithSlicing(true)
                                                             .WithMutabilityCheckRequest(true)
                                                             .WithLifetimeCheck(true, input.Lifetime, Lifetime.Timeless));
                if (!m.IsMismatch())
                {
                    m |= TypeMatch.Attachment;
                }
                return(m);
            }


            {
                IEnumerable <FunctionDefinition> out_conv = input.TargetType.ImplicitOutConverters().StoreReadOnly();
                bool conv_slicing_sub = input.TargetType.AllowSlicedSubstitution;
                foreach (FunctionDefinition func in out_conv)
                {
                    IEntityInstance conv_type = func.ResultTypeName.Evaluated(ctx, EvaluationCall.AdHocCrossJump).TranslateThrough(input);
                    //if (target == conv_type) // preventing circular conversion check
                    //  continue;

                    TypeMatch m = conv_type.MatchesTarget(ctx, target, matching.WithSlicing(conv_slicing_sub));
                    if (m == TypeMatch.Same || m == TypeMatch.Substitute)
                    {
                        return(TypeMatch.OutConversion);
                    }
                }
            }

            if (target.TargetType.AllowSlicedSubstitution)
            {
                matching.AllowSlicing = true;
            }


            TypeMatch match = TypeMatch.No;

            TypeMutability input_mutability = input.MutabilityOfType(ctx);

            if (matching.AllowSlicing)
            {
                IEnumerable <TypeAncestor> input_family = new[] { new TypeAncestor(input, 0) }
                .Concat(input.Inheritance(ctx).OrderedTypeAncestorsIncludingObject
                        // enum substitution works in reverse so we have to exclude these from here
                        .Where(it => !it.AncestorInstance.TargetType.Modifier.HasEnum));

                foreach (TypeAncestor inherited_input in input_family)
                {
                    if (matchTypes(ctx, input_mutability, input.Lifetime, inherited_input.AncestorInstance,
                                   target, matching, inherited_input.Distance, out TypeMatch m))
                    {
                        return(m);
                    }
                    else if (m != TypeMatch.No) // getting more specific rejection than just bare one
                    {
                        match = m;
                    }
                }
            }
            // when slicing is disabled we can compare try to substitute only the same type
            else if (input.Target == target.Target)
            {
                if (matchTypes(ctx, input_mutability, input.Lifetime, input, target, matching, distance: 0, match: out match))
                {
                    if (match != TypeMatch.Same && !match.IsMismatch())
                    {
                        throw new Exception($"Internal exception {match}");
                    }
                    return(match);
                }
            }

            if (input.TargetType.Modifier.HasEnum)
            {
                // another option for enum-"inheritance" would be dropping it altogether, and copying all the values from the
                // base enum. Adding conversion constructor from base to child type will suffice and allow to get rid
                // of those enum-inheritance matching

                // since we compare only enums here we allow slicing (because it is not slicing, just passing single int)
                match = inversedTypeMatching(ctx, input, new[] { new TypeAncestor(target, 0) }
                                             .Concat(target.Inheritance(ctx).OrderedTypeAncestorsIncludingObject)
                                             .Where(it => it.AncestorInstance.TargetType.Modifier.HasEnum), matching.WithSlicing(true));

                if (!match.IsMismatch())
                {
                    return(match);
                }
            }

            if (target.TargetsTemplateParameter)
            {
                // template parameter can have reversed inheritance defined via base-of constraints
                // todo: at this it should be already evaluated, so constraints should be surfables
                IEnumerable <IEntityInstance> base_of
                    = target.TemplateParameterTarget.Constraint.BaseOfNames.Select(it => it.Evaluated(ctx, EvaluationCall.AdHocCrossJump));

                match = inversedTypeMatching(ctx, input, new[] { new TypeAncestor(target, 0) }
                                             .Concat(base_of.Select(it => new TypeAncestor(it.Cast <EntityInstance>(), 1))), matching);

                if (!match.IsMismatch())
                {
                    return(match);
                }
            }

            return(match);
        }
Пример #30
0
 public NameReference CreateNameReference(IExpression prefix, EntityInstance targetInstance, bool isLocal)
 {
     return(NameReference.Create(prefix, this.Name,
                                 this.Parameters.Select(it => NameReference.Create(it.Name)), targetInstance, isLocal));
 }