public static Dictionary <string, (List <Type> Types, string inFunction)> UsedParameters( this ProfileMetaData profile, Context context) { var parameters = new Dictionary <string, (List <Type> Types, string usageLocation)>(); void AddParams(IExpression e, string inFunction) { var parms = e.UsedParameters(); foreach (var param in parms) { if (parameters.TryGetValue(param.ParamName, out var typesOldUsage)) { var(types, oldUsage) = typesOldUsage; var unified = types.SpecializeTo(param.Types); if (unified == null) { throw new ArgumentException("Inconsistent parameter usage: the paremeter " + param.ParamName + " is used\n" + $" in {oldUsage} as {string.Join(",", types)}\n" + $" in {inFunction} as {string.Join(",", param.Types)}\n" + $"which can not be unified"); } } else { parameters[param.ParamName] = (param.Types.ToList(), inFunction); } } } AddParams(profile.Access, "profile definition for " + profile.Name + ".access"); AddParams(profile.Oneway, "profile definition for " + profile.Name + ".oneway"); AddParams(profile.Speed, "profile definition for " + profile.Name + ".speed"); foreach (var(key, expr) in profile.Priority) { AddParams(new Parameter(key), profile.Name + ".priority.lefthand"); AddParams(expr, profile.Name + ".priority"); } var calledFunctions = profile.CalledFunctionsRecursive(context).Values .SelectMany(ls => ls).ToHashSet(); foreach (var calledFunction in calledFunctions) { var func = context.GetFunction(calledFunction); if (func is AspectMetadata meta && meta.ProfileInternal) { continue; } AddParams(func, "function " + calledFunction); } return(parameters); }
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 LuaPrinter1(ProfileMetaData profile, Context context, List <AspectTestSuite> aspectTestSuites, List <BehaviourTestSuite> profileTests) { _profile = profile; _context = context; _aspectTestSuites = aspectTestSuites?.Where(suite => suite != null) ?.Select(testSuite => testSuite.WithoutRelationTests())?.ToList(); _profileTests = profileTests; _skeleton = new LuaSkeleton.LuaSkeleton(context, false); _parameterPrinter = new LuaParameterPrinter(profile, _skeleton); }
public LuaPrinter2(ProfileMetaData profile, string behaviourName, Context context, List <AspectTestSuite> aspectTests, IEnumerable <BehaviourTestSuite> behaviourTestSuite, DateTime lastChangeTime) { _skeleton = new LuaSkeleton.LuaSkeleton(context, true); _profile = profile; _behaviourName = behaviourName; _context = context; _aspectTests = aspectTests; _behaviourTestSuite = behaviourTestSuite; _lastChangeTime = lastChangeTime; _parameterPrinter = new LuaParameterPrinter(_profile, _skeleton); }
public static Dictionary <string, List <string> > CalledFunctionsRecursive(this ProfileMetaData profile, Context c) { // Read as: this function calls the value-function var result = new Dictionary <string, List <string> >(); var calledFunctions = new Queue <string>(); void ScanExpression(IExpression e, string inFunction) { if (!result.ContainsKey(inFunction)) { result.Add(inFunction, new List <string>()); } e.Visit(x => { if (x is FunctionCall fc) { result[inFunction].Add(fc.CalledFunctionName); if (!result.ContainsKey(fc.CalledFunctionName)) { calledFunctions.Enqueue(fc.CalledFunctionName); } } return(true); }); } ScanExpression(profile.Access, profile.Name + ".access"); ScanExpression(profile.Oneway, profile.Name + ".oneway"); ScanExpression(profile.Speed, profile.Name + ".speed"); foreach (var(key, expr) in profile.Priority) { ScanExpression(new Parameter(key), $"{profile.Name}.priority.{key}.lefthand"); ScanExpression(expr, $"{profile.Name}.priority.{key}"); } while (calledFunctions.TryDequeue(out var calledFunction)) { var func = c.GetFunction(calledFunction); ScanExpression(func, calledFunction); } return(result); }
private static void PrintUsedTags(ProfileMetaData profile, Context context) { Console.WriteLine("\n\n\n---------- " + profile.Name + " --------------"); foreach (var(key, values) in profile.AllExpressions(context).PossibleTags()) { var vs = "*"; if (values.Any()) { vs = string.Join(", ", values); } Console.WriteLine(key + ": " + vs); } Console.WriteLine("\n\n\n------------------------"); }
private static void Repl(Context c, Dictionary <string, ProfileMetaData> profiles) { var profile = profiles["emergency_vehicle"]; var behaviour = profile.Behaviours.Keys.First(); do { Console.Write(profile.Name + "." + behaviour + " > "); var read = Console.ReadLine(); if (read == null) { return; // End of stream has been reached } if (read == "") { Console.WriteLine("looƆ sᴉ dɐWʇǝǝɹʇSuǝdO"); continue; } if (read.Equals("quit")) { return; } if (read.Equals("help")) { Console.WriteLine( Utils.Lines("select <behaviourName> to change behaviour or <vehicle.behaviourName> to change vehicle", "")); continue; } if (read.Equals("clear")) { for (var i = 0; i < 80; i++) { Console.WriteLine(); } continue; } if (read.StartsWith("select")) { var beh = read.Substring("select".Length + 1).Trim(); if (beh.Contains(".")) { var profileName = beh.Split(".")[0]; if (!profiles.TryGetValue(profileName, out var newProfile)) { Console.Error.WriteLine("Profile " + profileName + " not found, ignoring"); continue; } profile = newProfile; beh = beh.Substring(beh.IndexOf(".") + 1); } if (profile.Behaviours.ContainsKey(beh)) { behaviour = beh; Console.WriteLine("Switched to " + beh); } else { Console.WriteLine("Behaviour not found. Known behaviours are:\n " + string.Join("\n ", profile.Behaviours.Keys)); } continue; } var tagsRaw = read.Split(";").Select(s => s.Trim()); var tags = new Dictionary <string, string>(); foreach (var str in tagsRaw) { if (str == "") { continue; } var strSplit = str.Split("="); var k = strSplit[0].Trim(); var v = strSplit[1].Trim(); tags[k] = v; } try { var result = profile.Run(c, behaviour, tags); Console.WriteLine(result); } catch (Exception e) { Console.WriteLine(e); Console.WriteLine(e.Message); } } while (true); }
public LuaParameterPrinter(ProfileMetaData profile, LuaSkeleton.LuaSkeleton skeleton) { _profile = profile; _skeleton = skeleton; }
public static void SanityCheckProfile(this ProfileMetaData pmd, Context context) { var defaultParameters = pmd.DefaultParameters.Keys .Select(k => k.TrimStart('#')).ToList(); var usedMetadata = pmd.UsedParameters(context); string MetaList(IEnumerable <string> paramNames) { var metaInfo = ""; foreach (var paramName in paramNames) { var _ = usedMetadata.TryGetValue(paramName, out var inFunction) || usedMetadata.TryGetValue('#' + paramName, out inFunction); metaInfo += $"\n - {paramName} (used in {inFunction.inFunction})"; } return(metaInfo); } var usedParameters = usedMetadata.Keys.Select(key => key.TrimStart('#')).ToList(); var diff = usedParameters.ToHashSet().Except(defaultParameters).ToList(); if (diff.Any()) { throw new ArgumentException("No default value set for parameter: " + MetaList(diff)); } var unused = defaultParameters.Except(usedParameters); if (unused.Any()) { Console.WriteLine("[WARNING] A default value is set for parameter, but it is unused: " + string.Join(", ", unused)); } var paramsUsedInBehaviour = new HashSet <string>(); foreach (var(behaviourName, behaviourParams) in pmd.Behaviours) { var sum = 0.0; var explanation = ""; paramsUsedInBehaviour.UnionWith(behaviourParams.Keys.Select(k => k.Trim('#'))); foreach (var(paramName, _) in pmd.Priority) { if (!pmd.DefaultParameters.ContainsKey(paramName)) { throw new ArgumentException( $"The behaviour {behaviourName} uses a parameter for which no default is set: {paramName}"); } if (!behaviourParams.TryGetValue(paramName, out var weight)) { explanation += $"\n - {paramName} = default (not set)"; continue; } var weightObj = weight.Evaluate(context); if (!(weightObj is double d)) { throw new ArgumentException( $"The parameter {paramName} is not a numeric value in profile {behaviourName}"); } sum += Math.Abs(d); explanation += $"\n - {paramName} = {d}"; } if (Math.Abs(sum) < 0.0001) { throw new ArgumentException("Profile " + behaviourName + ": the summed parameters to calculate the weight are zero or very low:" + explanation); } } var defaultOnly = defaultParameters.Except(paramsUsedInBehaviour).ToList(); if (defaultOnly.Any()) { Console.WriteLine( $"[{pmd.Name}] WARNING: Some parameters only have a default value: {string.Join(", ", defaultOnly)}"); } }