# Tea quick reference

Tea is a statically typed scripting language that compiles to native code.
Read this before writing Tea, then look up unfamiliar APIs with `tea docs`.
The installed CLI's documentation describes its bundled version; the website
may describe a newer release. Each Tea code block below is a complete program
or test file.

## Bindings, strings, and control flow

Use `const` for bindings you do not reassign and `var` for mutable bindings.
Local types are inferred; an annotation uses `name: Type`. Use two-space
indentation. Keyword blocks close with `end`; struct, enum, and error
declarations use braces. Comments start with `#`. Statements need no semicolons.

Double quotes delimit ordinary strings. Backticks enable `${expression}`
interpolation. Output uses the built-in `@println` or `@print`.

```tea
const name = "Tea"
var count: Int = 0

while count < 2
  @println(`Hello, ${name}!`)
  count = count + 1
end

if count == 2
  @println("done")
else
  @println("unexpected")
end

const label = if(count > 0) "positive" else "zero"
@println(label)
```

Boolean operators are `&&`, `||`, and `!`; equality uses `==` and `!=`.
Use `for item in collection` to iterate. Use `match` with `case` arms for
pattern matching; `_` is the fallback pattern.

## Functions and types

Write functions with `def`, typed parameters, and `-> ReturnType`. Use `Void`
when no value is returned. `return` exits early; a final expression can supply
the return value. Common types are `Int`, `Float`, `Bool`, `String`,
`List[T]`, `Dict[K, V]`, and `T?` for optional values.

Lambdas use `|parameters| => expression`; function types use
`Func(ParameterTypes) -> ReturnType`.

```tea
def add(left: Int, right: Int) -> Int
  return left + right
end

def make_adder(base: Int) -> Func(Int) -> Int
  return |value: Int| => base + value
end

const add_two = make_adder(2)
@println(add(2, 3))
@println(add_two(5))
```

The compiler reports unused local bindings as errors. Use the values you
declare, and follow the compiler's diagnostics when correcting generated code.

## Collections

Lists use square brackets and hold one element type. Dictionaries use
`{key: value}` entries. Index with brackets; list indexing starts at zero.
Use `@len` for length and `@append` to append to a mutable list. Standard-library
helpers are module functions: look up their signatures instead of guessing
methods from another language.

```tea
var names = ["Ada", "Grace"]
@append(names, "Linus")

for name in names
  @println(name)
end

@println(names[0])
@println(@len(names))

const scores = {"Ada": 10, "Grace": 8}
for name, score in scores
  @println(`${name}: ${score}`)
end
```

## Structs, generics, and enums

Struct fields have explicit types. Construct a struct with named fields and
access them with dots. Generic parameters and explicit type arguments use
square brackets, including on functions. Enums declare named variants.

```tea
struct Box[T] {
  value: T
}

def identity[T](value: T) -> T
  return value
end

enum Color {
  Red
  Green
}

const boxed = Box[String](value: identity[String]("tea"))
@println(boxed.value)

const color = Color.Green
const label = match color
  case Color.Red => "red"
  case Color.Green => "green"
end
@println(label)
```

## Optional values

`nil` represents an absent value. `T?` allows either a `T` or `nil`.
Use `??` to supply a fallback. Postfix `!` unwraps an optional; only unwrap
when you know a value is present.

```tea
const nickname: String? = nil
@println(nickname ?? "guest")

const loaded: String? = "ready"
if loaded != nil
  @println(loaded!)
end
```

## Errors

Declare recoverable failures with `error` and named variants. A function's
signature advertises thrown errors after `!`. Use `throw` to raise a variant.
Recover with `try expression catch err` and `case is Error.Variant` arms.
Fields carried by a matched error are accessible on `err`.

```tea
error InputError {
  Empty(message: String)
}

def require_name(name: String) -> String ! InputError.Empty
  if name == ""
    throw InputError.Empty("name required")
  end
  return name
end

const name = try require_name("") catch err
  case is InputError.Empty
    @println(err.message)
    "guest"
end
@println(name)
```

## Modules and standard library

Import with `use alias from "module"`. Standard-library module names start
with `std.`. Call exported functions through the alias. Prefix declarations
with `pub` to export them. For local files, use a relative path such as
`use helpers from "./helpers.tea"`, resolved relative to the importing file.

```tea
use string from "std.string"

const parts = string.split("tea,chai", ",")
@println(parts[0])
@println(@len(parts))
```

Discover APIs using `tea docs std.string`, or request a single function with
`tea docs std.string.split`. `tea docs builtins` lists global `@` functions;
`tea docs @println` looks up one. Search names, signatures, and summaries with
`tea docs --search "command-line"`. Reference examples may be fragments that
need the displayed module import or additional setup.

## Tests and workflow

Put named `test` blocks in ordinary `.tea` files and import `std.assert`.
The default test directory is `tests/`; pass a path to test a different file
or directory.

```tea
use assert from "std.assert"

def double(value: Int) -> Int
  return value * 2
end

test "double multiplies by two"
  assert.eq(double(3), 6)
  assert.ok(double(0) == 0)
end
```

Run a script with `tea main.tea`; arguments after the file go to the script.
Build a native executable with `tea build main.tea` (default output:
`bin/main`). Format with `tea fmt main.tea` or check formatting with
`tea fmt main.tea --check`. Run tests with `tea test`, `tea test tests/`,
or `tea test example.tea`.

When editing Tea: look up unfamiliar APIs, write the smallest useful change,
format it, then run the relevant program and tests. Treat compiler errors
as feedback about actual Tea syntax and types rather than guessing from
similar languages. Consult `tea --help` and command-specific `--help` for
available options.
