Add option to extract constant tables, fix string.start

This commit is contained in:
Pieter Vander Vennet 2021-02-25 19:16:51 +01:00
parent 00fa1a8b67
commit aae20662e2
5 changed files with 78 additions and 59 deletions

View file

@ -218,6 +218,7 @@ namespace AspectedRouting.IO.LuaSkeleton
public string MappingToLua(Mapping m)
{
var isConstant = true;
var contents = m.StringToResultFunctions.Select(kv =>
{
var (key, expr) = kv;
@ -228,13 +229,23 @@ namespace AspectedRouting.IO.LuaSkeleton
left = key;
}
return left + " = " + ToLua(expr, key);
var luaExpr = ToLua(expr, key);
if (luaExpr.Contains("tags")) {
isConstant = false;
}
return left + " = " + luaExpr ;
}
);
return
var mapping =
"{\n " +
string.Join(",\n ", contents) +
"\n}";
if (_staticTables && isConstant) {
return AddConstant(mapping);
}
return mapping;
}
/// <summary>

View file

@ -1,30 +1,38 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using AspectedRouting.Language;
namespace AspectedRouting.IO.LuaSkeleton
{
/// <summary>
/// The 'LuaSkeleton' is a class which is used in Lua generation of profiles.
///
/// The lua skeleton basically keeps track of dependencies, and added functions.
/// Once done, all these can be retrieved as code.
///
/// E.g. if an expression is turned into lua with 'ToExpression', then the dependencies will be automatically added.
///
/// </summary>
public partial class LuaSkeleton
{
private readonly HashSet<string> _alreadyAddedFunctions = new HashSet<string>();
private readonly List<string> _constants = new List<string>();
private readonly Context _context;
private readonly HashSet<string> _dependencies = new HashSet<string>();
private readonly List<string> _functionImplementations = new List<string>();
private readonly HashSet<string> _alreadyAddedFunctions = new HashSet<string>();
public LuaSkeleton(Context context)
/// <summary>
/// It turns out that creating lua tables is a huge performance overhead.
/// Lots of functions however need a constant table to be invoked. Creating this table over and over is performance
/// issue.
/// If this flag is set, those constant tables are exported so they are created only once
/// </summary>
private readonly bool _staticTables;
public LuaSkeleton(Context context, bool staticTables = false)
{
_context = context;
_staticTables = staticTables;
}
internal void AddDep(string name)
@ -45,15 +53,11 @@ namespace AspectedRouting.IO.LuaSkeleton
public void AddDependenciesFor(IExpression e)
{
var (_, functionNames) = e.InList().DirectlyAndInderectlyCalled(_context);
foreach (var functionName in functionNames)
{
if (_context.DefinedFunctions.TryGetValue(functionName, out var aspectemeta))
{
AddFunction(aspectemeta);
foreach (var functionName in functionNames) {
if (_context.DefinedFunctions.TryGetValue(functionName, out var aspectMeta)) {
AddFunction(aspectMeta);
}
else
{
else {
AddDep(functionName);
}
}
@ -63,15 +67,12 @@ namespace AspectedRouting.IO.LuaSkeleton
{
var imps = new List<string>();
foreach (var name in _dependencies)
{
foreach (var name in _dependencies) {
var path = $"IO/lua/{name}.lua";
if (File.Exists(path))
{
if (File.Exists(path)) {
imps.Add(File.ReadAllText(path));
}
else
{
else {
throw new FileNotFoundException(path);
}
}
@ -79,5 +80,15 @@ namespace AspectedRouting.IO.LuaSkeleton
return imps;
}
public string AddConstant(string luaExpression)
{
_constants.Add(luaExpression);
return "c" + (_constants.Count - 1);
}
public IEnumerable<string> GenerateConstants()
{
return _constants.Select((c, i) => $"c{i} = {c}");
}
}
}

View file

@ -1,4 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using AspectedRouting.Language;
@ -88,6 +87,7 @@ namespace AspectedRouting.IO.itinero1
functions,
"---------------------- UTILS ------------------------".InList(),
dependencies,
_skeleton.GenerateConstants().ToList(),
"----------------------- TESTS ------------------------".InList(),
tests.InList(),
GenerateLegacyTail().InList()

View file

@ -10,10 +10,8 @@ namespace AspectedRouting.IO.itinero2
{
/// <summary>
/// Lua printer for itinero2-lua format
///
/// The itinero 2.0 lua profile is a whole lot simpler then the 1.0 format,
/// as a single profile there only describes a single behaviour of a vehicle:
///
/// It has:
/// - name: string, e.g. 'bicycle.fastest'
/// - factor(attributes, result): void, where 'attributes' are all the tags of the way,
@ -23,19 +21,18 @@ namespace AspectedRouting.IO.itinero2
/// - 'forward', a double describing the forwardfactor
/// - 'backward', the backward factor
/// - 'canstop', a boolean indicating if stopping along the road is possible
///
/// </summary>
public partial class LuaPrinter2
{
private readonly ProfileMetaData _profile;
private readonly string _behaviourName;
private readonly Context _context;
private readonly List<AspectTestSuite> _aspectTests;
private readonly string _behaviourName;
private readonly IEnumerable<BehaviourTestSuite> _behaviourTestSuite;
private readonly Context _context;
private readonly DateTime _lastChangeTime;
private readonly LuaParameterPrinter _parameterPrinter;
private readonly ProfileMetaData _profile;
private readonly LuaSkeleton.LuaSkeleton _skeleton;
private readonly LuaParameterPrinter _parameterPrinter;
public LuaPrinter2(ProfileMetaData profile, string behaviourName,
@ -43,7 +40,7 @@ namespace AspectedRouting.IO.itinero2
List<AspectTestSuite> aspectTests, IEnumerable<BehaviourTestSuite> behaviourTestSuite,
DateTime lastChangeTime)
{
_skeleton = new LuaSkeleton.LuaSkeleton(context);
_skeleton = new LuaSkeleton.LuaSkeleton(context, false);
_profile = profile;
_behaviourName = behaviourName;
_context = context;
@ -57,21 +54,19 @@ namespace AspectedRouting.IO.itinero2
{
var profileDescr = _profile.Behaviours[_behaviourName]["description"].Evaluate(_context).ToString();
var header =
new List<string>
{
new List<string> {
$"name = \"{_profile.Name}.{_behaviourName}\"",
$"generationDate = \"{_lastChangeTime:s}\"",
$"description = \"{profileDescr} ({_profile.Description})\""
};
var testPrinter = new LuaTestPrinter(_skeleton,
new List<string>() {"unitTestProfile2"});
new List<string> {"unitTestProfile2"});
var tests = testPrinter.GenerateFullTestSuite(
_behaviourTestSuite.ToList(),
new List<AspectTestSuite>(),
true);
var all = new List<string>
{
var all = new List<string> {
header.Lined(),
"",
GenerateMainFunction(),
@ -85,6 +80,8 @@ namespace AspectedRouting.IO.itinero2
"",
string.Join("\n\n", _skeleton.GenerateDependencies()), // Should be AFTER generating the main function!
"",
string.Join("\n\n", _skeleton.GenerateConstants()),
"",
tests,
"",

View file

@ -1,4 +1,4 @@
function string.start(strt, s)
function string_start(strt, s)
return string.sub(s, 1, string.len(strt)) == strt
end
@ -9,7 +9,7 @@ function remove_relation_prefix(tags, name)
local new_tags = {}
for k, v in pairs(tags) do
local prefix = "_relation:" .. name .. ":";
if (string.start(prefix, k)) then
if (string_start(prefix, k)) then
local new_key = "_relation:" .. string.sub(k, string.len(prefix) + 1) -- plus 1: sub uses one-based indexing to select the start
new_tags[new_key] = v
else