Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions language/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ The operator surface is small.
| Form | Meaning |
| ----------------- | --------------------------------------------------------------------------------------- |
| `expr.identifier` | Property access. Available on records, variant struct cases, `AnyAsset`, and `UtxoRef`. |
| `expr[expr]` | List indexing. The index expression must have type `Int`. |
| `expr[expr]` | Indexing. For a `List<T>` the index is any `Int` expression; for a `Tuple<...>` the index must be an integer literal in range, and the result type is that position's type. |
| `!expr` | Arithmetic negation. Applies to `Int`. |
| `a * b` | Multiplication. `Int * Int` multiplies integers; `AnyAsset * Int` (and `Int * AnyAsset`) scales asset quantities. |
| `a / b` | Integer division, truncating toward zero (`7 / 2` is `3`). `Int / Int` divides integers; `AnyAsset / Int` divides each asset quantity. Does not commute (`Int / AnyAsset` is invalid). Dividing by `0` is an error. |
Expand Down Expand Up @@ -115,17 +115,22 @@ MyRecord {

Fields written explicitly take precedence; remaining fields are taken from `source`.

### Lists and maps
### Lists, maps, and tuples

```tx3
[1, 2, 3] // List<Int>
[] // empty list — type from context

{1: "Value1", 2: "Value2"} // Map<Int, Bytes>

(1, 0xFF) // Tuple<Int, Bytes>
(1, 0xFF, true) // Tuple<Int, Bytes, Bool>
```

A `Map` literal must contain at least one entry; the first entry fixes the key and value types.

A tuple literal is two or more comma-separated expressions in parentheses, and its element types are taken positionally. `(e)` is grouping (not a one-tuple) and `()` is the unit value. Read an element back with a literal index — `pair[0]`, `pair[1]` — exactly like list indexing. See [Tuples](./types#tuples).

## Property access

Records and variant struct cases expose their named fields. `AnyAsset` and `UtxoRef` expose a fixed set of built-in properties:
Expand Down
31 changes: 30 additions & 1 deletion language/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,35 @@ type Datum {
}
```

### Tuples

`Tuple<T1, T2, ...>` is a fixed-arity, positionally-typed group of values. Unlike a `List`, each position can have a different type; unlike a record, the positions are unnamed. A tuple always has **two or more** elements.

```tx3
type Datum {
pair: Tuple<Int, Bytes>,
triple: Tuple<Int, Bytes, Bool>,
}
```

You build a tuple by writing two or more comma-separated expressions in parentheses; the element types are taken positionally:

```tx3
(42, 0xDEADBEEF) // Tuple<Int, Bytes>
(quantity, name, true) // Tuple<Int, Bytes, Bool>
```

`(e)` (a single parenthesized expression) is just grouping, and `()` is the unit value — neither is a tuple, which is why tuples start at two elements.

Read an element back by **positional index**, using the same bracket syntax as a list:

```tx3
pair[0] // the Int
pair[1] // the Bytes
```

The index must be an integer literal within range — a tuple cannot be indexed by a runtime value, since each position may have a different type, and an out-of-range index is a compile error.

## User-defined types

User-defined types are introduced with the `type` keyword. There are three shapes.
Expand Down Expand Up @@ -139,6 +168,6 @@ Cyclic aliases (`type A = B; type B = A;`) are rejected.

## Type equivalence

Two types are equivalent if they are the same primitive, the same `List<T>` (with equivalent `T`), the same `Map<K, V>` (with equivalent `K` and `V`), or refer to the same user-defined type after alias chasing.
Two types are equivalent if they are the same primitive, the same `List<T>` (with equivalent `T`), the same `Map<K, V>` (with equivalent `K` and `V`), the same `Tuple<...>` (same arity, with each position's type equivalent), or refer to the same user-defined type after alias chasing. Tuple equivalence is structural and order- and arity-sensitive: `Tuple<Int, Bytes>` and `Tuple<Bytes, Int>` are different types, and neither equals `Tuple<Int, Bytes, Bool>`.

There are no implicit conversions. `Int` does not silently turn into `Bytes`, and `Bytes` does not silently turn into `Address`, `UtxoRef`, or `AnyAsset`. Where a position expects a specific type, the expression must already have that type.