neyuki 0.1.1

A small Lua-like scripting language implemented in Rust
# Neyuki language reference


## Declarations


Use `local`, `const`, or `global` to introduce a binding. Type annotations are optional and are currently retained as syntax metadata.

```lua
local count: int = 0
const greeting = "hello"
global shared = nil
```

Const bindings cannot be reassigned. A `const function` also protects the
declared function field, while the containing table remains mutable:

```lua
local math = {}
const function math.exp(n: number): number
    return n
end

math.exp = 2 -- runtime error
```

Multiple local bindings are supported:

```lua
local ok, value = try(int, "12")
```

## Values and tables


Neyuki supports `nil`, booleans, arbitrary-precision integers, floating-point numbers, strings, functions, and tables. Array entries are one-based; named entries use `key = value`, or `["key"] = value` when the key is not a valid name (such as `content-type`).

Integer literals may be decimal, hexadecimal (`0x...`), or binary (`0b...`), and may contain `_` separators. Integer arithmetic remains exact; `/` produces a floating-point result, while `//`, `%`, and bitwise operators preserve integer values.

```lua
local values = {10, 20, 30}
local config = {name = "neyuki", enabled = true}
local headers = {["content-type"] = "text/plain"}
values[2] = 25
print(config.name)
```

## Functions and varargs


Functions may have typed parameters and return annotations. A final `...` parameter collects every argument after the required parameters. Its optional type annotation describes each collected value.

```lua
function maximum(first: number, ...: number): number
    local values = {first, ...}
    local result = values[1]
    for _, value in values do
        if value > result then
            result = value
        end
    end
    return result
end

print(maximum(3, 8, 5))
```

Inside a variadic function, `...` can be used as a table entry or as a call argument list. It is an error to evaluate it outside a variadic function.

`object:name(args)` calls the function stored in `object.name` with `object` passed as the first argument. It is shorthand for `object.name(object, args)` and is how the file objects from `@neyuki/fs` are used.

```lua
local file = fs.open("notes.txt")
print(file:read())
```

## Operators


Arithmetic operators are `+`, `-`, `*`, `/`, `//`, `%`, and `^`. Comparisons are `==`, `!=`, `<`, `<=`, `>`, and `>=`; tables and functions compare by identity, so a table is equal only to itself. Boolean operators are `and`, `or`, and `not`; `??` selects its right side only when the left side is `nil`. `..` concatenates strings and `#` returns string or array length.

Bitwise operators include `&`, `|`, `~`, `<<`, and `>>`. `>>` is an arithmetic shift, so it keeps the sign of negative numbers. The logical shifts `<<<` and `>>>` treat the left operand as an unsigned 64-bit word: bits shifted past the 64th are dropped, zeros are shifted in, and the result is never negative.

```lua
print(-8 >> 1)      -- -4
print(-1 >>> 60)    -- 15
print(1 <<< 63)     -- 9223372036854775808
print(1 <<< 64)     -- 0
```

Increment and decrement are statement operators for assignable targets:

```lua
count++
values[1]--
```

They add or subtract one and do not produce an expression value. `--` at the start of a line or after whitespace remains a line comment.

Compound assignment rewrites `target op= value` as `target = target op value` for `+=`, `-=`, `*=`, `/=`, `//=`, `%=`, `^=`, `..=`, `<<=`, `>>=`, `&=`, `|=` and `??=`. Several targets can be assigned at once; the right-hand side is evaluated before any target changes, and a call's extra results spread across the remaining targets:

```lua
total += price
a, b = b, a
x, y, z = pair()
```

## Control flow


Neyuki supports `if` / `elseif` / `else`, `while`, `repeat ... until`, and table iteration with `for`:

```lua
for index, value in values do
    print(index, value)
end
```

Conditions must evaluate to booleans. `break` and `continue` control loops.

## Strings


Single-quoted, double-quoted, and long-bracket strings are supported. Backtick-style interpolation evaluates expressions inside braces:

```lua
print(`value: {count}`)
```