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); } }
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); }
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); }