diff --git a/AspectedRouting.Test/AspectedRouting.Test.csproj b/AspectedRouting.Test/AspectedRouting.Test.csproj
index 0347b72..af03f82 100644
--- a/AspectedRouting.Test/AspectedRouting.Test.csproj
+++ b/AspectedRouting.Test/AspectedRouting.Test.csproj
@@ -7,14 +7,14 @@
-
-
-
-
+
+
+
+
-
+
\ No newline at end of file
diff --git a/AspectedRouting.Test/FunctionsTest.cs b/AspectedRouting.Test/FunctionsTest.cs
index f581623..2d51717 100644
--- a/AspectedRouting.Test/FunctionsTest.cs
+++ b/AspectedRouting.Test/FunctionsTest.cs
@@ -11,6 +11,21 @@ namespace AspectedRouting.Test
{
public class FunctionsTest
{
+ private readonly string constString = "{\"$const\": \"a\"}";
+
+ private readonly string IfDottedConditionJson
+ = "{" +
+ "\"$ifdotted\": {\"$eq\": \"yes\"}," +
+ "\"then\":{\"$const\": \"a\"}," +
+ "\"else\": {\"$const\": \"b\"}" +
+ "}";
+
+ private readonly string IfSimpleConditionJson
+ = "{" +
+ "\"$if\": true," +
+ "\"then\":\"thenResult\"," +
+ "\"else\": \"elseResult\"}";
+
private IExpression MustMatchJson()
{
var json = "{" +
@@ -32,10 +47,9 @@ namespace AspectedRouting.Test
[Fact]
public void TestAll_AllTags_Yes()
{
- var tagsAx = new Dictionary
- {
- {"a", "b"},
- {"x", "y"}
+ var tagsAx = new Dictionary {
+ { "a", "b" },
+ { "x", "y" }
};
var expr = new Apply(MustMatchJson(), new Constant(tagsAx)).Optimize();
@@ -46,9 +60,8 @@ namespace AspectedRouting.Test
[Fact]
public void TestAll_NoMatch_No()
{
- var tagsAx = new Dictionary
- {
- {"a", "b"},
+ var tagsAx = new Dictionary {
+ { "a", "b" }
};
var expr = new Apply(MustMatchJson(), new Constant(tagsAx)).Optimize();
@@ -59,10 +72,9 @@ namespace AspectedRouting.Test
[Fact]
public void TestAll_NoMatchDifferent_No()
{
- var tagsAx = new Dictionary
- {
- {"a", "b"},
- {"x", "someRandomValue"}
+ var tagsAx = new Dictionary {
+ { "a", "b" },
+ { "x", "someRandomValue" }
};
var expr = new Apply(MustMatchJson(), new Constant(tagsAx)).Optimize();
@@ -70,19 +82,6 @@ namespace AspectedRouting.Test
Assert.Equal("no", result);
}
- private string IfDottedConditionJson
- = "{" +
- "\"$ifdotted\": {\"$eq\": \"yes\"}," +
- "\"then\":{\"$const\": \"a\"}," +
- "\"else\": {\"$const\": \"b\"}" +
- "}";
-
- private string IfSimpleConditionJson
- = "{" +
- "\"$if\": true," +
- "\"then\":\"thenResult\"," +
- "\"else\": \"elseResult\"}";
-
[Fact]
public void TestParsing_SimpleIf_CorrectExpression()
{
@@ -129,9 +128,6 @@ namespace AspectedRouting.Test
Assert.Equal("b", resultF);
}
-
- private string constString = "{\"$const\": \"a\"}";
-
[Fact]
public void Parse_ConstString_TypeIsFree()
{
@@ -231,8 +227,7 @@ namespace AspectedRouting.Test
var e = new Var("e");
var f = new Var("f");
- var newTypes = Funcs.Const.Types.RenameVars(new[]
- {
+ var newTypes = Funcs.Const.Types.RenameVars(new[] {
new Curry(e, e),
new Curry(new Curry(b, f), new Curry(new Curry(a, b), new Curry(a, f)))
}).ToList();
@@ -308,9 +303,9 @@ namespace AspectedRouting.Test
var unifB = tags2pdouble.Unify(tags2double, true);
Assert.NotNull(unifB);
- var unifC = tags2double.Unify(tags2pdouble, false);
+ var unifC = tags2double.Unify(tags2pdouble);
Assert.NotNull(unifC);
- var unifD = tags2pdouble.Unify(tags2double, false);
+ var unifD = tags2pdouble.Unify(tags2double);
Assert.Null(unifD);
}
@@ -323,7 +318,7 @@ namespace AspectedRouting.Test
Typs.String,
new Curry(Typs.String, Typs.Bool));
var f0 = f.Specialize(strstrb);
- Assert.Equal(new[] {strstrb}, f0.Types);
+ Assert.Equal(new[] { strstrb }, f0.Types);
var strstrstr = new Curry(
Typs.String,
@@ -331,7 +326,7 @@ namespace AspectedRouting.Test
var f1 = f.Specialize(strstrstr);
- Assert.Equal(new[] {strstrb, strstrstr}, f1.Types);
+ Assert.Equal(new[] { strstrb, strstrstr }, f1.Types);
}
[Fact]
@@ -341,11 +336,11 @@ namespace AspectedRouting.Test
var p1 = Funcs.Const.Apply(new Constant(1.0)).Specialize(
new Curry(new Var("a"), Typs.Double));
- var exprs = new[] {p0, p1};
+ var exprs = new[] { p0, p1 };
var newTypes = exprs.SpecializeToCommonTypes(out var _);
Assert.Single(newTypes);
- exprs = new[] {p1, p0};
+ exprs = new[] { p1, p0 };
newTypes = exprs.SpecializeToCommonTypes(out var _);
Assert.Single(newTypes);
}
@@ -360,7 +355,7 @@ namespace AspectedRouting.Test
Assert.Null(result);
}
-
+
[Fact]
public void ParseFunction_Duration_TotalMinutes()
{
@@ -376,10 +371,8 @@ namespace AspectedRouting.Test
{
var e = new Apply(new Apply(Funcs.Default, new Constant("a")), Funcs.Id);
Assert.Single(e.Types);
-
+
Assert.Equal("string -> string", e.Types.First().ToString());
-
}
-
}
}
\ No newline at end of file
diff --git a/AspectedRouting.Test/LuaPrinterTest.cs b/AspectedRouting.Test/LuaPrinterTest.cs
index 940b9f3..39b1774 100644
--- a/AspectedRouting.Test/LuaPrinterTest.cs
+++ b/AspectedRouting.Test/LuaPrinterTest.cs
@@ -1,5 +1,4 @@
using System.Collections.Generic;
-using AspectedRouting.IO.itinero1;
using AspectedRouting.IO.LuaSkeleton;
using AspectedRouting.Language;
using AspectedRouting.Language.Functions;
@@ -13,12 +12,11 @@ namespace AspectedRouting.Test
public void ToLua_SimpleMapping_Table()
{
var mapping = new Mapping(
- new[] {"a", "b", "c"},
- new[]
- {
+ new[] { "a", "b", "c" },
+ new[] {
new Constant(5),
new Constant(6),
- new Constant(7),
+ new Constant(7)
}
);
@@ -34,13 +32,11 @@ namespace AspectedRouting.Test
public void ToLua_NestedMapping_Table()
{
var mapping = new Mapping(
- new[] {"a"},
- new[]
- {
- new Mapping(new[] {"b"},
- new[]
- {
- new Constant(42),
+ new[] { "a" },
+ new[] {
+ new Mapping(new[] { "b" },
+ new[] {
+ new Constant(42)
}
)
}
@@ -54,10 +50,8 @@ namespace AspectedRouting.Test
public void Sanity_EveryBasicFunction_HasDescription()
{
var missing = new List();
- foreach (var (_, f) in Funcs.Builtins)
- {
- if (string.IsNullOrEmpty(f.Description))
- {
+ foreach (var (_, f) in Funcs.Builtins) {
+ if (string.IsNullOrEmpty(f.Description)) {
missing.Add(f.Name);
}
}
@@ -65,15 +59,13 @@ namespace AspectedRouting.Test
Assert.True(0 == missing.Count,
"These functions do not have a description: " + string.Join(", ", missing));
}
-
+
[Fact]
public void Sanity_EveryBasicFunction_HasArgNames()
{
var missing = new List();
- foreach (var (_, f) in Funcs.Builtins)
- {
- if (f.ArgNames == null)
- {
+ foreach (var (_, f) in Funcs.Builtins) {
+ if (f.ArgNames == null) {
missing.Add(f.Name);
}
}
diff --git a/AspectedRouting.Test/MappingTest.cs b/AspectedRouting.Test/MappingTest.cs
index df92b98..21a07c9 100644
--- a/AspectedRouting.Test/MappingTest.cs
+++ b/AspectedRouting.Test/MappingTest.cs
@@ -9,18 +9,18 @@ namespace AspectedRouting.Test
[Fact]
public static void SimpleMapping_SimpleHighway_GivesResult()
{
- var maxspeed = new Mapping(new[] {"residential", "living_street"},
+ var maxspeed = new Mapping(new[] { "residential", "living_street" },
new[] {
new Constant(30),
new Constant(20)
}
);
- var resMaxspeed= maxspeed.Evaluate(new Context(), new Constant("residential"));
- Assert.Equal(30, resMaxspeed);
- var livingStreetMaxspeed= maxspeed.Evaluate(new Context(), new Constant("living_street"));
- Assert.Equal(20, livingStreetMaxspeed);
- var undefinedSpeed = maxspeed.Evaluate(new Context(), new Constant("some_unknown_highway_type"));
- Assert.Null(undefinedSpeed);
+ var resMaxspeed = maxspeed.Evaluate(new Context(), new Constant("residential"));
+ Assert.Equal(30, resMaxspeed);
+ var livingStreetMaxspeed = maxspeed.Evaluate(new Context(), new Constant("living_street"));
+ Assert.Equal(20, livingStreetMaxspeed);
+ var undefinedSpeed = maxspeed.Evaluate(new Context(), new Constant("some_unknown_highway_type"));
+ Assert.Null(undefinedSpeed);
}
}
}
\ No newline at end of file
diff --git a/AspectedRouting.Test/MustMatchTest.cs b/AspectedRouting.Test/MustMatchTest.cs
index fce7ff4..81a0d89 100644
--- a/AspectedRouting.Test/MustMatchTest.cs
+++ b/AspectedRouting.Test/MustMatchTest.cs
@@ -10,37 +10,37 @@ namespace AspectedRouting.Test
[Fact]
public void MustMatch_SimpleInput()
{
- var mapValue = new Mapping(new[] {"residential", "living_street"},
+ var mapValue = new Mapping(new[] { "residential", "living_street" },
new[] {
new Constant("yes"),
new Constant("no")
});
- var mapTag = new Mapping(new[] {"highway"}, new[] {mapValue});
+ var mapTag = new Mapping(new[] { "highway" }, new[] { mapValue });
var mm = Funcs.MustMatch
.Apply(
- new Constant(new[] {new Constant("highway")}),
+ new Constant(new[] { new Constant("highway") }),
Funcs.StringStringToTags.Apply(mapTag)
)
;
var residential = mm.Apply(new Constant(new Dictionary {
- {"highway", "residential"}
+ { "highway", "residential" }
})).Evaluate(new Context());
Assert.Equal("yes", residential);
var living = mm.Apply(new Constant(new Dictionary {
- {"highway", "living_street"}
+ { "highway", "living_street" }
})).Evaluate(new Context());
Assert.Equal("no", living);
var unknown = mm.Apply(new Constant(new Dictionary {
- {"highway", "unknown_type"}
+ { "highway", "unknown_type" }
})).Evaluate(new Context());
Assert.Equal("yes", unknown);
var missing = mm.Apply(new Constant(new Dictionary {
- {"proposed:highway", "unknown_type"}
+ { "proposed:highway", "unknown_type" }
})).Evaluate(new Context());
Assert.Equal("no", missing);
}
diff --git a/AspectedRouting.Test/Snippets/SnippetTests.cs b/AspectedRouting.Test/Snippets/SnippetTests.cs
index f0c2a10..5cc36d2 100644
--- a/AspectedRouting.Test/Snippets/SnippetTests.cs
+++ b/AspectedRouting.Test/Snippets/SnippetTests.cs
@@ -43,7 +43,7 @@ namespace AspectedRouting.Test.Snippets
var func = new Apply(
Funcs.StringStringToTags,
new Mapping(
- new[] {"bicycle", "access"},
+ new[] { "bicycle", "access" },
new IExpression[] {
Funcs.Id,
Funcs.Id
@@ -51,7 +51,7 @@ namespace AspectedRouting.Test.Snippets
)
);
- var tags = new LuaLiteral(new[] {Typs.Tags}, "tags");
+ var tags = new LuaLiteral(new[] { Typs.Tags }, "tags");
var code = gen.Convert(lua, "result",
new List {
@@ -71,7 +71,7 @@ namespace AspectedRouting.Test.Snippets
public void SimpleMappingSnippet_SimpleMapping_GeneratesLua()
{
var mapping = new Mapping(
- new[] {"1", "-1"},
+ new[] { "1", "-1" },
new IExpression[] {
new Constant("with"),
new Constant("against")
@@ -86,6 +86,5 @@ namespace AspectedRouting.Test.Snippets
"local v\nv = tags.oneway\n\nif (v == \"1\") then\n result = \"with\"\nelseif (v == \"-1\") then\n result = \"against\"\nend";
Assert.Equal(expected, code);
}
-
}
}
\ No newline at end of file
diff --git a/AspectedRouting.Test/TestInterpreter.cs b/AspectedRouting.Test/TestInterpreter.cs
index 6ff1f60..d4cc4d0 100644
--- a/AspectedRouting.Test/TestInterpreter.cs
+++ b/AspectedRouting.Test/TestInterpreter.cs
@@ -18,11 +18,10 @@ namespace AspectedRouting.Test
"{\"name\": \"legal_maxspeed_be\",\"description\": \"Gives, for each type of highway, which the default legal maxspeed is in Belgium. This file is intended to be reused for in all vehicles, from pedestrian to car. In some cases, a legal maxspeed is not really defined (e.g. on footways). In that case, a socially acceptable speed should be taken (e.g.: a bicycle on a pedestrian path will go say around 12km/h)\",\"unit\": \"km/h\",\"$max\": {\"maxspeed\": \"$parse\",\"highway\": {\"residential\": 30},\"ferry\":5}}";
var aspect = JsonParser.AspectFromJson(null, json, null);
- var tags = new Dictionary
- {
- {"maxspeed", "42"},
- {"highway", "residential"},
- {"ferry", "yes"}
+ var tags = new Dictionary {
+ { "maxspeed", "42" },
+ { "highway", "residential" },
+ { "ferry", "yes" }
};
Assert.Equal("tags -> pdouble", string.Join(", ", aspect.Types));
@@ -40,11 +39,10 @@ namespace AspectedRouting.Test
var aspect = JsonParser.AspectFromJson(null, json, null);
Assert.Equal(
- new Dictionary>
- {
- {"maxspeed", new HashSet()},
- {"highway", new HashSet {"residential"}},
- {"ferry", new HashSet()}
+ new Dictionary> {
+ { "maxspeed", new HashSet() },
+ { "highway", new HashSet { "residential" } },
+ { "ferry", new HashSet() }
},
aspect.PossibleTags());
}
@@ -79,7 +77,7 @@ namespace AspectedRouting.Test
public void EitherFunc_SpecializeToString_Const()
{
var a = new Constant("a");
-
+
var mconst = new Apply(new Apply(Funcs.EitherFunc, Funcs.Id), Funcs.Const);
var specialized = new Apply(mconst, a).Specialize(Typs.String);
@@ -125,7 +123,7 @@ namespace AspectedRouting.Test
public void MaxTest()
{
var ls = new Constant(new ListType(Typs.Double),
- new[] {1.1, 2.0, 3.0}.Select(d => (object) d));
+ new[] { 1.1, 2.0, 3.0 }.Select(d => (object)d));
Assert.Equal("[1.1, 2, 3] : list (double)",
ls.Evaluate(null).Pretty() + " : " + string.Join(", ", ls.Types));
var mx = Funcs.Max.Apply(ls);
@@ -164,7 +162,7 @@ namespace AspectedRouting.Test
[Fact]
public void TestStringGeneration()
{
- var v = Var.Fresh(new HashSet {"$a", "$b"});
+ var v = Var.Fresh(new HashSet { "$a", "$b" });
Assert.Equal("$c", v.Name);
}
@@ -176,9 +174,9 @@ namespace AspectedRouting.Test
var app = new Apply(
new Apply(
new Apply(Funcs.Id, Funcs.Id), Funcs.Id), a);
- var (f, args ) = app.DeconstructApply().Value;
- Assert.Equal(Funcs.Id.Name, ((Function) f).Name);
- Assert.Equal(new List {Funcs.Id, Funcs.Id, a}.Select(e => e.ToString()),
+ var (f, args) = app.DeconstructApply().Value;
+ Assert.Equal(Funcs.Id.Name, ((Function)f).Name);
+ Assert.Equal(new List { Funcs.Id, Funcs.Id, a }.Select(e => e.ToString()),
args.Select(e => e.ToString()));
}
diff --git a/AspectedRouting.Test/TypingTests.cs b/AspectedRouting.Test/TypingTests.cs
index c1f6a3f..9878126 100644
--- a/AspectedRouting.Test/TypingTests.cs
+++ b/AspectedRouting.Test/TypingTests.cs
@@ -52,8 +52,8 @@ namespace AspectedRouting.Test
new Curry(Typs.Tags, Typs.Double), x
);
}
-
-
+
+
[Fact]
public void WidestCommonGround_StringAndString_String()
{
diff --git a/AspectedRouting.sln.DotSettings.user b/AspectedRouting.sln.DotSettings.user
index 3a4c3c8..0b2a2e5 100644
--- a/AspectedRouting.sln.DotSettings.user
+++ b/AspectedRouting.sln.DotSettings.user
@@ -1,4 +1,5 @@
+ ERROR<SessionState ContinuousTestingMode="0" Name="DefaultSnippet_SimpleDefault_GetsLua" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<TestAncestor>
<TestId>xUnit::A1309041-8AAE-42D7-A886-94C9FFC6A28C::.NETCoreApp,Version=v3.1::AspectedRouting.Test.Snippets.SnippetTests</TestId>
diff --git a/AspectedRouting/AspectedRouting.csproj b/AspectedRouting/AspectedRouting.csproj
index 4e00b5b..12d4492 100644
--- a/AspectedRouting/AspectedRouting.csproj
+++ b/AspectedRouting/AspectedRouting.csproj
@@ -13,7 +13,7 @@
PreserveNewest
- PreserveNewest
+ PreserveNewest
diff --git a/AspectedRouting/IO/LuaSkeleton/LuaLiteral.cs b/AspectedRouting/IO/LuaSkeleton/LuaLiteral.cs
index e36ccf0..8633e55 100644
--- a/AspectedRouting/IO/LuaSkeleton/LuaLiteral.cs
+++ b/AspectedRouting/IO/LuaSkeleton/LuaLiteral.cs
@@ -9,19 +9,17 @@ namespace AspectedRouting.IO.LuaSkeleton
public class LuaLiteral : IExpression
{
public readonly string Lua;
- public IEnumerable Types { get; }
- public LuaLiteral(Type type, string lua):this(new [] {type}, lua)
- {
-
- }
+ public LuaLiteral(Type type, string lua) : this(new[] { type }, lua) { }
public LuaLiteral(IEnumerable types, string lua)
{
Lua = lua;
Types = types;
}
-
+
+ public IEnumerable Types { get; }
+
public object Evaluate(Context c, params IExpression[] arguments)
{
throw new NotImplementedException();
@@ -32,11 +30,11 @@ namespace AspectedRouting.IO.LuaSkeleton
return this;
}
- public IExpression PruneTypes(Func allowedTypes)
+ public IExpression PruneTypes(System.Func allowedTypes)
{
- var passed = this.Types.Where(allowedTypes);
+ var passed = Types.Where(allowedTypes);
if (passed.Any()) {
- return new LuaLiteral(passed, this.Lua);
+ return new LuaLiteral(passed, Lua);
}
return null;
@@ -44,13 +42,12 @@ namespace AspectedRouting.IO.LuaSkeleton
public IExpression Optimize()
{
- return this;
+ return this;
}
public void Visit(Func f)
{
throw new NotImplementedException();
}
-
}
}
\ No newline at end of file
diff --git a/AspectedRouting/IO/LuaSkeleton/LuaParameterPrinter.Parameters.cs b/AspectedRouting/IO/LuaSkeleton/LuaParameterPrinter.Parameters.cs
index 7dfc538..37a294e 100644
--- a/AspectedRouting/IO/LuaSkeleton/LuaParameterPrinter.Parameters.cs
+++ b/AspectedRouting/IO/LuaSkeleton/LuaParameterPrinter.Parameters.cs
@@ -6,8 +6,8 @@ namespace AspectedRouting.IO.itinero1
{
public class LuaParameterPrinter
{
- private ProfileMetaData _profile;
- private LuaSkeleton.LuaSkeleton _skeleton;
+ private readonly ProfileMetaData _profile;
+ private readonly LuaSkeleton.LuaSkeleton _skeleton;
public LuaParameterPrinter(ProfileMetaData profile, LuaSkeleton.LuaSkeleton skeleton)
{
@@ -18,8 +18,7 @@ namespace AspectedRouting.IO.itinero1
public string GenerateDefaultParameters()
{
- var impl = new List()
- {
+ var impl = new List {
"function default_parameters()",
" local parameters = {}",
DeclareParametersFor(_profile.DefaultParameters),
@@ -31,34 +30,26 @@ namespace AspectedRouting.IO.itinero1
}
///
- /// Generates a piece of code of the following format:
- ///
- /// parameters["x"] = a;
- /// parameters["y"] = b:
- /// ...
- ///
- /// Where x=a and y=b are defined in the profile
- ///
- /// Dependencies are added.
- ///
- /// Note that the caller should still add `local paramaters = default_parameters()`
- ///
+ /// Generates a piece of code of the following format:
+ /// parameters["x"] = a;
+ /// parameters["y"] = b:
+ /// ...
+ /// Where x=a and y=b are defined in the profile
+ /// Dependencies are added.
+ /// Note that the caller should still add `local paramaters = default_parameters()`
///
///
///
public string DeclareParametersFor(Dictionary subParams)
{
var impl = "";
- foreach (var (paramName, value) in subParams)
- {
- if (paramName.Equals("description"))
- {
+ foreach (var (paramName, value) in subParams) {
+ if (paramName.Equals("description")) {
continue;
}
var paramNameTrimmed = paramName.TrimStart('#').AsLuaIdentifier();
- if (!string.IsNullOrEmpty(paramNameTrimmed))
- {
+ if (!string.IsNullOrEmpty(paramNameTrimmed)) {
impl += $" parameters.{paramNameTrimmed} = {_skeleton.ToLua(value)}\n";
}
}
diff --git a/AspectedRouting/IO/md/ProfileToMD.cs b/AspectedRouting/IO/md/ProfileToMD.cs
new file mode 100644
index 0000000..82cdf47
--- /dev/null
+++ b/AspectedRouting/IO/md/ProfileToMD.cs
@@ -0,0 +1,225 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using AspectedRouting.Language;
+using AspectedRouting.Language.Expression;
+using AspectedRouting.Tests;
+
+namespace AspectedRouting.IO.md
+{
+ internal class MarkDownSection
+ {
+ private readonly List parts = new List();
+
+ public string ToString()
+ {
+ return string.Join("\n\n", parts);
+ }
+
+ public void AddTitle(string title, int level)
+ {
+ var str = "";
+ for (var i = 0; i < level; i++) {
+ str += "#";
+ }
+
+ str += " " + title;
+ parts.Add(str);
+ }
+
+ public void Add(params string[] paragraph)
+ {
+ parts.Add(string.Join("\n", paragraph));
+ }
+
+ public void AddList(List items)
+ {
+ parts.Add(string.Join("\n", items.Select(i => " - " + i)));
+ }
+ }
+
+
+ public class ProfileToMD
+ {
+ private readonly string _behaviour;
+ private readonly Context _c;
+ private readonly ProfileMetaData _profile;
+ private readonly MarkDownSection md = new MarkDownSection();
+
+ public ProfileToMD(ProfileMetaData profile, string behaviour, Context c)
+ {
+ _profile = profile;
+ _behaviour = behaviour;
+ _c = c.WithAspectName(behaviour);
+ _c.DefinedFunctions["speed"] = new AspectMetadata(profile.Speed, "speed", "The speed this vehicle is going",
+ "", "km/h", "", true);
+ if (!profile.Behaviours.ContainsKey(behaviour)) {
+ throw new ArgumentException("Profile does not contain behaviour " + behaviour);
+ }
+ }
+
+ private decimal R(double d)
+ {
+ return Math.Round((decimal)d, 2);
+ }
+
+ /**
+ * Calculates an entry with `speed`, `priority` for the profile
+ */
+ public string TableEntry(string msg, Dictionary tags, ProfileResult? reference,
+ bool nullOnSame = false)
+ {
+ var profile = _profile.Run(_c, _behaviour, tags);
+ if (!reference.HasValue) {
+ return "| " + msg + " | " + profile.Speed + " | " + profile.Priority + " | ";
+ }
+
+ if (reference.Equals(profile) && nullOnSame) {
+ return null;
+ }
+
+ return "| " + msg + " | " + R(profile.Speed) + " | " +
+ R(profile.Speed / reference.Value.Speed) + " | " +
+ R(profile.Priority) + " | " + R(profile.Priority / reference.Value.Priority) + " | " +
+ profile.Access + " | " + profile.Oneway;
+ }
+
+ public void addTagsTable(ProfileResult reference, Dictionary> usedTags)
+ {
+ var p = _profile;
+ var b = _profile.Behaviours[_behaviour];
+
+ var tableEntries = new List();
+ foreach (var (key, vals) in usedTags) {
+ var values = vals;
+ if (values.Count == 0 && key == "maxspeed") {
+ tableEntries.Add($" | {key}=* (example values below)");
+ values = new HashSet {
+ "20", "30", "50", "70", "90", "120", "150"
+ };
+ }
+
+ if (values.Count == 0) {
+ tableEntries.Add($" | {key}=*");
+ }
+
+ if (values.Count > 0) {
+ foreach (var value in values) {
+ var tags = new Dictionary {
+ [key] = value
+ };
+ var entry = TableEntry($"{key}={value} ", tags, reference);
+ if (entry == null) {
+ continue;
+ }
+
+ tableEntries.Add(entry);
+ }
+ }
+ }
+
+ md.Add("| Tags | Speed (km/h) | speedfactor | Priority | priorityfactor | access | oneway | ",
+ "| ---- | ------------ | ----------- | -------- | --------------- | ----- | ------ |",
+ string.Join("\n", tableEntries));
+ }
+
+ public Dictionary TagsWithPriorityInfluence()
+ {
+
+ var p = _profile;
+ var parameters = _profile.ParametersFor(_behaviour);
+ var withInfluence = new Dictionary();
+
+ foreach (var kv in p.Priority) {
+ if (parameters[kv.Key].Equals(0.0) || parameters[kv.Key].Equals(0)) {
+ continue;
+ }
+
+ withInfluence[kv.Key] = kv.Value;
+ }
+
+ return withInfluence;
+ }
+
+
+ public string MainFormula()
+ {
+ var p = _profile;
+ var b = _profile.Behaviours[_behaviour];
+
+ var overridenParams = new HashSet();
+ var paramValues = new Dictionary();
+ foreach (var kv in p.DefaultParameters) {
+ paramValues[kv.Key] = kv.Value.Evaluate(_c);
+ }
+
+ foreach (var kv in b) {
+ paramValues[kv.Key] = kv.Value.Evaluate(_c);
+ overridenParams.Add(kv.Key);
+ }
+
+ var mainFormulaParts = p.Priority.Select(delegate(KeyValuePair kv) {
+ var key = kv.Key;
+ var param = paramValues[key];
+ if (param.Equals(0) || param.Equals(0.0)) {
+ return "";
+ }
+
+ if (overridenParams.Contains(key)) {
+ param = "**" + param + "**";
+ }
+
+
+ var called = kv.Value.DirectlyCalled();
+ return param + " * `" + string.Join("", called.calledFunctionNames) + "`";
+ });
+
+ var mainFormula = string.Join(" + ", mainFormulaParts.Where(p => p != ""));
+ return mainFormula;
+ }
+
+ public override string ToString()
+ {
+ var p = _profile;
+ var b = _profile.Behaviours[_behaviour];
+ md.AddTitle(_profile.Name + "." + _behaviour, 1);
+
+ md.Add(p.Description);
+
+ if (b.ContainsKey("description")) {
+ md.Add(b["description"].Evaluate(_c).ToString());
+ }
+
+
+ md.Add("This profile is calculated as following (non-default keys are bold):", MainFormula());
+
+ var residentialTags = new Dictionary {
+ ["highway"] = "residential"
+ };
+
+ md.Add("| Tags | Speed (km/h) | Priority",
+ "| ---- | ----- | ---------- | ",
+ TableEntry("Residential highway (reference)", residentialTags, null));
+ var reference = _profile.Run(_c, _behaviour, residentialTags);
+ md.AddTitle("Tags influencing priority", 2);
+ md.Add(
+ "Priority is what influences which road to take. The routeplanner will search a way where `1/priority` is minimal.");
+ addTagsTable(reference, TagsWithPriorityInfluence().Values.PossibleTagsRecursive(_c));
+
+ md.AddTitle("Tags influencing speed", 2);
+ md.Add(
+ "Speed is used to calculate how long the trip will take, but does _not_ influence which route is taken. Some profiles do use speed as a factor in priority too - in this case, these tags will be mentioned above too.");
+ addTagsTable(reference, _profile.Speed.PossibleTagsRecursive(_c));
+
+ md.AddTitle("Tags influencing access", 2);
+ md.Add("These tags influence whether or not this road can be taken with this vehicle or behaviour");
+ addTagsTable(reference, _profile.Access.PossibleTagsRecursive(_c));
+ md.AddTitle("Tags influencing oneway", 2);
+ md.Add("These tags influence whether or not this road can be taken in all directions or not");
+ addTagsTable(reference, _profile.Oneway.PossibleTagsRecursive(_c));
+
+
+ return md.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/AspectedRouting/IO/md/Readme.part0.md b/AspectedRouting/IO/md/Readme.part0.md
index 01ef155..5305a65 100644
--- a/AspectedRouting/IO/md/Readme.part0.md
+++ b/AspectedRouting/IO/md/Readme.part0.md
@@ -2,7 +2,8 @@
## Introduction
-Generating a good route for travellers is hard; especially for cyclists. They can be very picky and the driving style and purposes are diverse. Think about:
+Generating a good route for travellers is hard; especially for cyclists. They can be very picky and the driving style
+and purposes are diverse. Think about:
- A lightweight food delivery driver, who wants to be at their destination as soon as possible
- A cargo bike, possibly with a cart or electrically supported, doing heavy delivery
@@ -10,13 +11,18 @@ Generating a good route for travellers is hard; especially for cyclists. They ca
- Grandma cycling along a canal on sunday afternoon
- Someone bringing their kids to school
-It is clear that these persona's on top have very different wishes for their route. A road with a high car pressure won't pose a problem for the food delivery, whereas grandma wouldn't even think about going there. And this is without mentioning the speed these cyclists drive, where they are allowed to drive, ...
+It is clear that these persona's on top have very different wishes for their route. A road with a high car pressure
+won't pose a problem for the food delivery, whereas grandma wouldn't even think about going there. And this is without
+mentioning the speed these cyclists drive, where they are allowed to drive, ...
-Generating a cycle route for these persons is thus clearly far from simply picking the shortest possible path. On top of that, a consumer expects the route calculations to be both customizable and to be blazingly fast.
+Generating a cycle route for these persons is thus clearly far from simply picking the shortest possible path. On top of
+that, a consumer expects the route calculations to be both customizable and to be blazingly fast.
In order to simplify the generation of these routing profiles, this repository introduces _aspected routing_.
-In _aspected routing_, one does not try to tackle the routing problem all at once, but one tries to dissassemble the preferences of the travellers into multiple, orthogonal aspects. These aspects can then be combined in a linear way, giving a fast and flexible system.
+In _aspected routing_, one does not try to tackle the routing problem all at once, but one tries to dissassemble the
+preferences of the travellers into multiple, orthogonal aspects. These aspects can then be combined in a linear way,
+giving a fast and flexible system.
Some aspects can be:
@@ -38,9 +44,12 @@ Even though this repository is heavily inspired on OpenStreetMap, it can be gene
## Road network assumptions
-The only assumptions made are that roads have a **length** and a collection of **tags**, this is a dictionary mapping strings onto strings. These tags encode the properties of the road (e.g. road classification, name, surface, ...)
+The only assumptions made are that roads have a **length** and a collection of **tags**, this is a dictionary mapping
+strings onto strings. These tags encode the properties of the road (e.g. road classification, name, surface, ...)
-OpenStreetMap also has a concept of **relations**. A special function is available for that. However, in a preprocessing step, the relations that a road is a member of, are converted into tags on every way with a `_network:i:key=value` format, where `i` is the number of the relation, and `key`=`value` is a tag present on the relation.
+OpenStreetMap also has a concept of **relations**. A special function is available for that. However, in a preprocessing
+step, the relations that a road is a member of, are converted into tags on every way with a `_network:i:key=value`
+format, where `i` is the number of the relation, and `key`=`value` is a tag present on the relation.
## Describing an aspect
diff --git a/AspectedRouting/IO/md/helpText.md b/AspectedRouting/IO/md/helpText.md
index 9aa801e..cf334c3 100644
--- a/AspectedRouting/IO/md/helpText.md
+++ b/AspectedRouting/IO/md/helpText.md
@@ -7,6 +7,7 @@
- string
- tags
- bool
+
## Builtin functions
- eq
@@ -37,7 +38,6 @@
- eitherFunc
- stringToTags
-
### Function overview
#### eq
@@ -49,8 +49,6 @@ $a | $a | string |
Returns 'yes' if both values _are_ the same
-
-
Lua implementation:
````lua
@@ -64,7 +62,6 @@ end
````
-
#### notEq
a | b | returns |
@@ -75,8 +72,6 @@ bool | bool |
OVerloaded function, either boolean not or returns 'yes' if the two passed in values are _not_ the same;
-
-
Lua implementation:
````lua
@@ -93,7 +88,6 @@ function notEq(a, b)
end
````
-
#### not
a | b | returns |
@@ -104,8 +98,6 @@ bool | bool |
OVerloaded function, either boolean not or returns 'yes' if the two passed in values are _not_ the same;
-
-
Lua implementation:
````lua
@@ -122,7 +114,6 @@ function notEq(a, b)
end
````
-
#### inv
d | returns |
@@ -132,8 +123,6 @@ double | double |
Calculates `1/d`
-
-
Lua implementation:
````lua
@@ -142,7 +131,6 @@ function inv(n)
end
````
-
#### default
defaultValue | f | returns |
@@ -151,8 +139,6 @@ $a | $b -> $a | $b | $a |
Calculates function `f` for the given argument. If the result is `null`, the default value is returned instead
-
-
Lua implementation:
````lua
@@ -164,7 +150,6 @@ function default(defaultValue, realValue)
end
````
-
#### parse
s | returns |
@@ -174,8 +159,6 @@ string | pdouble |
Parses a string into a numerical value
-
-
Lua implementation:
````lua
@@ -208,7 +191,6 @@ function parse(string)
end
````
-
#### to_string
obj | returns |
@@ -217,8 +199,6 @@ $a | string |
Converts a value into a human readable string
-
-
Lua implementation:
````lua
@@ -227,7 +207,6 @@ function to_string(o)
end
````
-
#### concat
a | b | returns |
@@ -236,8 +215,6 @@ string | string | string |
Concatenates two strings
-
-
Lua implementation:
````lua
@@ -246,7 +223,6 @@ function concat(a, b)
end
````
-
#### containedIn
list | a | returns |
@@ -255,8 +231,6 @@ list ($a) | $a | bool |
Given a list of values, checks if the argument is contained in the list.
-
-
Lua implementation:
````lua
@@ -271,7 +245,6 @@ function containedIn(list, a)
end
````
-
#### min
list | returns |
@@ -284,8 +257,6 @@ list (bool) | bool |
Out of a list of values, gets the smallest value. IN case of a list of bools, this acts as `and`
-
-
Lua implementation:
````lua
@@ -303,7 +274,6 @@ function min(list)
end
````
-
#### and
list | returns |
@@ -316,8 +286,6 @@ list (bool) | bool |
Out of a list of values, gets the smallest value. IN case of a list of bools, this acts as `and`
-
-
Lua implementation:
````lua
@@ -335,7 +303,6 @@ function min(list)
end
````
-
#### max
list | returns |
@@ -348,8 +315,6 @@ list (bool) | bool |
Returns the biggest value in the list. For a list of booleans, this acts as 'or'
-
-
Lua implementation:
````lua
@@ -367,7 +332,6 @@ function max(list)
end
````
-
#### or
list | returns |
@@ -380,8 +344,6 @@ list (bool) | bool |
Returns the biggest value in the list. For a list of booleans, this acts as 'or'
-
-
Lua implementation:
````lua
@@ -399,7 +361,6 @@ function max(list)
end
````
-
#### sum
list | returns |
@@ -412,8 +373,6 @@ list (bool) | int |
Sums all the numbers in the given list. If the list contains bool, `yes` or `true` will be considered to equal `1`
-
-
Lua implementation:
````lua
@@ -429,7 +388,6 @@ function sum(list)
end
````
-
#### multiply
list | returns |
@@ -442,8 +400,6 @@ list (bool) | bool |
Multiplies all the values in a given list. On a list of booleans, this acts as 'and' or 'all'
-
-
Lua implementation:
````lua
@@ -456,7 +412,6 @@ function multiply(list)
end
````
-
#### firstMatchOf
s | returns |
@@ -465,8 +420,6 @@ list (string) | tags -> list ($a) | tags | $a |
Parses a string into a numerical value
-
-
Lua implementation:
````lua
@@ -492,18 +445,15 @@ function first_match_of(tags, result, order_of_keys, table)
end
````
-
#### mustMatch
neededKeys (filled in by parser) | f | returns |
--- | --- | --- |
list (string) | tags -> list (bool) | tags | bool |
-Every key that is used in the subfunction must be present.
-If, on top, a value is present with a mapping, every key/value will be executed and must return a value that is not 'no' or 'false'
-Note that this is a privileged builtin function, as the parser will automatically inject the keys used in the called function.
-
-
+Every key that is used in the subfunction must be present. If, on top, a value is present with a mapping, every
+key/value will be executed and must return a value that is not 'no' or 'false' Note that this is a privileged builtin
+function, as the parser will automatically inject the keys used in the called function.
Lua implementation:
@@ -572,7 +522,6 @@ function must_match(tags, result, needed_keys, table)
end
````
-
#### memberOf
f | tags | returns |
@@ -586,15 +535,18 @@ In order to use this for itinero 1.0, the membership _must_ be the top level exp
Conceptually, when the aspect is executed for a way, every relation will be used as argument in the subfunction `f`
If this subfunction returns 'true', the entire aspect will return true.
-In the lua implementation for itinero 1.0, this is implemented slightly different: a flag `_relation:="yes"` will be set if the aspect matches on every way for where this aspect matches.
-However, this plays poorly with parameters (e.g.: what if we want to cycle over a highway which is part of a certain cycling network with a certain `#network_name`?) Luckily, parameters can only be simple values. To work around this problem, an extra tag is introduced for _every single profile_:`_relation::=yes'. The subfunction is thus executed `countOr(relations) * countOf(profiles)` time, yielding `countOf(profiles)` tags. The profile function then picks the tags for himself and strips the `:` away from the key.
-
-
+In the lua implementation for itinero 1.0, this is implemented slightly different: a
+flag `_relation:="yes"` will be set if the aspect matches on every way for where this aspect matches.
+However, this plays poorly with parameters (e.g.: what if we want to cycle over a highway which is part of a certain
+cycling network with a certain `#network_name`?) Luckily, parameters can only be simple values. To work around this
+problem, an extra tag is introduced for _every single
+profile_:`_relation::=yes'. The subfunction is thus executed `countOr(relations) * countOf(
+profiles)` time, yielding `countOf(
+profiles)` tags. The profile function then picks the tags for himself and strips the `:` away from the
+key.
In the test.csv, one can simply use `_relation:=yes` to mimic relations in your tests
-
-
Lua implementation:
````lua
@@ -610,7 +562,6 @@ function member_of(calledIn, parameters, tags, result)
end
````
-
#### if_then_else
condition | then | else | returns |
@@ -618,9 +569,8 @@ condition | then | else | returns |
bool | $a | $a | $a |
bool | $a | $a |
-Selects either one of the branches, depending on the condition.If the `else` branch is not set, `null` is returned in the condition is false.
-
-
+Selects either one of the branches, depending on the condition.If the `else` branch is not set, `null` is returned in
+the condition is false.
Lua implementation:
@@ -634,7 +584,6 @@ function if_then_else(condition, thn, els)
end
````
-
#### if
condition | then | else | returns |
@@ -642,9 +591,8 @@ condition | then | else | returns |
bool | $a | $a | $a |
bool | $a | $a |
-Selects either one of the branches, depending on the condition.If the `else` branch is not set, `null` is returned in the condition is false.
-
-
+Selects either one of the branches, depending on the condition.If the `else` branch is not set, `null` is returned in
+the condition is false.
Lua implementation:
@@ -658,7 +606,6 @@ function if_then_else(condition, thn, els)
end
````
-
#### id
a | returns |
@@ -667,8 +614,6 @@ $a | $a |
Returns the argument unchanged - the identity function. Seems useless at first sight, but useful in parsing
-
-
Lua implementation:
````lua
@@ -677,7 +622,6 @@ function id(v)
end
````
-
#### const
a | b | returns |
@@ -686,8 +630,6 @@ $a | $b | $a |
Small utility function, which takes two arguments `a` and `b` and returns `a`. Used extensively to insert freedom
-
-
Lua implementation:
````lua
@@ -696,7 +638,6 @@ function const(a, b)
end
````
-
#### constRight
a | b | returns |
@@ -705,24 +646,20 @@ $a | $b | $b |
Small utility function, which takes two arguments `a` and `b` and returns `b`. Used extensively to insert freedom
-
-
Lua implementation:
````lua
````
-
#### dot
f | g | a | returns |
--- | --- | --- | --- |
$b -> $c | $a -> $b | $a | $c |
-Higher order function: converts `f (g a)` into `(dot f g) a`. In other words, this fuses `f` and `g` in a new function, which allows the argument to be lifted out of the expression
-
-
+Higher order function: converts `f (g a)` into `(dot f g) a`. In other words, this fuses `f` and `g` in a new function,
+which allows the argument to be lifted out of the expression
Lua implementation:
@@ -730,16 +667,14 @@ Lua implementation:
````
-
#### listDot
list | a | returns |
--- | --- | --- |
list ($a -> $b) | $a | list ($b) |
-Listdot takes a list of functions `[f, g, h]` and and an argument `a`. It applies the argument on every single function.It conveniently lifts the argument out of the list.
-
-
+Listdot takes a list of functions `[f, g, h]` and and an argument `a`. It applies the argument on every single
+function.It conveniently lifts the argument out of the list.
Lua implementation:
@@ -748,7 +683,6 @@ Lua implementation:
-- listDot
````
-
#### eitherFunc
f | g | a | returns |
@@ -756,21 +690,24 @@ f | g | a | returns |
$a -> $b | $c -> $d | $a | $b |
$a -> $b | $c -> $d | $c | $d |
-EitherFunc is a small utility function, mostly used in the parser. It allows the compiler to choose a function, based on the types.
+EitherFunc is a small utility function, mostly used in the parser. It allows the compiler to choose a function, based on
+the types.
-Consider the mapping `{'someKey':'someValue'}`. Under normal circumstances, this acts as a pointwise-function, converting the string `someKey` into `someValue`, just like an ordinary dictionary would do. However, in the context of `mustMatch`, we would prefer this to act as a _check_, that the highway _has_ a key `someKey` which is `someValue`, thus acting as `{'someKey': {'$eq':'someValue'}}. Both behaviours are automatically supported in parsing, by parsing the string as `(eitherFunc id eq) 'someValue'`. The type system is then able to figure out which implementation is needed.
+Consider the mapping `{'someKey':'someValue'}`. Under normal circumstances, this acts as a pointwise-function,
+converting the string `someKey` into `someValue`, just like an ordinary dictionary would do. However, in the context
+of `mustMatch`, we would prefer this to act as a _check_, that the highway _has_ a key `someKey` which is `someValue`,
+thus acting
+as `{'someKey': {'$eq':'someValue'}}. Both behaviours are automatically supported in parsing, by parsing the string as `(
+eitherFunc id eq) 'someValue'`. The type system is then able to figure out which implementation is needed.
Disclaimer: _you should never ever need this in your profiles_
-
-
Lua implementation:
````lua
````
-
#### stringToTags
f | tags | returns |
@@ -779,8 +716,6 @@ string -> string -> $a | tags | list ($a) |
stringToTags converts a function `string -> string -> a` into a function `tags -> [a]`
-
-
Lua implementation:
````lua
diff --git a/AspectedRouting/Language/Analysis.cs b/AspectedRouting/Language/Analysis.cs
index 4b07bcc..7cf247f 100644
--- a/AspectedRouting/Language/Analysis.cs
+++ b/AspectedRouting/Language/Analysis.cs
@@ -10,7 +10,6 @@ namespace AspectedRouting.Language
{
public static class Analysis
{
-
public static Dictionary Types, string inFunction)> UsedParameters(
this ProfileMetaData profile, Context context)
{
@@ -20,23 +19,19 @@ namespace AspectedRouting.Language
void AddParams(IExpression e, string inFunction)
{
var parms = e.UsedParameters();
- foreach (var param in parms)
- {
- if (parameters.TryGetValue(param.ParamName, out var typesOldUsage))
- {
+ 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)
- {
+ 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");
+ "which can not be unified");
}
}
- else
- {
+ else {
parameters[param.ParamName] = (param.Types.ToList(), inFunction);
}
}
@@ -47,19 +42,16 @@ namespace AspectedRouting.Language
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)
- {
+ 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)
- {
+ foreach (var calledFunction in calledFunctions) {
var func = context.GetFunction(calledFunction);
- if (func is AspectMetadata meta && meta.ProfileInternal)
- {
+ if (func is AspectMetadata meta && meta.ProfileInternal) {
continue;
}
@@ -74,10 +66,8 @@ namespace AspectedRouting.Language
public static HashSet UsedParameters(this IExpression e)
{
var result = new HashSet();
- e.Visit(expr =>
- {
- if (expr is Parameter p)
- {
+ e.Visit(expr => {
+ if (expr is Parameter p) {
result.Add(p);
}
@@ -98,18 +88,14 @@ namespace AspectedRouting.Language
void ScanExpression(IExpression e, string inFunction)
{
- if (!result.ContainsKey(inFunction))
- {
+ if (!result.ContainsKey(inFunction)) {
result.Add(inFunction, new List());
}
- e.Visit(x =>
- {
- if (x is FunctionCall fc)
- {
+ e.Visit(x => {
+ if (x is FunctionCall fc) {
result[inFunction].Add(fc.CalledFunctionName);
- if (!result.ContainsKey(fc.CalledFunctionName))
- {
+ if (!result.ContainsKey(fc.CalledFunctionName)) {
calledFunctions.Enqueue(fc.CalledFunctionName);
}
}
@@ -123,14 +109,12 @@ namespace AspectedRouting.Language
ScanExpression(profile.Oneway, profile.Name + ".oneway");
ScanExpression(profile.Speed, profile.Name + ".speed");
- foreach (var (key, expr) in profile.Priority)
- {
+ 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))
- {
+ while (calledFunctions.TryDequeue(out var calledFunction)) {
var func = c.GetFunction(calledFunction);
ScanExpression(func, calledFunction);
}
@@ -148,16 +132,14 @@ namespace AspectedRouting.Language
var queue = new Queue();
exprs.ForEach(queue.Enqueue);
- while (queue.TryDequeue(out var next))
- {
+ while (queue.TryDequeue(out var next)) {
var (p, deps) = next.DirectlyCalled();
parameters.UnionWith(p);
var toCheck = deps.Except(dependencies);
dependencies.UnionWith(deps);
- foreach (var fName in toCheck)
- {
- queue.Enqueue(ctx.GetFunction(fName));
+ foreach (var fName in toCheck) {
+ queue.Enqueue(ctx.GetFunction(fName));
}
}
@@ -166,7 +148,8 @@ namespace AspectedRouting.Language
///
- /// Generates an overview of the dependencies of the expression, both which parameters it needs and what other functions (builtin or defined) it needs.
+ /// Generates an overview of the dependencies of the expression, both which parameters it needs and what other
+ /// functions (builtin or defined) it needs.
///
///
///
@@ -176,15 +159,12 @@ namespace AspectedRouting.Language
var parameters = new HashSet();
var dependencies = new HashSet();
- expr.Visit(e =>
- {
- if (e is FunctionCall fc)
- {
+ expr.Visit(e => {
+ if (e is FunctionCall fc) {
dependencies.Add(fc.CalledFunctionName);
}
- if (e is Parameter p)
- {
+ if (e is Parameter p) {
parameters.Add(p.ParamName);
}
@@ -197,8 +177,7 @@ namespace AspectedRouting.Language
public static string TypeBreakdown(this IExpression e)
{
-
- return e.ToString() + " : "+string.Join(" ; ", e.Types);
+ return e + " : " + string.Join(" ; ", e.Types);
}
public static void SanityCheckProfile(this ProfileMetaData pmd, Context context)
@@ -212,8 +191,7 @@ namespace AspectedRouting.Language
string MetaList(IEnumerable paramNames)
{
var metaInfo = "";
- foreach (var paramName in paramNames)
- {
+ foreach (var paramName in paramNames) {
var _ = usedMetadata.TryGetValue(paramName, out var inFunction) ||
usedMetadata.TryGetValue('#' + paramName, out inFunction);
metaInfo += $"\n - {paramName} (used in {inFunction.inFunction})";
@@ -225,43 +203,36 @@ namespace AspectedRouting.Language
var usedParameters = usedMetadata.Keys.Select(key => key.TrimStart('#')).ToList();
var diff = usedParameters.ToHashSet().Except(defaultParameters).ToList();
- if (diff.Any())
- {
+ if (diff.Any()) {
throw new ArgumentException("No default value set for parameter: " + MetaList(diff));
}
var unused = defaultParameters.Except(usedParameters);
- if (unused.Any())
- {
+ if (unused.Any()) {
Console.WriteLine("[WARNING] A default value is set for parameter, but it is unused: " +
- string.Join(", ", unused));
+ string.Join(", ", unused));
}
var paramsUsedInBehaviour = new HashSet();
- foreach (var (behaviourName, behaviourParams) in pmd.Behaviours)
- {
+ 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))
- {
+ 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))
- {
+ if (!behaviourParams.TryGetValue(paramName, out var weight)) {
explanation += $"\n - {paramName} = default (not set)";
continue;
}
var weightObj = weight.Evaluate(context);
- if (!(weightObj is double d))
- {
+ if (!(weightObj is double d)) {
throw new ArgumentException(
$"The parameter {paramName} is not a numeric value in profile {behaviourName}");
}
@@ -270,8 +241,7 @@ namespace AspectedRouting.Language
explanation += $"\n - {paramName} = {d}";
}
- if (Math.Abs(sum) < 0.0001)
- {
+ if (Math.Abs(sum) < 0.0001) {
throw new ArgumentException("Profile " + behaviourName +
": the summed parameters to calculate the weight are zero or very low:" +
explanation);
@@ -280,8 +250,7 @@ namespace AspectedRouting.Language
var defaultOnly = defaultParameters.Except(paramsUsedInBehaviour).ToList();
- if (defaultOnly.Any())
- {
+ if (defaultOnly.Any()) {
Console.WriteLine(
$"[{pmd.Name}] WARNING: Some parameters only have a default value: {string.Join(", ", defaultOnly)}");
}
@@ -289,39 +258,32 @@ namespace AspectedRouting.Language
public static void SanityCheck(this IExpression e)
{
- e.Visit(expr =>
- {
+ e.Visit(expr => {
var order = new List();
var mapping = new List();
if (Deconstruct.UnApply(
- Deconstruct.UnApply(Deconstruct.IsFunc(Funcs.FirstOf), Deconstruct.Assign(order)),
- Deconstruct.Assign(mapping)
- ).Invoke(expr))
- {
- var expectedKeys = ((IEnumerable