Language reference
This document provides a reference guide for the Lead language syntax, operators, and language constructs. Use this guide to understand the core language features and their usage.
Types
Multiple types are available in the langauge. Those available to the user are listed below.
Numbers
Numeric literals represent integer.
Example: 42 or -23
Boolean
Boolean values are true or false. They are used for conditionals and logical expressions.
Example: true or false
Strings
Strings are quoted text values. They may contain escaped characters such as \" for a quote and \\ for a backslash. Strings are commonly used for path segments and textual data.
Strings may also contain sequence ${expr} containing a sub expression. Usually for embedding a variable. This is identical to concatenation of the parts using + operator.
Example: "hellorld" or "Hello ${name}!"
Objects
Objects are collections of named fields written with { key = value, ... }. They are used for structured data, function arguments, and configuration.
Example:
{
src = "src";
out = "build";
}
Lists
Lists are ordered collections written as [item1, item2, ...]. They hold a sequence of values of any type.
Items are separated with ,. Last element may have an optional trailing ,.
Example:
[
"a.c",
"b.c",
"c.c"
]
Paths
Paths represent filesystem locations and may refer to either files or directories. Paths are built from builtin values such as cwd and are manipulated with the / operator.
Example:
|{cwd, ...}|
let
src = cwd / "src" / "main.c";
in
src
Path locking
Paths are locked to a given directory, and can never traverse outside of the directory.
Failing example: srcdir / ".." will not work due to locking.
|{cwd, ...}|
let
srcdir = pb.lock (cwd / "src");
back = srcdir / "..";
in
back
Builds
Build objects are returned by internal pb.build represneting a build operation.
Build rules
Build rule objects are returned by internal pb.rule represneting a build rule.
Build rule placeholder object
A placeholder for a variable, available internally in the function defining a pb.rule.
Expressions structure
Following operators are available:
| Operator | Precedence | Description |
|---|---|---|
|matcher| expr |
1 | Function definition |
lhs -> rhs |
2 | Logical implication |
lhs || rhs |
3 | Logical or |
lhs && rhs |
4 | Logical and |
lhs == rhs |
5 | Equal |
lhs != rhs |
5 | Not equal |
lhs < rhs |
6 | Less than |
lhs <= rhs |
6 | Less than or equal |
lhs > rhs |
6 | Greater than |
lhs >= rhs |
6 | Greater than or equal |
lhs // rhs |
7 | Object update/merge |
!expr |
8 | Logical not |
lhs + rhs |
9 | Addition or string concatentation |
lhs - rhs |
9 | Subtraction |
lhs * rhs |
10 | Multiplication |
lhs / rhs |
10 | Division or path extension |
lhs ++ rhs |
11 | List concactenation |
lhs ? rhs |
12 | Has attribute |
-expr |
13 | Numeric negation |
func arg |
14 | Function call |
object.ident |
15 | attribute selection |
( func <- init .. list ) |
16 | list fold |
[ func <- iterable ] |
16 | list map |
{ func <- iterable } |
16 | object map |
Function defintion
A function is represented as |matchers| expr, where matcher is a list of zero or more matchers,
separated by space, providing input variables to the expression expr.
Matchers can be any matcher defined in the matcher chapter below.
No matchers in the list is equivalent to no function definition at all. Thus || expr is equal to expr
Multiple matchers is equal to multiple nested functions. Thus |a b| expr is equal to |a| |b| expr.
More information available in function chapter in the documentation.
Logical "and" and "or"
&& and || is evaluated lazy.
- Given
rhs && lhs, andrhsis false, thenlhsis not evaluated. - Given
rhs || lhs, andrhsis true, thenlhsis not evaluated.
List and object iteration
Lists and objects can be iterated over, using the map construct.
The map construct has two variants:
- generate a list:
[ func <- iterable ] - generate an object:
{ func <- iterable }
iterable can be either a list or object, and func is a function that
transform each element in iterable to an output element.
For lists, element is passed, or received directly. For objects, each element
is represented to func as a tuple of (key, value), both as argument and
return value.
This means four combinations:
| From | To | representation |
|---|---|---|
| List | List | [ |input_val| output_val <- input_list ] |
| List | Object | { |input_val| (output_key, output_value) <- source_list } |
| Object | List | [ |(input_key, input_val)| output_val <- input_object ] |
| Object | Object | { |(input_key, input_val)| (output_key, output_value) <- source_object } |