23 KiB
Types
- double
- pdouble
- nat
- int
- string
- tags
- bool
Builtin functions
- eq
- notEq
- not
- inv
- default
- parse
- to_string
- concat
- containedIn
- min
- and
- max
- or
- sum
- plus
- add
- multiply
- atleast
- firstMatchOf
- mustMatch
- memberOf
- if_then_else
- if
- if_then_else_dotted
- ifdotted
- ifDotted
- id
- firstArg
- const
- constRight
- dot
- listDot
- eitherFunc
- stringToTags
- head
Function overview
eq
| a | b | returns |
|---|---|---|
| $a | $a | bool |
| $a | $a | string |
Returns 'yes' if both values are the same
Lua implementation:
function eq(a, b)
if (a == b) then
return "yes"
else
return "no"
end
end
notEq
| a | b | returns |
|---|---|---|
| $a | $a | bool |
| $a | $a | string |
| bool | bool |
OVerloaded function, either boolean not or returns 'yes' if the two passed in values are not the same;
Lua implementation:
function notEq(a, b)
if (b == nil) then
b = "yes"
end
if (a ~= b) then
return "yes"
else
return "no"
end
end
not
| a | b | returns |
|---|---|---|
| $a | $a | bool |
| $a | $a | string |
| bool | bool |
OVerloaded function, either boolean not or returns 'yes' if the two passed in values are not the same;
Lua implementation:
function notEq(a, b)
if (b == nil) then
b = "yes"
end
if (a ~= b) then
return "yes"
else
return "no"
end
end
inv
| d | returns |
|---|---|
| pdouble | pdouble |
| double | double |
Calculates 1/d
Lua implementation:
function inv(n)
return 1/n
end
default
| defaultValue | f | returns |
|---|---|---|
| $a | $b -> $a | $b |
Calculates function f for the given argument. If the result is null, the default value is returned instead
Lua implementation:
function default(defaultValue, realValue)
if(realValue ~= nil) then
return realValue
end
return defaultValue
end
parse
| s | returns |
|---|---|
| string | double |
| string | pdouble |
Parses a string into a numerical value. Returns 'null' if parsing fails or no input is given. If a duration is given (e.g. 01:15), then the number of minutes (75) is returned
Lua implementation:
function parse(string)
if (string == nil) then
return 0
end
if (type(string) == "number") then
return string
end
if (string == "yes" or string == "true") then
return 1
end
if (string == "no" or string == "false") then
return 0
end
if (type(string) == "boolean") then
if (string) then
return 1
else
return 0
end
end
if(string:match("%d+:%d+")) then
-- duration in minute
local duration = 0
for part in string:gmatch "%d+" do
duration = duration * 60 + tonumber(part)
end
return duration
end
return tonumber(string)
end
to_string
| obj | returns |
|---|---|
| $a | string |
Converts a value into a human readable string
Lua implementation:
function to_string(o)
return o;
end
concat
| a | b | returns |
|---|---|---|
| string | string | string |
Concatenates two strings
Lua implementation:
function concat(a, b)
return a .. b
end
containedIn
| list | a | returns |
|---|---|---|
| list ($a) | $a | bool |
Given a list of values, checks if the argument is contained in the list.
Lua implementation:
function containedIn(list, a)
for _, value in pairs(list) do
if (value == a) then
return true
end
end
return false;
end
min
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | bool |
Out of a list of values, gets the smallest value. In case of a list of bools, this acts as and. Note that 'null'-values are ignored.
Lua implementation:
function min(list)
local min
for _, value in pairs(list) do
if(value ~= nil) then
if (min == nil) then
min = value
elseif (value < min) then
min = value
end
end
end
return min;
end
and
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | bool |
Out of a list of values, gets the smallest value. In case of a list of bools, this acts as and. Note that 'null'-values are ignored.
Lua implementation:
function min(list)
local min
for _, value in pairs(list) do
if(value ~= nil) then
if (min == nil) then
min = value
elseif (value < min) then
min = value
end
end
end
return min;
end
max
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | bool |
Returns the biggest value in the list. For a list of booleans, this acts as 'or'
Lua implementation:
function max(list)
local max
for _, value in pairs(list) do
if (value ~= nil) then
if (max == nil) then
max = value
elseif (max < value) then
max = value
end
end
end
return max;
end
or
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | bool |
Returns the biggest value in the list. For a list of booleans, this acts as 'or'
Lua implementation:
function max(list)
local max
for _, value in pairs(list) do
if (value ~= nil) then
if (max == nil) then
max = value
elseif (max < value) then
max = value
end
end
end
return max;
end
sum
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | int |
Sums all the numbers in the given list. If the list is a list of booleans, yes or true will be considered to equal 1. Null values are ignored (and thus handled as being 0)
Lua implementation:
function sum(list)
local sum = 0
for _, value in pairs(list) do
if(value ~= nil) then
if(value == 'yes' or value == 'true') then
value = 1
end
sum = sum + value
end
end
return sum;
end
plus
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | int |
Sums all the numbers in the given list. If the list is a list of booleans, yes or true will be considered to equal 1. Null values are ignored (and thus handled as being 0)
Lua implementation:
function sum(list)
local sum = 0
for _, value in pairs(list) do
if(value ~= nil) then
if(value == 'yes' or value == 'true') then
value = 1
end
sum = sum + value
end
end
return sum;
end
add
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | int |
Sums all the numbers in the given list. If the list is a list of booleans, yes or true will be considered to equal 1. Null values are ignored (and thus handled as being 0)
Lua implementation:
function sum(list)
local sum = 0
for _, value in pairs(list) do
if(value ~= nil) then
if(value == 'yes' or value == 'true') then
value = 1
end
sum = sum + value
end
end
return sum;
end
multiply
| list | returns |
|---|---|
| list (nat) | nat |
| list (int) | int |
| list (pdouble) | pdouble |
| list (double) | double |
| list (bool) | bool |
Multiplies all the values in a given list. On a list of booleans, this acts as 'and' or 'all', as false and no are interpreted as zero. Null values are ignored and thus considered to be one
Lua implementation:
function multiply(list)
local factor = 1
for _, value in pairs(list) do
if (value ~= nil) then
factor = factor * value
end
end
return factor;
end
atleast
| minimum | f | then | else | returns |
|---|---|---|---|---|
| double | $b -> double | $a | $a | $b |
Returns 'yes' if the second argument is bigger then the first argument. (Works great in combination with $dot)
Lua implementation:
function atleast(minimumExpected, actual, thn, els)
if (minimumExpected <= actual) then
return thn;
end
return els
end
firstMatchOf
| s | returns |
|---|---|
| list (string) | tags -> list ($a) |
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.
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.
Lua implementation:
function first_match_of(tags, result, order_of_keys, table)
for _, key in pairs(order_of_keys) do
local v = tags[key]
if (v ~= nil) then
local mapping = table[key]
if (type(mapping) == "table") then
local resultValue = mapping[v]
if (resultValue ~= nil) then
result.attributes_to_keep[key] = v
return resultValue
end
else
result.attributes_to_keep[key] = v
return mapping
end
end
end
return nil;
end
mustMatch
| neededKeys (filled in by parser) | f | returns |
|---|---|---|
| list (string) | tags -> list (string) | tags |
Checks that every specified key is present and gives a non-false value . 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:
--[[
must_match checks that a collection of tags matches a specification.
The function is not trivial and contains a few subtilities.
Consider the following source:
{"$mustMatch":{ "a":"X", "b":{"not":"Y"}}}
This is desugared into
{"$mustMatch":{ "a":{"$eq":"X"}, "b":{"not":"Y"}}}
When applied on the tags {"a" : "X"}, this yields the table {"a":"yes", "b":"yes} (as `notEq` "Y" "nil") yields "yes"..
MustMatch checks that every key in this last table yields yes - even if it is not in the original tags!
]]
function must_match(tags, result, needed_keys, table)
for _, key in ipairs(needed_keys) do
local v = table[key] -- use the table here, as a tag that must _not_ match might be 'nil' in the tags
if (v == nil) then
return false
end
local mapping = table[key]
if (type(mapping) == "table") then
local resultValue = mapping[v]
if (resultValue == nil or
resultValue == false or
resultValue == "no" or
resultValue == "false") then
return false
end
elseif (type(mapping) == "string") then
local bool = mapping
if (bool == "no" or bool == "0") then
return false
end
if (bool ~= "yes" and bool ~= "1") then
error("MustMatch got a string value it can't handle: " .. bool)
end
elseif (type(mapping) == "boolean") then
if(not mapping) then
return false
end
else
error("The mapping is not a table. This is not supported. We got " .. tostring(mapping) .. " (" .. type(mapping)..")")
end
end
-- Now that we know for sure that every key matches, we add them all
for _, key in ipairs(needed_keys) do
local v = tags[key] -- this is the only place where we use the original tags
if (v ~= nil) then
result.attributes_to_keep[key] = v
end
end
return true
end
memberOf
| f | tags | returns |
|---|---|---|
| tags -> bool | tags | bool |
This function returns true, if the way is member of a relation matching the specified function.
In order to use this for itinero 1.0, the membership must be the top level expression.
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:<aspect_name>="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:<profile_name>:<aspect_name>=yes'. The subfunction is thus executed countOr(relations) * countOf(profiles)time, yieldingcountOf(profiles)tags. The profile function then picks the tags for himself and strips the<profile_name>:` away from the key.
In the test.csv, one can simply use _relation:<aspect_name>=yes to mimic relations in your tests
Lua implementation:
function member_of(calledIn, parameters, tags, result)
local k = "_relation:" .. calledIn
-- This tag is conventiently setup by all the preprocessors, which take the parameters into account
local doesMatch = tags[k]
if (doesMatch == "yes") then
result.attributes_to_keep[k] = "yes"
return true
end
return false
end
if_then_else
| condition | then | else | returns |
|---|---|---|---|
| bool | $a | $a | $a |
| bool | $a | $a | |
| string | $a | $a | $a |
| string | $a | $a |
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.
Lua implementation:
function if_then_else(condition, thn, els)
if (condition ~= nil and (condition == "yes" or condition == true or condition == "true") then
return thn
else
return els -- if no third parameter is given, 'els' will be nil
end
end
if
| condition | then | else | returns |
|---|---|---|---|
| bool | $a | $a | $a |
| bool | $a | $a | |
| string | $a | $a | $a |
| string | $a | $a |
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.
Lua implementation:
function if_then_else(condition, thn, els)
if (condition ~= nil and (condition == "yes" or condition == true or condition == "true") then
return thn
else
return els -- if no third parameter is given, 'els' will be nil
end
end
if_then_else_dotted
| condition | then | else | returns |
|---|---|---|---|
| $b -> bool | $b -> $a | $b | $a |
| $b -> string | $b -> $a | $b | $a |
| $b -> bool | $b -> $a | $b -> $a | $b |
| $b -> string | $b -> $a | $b -> $a | $b |
An if_then_else, but one which takes an extra argument and applies it on the condition, then and else.
Consider fc, fthen and felse are all functions taking an a, then:
(ifDotted fc fthen felse) a === (if (fc a) (fthen a) (felse a)Selects either one of the branches, depending on the condition. The 'then' branch is returned if the condition returns the string yesortrueor the booleantrueIf the elsebranch is not set,null` is returned in the condition is false.In case the condition returns 'null', then the 'else'-branch is taken.
Lua implementation:
function applyIfNeeded(f, arg)
if(f == nil) then
return nil
end
if(type(f) == "function") then
return f(arg)
else
return f
end
end
function if_then_else_dotted(conditionf, thnf, elsef, arg)
local condition = applyIfNeeded(conditionf, arg);
if (condition) then
return applyIfNeeded(thnf, arg)
else
return applyIfNeeded(elsef, arg) -- if no third parameter is given, 'els' will be nil
end
end
ifdotted
| condition | then | else | returns |
|---|---|---|---|
| $b -> bool | $b -> $a | $b | $a |
| $b -> string | $b -> $a | $b | $a |
| $b -> bool | $b -> $a | $b -> $a | $b |
| $b -> string | $b -> $a | $b -> $a | $b |
An if_then_else, but one which takes an extra argument and applies it on the condition, then and else.
Consider fc, fthen and felse are all functions taking an a, then:
(ifDotted fc fthen felse) a === (if (fc a) (fthen a) (felse a)Selects either one of the branches, depending on the condition. The 'then' branch is returned if the condition returns the string yesortrueor the booleantrueIf the elsebranch is not set,null` is returned in the condition is false.In case the condition returns 'null', then the 'else'-branch is taken.
Lua implementation:
function applyIfNeeded(f, arg)
if(f == nil) then
return nil
end
if(type(f) == "function") then
return f(arg)
else
return f
end
end
function if_then_else_dotted(conditionf, thnf, elsef, arg)
local condition = applyIfNeeded(conditionf, arg);
if (condition) then
return applyIfNeeded(thnf, arg)
else
return applyIfNeeded(elsef, arg) -- if no third parameter is given, 'els' will be nil
end
end
ifDotted
| condition | then | else | returns |
|---|---|---|---|
| $b -> bool | $b -> $a | $b | $a |
| $b -> string | $b -> $a | $b | $a |
| $b -> bool | $b -> $a | $b -> $a | $b |
| $b -> string | $b -> $a | $b -> $a | $b |
An if_then_else, but one which takes an extra argument and applies it on the condition, then and else.
Consider fc, fthen and felse are all functions taking an a, then:
(ifDotted fc fthen felse) a === (if (fc a) (fthen a) (felse a)Selects either one of the branches, depending on the condition. The 'then' branch is returned if the condition returns the string yesortrueor the booleantrueIf the elsebranch is not set,null` is returned in the condition is false.In case the condition returns 'null', then the 'else'-branch is taken.
Lua implementation:
function applyIfNeeded(f, arg)
if(f == nil) then
return nil
end
if(type(f) == "function") then
return f(arg)
else
return f
end
end
function if_then_else_dotted(conditionf, thnf, elsef, arg)
local condition = applyIfNeeded(conditionf, arg);
if (condition) then
return applyIfNeeded(thnf, arg)
else
return applyIfNeeded(elsef, arg) -- if no third parameter is given, 'els' will be nil
end
end
id
| a | returns |
|---|---|
| $a | $a |
Returns the argument unchanged - the identity function. Seems useless at first sight, but useful in parsing
Lua implementation:
function id(v)
return v
end
firstArg
| a | b | returns |
|---|---|---|
| $a | $b | $a |
Small utility function, which takes two arguments a and b and returns a. Used extensively to insert freedom
Lua implementation:
function firstArg(a, b)
-- it turns out that 'const' is a reserved token in some lua implementations
return a
end
const
| a | b | returns |
|---|---|---|
| $a | $b | $a |
Small utility function, which takes two arguments a and b and returns a. Used extensively to insert freedom
Lua implementation:
function firstArg(a, b)
-- it turns out that 'const' is a reserved token in some lua implementations
return a
end
constRight
| a | b | returns |
|---|---|---|
| $a | $b | $b |
Small utility function, which takes two arguments a and b and returns b. Used extensively to insert freedom
Lua implementation:
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
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.
Lua implementation:
-- TODO
-- listDot
eitherFunc
| 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.
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:
stringToTags
| f | tags | returns |
|---|---|---|
| string -> string -> $a | tags | list ($a) |
stringToTags converts a function string -> string -> a into a function tags -> [a]. It is used internally to convert a hash of functions. stringToTags shouldn't be needed when implementing profiles.
Lua implementation:
print("ERROR: stringToTag is needed. This should not happen")
head
| ls | returns |
|---|---|
| list ($a) | $a |
| $b -> list ($a) | $b |
Select the first non-null value of a list; returns 'null' on empty list or on null
Lua implementation:
function head(ls)
if(ls == nil) then
return nil
end
for _, v in pairs(ls) do
if(v ~= nil) then
return v
end
end
return nil
end