# U Language Grammar Reference
# Version 1.0 — July 2026
#
# This file defines the grammar consumed by:
#   - The u2c compiler (compiler/u2c/tokenizer.py + parser.py)
#   - The TextMate grammar (u.tmLanguage.json)
#   - The VS Code extension
#   - The JetBrains plugin
#   - The browser playground (site/assets/udoc.js)

## 1. Keywords (13 single-letter + contextual)

# Single-letter keywords — each is a leading token, never a variable name.
# Single-letter identifiers are reserved; variable names must be ≥2 chars.

a    # async — marks a function as a fiber (async execution)
c    # copy — prefix operator: c expr (value copy), c+R expr (heap copy)
d    # data type — declares a class/struct: d Name : Parent
e    # event — e(obj).emit(val), e(obj).on(handler)
f    # function — f name(params) -> ReturnType ! ErrorType
o    # open — module import: o "path", o Name from "path"
r    # return — r => expr
t    # this — self-reference in methods: t.field
u    # you / AI-managed — u f name(...) marks LLM-generated function
w    # wield / infinity — the value ∞ (loop bound, range end)
x    # exception — x ErrorType(...) throws, x.on(handler) catches
z    # zero-cost / compile-time — z f name(...) evaluates at compile time

# Contextual: `u` is only a keyword when followed by `f` at the start
# of a declaration. `u` as a variable name requires ≥2 chars anyway.

## 2. Built-in constants

none    # the absence of a value (null)
true    # boolean true
false   # boolean false

## 3. Scalar types (single-letter + width variants)

I       # integer (platform-width, default 64-bit)
N       # number (IEEE 754 double)
S       # string (UTF-8, immutable)
L       # logical (boolean)
B       # byte (unsigned 8-bit)
D       # date (ISO 8601 timestamp)
Q       # quotient (exact rational — arXiv:2607.22612)

# Width variants
I8  I16  I32  I64    # signed integers
U8  U16  U32  U64    # unsigned integers
N32  N64             # IEEE 754 float/double

## 4. Modifiers (position-dependent defaults)

+M    # mutable          (default: -M, parameters are read-only)
+E    # effectful        (default: -E, functions are pure)
+D    # nondeterministic (default: -D, functions are deterministic)
+R    # heap-allocated   (default: -R, values are stack/inline)
+N    # nullable         (default: -N, values are non-null)
+A    # async            (default: -A, functions are synchronous)
+V    # vectorizable     (default: -V, no SIMD constraint)
+G    # global/static    (default: -G, functions are instance)

## 5. Operators

# Arithmetic
+  -  *  /  %

# Comparison (return L)
==  !=  <  >  <=  >=

# Logical
&   # and
|   # or
!   # not (prefix), also error declaration (f name() -> T ! Error)

# Assignment
=

# Special
=>   # return arrow: r => expr
->   # type arrow: f name() -> ReturnType
<<   # MVCC patch: obj << { field: value }
>>   # (reserved)
::   # type narrowing: val :: Type
..   # range: [start..end], [start..w]
?    # guard: condition ? action
.    # member access: obj.field, obj.method()

# Collection
[]   # indexing: arr[i], also array type: [I]
{}   # object literal: { key: value }
()   # grouping, params, call args

## 6. Comments

//   # line comment — to end of line
///  # doc comment — parsed by UDoc, used as LLM intent for u f

# Structured doc tags (for u f functions):
/// @intent      # what the function should accomplish
/// @constraint  # invariants the body must maintain
/// @perf        # performance requirements
/// @example     # input/output examples
/// @security    # security-sensitive requirements
/// @generated   # (in .gen.u) metadata header

## 7. String literals

"hello"              # plain string
"name is ${name}"    # interpolation with ${}
`SELECT * FROM ${t}` # SQL template (backtick) — parameterized

## 8. Numeric literals

42       # integer
3.14     # float
0xFF     # hex integer
0b1010   # binary integer

## 9. Indentation

# U uses tab indentation (like Python uses spaces).
# One tab = one nesting level. No braces.
# The parser expects exactly one tab per level.

## 10. Declaration forms

# Function
f name(param: Type, param: Type +M) -> ReturnType ! ErrorType
	body

# Async function
a f name() -> Type
	body

# Compile-time function
z f name() -> Type
	body

# AI-managed function
u f name() -> Type
	...  # body generated by LLM

# Data type (class)
d ClassName : ParentClass
	field: Type
	field: Type +M +R

# Module import
o "relative/path"
o ClassName from "path"

## 11. Control flow

# Guard (ternary — condition ? action)
val < 0 ? x TooSmall()
val < 0 ? r => 0

# Iteration
items.on(val => process(val))
items.map(val => val * 2)
items.filter(val => val > 0)
items.reduce((acc, val) => acc + val, 0)

# Transaction block
<< (
	target1 << { field: value }
	target2 << { field: value }
)

# Range
[1..100]     # finite
[0..w]       # infinite (w = infinity)

## 12. Error handling

# Throw
x ErrorType({ field: value })

# Catch (subscribe to errors)
x.on((err: ErrorType) => handle(err))

## 13. Event system

# Emit
e(obj).emit(EventType({ field: value }))

# Subscribe
e(obj).on(handler, { owner: t })

## 14. Copy and type check

# Copy
c expr        # stack copy
c+R expr      # heap copy

# Type narrowing
val :: Type   # narrows val to Type in scope
