Exemplo n.º 1
0
        public static Dictionary <string, IExpression> MembershipMappingsFor(ProfileMetaData profile, Context context)
        {
            var calledFunctions = profile.Priority.Values.ToHashSet();

            calledFunctions.Add(profile.Speed);
            calledFunctions.Add(profile.Access);
            calledFunctions.Add(profile.Oneway);


            var calledFunctionQueue      = new Queue <string>();
            var alreadyAnalysedFunctions = new HashSet <string>();
            var memberships = new Dictionary <string, IExpression>();

            void HandleExpression(IExpression e, string calledIn)
            {
                e.Visit(f =>
                {
                    var mapping = new List <IExpression>();
                    if (Deconstruct.UnApply(Deconstruct.IsFunc(Funcs.MemberOf),
                                            Deconstruct.Assign(mapping)
                                            ).Invoke(f))
                    {
                        memberships.Add(calledIn, mapping.First());
                        return(false);
                    }

                    if (f is FunctionCall fc)
                    {
                        calledFunctionQueue.Enqueue(fc.CalledFunctionName);
                    }

                    return(true);
                });
            }

            foreach (var e in calledFunctions)
            {
                HandleExpression(e, "profile_root");
            }

            while (calledFunctionQueue.TryDequeue(out var functionName))
            {
                if (alreadyAnalysedFunctions.Contains(functionName))
                {
                    continue;
                }

                alreadyAnalysedFunctions.Add(functionName);

                var functionImplementation = context.GetFunction(functionName);
                HandleExpression(functionImplementation, functionName);
            }


            return(memberships);
        }
Exemplo n.º 2
0
        public static void SanityCheck(this IExpression e)
        {
            e.Visit(expr =>
            {
                var order   = new List <IExpression>();
                var mapping = new List <IExpression>();
                if (Deconstruct.UnApply(
                        Deconstruct.UnApply(Deconstruct.IsFunc(Funcs.FirstOf), Deconstruct.Assign(order)),
                        Deconstruct.Assign(mapping)
                        ).Invoke(expr))
                {
                    var expectedKeys = ((IEnumerable <object>)order.First().Evaluate(null)).Select(o =>
                    {
                        if (o is IExpression x)
                        {
                            return((string)x.Evaluate(null));
                        }

                        return((string)o);
                    })
                                       .ToHashSet();
                    var actualKeys       = mapping.First().PossibleTags().Keys;
                    var missingInOrder   = actualKeys.Where(key => !expectedKeys.Contains(key)).ToList();
                    var missingInMapping = expectedKeys.Where(key => !actualKeys.Contains(key)).ToList();
                    if (missingInOrder.Any() || missingInMapping.Any())
                    {
                        var missingInOrderMsg = "";
                        if (missingInOrder.Any())
                        {
                            missingInOrderMsg = $"The order misses keys {string.Join(",", missingInOrder)}\n";
                        }

                        var missingInMappingMsg = "";
                        if (missingInMapping.Any())
                        {
                            missingInMappingMsg =
                                $"The mapping misses mappings for keys {string.Join(", ", missingInMapping)}\n";
                        }

                        throw new ArgumentException(
                            "Sanity check failed: the specified order of firstMatchOf contains to little or to much keys:\n" +
                            missingInOrderMsg + missingInMappingMsg
                            );
                    }
                }

                return(true);
            });
        }