From ff98d2fcf30ba5516066092e1d92040d9a71a27d Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Tue, 5 Jul 2022 11:23:48 +0200 Subject: [PATCH] Improve documentation and formatting --- AspectedRouting/IO/itinero2/Relations.md | 3 ++ .../JsonParser.ParseAspectProfile.cs | 8 ++--- AspectedRouting/IO/md/helpText.md | 2 +- .../Language/Functions/Constant.cs | 3 +- .../Language/Functions/EitherFunc.cs | 6 ++-- .../Language/Functions/FirstMatchOf.cs | 9 ++++-- AspectedRouting/Language/Functions/If.cs | 5 ++-- .../Language/Functions/MemberOf.cs | 30 +++++++++++-------- 8 files changed, 38 insertions(+), 28 deletions(-) create mode 100644 AspectedRouting/IO/itinero2/Relations.md diff --git a/AspectedRouting/IO/itinero2/Relations.md b/AspectedRouting/IO/itinero2/Relations.md new file mode 100644 index 0000000..2f0f8f2 --- /dev/null +++ b/AspectedRouting/IO/itinero2/Relations.md @@ -0,0 +1,3 @@ +# What about relations in Itinero 2.0? + +Relations have moved to the preprocessor, where they do put a tag on the members of the relation. This is done with a TagsFilter \ No newline at end of file diff --git a/AspectedRouting/IO/jsonParser/JsonParser.ParseAspectProfile.cs b/AspectedRouting/IO/jsonParser/JsonParser.ParseAspectProfile.cs index f681bdc..2d571ed 100644 --- a/AspectedRouting/IO/jsonParser/JsonParser.ParseAspectProfile.cs +++ b/AspectedRouting/IO/jsonParser/JsonParser.ParseAspectProfile.cs @@ -163,11 +163,9 @@ namespace AspectedRouting.IO.jsonParser ); } - private static readonly IExpression _mconst = - new Apply(new Apply(Funcs.EitherFunc, Funcs.Id), Funcs.Const); + private static readonly IExpression _mconst = Funcs.EitherFunc.Apply( Funcs.Id, Funcs.Const); - private static readonly IExpression _mappingWrapper = - new Apply(new Apply(Funcs.EitherFunc, Funcs.Id), Funcs.StringStringToTags); + private static readonly IExpression _mappingWrapper = Funcs.EitherFunc.Apply( Funcs.Id, Funcs.StringStringToTags); private static IExpression ParseMapping(IEnumerable allArgs, Context context) { @@ -201,7 +199,7 @@ namespace AspectedRouting.IO.jsonParser { var simpleMapping = new Mapping(keys, exprs); - var wrapped = (IExpression) new Apply(_mappingWrapper, simpleMapping); + var wrapped = _mappingWrapper.Apply(simpleMapping); if (keys.Count == 1) { // We can interpret this directly without going through a list diff --git a/AspectedRouting/IO/md/helpText.md b/AspectedRouting/IO/md/helpText.md index cf334c3..0360cb2 100644 --- a/AspectedRouting/IO/md/helpText.md +++ b/AspectedRouting/IO/md/helpText.md @@ -697,7 +697,7 @@ Consider the mapping `{'someKey':'someValue'}`. Under normal circumstances, this 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 `( +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_ diff --git a/AspectedRouting/Language/Functions/Constant.cs b/AspectedRouting/Language/Functions/Constant.cs index e7de7d4..be699cc 100644 --- a/AspectedRouting/Language/Functions/Constant.cs +++ b/AspectedRouting/Language/Functions/Constant.cs @@ -245,7 +245,7 @@ namespace AspectedRouting.Language.Functions public override string ToString() { - return _o.Pretty(); + return ObjectExtensions.Pretty(_o); } } @@ -254,6 +254,7 @@ namespace AspectedRouting.Language.Functions public static string Pretty(this object o, Context context = null) { switch (o) { + case null: return "null"; case Dictionary d: var txt = ""; foreach (var (k, v) in d) { diff --git a/AspectedRouting/Language/Functions/EitherFunc.cs b/AspectedRouting/Language/Functions/EitherFunc.cs index 27d6b97..5df91c5 100644 --- a/AspectedRouting/Language/Functions/EitherFunc.cs +++ b/AspectedRouting/Language/Functions/EitherFunc.cs @@ -13,9 +13,9 @@ namespace AspectedRouting.Language.Functions "" + "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.\n\n" + + "`{'someKey': {'$eq':'someValue'}}`. " + + "Both behaviours are automatically supported in parsing, by parsing all string as `(eitherFunc id eq) 'someValue'`. " + + "The type system is then able to figure out which implementation is needed an discards the unneeded implementations.\n\n" + "Disclaimer: _you should never ever need this in your profiles_"; public override List ArgNames { get; } = new List{"f","g","a"}; diff --git a/AspectedRouting/Language/Functions/FirstMatchOf.cs b/AspectedRouting/Language/Functions/FirstMatchOf.cs index 136e407..a2c6c82 100644 --- a/AspectedRouting/Language/Functions/FirstMatchOf.cs +++ b/AspectedRouting/Language/Functions/FirstMatchOf.cs @@ -8,15 +8,18 @@ namespace AspectedRouting.Language.Functions { public class FirstMatchOf : Function { - public override string Description { get; } = "This higherorder function takes a list of keys, a mapping (function over tags) and a collection of tags. It will try the function for the first key (and it's respective value). If the function fails (it gives null), it'll try the next key.\n\n" + - "E.g. `$firstMatchOf ['maxspeed','highway'] {'maxspeed' --> $parse, 'highway' --> {residential --> 30, tertiary --> 50}}` applied on `{maxspeed=70, highway=tertiary}` will yield `70` as that is the first key in the list; `{highway=residential}` will yield `30`."; + public override string Description { get; } = "This higher-order function takes a list of keys, a mapping (function over tags) and a collection of tags." + + "It will try the function for the first key (and it's respective value). If the function fails (it gives null), it'll try the next key.\n\n" + + "E.g. `$firstMatchOf ['maxspeed','highway'] {'maxspeed' --> $parse, 'highway' --> {residential --> 30, tertiary --> 50}}` applied on `{maxspeed=70, highway=tertiary}`" + + " will yield `70` as that is the first key in the list; `{highway=residential}` will yield `30`."; public override List ArgNames { get; } = new List {"s"}; public FirstMatchOf() : base("first_match_of", true, new[] { // [String] -> (Tags -> [a]) -> Tags -> a - Curry.ConstructFrom(new Var("a"), // Result type on top! + Curry.ConstructFrom( + new Var("a"), // Result type on top! new ListType(Typs.String), new Curry(Typs.Tags, new ListType(new Var("a"))), Typs.Tags diff --git a/AspectedRouting/Language/Functions/If.cs b/AspectedRouting/Language/Functions/If.cs index d7cb4e9..a19577c 100644 --- a/AspectedRouting/Language/Functions/If.cs +++ b/AspectedRouting/Language/Functions/If.cs @@ -10,8 +10,9 @@ namespace AspectedRouting.Language.Functions private static Var b = new Var("b"); public override string Description { get; } = "Selects either one of the branches, depending on the condition." + - " The 'then' branch is returned if the condition returns the string `yes` or `true`. Otherwise, the `else` branch is taken (including if the condition returns `null`)" + - "If the `else` branch is not set, `null` is returned in the condition is false."; + " The 'then' branch is returned if the condition returns the string `yes` or `true`." + + " Otherwise, the `else` branch is taken (including if the condition returns `null`)" + + "If the `else` branch is not set, `null` is returned if the condition evaluates to false."; public override List ArgNames { get; } = new List {"condition", "then", "else"}; public If() : base("if_then_else", true, diff --git a/AspectedRouting/Language/Functions/MemberOf.cs b/AspectedRouting/Language/Functions/MemberOf.cs index 28d6c50..b26e67e 100644 --- a/AspectedRouting/Language/Functions/MemberOf.cs +++ b/AspectedRouting/Language/Functions/MemberOf.cs @@ -28,7 +28,7 @@ namespace AspectedRouting.Language.Functions " a flag `_relation:=\"yes\"` will be set if the aspect matches on every way for where this aspect matches.\n" + "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." + + "`_relation::=yes'. The subfunction is thus executed `countOf(relations) * countOf(profiles)` time, yielding `countOf(profiles)` tags." + " The profile function then picks the tags for himself and strips the `:` away from the key.\n\n" + "\n\n" + "In the test.csv, one can simply use `_relation:=yes` to mimic relations in your tests"; @@ -49,19 +49,23 @@ namespace AspectedRouting.Language.Functions // In the case of tests, relations might be added with "_relation:1:" // So, we create this table as dictionary var relationTags = new Dictionary>(); - foreach (var tag in tags) { - if (tag.Key.StartsWith("_relation:")) { - var keyParts = tag.Key.Split(":"); - if (keyParts.Length != 3) { - continue; - } - var relationName = keyParts[1]; - if (!relationTags.ContainsKey(relationName)) { - relationTags.Add(relationName, new Dictionary()); - } - - relationTags[relationName].Add(keyParts[2], tag.Value); + foreach (var tag in tags) + { + if (!tag.Key.StartsWith("_relation:")) + { + continue; } + + var keyParts = tag.Key.Split(":"); + if (keyParts.Length != 3) { + continue; + } + var relationName = keyParts[1]; + if (!relationTags.ContainsKey(relationName)) { + relationTags.Add(relationName, new Dictionary()); + } + + relationTags[relationName].Add(keyParts[2], tag.Value); } foreach (var relationTagging in relationTags) {