{"id":19237982,"url":"https://github.com/audulus/lyte","last_synced_at":"2026-04-17T03:06:09.920Z","repository":{"id":39513390,"uuid":"355760069","full_name":"audulus/lyte","owner":"audulus","description":"A programming language for Audulus nodes","archived":false,"fork":false,"pushed_at":"2026-03-06T00:07:52.000Z","size":979,"stargazers_count":38,"open_issues_count":3,"forks_count":1,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-03-06T01:50:48.085Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/audulus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-04-08T04:11:46.000Z","updated_at":"2026-03-06T00:07:55.000Z","dependencies_parsed_at":"2026-03-06T00:30:29.037Z","dependency_job_id":null,"html_url":"https://github.com/audulus/lyte","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/audulus/lyte","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audulus%2Flyte","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audulus%2Flyte/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audulus%2Flyte/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audulus%2Flyte/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/audulus","download_url":"https://codeload.github.com/audulus/lyte/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/audulus%2Flyte/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30204729,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T19:07:06.838Z","status":"ssl_error","status_checked_at":"2026-03-06T18:57:34.882Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T16:28:54.938Z","updated_at":"2026-04-03T00:33:04.645Z","avatar_url":"https://github.com/audulus.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lyte\n\n![build status](https://github.com/audulus/lyte/actions/workflows/rust.yml/badge.svg)\n[![dependency status](https://deps.rs/repo/github/audulus/lyte/status.svg)](https://deps.rs/repo/github/audulus/lyte)\n\nLyte is a simple, statically-typed programming language designed for writing [Audulus](https://audulus.com) nodes. It compiles to native code via Cranelift or LLVM, with a VM backend for environments where JIT isn't available (iOS).\n\n## Goals\n\n- Familiar syntax (a mix of Rust and Swift)\n- Function and operator overloading\n- Generics constrained by interfaces\n- Type inference\n- No GC — no recursive data structures, no heap allocation\n- Memory safety with static bounds checking\n- Cranelift and LLVM JIT backends\n- VM backend for sandboxed environments (iOS)\n- Safe cancellation of long-running programs\n\n## Quick Start\n\n```bash\n# Build\ncargo build\n\n# Run a file with JIT\ncargo run --bin lyte hello.lyte -c\n\n# Run a file with VM\ncargo run --bin lyte hello.lyte -r\n\n# Run all tests\ncargo test --workspace\n```\n\n### LLVM JIT Backend (Optional)\n\nLyte includes an optional LLVM JIT backend alongside the default Cranelift backend. To use it, you need LLVM 18 installed:\n\n```bash\n# macOS (Homebrew)\nbrew install llvm@18\n\n# Build with LLVM support (requires the \"llvm\" feature)\nLLVM_SYS_180_PREFIX=/opt/homebrew/opt/llvm@18 LIBRARY_PATH=\"/opt/homebrew/lib:$LIBRARY_PATH\" \\\n  cargo build --features llvm\n\n# Run a file with the LLVM backend\nLLVM_SYS_180_PREFIX=/opt/homebrew/opt/llvm@18 LIBRARY_PATH=\"/opt/homebrew/lib:$LIBRARY_PATH\" \\\n  cargo run -p lyte-cli --features llvm -- hello.lyte -l\n```\n\nOn Linux, install LLVM 18 via your package manager (e.g. `apt install llvm-18-dev libzstd-dev`) and set `LLVM_SYS_180_PREFIX` to the install prefix (e.g. `/usr/lib/llvm-18`).\n\n## Language Tour\n\n### Hello World\n\n```rust\nmain {\n    println(\"hello world\")\n}\n```\n\n### Variables and Control Flow\n\n```rust\nmain {\n    var x = 42\n    let y = x + 1    // immutable binding\n\n    if x \u003e 0 {\n        println(\"positive\")\n    } else {\n        println(\"non-positive\")\n    }\n\n    var sum = 0\n    for i in 0 .. 10 {\n        sum = sum + i\n    }\n}\n```\n\n### Functions\n\nFunctions support type annotations, overloading, and implicit returns (the last expression is the return value).\n\n```rust\nadd(a: i32, b: i32) -\u003e i32 {\n    a + b\n}\n\nadd(a: f32, b: f32) -\u003e f32 {\n    a + b\n}\n\nfact(x: i32) -\u003e i32 {\n    if x == 1 { return 1 }\n    x * fact(x - 1)\n}\n\nmain {\n    assert(add(2, 3) == 5)\n    assert(add(1.0, 2.0) == 3.0)\n    assert(fact(5) == 120)\n}\n```\n\n### Structs\n\n```rust\nstruct Point {\n    x: f32,\n    y: f32\n}\n\nlength(p: Point) -\u003e f32 {\n    sqrt(p.x * p.x + p.y * p.y)\n}\n\nmain {\n    var p: Point\n    p.x = 3.0\n    p.y = 4.0\n    assert(length(p) == 5.0)\n}\n```\n\n### Operator Overloading\n\nDefine `__add`, `__sub`, `__mul`, etc. for custom types:\n\n```rust\n__add(lhs: Point, rhs: Point) -\u003e Point {\n    var p: Point\n    p.x = lhs.x + rhs.x\n    p.y = lhs.y + rhs.y\n    p\n}\n\n__mul(lhs: Point, rhs: f32) -\u003e Point {\n    var p: Point\n    p.x = lhs.x * rhs\n    p.y = lhs.y * rhs\n    p\n}\n```\n\n### Enums\n\n```rust\nenum Direction { Up, Down, Left, Right }\n\nis_vertical(d: Direction) -\u003e bool {\n    (d == .Up) || (d == .Down)\n}\n\nmain {\n    var d = Direction.Up\n    assert(is_vertical(d))\n    assert(!is_vertical(.Left))\n}\n```\n\n### Arrays\n\nFixed-size arrays with static bounds checking:\n\n```rust\nmain {\n    var a = [1, 2, 3, 4, 5]\n    assert(a[0] == 1)\n    assert(a.len == 5)\n\n    var grid: [f32; 64]\n    for i in 0 .. 64 {\n        grid[i] = 0.0\n    }\n}\n```\n\n### Tuples\n\n```rust\nmain {\n    var pair = (1, 2)\n    assert(pair.0 == 1)\n    assert(pair.1 == 2)\n}\n```\n\n### Slices\n\nSlices are dynamically-sized views into arrays, passed by reference:\n\n```rust\nsum(a: [i32]) -\u003e i32 {\n    var s = 0\n    for i in 0 .. a.len {\n        s = s + a[i]\n    }\n    s\n}\n\nmain {\n    assert(sum([1, 2, 3]) == 6)\n\n    var data = [10, 20, 30, 40, 50]\n    assert(sum(data) == 150)\n}\n```\n\n### Lambdas and Closures\n\n```rust\napply(x: i32, f: i32 -\u003e i32) -\u003e i32 {\n    f(x)\n}\n\nmain {\n    var f = |x| x * 2\n    assert(f(3) == 6)\n\n    assert(apply(5, |x| x + 1) == 6)\n\n    // closures capture variables by reference\n    var count = 0\n    var inc = || count = count + 1\n    inc()\n    inc()\n    assert(count == 2)\n}\n```\n\n### Generics\n\nGeneric functions infer type parameters from arguments:\n\n```rust\nid\u003cT\u003e(x: T) -\u003e T { x }\n\nmap\u003cT0, T1, N\u003e(a: [T0; N], f: T0 -\u003e T1) -\u003e [T1; N] {\n    var i = 0\n    var b: [T1; N]\n    while i \u003c a.len {\n        b[i] = f(a[i])\n        i = i + 1\n    }\n    b\n}\n\nmain {\n    assert(id(42) == 42)\n    assert(id(\"hello\") == \"hello\")\n    assert(map([1, 2, 3], |x| x + 1) == [2, 3, 4])\n}\n```\n\n### Generic Structs\n\n```rust\nstruct Pair\u003cA, B\u003e {\n    first: A,\n    second: B\n}\n\nmain {\n    var p: Pair\u003ci32, f32\u003e\n    p.first = 1\n    p.second = 2.0\n}\n```\n\n### Interfaces\n\nInterfaces constrain generics and enable static dispatch:\n\n```rust\ninterface Compare\u003cA\u003e {\n    cmp(lhs: A, rhs: A) -\u003e i32\n}\n\nsort\u003cT, N\u003e(array: [T; N]) -\u003e [T; N] where Compare\u003cT\u003e {\n    var a = array\n    var i = 0\n    while i \u003c a.len {\n        var j = 0\n        while j \u003c a.len - 1 - i {\n            if cmp(a[j], a[j + 1]) \u003e 0 {\n                var tmp = a[j]\n                a[j] = a[j + 1]\n                a[j + 1] = tmp\n            }\n            j = j + 1\n        }\n        i = i + 1\n    }\n    a\n}\n\n// Implement Compare for i32\ncmp(lhs: i32, rhs: i32) -\u003e i32 { lhs - rhs }\n\nmain {\n    assert(sort([3, 1, 2]) == [1, 2, 3])\n}\n```\n\n### A Real-World Example: Biquad Filter\n\n```rust\nstruct Biquad {\n    b0: f32, b1: f32, b2: f32,\n    a1: f32, a2: f32,\n    x1: f32, x2: f32,\n    y1: f32, y2: f32\n}\n\nlpf(fc: f32, fs: f32, q: f32) -\u003e Biquad {\n    var w0 = 2.0 * 3.14159265 * fc / fs\n    var alpha = sin(w0) / (2.0 * q)\n    var cs = cos(w0)\n    var a0 = 1.0 + alpha\n    var inv = 1.0 / a0\n\n    var bq: Biquad\n    bq.b1 = (1.0 - cs) * inv\n    bq.b0 = bq.b1 / 2.0\n    bq.b2 = bq.b0\n    bq.a1 = (0.0 - 2.0 * cs) * inv\n    bq.a2 = (1.0 - alpha) * inv\n    return bq\n}\n\nprocess(bq: Biquad, x: f32) -\u003e (Biquad, f32) {\n    var y = bq.b0*x + bq.b1*bq.x1 + bq.b2*bq.x2\n              - bq.a1*bq.y1 - bq.a2*bq.y2\n    bq.x2 = bq.x1\n    bq.x1 = x\n    bq.y2 = bq.y1\n    bq.y1 = y\n    (bq, y)\n}\n```\n\n## Language Server\n\nLyte includes an LSP server (`lyte-lsp`) that provides IDE features for any editor that supports the Language Server Protocol.\n\n### Features\n\n- **Diagnostics** — parse errors, type errors, and safety warnings as you type\n- **Hover** — show inferred types for expressions and variables\n- **Go to Definition** — jump to function and struct field definitions\n\n### Building\n\n```bash\ncargo build -p lyte-lsp\n```\n\nThe binary is at `target/debug/lyte-lsp` (or `target/release/lyte-lsp` with `--release`).\n\n### VS Code\n\nA VS Code extension is included in `vscode-lyte/`. To install it locally:\n\n```bash\ncd vscode-lyte\nnpm install\ncode --install-extension .\n```\n\nThe extension activates on `.lyte` files and starts the language server automatically. Set `lyte.lspPath` in VS Code settings if the `lyte-lsp` binary isn't on your `PATH`.\n\n### Other Editors\n\nPoint your editor's LSP client at the `lyte-lsp` binary. It communicates over stdin/stdout using the standard LSP protocol. For example, in Neovim with `nvim-lspconfig`:\n\n```lua\nvim.lsp.start({\n    name = 'lyte',\n    cmd = { 'lyte-lsp' },\n    filetypes = { 'lyte' },\n})\n```\n\n## Embedding via Swift Package\n\nLyte is available as a Swift package for embedding in macOS and iOS apps. Add it to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/audulus/lyte.git\", from: \"0.12.0\")\n]\n```\n\nThe package auto-selects the best backend: LLVM JIT on ARM macOS, VM on iOS and other platforms.\n\n```swift\nlet compiler = LyteCompiler(entryPoints: [\"init\", \"process\"])\ntry compiler.addSource(source, filename: \"node.lyte\")\nlet program = try compiler.compile()\n\nlet globals = program.allocGlobals()\nlet initEP = program.entryPoint(named: \"init\")!\nlet processEP = program.entryPoint(named: \"process\")!\n\ninitEP.call(globals: globals)     // initialize state\nprocessEP.call(globals: globals)  // run on audio thread\n```\n\nEntry point handles are resolved once at compile time and called with zero overhead — no string lookups on the hot path.\n\n## Releasing\n\nCreating a release builds and publishes the xcframework automatically:\n\n```bash\ngh release create v0.12\n```\n\nThis triggers the `release.yml` CI workflow which:\n\n1. Builds `CLyte.xcframework` for macOS (ARM64 + x86_64) and iOS\n2. Uploads `CLyte.xcframework.zip` as a release asset\n3. Computes the checksum and updates `Package.swift` on main\n\nThe xcframework is self-contained — LLVM dependencies (zstd, ffi) are statically linked into the ARM64 macOS library. Swift consumers only need system libraries (libc++, libz, libcurses).\n\n## Architecture\n\nThe compiler pipeline:\n\n1. **Lexer** — tokenizes source text\n2. **Parser** — builds an AST\n3. **Type Checker** — Hindley-Milner inference with constraint solving\n4. **Safety Checker** — static bounds checking and division-by-zero detection via abstract interpretation\n5. **Code Generation** — Cranelift JIT, LLVM JIT, or VM bytecode\n\nSee [`src/README.md`](src/README.md) for detailed design notes.\n\n## Benchmarks\n\nThree benchmarks compare Lyte (VM, ARM64 VM, JIT, LLVM) against C, Lua 5.5, and LuaJIT:\n\n| Benchmark | Description |\n|-----------|-------------|\n| **Biquad** | 10M samples through a 1kHz lowpass filter (DSP) |\n| **Sort** | Quicksort 10K elements × 50 iterations |\n| **FFT** | 1024-point radix-2 FFT × 2000 iterations |\n\nResults from the latest CI run are in the [Actions workflow summary](../../actions/workflows/rust.yml) (click the latest run, scroll to \"Benchmark Results\").\n\n```bash\n./benchmark/run.sh        # run locally (requires lua and luajit)\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faudulus%2Flyte","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faudulus%2Flyte","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faudulus%2Flyte/lists"}