std/expression/lib
std/expression/src/lib.trb
Quoted expressions: Expression, the typed tree a quoted parameter hands over, and ExpressionNode, the plain
data anyone can build, match and transform. assert and nameOf are what most callers reach for; a provider
that renders its own explanation of a captured expression works with ExpressionNode directly.
type Expression
native type Expression<Value>
The typed tree behind a quoted parameter: Expression<Value> type checks its argument as an ordinary Value and
hands it over together with the expression tree that produced it.
A caller writes nothing special for this - passing an ordinary Value where a parameter is declared
Expression<Value> is enough. Only the compiler creates one; ExpressionNode is the data an ordinary function
can build as well.
Related
assert- the one function most callers need anExpression<Bool>for.
field tree
tree: ExpressionNode
Static data, created at compile time.
field source
source: String
The source text of the quoted expression: "_.age >= minAge"
field location
location: SourceLocation
Where the quoted expression starts in its file.
fn value
native fn value(): Value
The ordinary value (for function types: the closure). Evaluated at most once.
fn captures
native fn captures(): List<EncodedValue>
The values of the captured variables, in the order of their Captured.index.
type SourceLocation
type SourceLocation with Show
A place in a source file: what Expression.location and a diagnostic point at.
type TypeReference
type TypeReference with Show
A description of a type. Data, not reflection: there is no way back from a TypeReference to a type.
type UnaryOperator
type UnaryOperator
The prefix operators a quoted expression can carry, one case per operator.
type BinaryOperator
type BinaryOperator
The infix operators a quoted expression can carry, one case per operator.
case Add
case Add
+.
case Subtract
case Subtract
-.
case Multiply
case Multiply
*.
case Divide
case Divide
/.
case Remainder
case Remainder
%.
case Power
case Power
**.
case BitwiseAnd
case BitwiseAnd
&.
case BitwiseOr
case BitwiseOr
|.
case BitwiseExclusiveOr
case BitwiseExclusiveOr
^.
case ShiftLeft
case ShiftLeft
<<.
case ShiftRight
case ShiftRight
>>.
case Equal
case Equal
==.
case NotEqual
case NotEqual
!=.
case Less
case Less
<.
case LessOrEqual
case LessOrEqual
<=.
case Greater
case Greater
>.
case GreaterOrEqual
case GreaterOrEqual
>=.
case And
case And
&&.
case Or
case Or
||.
type ExpressionNode
type ExpressionNode
Names are already resolved and everything is typed: implicit _, named closure parameters, receivers and
implicit self show up as explicit Parameter, Field and Call nodes.
An ordinary ADT. New node kinds come with new versions of the language; providers end their match with
_ => Fail(Unsupported(...)) anyway, because they need that arm for calls they do not know.
case Literal
case Literal(value: EncodedValue, of: TypeReference)
A literal value written in the source.
case Parameter
case Parameter(index: Int, name: String, of: TypeReference)
An explicit parameter of the quoted closure, or its implicit _.
case Captured
case Captured(index: Int, name: String, of: TypeReference)
A binding from outside the quoted expression, captured by value.
case Field
case Field(target: ExpressionNode, name: String, of: TypeReference)
A field read off target, or a receiver method turned into a field access.
case Call
case Call(target: ExpressionNode?, owner: TypeReference, method: String, arguments: List<ExpressionNode>, of: TypeReference)
A method call on target, or a free function call when target is None.
case Construct
case Construct(arguments: List<ExpressionNode>, of: TypeReference)
A constructor call for the type of.
case Unary
case Unary(operator: UnaryOperator, operand: ExpressionNode, of: TypeReference)
A prefix operator applied to operand.
case Binary
case Binary(operator: BinaryOperator, left: ExpressionNode, right: ExpressionNode, of: TypeReference)
An infix operator applied to left and right.
case Conditional
case Conditional(condition: ExpressionNode, then: ExpressionNode, otherwise: ExpressionNode, of: TypeReference)
An if/else expression.
case Lambda
case Lambda(parameters: List<String>, body: ExpressionNode, of: TypeReference)
A closure literal, with its parameter names and its body.
case Items
case Items(items: List<ExpressionNode>, of: TypeReference)
A list or tuple literal.
case Interpolation
case Interpolation(parts: List<ExpressionNode>)
"{a} and {b}": literals and expressions in order. ?. and ?? have no nodes, they are calls on Option.
fn capturedNodes
fn capturedNodes(): List<ExpressionNode>
All Captured nodes below this node, e.g. to explain a failed assertion.
fn nameOf
fn nameOf<Value>(expression: Expression<Value>): String
The name of what was written, never its value: nameOf(user.email) is "email", nameOf(limit) is "limit".
For a type there is the compile-time function typeName<User>() instead.
Examples
fn label(value: Expression<Int>): String {
nameOf value
}
const limit = 5
print label(limit)
fn assert
fn assert(condition: Expression<Bool>)
Panics if condition is false. There are no matchers: the message names the source text of the condition and
every value the condition read from around it, one per line, and then the site:
panic: Assertion failed: count < limit
count = the Int 7
limit = the Int 5
at acme/app/src/main.trb:12:1
A scalar - every integer type, every float, Bool, Char and String - is shown as the <kind> <value>,
where the word is the language's name for the kind of value and not the name of its type, so Int for an Int64
and Float for a Float64. Everything else is shown by its name and its type, found: Point: a value of the
program shown in full needs the whole Show machinery of its type and of every type under it in the binary, and
one type that has none would refuse the whole build. Until a capture carries its own encoded value, that is the
one thing the two implementations word differently - the interpreter writes a value of type List where a
compiled binary writes the name and the type.
Examples
const limit = 5
const count = 7
assert(count < limit)
Panics
When condition is false.