Purpose Author Language License

https://github.com/aiez/luk

luk is the .luk language: Lua plus fn, ^ for return, := locals, !=, and Python-style comprehensions. Blocks stay pure Lua (then/do/else/end), so any Lua is (almost) valid luk. One ~70-line module, luk.lua, does whole-source transpilation and installs a require() hook for .luk modules.

git clone https://github.com/aiez/luk && cd luk
./luk fft.luk                 # transpile + run, args pass through
./luk -d fft.luk > fft.lua    # dump generated Lua
make fft.lua                  # same, via Makefile

For the optimizer shipped with luk (fft.luk) see fft.md.

Sections: NAME | SYNOPSIS | LANGUAGE REFERENCE | PERFORMANCE | FILES | VIM SUPPORT | SEE ALSO | LICENSE | AUTHOR

Files: luk.lua | fft.luk | lib.luk | fft.lua | lib.lua | fft.md | luk.rc | luk.vim

NAME

luk - .luk-to-Lua transpiler (single-file, no deps)

SYNOPSIS

./luk FILE.luk [args...]     # transpile + run
./luk -d FILE.luk            # dump generated Lua
lua -e 'io.write(require"luk"(io.read"*a"))' <IN.luk >OUT.lua
-- or programmatically:
--   local lua_src = require("luk")(luk_src)

Requiring luk also installs a require() hook: require"xx" loads xx.luk if present (transpiled, with real error line numbers), else falls back to plain Lua. require"xx.luk" forces the .luk version.

LANGUAGE REFERENCE

Blocks are pure Lua: if c then ... else ... end, for ... do ... end, while ... do ... end. Everything below is whole-source token rewriting; strings and comments are hidden first, so sigils inside them are safe.

Keywords

fn                 -> function
!=                 -> ~=     (Lua's not-equal)

Return

^ EXPR             -> return EXPR

^ means return only at a statement start: start of line, or after ;, then, do, else, or a fn(...) parameter list. Infix exponentiation a^b is untouched.

double := fn(z) ^ z * 2 end
pick   := fn(b) if b then ^ "yes" else ^ "no" end end

Local declarations

NAME := EXPR       -> local NAME = EXPR
A, B := X, Y       -> local A, B = X, Y

Comprehensions (may span lines; no nesting)

[EXPR for V in ITER]              -- list
[EXPR for V in ITER if COND]
{K, V for K, V in ITER}           -- dict
{K, V for K, V in ITER if COND}

ITER auto-wrapping:

- 1 var, no "(" in ITER  -> ipairs(ITER)
- 2 vars, no "(" in ITER -> pairs(ITER)
- else passed through as-is

Limit: a dict comprehension's key expression must not contain a bare comma.

Misc

PERFORMANCE

Runtime, default mode (depth=4, 16 trees built):

file       rows    fft.py   fft.lua  fft.luk (transpile+run)
--------   -----   ------   ------   -----------------------
auto93     398     0.080s   0.038s   0.035s
SS-N      53663    9.18s    5.86s    6.15s

Lua 1.5x-2.5x faster than Python. Transpile is whole-source gsub, ~1ms for a 250-line file: negligible on any real workload.

FILES

luk.lua      .luk -> .lua transpiler + require() hook
luk          runner: transpile + run (./luk FILE.luk)
lib.luk      "battery" helpers (argmin, sum, csv, of, ...)
fft.luk      example: multi-objective regression tree
Makefile     rule:  %.lua: %.luk luk.lua
sandbox/     retired v0.1 indentation-based dialect (luk2)

VIM SUPPORT

syntax: luk.vim (Lua syntax + luk overlay)
shell with .luk-aware vi: make fsh (see luk.rc)

SEE ALSO

fft.md                   help page for the fft.lua app
https://github.com/aiez/fft       Python sibling project
https://github.com/aiez/optimiz   example CSVs
https://github.com/aiez/konfig    shared Makefile

LICENSE

MIT. (c) 2026 Tim Menzies.

AUTHOR

Tim Menzies <timm@ieee.org>

built by gistsite