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