Syntax
The following listing shows the concrete syntax of Plutus. The corresponding Haskell definition can be found in UntypedPlutusCore.Core.Type.
πΏ, π, π β Term ::= π₯ variable
| (con T π) constant π with type T
| (builtin π) built-in
| (lam π₯ π) lambda abstraction
| [π π] application
| (delay π) delayed execution of a term
| (force π) force execution of a term
| (constr π πβ β¦ πβ) constructor with tag π and π arguments (π β₯ 0).
Available since 1.1.0
| (case π πβ β¦ πβ) case analysis with π alternatives (π β₯ 0).
Available since 1.1.0
| (error) error
π β Program ::= (program π£ π) versioned program
Plutus (Untyped Plutus Core) is untyped in the sense that variables donβt have type tags. Constants, however, do carry type tags. A constant must be of a built-in type. Built-in types and functions are listed in Built-in Types and Functions.
Version Numbers
The π£ in a program is the Plutus Core language version, in the form of x.y.z
.
This is distinct from the Plutus ledger language version.
For a detailed explanation, see Different Notions of Version.
Iterated Applications
An application of a term π to a term π is represented by [π π]
.
We may occasionally write [π πβ β¦ πβ]
or [π π]
as an abbreviation for an iterated application [ β¦ [[π πβ] πβ] β¦ πβ]
.
Constructor Tags
Constructor tags can in principle be any natural number.
In practice, since they cannot be dynamically constructed, we can limit them to a fixed size without having to worry about overflow.
So we limit them to 64 bits, although this is currently only enforced in the binary format.
The Haskell definition uses Word64
for the tag.
de Bruijn Indices
Variable π₯
in the above listing can be either textual strings or de Bruijn indices.
De Bruijn indices are used in serialized scripts.
It therefore makes the most sense for a CEK machine implementation to use de Bruijn indices.
When using de Bruijn indices, the binder π₯
in (lam π₯ π)
is irrelevant, and any number can be used.
0 is a good choice since it is not a valid de Bruijn index.