More typesystem fixes, atleast now properly works
This commit is contained in:
parent
173756818e
commit
57704f5ee5
21 changed files with 262 additions and 88 deletions
|
@ -329,12 +329,17 @@ namespace AspectedRouting.Test
|
||||||
[Fact]
|
[Fact]
|
||||||
public void SpecializeToCommonType()
|
public void SpecializeToCommonType()
|
||||||
{
|
{
|
||||||
var p0 = Funcs.Parse;
|
var p0 = Funcs.Parse.Specialize(new Curry(Typs.String, Typs.PDouble));
|
||||||
var p1 = Funcs.Const.Apply(new Constant(1.0));
|
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 specializedExpressions);
|
var newTypes = exprs.SpecializeToCommonTypes(out var _);
|
||||||
Assert.Single(newTypes);
|
Assert.Single( newTypes);
|
||||||
|
|
||||||
|
exprs = new[] {p1, p0};
|
||||||
|
newTypes = exprs.SpecializeToCommonTypes(out var _);
|
||||||
|
Assert.Single( newTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -25,7 +25,7 @@ namespace AspectedRouting.Test
|
||||||
{"ferry", "yes"}
|
{"ferry", "yes"}
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.Equal("tags -> double", string.Join(", ", aspect.Types));
|
Assert.Equal("tags -> pdouble", string.Join(", ", aspect.Types));
|
||||||
Assert.Equal(42d, new Apply(aspect, new Constant(tags)).Evaluate(null));
|
Assert.Equal(42d, new Apply(aspect, new Constant(tags)).Evaluate(null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,4 @@
|
||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=af5d2251_002D713d_002D473f_002D9157_002D89c9d06216e5/@EntryIndexedValue"><SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="All tests from &lt;AspectedRouting.Test&gt;" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=acd4e5d9_002D8d57_002D4495_002Da7aa_002D38598b9e98e0/@EntryIndexedValue"><SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="All tests from &lt;AspectedRouting.Test&gt;" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
<Project Location="/home/pietervdvn/werk/AspectedRouting/AspectedRouting.Test" Presentation="&lt;AspectedRouting.Test&gt;" />
|
<Project Location="/home/pietervdvn/werk/AspectedRouting/AspectedRouting.Test" Presentation="&lt;AspectedRouting.Test&gt;" />
|
||||||
</SessionState></s:String>
|
|
||||||
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=bad1d05d_002Df895_002D4e7d_002Da6e2_002Dede32f077b26/@EntryIndexedValue"><SessionState ContinuousTestingIsOn="False" ContinuousTestingMode="0" FrameworkVersion="{x:Null}" IsLocked="False" Name="SpecializeToCommonType" PlatformMonoPreference="{x:Null}" PlatformType="{x:Null}" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
|
||||||
<TestAncestor>
|
|
||||||
<TestId>xUnit::A1309041-8AAE-42D7-A886-94C9FFC6A28C::.NETCoreApp,Version=v3.1::AspectedRouting.Test.FunctionsTest.SpecializeToCommonType</TestId>
|
|
||||||
</TestAncestor>
|
|
||||||
</SessionState></s:String></wpf:ResourceDictionary>
|
</SessionState></s:String></wpf:ResourceDictionary>
|
|
@ -169,6 +169,7 @@ namespace AspectedRouting.IO.LuaSkeleton
|
||||||
return called.Name;
|
return called.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddDependenciesFor(called);
|
||||||
AddFunction(called);
|
AddFunction(called);
|
||||||
return $"{fc.CalledFunctionName.AsLuaIdentifier()}(parameters, tags, result)";
|
return $"{fc.CalledFunctionName.AsLuaIdentifier()}(parameters, tags, result)";
|
||||||
case Constant c:
|
case Constant c:
|
||||||
|
|
|
@ -60,9 +60,8 @@ namespace AspectedRouting.IO.itinero1
|
||||||
|
|
||||||
|
|
||||||
var exprInLua = _skeleton.ToLua(expression.Optimize());
|
var exprInLua = _skeleton.ToLua(expression.Optimize());
|
||||||
var subs = new Curry(Typs.Tags, new Var(("a"))).UnificationTable(expression.Types.First());
|
var resultTypes = expression.Types.Select(t => t.Uncurry().Last());
|
||||||
if (subs != null && subs.TryGetValue("$a", out var resultType) &&
|
if (resultTypes.Any(t => t.Name.Equals(Typs.Bool.Name)))
|
||||||
(resultType.Equals(Typs.Bool) || resultType.Equals(Typs.String)))
|
|
||||||
{
|
{
|
||||||
_skeleton. AddDep("parse");
|
_skeleton. AddDep("parse");
|
||||||
exprInLua = "parse(" + exprInLua + ")";
|
exprInLua = "parse(" + exprInLua + ")";
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
function atleast(minimumExpected, actual, thn, els)
|
||||||
|
if (minimumExpected <= actual) then
|
||||||
|
return thn;
|
||||||
|
end
|
||||||
|
return els
|
||||||
|
end
|
|
@ -197,13 +197,8 @@ namespace AspectedRouting.Language
|
||||||
|
|
||||||
public static string TypeBreakdown(this IExpression e)
|
public static string TypeBreakdown(this IExpression e)
|
||||||
{
|
{
|
||||||
var text = "";
|
|
||||||
e.Visit(x =>
|
return e.ToString() + " : "+string.Join(" ; ", e.Types);
|
||||||
{
|
|
||||||
text += $"\n\n{x}\n : {string.Join("\n : ", x.Types)}";
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void SanityCheckProfile(this ProfileMetaData pmd, Context context)
|
public static void SanityCheckProfile(this ProfileMetaData pmd, Context context)
|
||||||
|
|
|
@ -83,14 +83,15 @@ namespace AspectedRouting.Language.Expression
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_debugInfo = $"\n{f.Optimize().TypeBreakdown()}\n" +
|
_debugInfo = $"\n{f.Optimize().TypeBreakdown().Indent()}\n" +
|
||||||
$"is applied on an argument with types:" +
|
$"is given the argument: " +
|
||||||
$"{string.Join(", ", argument.Optimize().Types)}";
|
"(" + argument.Optimize().TypeBreakdown() + ")";
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
_debugInfo = $"\n{f.TypeBreakdown()}\n" +
|
_debugInfo =$"\n (NO OPT) {f.TypeBreakdown().Indent()}\n" +
|
||||||
$"{argument.TypeBreakdown()}";
|
$"is given the argument: " +
|
||||||
|
"(" + argument.TypeBreakdown() + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -197,6 +198,7 @@ namespace AspectedRouting.Language.Expression
|
||||||
|
|
||||||
if (Types.Count() > 1)
|
if (Types.Count() > 1)
|
||||||
{
|
{
|
||||||
|
// Too much types to optimize
|
||||||
var optimized = new Dictionary<Type, (IExpression f, IExpression a)>();
|
var optimized = new Dictionary<Type, (IExpression f, IExpression a)>();
|
||||||
foreach (var (resultType, (f, a)) in FunctionApplications)
|
foreach (var (resultType, (f, a)) in FunctionApplications)
|
||||||
{
|
{
|
||||||
|
@ -209,6 +211,7 @@ namespace AspectedRouting.Language.Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// id a => a
|
||||||
var arg = new List<IExpression>();
|
var arg = new List<IExpression>();
|
||||||
if (
|
if (
|
||||||
Deconstruct.UnApplyAny(
|
Deconstruct.UnApplyAny(
|
||||||
|
@ -220,6 +223,37 @@ namespace AspectedRouting.Language.Expression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// ifdotted fcondition fthen felse arg => if (fcondition arg) (fthen arg) (felse arg)
|
||||||
|
var fcondition = new List<IExpression>();
|
||||||
|
var fthen = new List<IExpression>();
|
||||||
|
var felse = new List<IExpression>();
|
||||||
|
var arg = new List<IExpression>();
|
||||||
|
|
||||||
|
if (
|
||||||
|
Deconstruct.UnApplyAny(
|
||||||
|
Deconstruct.UnApply(
|
||||||
|
Deconstruct.UnApply(
|
||||||
|
Deconstruct.UnApply(
|
||||||
|
Deconstruct.IsFunc(Funcs.IfDotted),
|
||||||
|
Deconstruct.Assign(fcondition)),
|
||||||
|
Deconstruct.Assign(fthen)),
|
||||||
|
Deconstruct.Assign(felse)),
|
||||||
|
Deconstruct.Assign(arg)
|
||||||
|
).Invoke(this))
|
||||||
|
{
|
||||||
|
var a = arg.First();
|
||||||
|
return
|
||||||
|
Funcs.If.Apply(
|
||||||
|
fcondition.First().Apply(a),
|
||||||
|
fthen.First().Apply(a),
|
||||||
|
felse.First().Apply(a)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
var (f, a) = FunctionApplications.Values.First();
|
var (f, a) = FunctionApplications.Values.First();
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,11 @@ namespace AspectedRouting.Language.Expression
|
||||||
priority += aspectInfluence * aspectWeight;
|
priority += aspectInfluence * aspectWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priority <= 0)
|
||||||
|
{
|
||||||
|
canAccess = "no";
|
||||||
|
}
|
||||||
|
|
||||||
return new ProfileResult((string) canAccess, (string) oneway, speed, priority,
|
return new ProfileResult((string) canAccess, (string) oneway, speed, priority,
|
||||||
string.Join("\n ", weightExplanation));
|
string.Join("\n ", weightExplanation));
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,18 +45,27 @@ namespace AspectedRouting.Language.Functions
|
||||||
public override object Evaluate(Context c, params IExpression[] arguments)
|
public override object Evaluate(Context c, params IExpression[] arguments)
|
||||||
{
|
{
|
||||||
var minimum = arguments[0].Evaluate(c);
|
var minimum = arguments[0].Evaluate(c);
|
||||||
var f = (IExpression) arguments[1].Evaluate(c);
|
|
||||||
var then = arguments[2].Evaluate(c);
|
var then = arguments[2].Evaluate(c);
|
||||||
var @else = arguments[3].Evaluate(c);
|
var @else = arguments[3].Evaluate(c);
|
||||||
var x = arguments[4];
|
var x = arguments[4];
|
||||||
|
|
||||||
var arg1 = f.Evaluate(c, x);
|
var arg1 = arguments[1].Evaluate(c, x);
|
||||||
|
|
||||||
if (minimum == null || arg1 == null)
|
if (minimum == null || arg1 == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (minimum is IExpression e)
|
||||||
|
{
|
||||||
|
minimum = e.Evaluate(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arg1 is IExpression e1)
|
||||||
|
{
|
||||||
|
arg1 = e1.Evaluate(c);
|
||||||
|
}
|
||||||
|
|
||||||
if (minimum is int i0)
|
if (minimum is int i0)
|
||||||
{
|
{
|
||||||
minimum = (double) i0;
|
minimum = (double) i0;
|
||||||
|
|
|
@ -18,6 +18,10 @@ namespace AspectedRouting.Language.Functions
|
||||||
if (o is IEnumerable<IExpression> enumerable)
|
if (o is IEnumerable<IExpression> enumerable)
|
||||||
{
|
{
|
||||||
o = enumerable.ToList();
|
o = enumerable.ToList();
|
||||||
|
if (enumerable.Any(x => x == null))
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("Some subexpression is null");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_o = o;
|
_o = o;
|
||||||
|
@ -29,6 +33,10 @@ namespace AspectedRouting.Language.Functions
|
||||||
if (o is IEnumerable<IExpression> enumerable)
|
if (o is IEnumerable<IExpression> enumerable)
|
||||||
{
|
{
|
||||||
o = enumerable.ToList();
|
o = enumerable.ToList();
|
||||||
|
if (enumerable.Any(x => x == null))
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("Some subexpression is null");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_o = o;
|
_o = o;
|
||||||
|
@ -39,6 +47,10 @@ namespace AspectedRouting.Language.Functions
|
||||||
var tps = exprs
|
var tps = exprs
|
||||||
.SpecializeToCommonTypes(out var specializedVersions)
|
.SpecializeToCommonTypes(out var specializedVersions)
|
||||||
.Select(t => new ListType(t));
|
.Select(t => new ListType(t));
|
||||||
|
if(specializedVersions.Any(x => x == null))
|
||||||
|
{
|
||||||
|
throw new Exception("Specializing to common types failed for "+string.Join("," ,exprs.Select(e => e.ToString())));
|
||||||
|
}
|
||||||
Types = tps.ToList();
|
Types = tps.ToList();
|
||||||
_o = specializedVersions;
|
_o = specializedVersions;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +61,10 @@ namespace AspectedRouting.Language.Functions
|
||||||
{
|
{
|
||||||
Types = exprs
|
Types = exprs
|
||||||
.SpecializeToCommonTypes(out var specializedVersions).Select(t => new ListType(t)).ToList();
|
.SpecializeToCommonTypes(out var specializedVersions).Select(t => new ListType(t)).ToList();
|
||||||
|
if (specializedVersions.Any(x => x == null))
|
||||||
|
{
|
||||||
|
throw new NullReferenceException("Some subexpression is null");
|
||||||
|
}
|
||||||
_o = specializedVersions.ToList();
|
_o = specializedVersions.ToList();
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|
|
@ -8,9 +8,10 @@ namespace AspectedRouting.Language.Functions
|
||||||
{
|
{
|
||||||
public class Dot : Function
|
public class Dot : Function
|
||||||
{
|
{
|
||||||
public override string Description { get; } = "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 ";
|
public override string Description { get; } =
|
||||||
|
"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 ";
|
||||||
|
|
||||||
public override List<string> ArgNames { get; } = new List<string>{"f","g","a"};
|
public override List<string> ArgNames { get; } = new List<string> {"f", "g", "a"};
|
||||||
public static readonly Var A = new Var("a");
|
public static readonly Var A = new Var("a");
|
||||||
public static readonly Var B = new Var("b");
|
public static readonly Var B = new Var("b");
|
||||||
public static readonly Var C = new Var("c");
|
public static readonly Var C = new Var("c");
|
||||||
|
@ -33,6 +34,10 @@ namespace AspectedRouting.Language.Functions
|
||||||
|
|
||||||
public override object Evaluate(Context c, params IExpression[] arguments)
|
public override object Evaluate(Context c, params IExpression[] arguments)
|
||||||
{
|
{
|
||||||
|
if (arguments.Count() <= 2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
var f0 = arguments[0];
|
var f0 = arguments[0];
|
||||||
var f1 = arguments[1];
|
var f1 = arguments[1];
|
||||||
var resultType = ((Curry) f1.Types.First()).ResultType;
|
var resultType = ((Curry) f1.Types.First()).ResultType;
|
||||||
|
|
|
@ -38,8 +38,7 @@ namespace AspectedRouting.Language
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="argument"></param>
|
/// <param name="argument"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
// IExpression OptimizeWithArgument(IExpression argument);
|
// IExpression OptimizeWithArgument(IExpression argument);
|
||||||
|
|
||||||
void Visit(Func<IExpression, bool> f);
|
void Visit(Func<IExpression, bool> f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +46,7 @@ namespace AspectedRouting.Language
|
||||||
{
|
{
|
||||||
public static object Run(this IExpression e, Context c, Dictionary<string, string> tags)
|
public static object Run(this IExpression e, Context c, Dictionary<string, string> tags)
|
||||||
{
|
{
|
||||||
return e.Apply(new []{new Constant(tags)}).Evaluate(c);
|
return e.Apply(new[] {new Constant(tags)}).Evaluate(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IExpression Specialize(this IExpression e, Type t)
|
public static IExpression Specialize(this IExpression e, Type t)
|
||||||
|
@ -101,8 +100,11 @@ namespace AspectedRouting.Language
|
||||||
out IEnumerable<Type> specializedTypes, out IEnumerable<IExpression> specializedExpressions)
|
out IEnumerable<Type> specializedTypes, out IEnumerable<IExpression> specializedExpressions)
|
||||||
{
|
{
|
||||||
specializedTypes = null;
|
specializedTypes = null;
|
||||||
var expressions = exprs.ToList();
|
var exprsForTypes = exprs.SortWidestToSmallest();
|
||||||
foreach (var f in expressions)
|
exprsForTypes.Reverse();
|
||||||
|
|
||||||
|
|
||||||
|
foreach (var f in exprsForTypes)
|
||||||
{
|
{
|
||||||
if (specializedTypes == null)
|
if (specializedTypes == null)
|
||||||
{
|
{
|
||||||
|
@ -110,9 +112,7 @@ namespace AspectedRouting.Language
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO FIXME
|
var specialized = f.Types.RenameVars(specializedTypes).SpecializeTo(specializedTypes, false);
|
||||||
// EITHER THE TYPES HAVE TO BE FROM SPECIFIC TO NON-SPECIFIC ORDER OR VICE VERSA
|
|
||||||
var specialized = f.Types.RenameVars(specializedTypes).SpecializeTo(specializedTypes);
|
|
||||||
// ReSharper disable once JoinNullCheckWithUsage
|
// ReSharper disable once JoinNullCheckWithUsage
|
||||||
if (specialized == null)
|
if (specialized == null)
|
||||||
{
|
{
|
||||||
|
@ -126,7 +126,15 @@ namespace AspectedRouting.Language
|
||||||
}
|
}
|
||||||
|
|
||||||
var tps = specializedTypes;
|
var tps = specializedTypes;
|
||||||
return specializedExpressions = expressions.Select(expr => expr.Specialize(tps));
|
|
||||||
|
var optExprs = new List<IExpression>();
|
||||||
|
foreach (var expr in exprs)
|
||||||
|
{
|
||||||
|
var exprOpt = expr.Specialize(tps);
|
||||||
|
optExprs.Add(exprOpt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return specializedExpressions = optExprs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ namespace AspectedRouting.Language.Typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static HashSet<Type> SpecializeTo(this IEnumerable<Type> types0, IEnumerable<Type> allowedTypes)
|
public static HashSet<Type> SpecializeTo(this IEnumerable<Type> types0, IEnumerable<Type> allowedTypes, bool reverseSuperSet = true)
|
||||||
{
|
{
|
||||||
var results = new HashSet<Type>();
|
var results = new HashSet<Type>();
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ namespace AspectedRouting.Language.Typ
|
||||||
{
|
{
|
||||||
foreach (var allowed in allowedTypes)
|
foreach (var allowed in allowedTypes)
|
||||||
{
|
{
|
||||||
var unified = t0.Unify(allowed, true);
|
var unified = t0.Unify(allowed, reverseSuperSet);
|
||||||
if (unified != null)
|
if (unified != null)
|
||||||
{
|
{
|
||||||
results.Add(unified);
|
results.Add(unified);
|
||||||
|
@ -70,9 +71,10 @@ namespace AspectedRouting.Language.Typ
|
||||||
{
|
{
|
||||||
return SelectSmallestUnion(t1, subbed);
|
return SelectSmallestUnion(t1, subbed);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SelectSmallestUnion(subbed, t1);
|
return SelectSmallestUnion(subbed, t1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Type SelectSmallestUnion(this Type wider, Type smaller, bool reverse = false)
|
private static Type SelectSmallestUnion(this Type wider, Type smaller, bool reverse = false)
|
||||||
{
|
{
|
||||||
switch (wider)
|
switch (wider)
|
||||||
|
@ -99,6 +101,81 @@ namespace AspectedRouting.Language.Typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<IExpression> SortWidestToSmallest(this IEnumerable<IExpression> expressions)
|
||||||
|
{
|
||||||
|
var all = expressions.ToHashSet();
|
||||||
|
var sorted = new List<IExpression>();
|
||||||
|
while (all.Any())
|
||||||
|
{
|
||||||
|
var widest = SelectWidestType(all);
|
||||||
|
if (widest == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Can not sort widest to smallest");
|
||||||
|
}
|
||||||
|
all.Remove(widest);
|
||||||
|
sorted.Add(widest);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IExpression SelectSmallestType(IEnumerable<IExpression> expressions)
|
||||||
|
{
|
||||||
|
IExpression smallest = null;
|
||||||
|
foreach (var current in expressions)
|
||||||
|
{
|
||||||
|
if (smallest == null)
|
||||||
|
{
|
||||||
|
smallest = current;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (smallest.Types.AllAreSuperset(current.Types))
|
||||||
|
{
|
||||||
|
smallest = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return smallest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IExpression SelectWidestType(IEnumerable<IExpression> expressions)
|
||||||
|
{
|
||||||
|
IExpression widest = null;
|
||||||
|
foreach (var current in expressions)
|
||||||
|
{
|
||||||
|
if (widest == null)
|
||||||
|
{
|
||||||
|
widest = current;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current.Types.AllAreSuperset(widest.Types))
|
||||||
|
{
|
||||||
|
widest = current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return widest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool AllAreSuperset(this IEnumerable<Type> shouldBeSuper, IEnumerable<Type> shouldBeSmaller)
|
||||||
|
{
|
||||||
|
foreach (var super in shouldBeSuper)
|
||||||
|
{
|
||||||
|
foreach (var smaller in shouldBeSmaller)
|
||||||
|
{
|
||||||
|
if (!super.IsSuperSet(smaller))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Tries to unify t0 with all t1's.
|
/// Tries to unify t0 with all t1's.
|
||||||
/// Every match is returned
|
/// Every match is returned
|
||||||
|
@ -136,7 +213,6 @@ namespace AspectedRouting.Language.Typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static Type Substitute(this Type t0, Dictionary<string, Type> substitutions)
|
public static Type Substitute(this Type t0, Dictionary<string, Type> substitutions)
|
||||||
{
|
{
|
||||||
switch (t0)
|
switch (t0)
|
||||||
|
@ -161,7 +237,8 @@ namespace AspectedRouting.Language.Typ
|
||||||
/// <param name="t0"></param>
|
/// <param name="t0"></param>
|
||||||
/// <param name="t1"></param>
|
/// <param name="t1"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static Dictionary<string, Type> UnificationTable(this Type t0, Type t1, bool reverseSupersetRelation = false)
|
public static Dictionary<string, Type> UnificationTable(this Type t0, Type t1,
|
||||||
|
bool reverseSupersetRelation = false)
|
||||||
{
|
{
|
||||||
var substitutionsOn0 = new Dictionary<string, Type>();
|
var substitutionsOn0 = new Dictionary<string, Type>();
|
||||||
|
|
||||||
|
@ -235,7 +312,7 @@ namespace AspectedRouting.Language.Typ
|
||||||
AddSubs(v.Name, t0);
|
AddSubs(v.Name, t0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!reverseSupersetRelation && !t0.IsSuperSet(t1))
|
if (!reverseSupersetRelation && !t0.IsSuperSet(t1))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
|
@ -281,6 +358,11 @@ namespace AspectedRouting.Language.Typ
|
||||||
|
|
||||||
public static bool IsSuperSet(this Type t0, Type t1)
|
public static bool IsSuperSet(this Type t0, Type t1)
|
||||||
{
|
{
|
||||||
|
if (t0 is Var || t1 is Var)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
switch (t0)
|
switch (t0)
|
||||||
{
|
{
|
||||||
case StringType _ when t1 is BoolType _:
|
case StringType _ when t1 is BoolType _:
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace AspectedRouting
|
||||||
foreach (var file in jsonFileNames)
|
foreach (var file in jsonFileNames)
|
||||||
{
|
{
|
||||||
var fi = new FileInfo(file);
|
var fi = new FileInfo(file);
|
||||||
|
|
||||||
var aspect = JsonParser.AspectFromJson(context, File.ReadAllText(file), fi.Name);
|
var aspect = JsonParser.AspectFromJson(context, File.ReadAllText(file), fi.Name);
|
||||||
if (aspect == null) continue;
|
if (aspect == null) continue;
|
||||||
|
|
||||||
|
@ -63,11 +63,6 @@ namespace AspectedRouting
|
||||||
var result = new List<(ProfileMetaData profile, List<BehaviourTestSuite> profileTests)>();
|
var result = new List<(ProfileMetaData profile, List<BehaviourTestSuite> profileTests)>();
|
||||||
foreach (var jsonFile in jsonFiles)
|
foreach (var jsonFile in jsonFiles)
|
||||||
{
|
{
|
||||||
if (!jsonFile.Contains("bicycle"))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var profile =
|
var profile =
|
||||||
|
@ -227,6 +222,7 @@ namespace AspectedRouting
|
||||||
|
|
||||||
|
|
||||||
// With everything parsed and typechecked, time for tests
|
// With everything parsed and typechecked, time for tests
|
||||||
|
var testsOk = true;
|
||||||
foreach (var (aspect, t) in aspects)
|
foreach (var (aspect, t) in aspects)
|
||||||
{
|
{
|
||||||
if (t == null)
|
if (t == null)
|
||||||
|
@ -235,18 +231,27 @@ namespace AspectedRouting
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t.Run();
|
testsOk &= t.Run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
foreach (var (profile, profileTests) in profiles)
|
foreach (var (profile, profileTests) in profiles)
|
||||||
{
|
{
|
||||||
foreach (var test in profileTests)
|
foreach (var test in profileTests)
|
||||||
{
|
{
|
||||||
test.Run(context);
|
testsOk &= test.Run(context);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!testsOk)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Some tests failed, quitting now without generating output");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (profile, profileTests) in profiles)
|
||||||
|
{
|
||||||
PrintUsedTags(profile, context);
|
PrintUsedTags(profile, context);
|
||||||
|
|
||||||
var aspectTests = aspects.Select(a => a.tests).ToList();
|
var aspectTests = aspects.Select(a => a.tests).ToList();
|
||||||
|
|
|
@ -61,7 +61,7 @@ namespace AspectedRouting.Tests
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void Run()
|
public bool Run()
|
||||||
{
|
{
|
||||||
var failed = false;
|
var failed = false;
|
||||||
var testCase = 0;
|
var testCase = 0;
|
||||||
|
@ -88,12 +88,9 @@ namespace AspectedRouting.Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failed)
|
|
||||||
{
|
|
||||||
throw new ArgumentException("Some test failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine($"[{FunctionToApply.Name}] {testCase} tests successful");
|
Console.WriteLine($"[{FunctionToApply.Name}] {testCase} tests " + (failed ? "failed" : "successful"));
|
||||||
|
return !failed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -77,8 +77,7 @@ namespace AspectedRouting.Tests
|
||||||
weight = double.Parse(testData[3]);
|
weight = double.Parse(testData[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var expected = new ProfileResult(
|
var expected = new ProfileResult(
|
||||||
testData[0],
|
testData[0],
|
||||||
testData[1],
|
testData[1],
|
||||||
|
@ -88,9 +87,10 @@ namespace AspectedRouting.Tests
|
||||||
|
|
||||||
if (expected.Priority == 0 && expected.Access != "no")
|
if (expected.Priority == 0 && expected.Access != "no")
|
||||||
{
|
{
|
||||||
throw new ArgumentException("A priority of zero is interpreted as 'no access' - don't use it");
|
throw new ArgumentException(
|
||||||
|
"A priority of zero is interpreted as 'no access' - don't use it");
|
||||||
}
|
}
|
||||||
|
|
||||||
var vals = testData.GetRange(4, testData.Count - 4);
|
var vals = testData.GetRange(4, testData.Count - 4);
|
||||||
var tags = new Dictionary<string, string>();
|
var tags = new Dictionary<string, string>();
|
||||||
for (int i = 0; i < keys.Count; i++)
|
for (int i = 0; i < keys.Count; i++)
|
||||||
|
@ -192,11 +192,8 @@ namespace AspectedRouting.Tests
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Run(Context c)
|
public bool Run(Context c)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
var allOk = true;
|
var allOk = true;
|
||||||
var i = 1;
|
var i = 1;
|
||||||
foreach (var (expected, tags) in Tests)
|
foreach (var (expected, tags) in Tests)
|
||||||
|
@ -213,14 +210,9 @@ namespace AspectedRouting.Tests
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!allOk)
|
Console.WriteLine($"[{Profile.Name}] {Tests.Count()} tests " + (allOk ? "successfull" : "executed, some failed") +
|
||||||
{
|
$" for behaviour {BehaviourName}");
|
||||||
throw new ArgumentException("Some tests failed for " + BehaviourName);
|
return allOk;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Console.WriteLine($"[{Profile.Name}] {Tests.Count()} tests successful for behaviour {BehaviourName}");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -39,7 +39,17 @@
|
||||||
"#timeNeeded": "$speed",
|
"#timeNeeded": "$speed",
|
||||||
"#distance": "$distance",
|
"#distance": "$distance",
|
||||||
"#trespassingPenalty": "$clean_permission_score",
|
"#trespassingPenalty": "$clean_permission_score",
|
||||||
"#leastSafetyPenalty": 0
|
"#leastSafetyPenalty": {
|
||||||
|
"$multiply": [
|
||||||
|
"$speed",
|
||||||
|
{
|
||||||
|
"$atleast": "#leastSafetyRequired",
|
||||||
|
"f": "$bicycle.safety",
|
||||||
|
"then": 0,
|
||||||
|
"else": -1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"defaults": {
|
"defaults": {
|
||||||
"#defaultSpeed": 15,
|
"#defaultSpeed": 15,
|
||||||
|
@ -56,16 +66,18 @@
|
||||||
"#trespassingPenalty": 15,
|
"#trespassingPenalty": 15,
|
||||||
"#": "This is not a priority weight, but rather a kind of access restriction. If 'leastafety' is not met, a huge penalty is applied, namely #leastSafetyPenalty. Note: 0.1 is the safety level of a primary without cycle highway",
|
"#": "This is not a priority weight, but rather a kind of access restriction. If 'leastafety' is not met, a huge penalty is applied, namely #leastSafetyPenalty. Note: 0.1 is the safety level of a primary without cycle highway",
|
||||||
"#leastSafetyRequired": 0.11,
|
"#leastSafetyRequired": 0.11,
|
||||||
"#leastSafetyPenalty": 2
|
"#leastSafetyPenalty": 0
|
||||||
},
|
},
|
||||||
"behaviours": {
|
"behaviours": {
|
||||||
"fastest": {
|
"fastest": {
|
||||||
"description": "The fastest route to your destination",
|
"description": "The fastest route to your destination",
|
||||||
"#timeNeeded": 1
|
"#timeNeeded": 1,
|
||||||
|
"#leastSafetyPenalty": 2
|
||||||
},
|
},
|
||||||
"shortest": {
|
"shortest": {
|
||||||
"description": "The shortest route, independent of of speed",
|
"description": "The shortest route, independent of of speed",
|
||||||
"#distance": 1
|
"#distance": 1,
|
||||||
|
"#leastSafetyPenalty": 2
|
||||||
},
|
},
|
||||||
"safety": {
|
"safety": {
|
||||||
"description": "A defensive route shying away from big roads with lots of cars",
|
"description": "A defensive route shying away from big roads with lots of cars",
|
||||||
|
@ -73,7 +85,8 @@
|
||||||
},
|
},
|
||||||
"comfort": {
|
"comfort": {
|
||||||
"description": "A comfortable route preferring well-paved roads, smaller roads and a bit of scenery at the cost of speed",
|
"description": "A comfortable route preferring well-paved roads, smaller roads and a bit of scenery at the cost of speed",
|
||||||
"#comfort": 1
|
"#comfort": 1,
|
||||||
|
"#leastSafetyPenalty": 2
|
||||||
},
|
},
|
||||||
"comfort_safety": {
|
"comfort_safety": {
|
||||||
"description": "A route which aims to be both safe and comfortable at the cost of speed",
|
"description": "A route which aims to be both safe and comfortable at the cost of speed",
|
||||||
|
@ -84,7 +97,8 @@
|
||||||
"description": "A profile for a bike with an electrical motor where the engine doesn't go faster then 25km/h (thus NOT the speed-pedelec). This is a variation of the normal fastest, but with a faster default speed. As the maxspeed is 30, it'll resemble shortest a bit more on 'normal' streets and will penalize slower roads more",
|
"description": "A profile for a bike with an electrical motor where the engine doesn't go faster then 25km/h (thus NOT the speed-pedelec). This is a variation of the normal fastest, but with a faster default speed. As the maxspeed is 30, it'll resemble shortest a bit more on 'normal' streets and will penalize slower roads more",
|
||||||
"#defaultSpeed": 23,
|
"#defaultSpeed": 23,
|
||||||
"#maxspeed": 30,
|
"#maxspeed": 30,
|
||||||
"#timeNeeded": 1
|
"#timeNeeded": 1,
|
||||||
|
"#leastSafetyPenalty": 2
|
||||||
},
|
},
|
||||||
"networks": {
|
"networks": {
|
||||||
"description": "A recreative route following any existing cycling network. Might make a few detours",
|
"description": "A recreative route following any existing cycling network. Might make a few detours",
|
||||||
|
@ -111,7 +125,8 @@
|
||||||
"cycle_highway": {
|
"cycle_highway": {
|
||||||
"description": "A route preferring the 'cycle-highways'. On non-cycleways, fastest is used (with a very low factor) in order to make sure the behaviour there is defined ",
|
"description": "A route preferring the 'cycle-highways'. On non-cycleways, fastest is used (with a very low factor) in order to make sure the behaviour there is defined ",
|
||||||
"#cycleHighwayNetworkScore": 20,
|
"#cycleHighwayNetworkScore": 20,
|
||||||
"#timeNeeded": 0.1
|
"#timeNeeded": 0.1,
|
||||||
|
"#leastSafetyPenalty": 2
|
||||||
},
|
},
|
||||||
"node_network": {
|
"node_network": {
|
||||||
"description": "A route following the recreational node network. Might make detours",
|
"description": "A route following the recreational node network. Might make detours",
|
||||||
|
|
|
@ -27,9 +27,14 @@
|
||||||
"speed":{
|
"speed":{
|
||||||
"$min":
|
"$min":
|
||||||
[
|
[
|
||||||
{"$multiply":["#defaultSpeed", "$bicycle.speed_factor"]},
|
"#maxspeed",
|
||||||
"$legal_maxspeed_be",
|
"$legal_maxspeed_be",
|
||||||
"#maxspeed"
|
{
|
||||||
|
"$multiply": [
|
||||||
|
"#defaultSpeed",
|
||||||
|
"$bicycle.speed_factor"
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"access":"$speedPedelec.access_be",
|
"access":"$speedPedelec.access_be",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
access,oneway,speed,priority,highway,bicycle,surface,cycleway:left,oneway,oneway:bicycle,access,maxspeed,junction
|
access,oneway,speed,priority,highway,bicycle,surface,cycleway:left,oneway,oneway:bicycle,access,maxspeed,junction
|
||||||
no,both,0,0,,,,,,,,,
|
no,both,0,0,,,,,,,,,
|
||||||
designated,both,15,15,cycleway,,,,,,,,
|
designated,both,15,15,cycleway,,,,,,,,
|
||||||
yes,both,15,15,primary,,,,,,,,
|
no,both,15,-15,primary,,,,,,,,
|
||||||
yes,both,15,15,primary,yes,,,,,,,
|
no,both,15,-15,primary,yes,,,,,,,
|
||||||
yes,both,15,15,residential,,,,,,,,
|
yes,both,15,15,residential,,,,,,,,
|
||||||
yes,both,13.5,13.5,residential,yes,sett,,,,,,
|
yes,both,13.5,13.5,residential,yes,sett,,,,,,
|
||||||
dismount,both,2.25,2.25,pedestrian,,,,,,,,
|
dismount,both,2.25,2.25,pedestrian,,,,,,,,
|
||||||
|
|
|
|
@ -2,4 +2,4 @@ access,oneway,speed,priority,highway,surface
|
||||||
no,both,0,0,,
|
no,both,0,0,,
|
||||||
designated,both,15,1,cycleway,
|
designated,both,15,1,cycleway,
|
||||||
yes,both,5.25,1,path,ground
|
yes,both,5.25,1,path,ground
|
||||||
yes,both,15,1,primary,
|
no,both,15,-29,primary,
|
||||||
|
|
|
Loading…
Add table
Add a link
Reference in a new issue