## 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: ````lua 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: ````lua 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: ````lua 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: ````lua function inv(n) return 1/n end ```` #### default defaultValue | f | returns | --- | --- | --- | $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 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: ````lua 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: ````lua function to_string(o) return o; end ```` #### concat a | b | returns | --- | --- | --- | string | string | string | Concatenates two strings Lua implementation: ````lua 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: ````lua 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: ````lua 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: ````lua 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: ````lua 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: ````lua 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: ````lua 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: ````lua 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: ````lua 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: ````lua 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 | $a | Returns 'yes' if the second argument is bigger then the first argument. (Works great in combination with $dot) Lua implementation: ````lua function atleast(minimumExpected, actual, thn, els) if (minimumExpected <= actual) then return thn; end return els end ```` #### firstMatchOf s | returns | --- | --- | list (string) | tags -> list ($a) | tags | $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: ````lua 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 | bool | 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: ````lua --[[ 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:="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 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: ````lua 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: ````lua 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 | $a | $b -> string | $b -> $a | $b -> $a | $b | $a | 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 `yes` or `true` or the boolean `true`If the `else` branch 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: ````lua 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 | $a | $b -> string | $b -> $a | $b -> $a | $b | $a | 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 `yes` or `true` or the boolean `true`If the `else` branch 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: ````lua 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 | $a | $b -> string | $b -> $a | $b -> $a | $b | $a | 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 `yes` or `true` or the boolean `true`If the `else` branch 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: ````lua 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: ````lua 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: ````lua 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: ````lua 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: ````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 Lua implementation: ````lua ```` #### 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: ````lua -- 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: ````lua ```` #### 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: ````lua print("ERROR: stringToTag is needed. This should not happen") ```` #### head ls | returns | --- | --- | list ($a) | $a | $b -> list ($a) | $b | $a | Select the first non-null value of a list; returns 'null' on empty list or on null Lua implementation: ````lua 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 ````