{"id":51419691,"url":"https://github.com/oboard/rune-lang","last_synced_at":"2026-07-04T23:01:29.593Z","repository":{"id":359395204,"uuid":"1245396063","full_name":"oboard/rune-lang","owner":"oboard","description":null,"archived":false,"fork":false,"pushed_at":"2026-07-01T16:43:30.000Z","size":2644,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-01T18:25:28.610Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://rune-lang.vercel.app","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oboard.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":"2026-05-21T07:23:26.000Z","updated_at":"2026-07-01T16:43:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/oboard/rune-lang","commit_stats":null,"previous_names":["oboard/rune-lang"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/oboard/rune-lang","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oboard%2Frune-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oboard%2Frune-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oboard%2Frune-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oboard%2Frune-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oboard","download_url":"https://codeload.github.com/oboard/rune-lang/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oboard%2Frune-lang/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35138079,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-04T02:00:05.987Z","response_time":113,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":"2026-07-04T23:01:28.927Z","updated_at":"2026-07-04T23:01:29.581Z","avatar_url":"https://github.com/oboard.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rune Language\n\nRune is an expression-oriented language toolchain written in Go. The current\nimplementation parses Rune source, checks types, lowers to IR, and can either\ninterpret, compile to Go, or emit TypeScript.\n\n```text\nRune source\n  -\u003e lexer/parser\n  -\u003e AST\n  -\u003e semantic/type check\n  -\u003e IR\n  -\u003e interpreter, Go codegen, or TypeScript codegen\n  -\u003e go run / go build\n```\n\nThe fastest path for Rune is still: build a practical language that compiles to\nGo and reuses Go's runtime, GC, module system, and cross compilation.\n\n## Quick Start\n\n```sh\nscripts/dev.sh\nscripts/dev.sh --shell\nscripts/dev.sh --vscode\n```\n\nOr run the toolchain directly:\n\n```sh\ngo run ./cmd/rune check examples/fib.rn\ngo run ./cmd/rune check core\ngo run ./cmd/rune fmt examples/fib.rn\ngo run ./cmd/rune run examples/fib.rn\ngo run ./cmd/rune build -o /tmp/rune-fib examples/fib.rn\ngo run ./cmd/rune ts examples/counter.rn\ngo run ./cmd/rune repl\ngo run ./cmd/rune lsp\n```\n\nBuild the local CLI used by the VSCode extension:\n\n```sh\ngo build -o .bin/rune ./cmd/rune\n```\n\n## CLI\n\n```text\nrune check \u003cpath\u003e      Parse and type-check a file or directory\nrune fmt \u003cpath\u003e        Format a file or directory (alias: format)\nrune run \u003cpath\u003e        Run a file, or a directory with one main\nrune build \u003cfile.rn\u003e   Compile a Rune program to an executable\nrune ts \u003cfile.rn\u003e      Compile a Rune program to TypeScript\nrune repl              Start the Rune REPL\nrune lsp               Start the Rune language server\n```\n\n`rune lsp` serves over stdio by default and also accepts `--stdio`.\n\n## Project Layout\n\n```text\ncmd/rune/              CLI entrypoint\ninternal/lexer/        Lexer\ninternal/parser/       Parser\ninternal/ast/          AST\ninternal/checker/      Type checking and inference\ninternal/ir/           Shared IR\ninternal/interpreter/  IR interpreter\ninternal/codegen/go/   Rune -\u003e Go backend\ninternal/codegen/typescript/\n                       Rune -\u003e TypeScript backend\ninternal/format/       Formatter\ninternal/lsp/          Language server\ninternal/repl/         REPL\ncore/                  Rune core library stubs\nexamples/              Runnable and type-checking examples\nselfhost/              Rune implementations of bootstrap components\nvscode-rune/           VSCode extension\ntree-sitter-rune/      Future Tree-sitter grammar scaffold\n```\n\nRune files can import other Rune files with Dart-like file imports:\n\n```rune\n@\"./helper.rn\"\n\nmain() =\u003e @io.println(helper())\n```\n\nImported Rune declarations are private by default. Add `+` before a helper\ndeclaration in `helper.rn` when callers in other files should use it:\n\n```rune\n+ helper() -\u003e Int =\u003e 42\n```\n\nThe self-hosted lexer, parser, IR, interpreter, and first compiler emitter\nlive under `selfhost/`; see `examples/lexer_bootstrap.rn`,\n`examples/parser_bootstrap.rn`, `examples/compiler_bootstrap.rn`, and the\n`tests/*_bootstrap.rn` files for the current bootstrap entry points.\n\n## Language Snapshot\n\nRune functions are mappings from parameters to expressions:\n\n```rune\nadd(a: Int, b: Int) -\u003e Int =\u003e a + b\n\nmain() =\u003e {\n  @io.println(add(1, 2))\n}\n```\n\nTop-level declarations and enum members are private by default. Prefix a\nfunction, type, or enum member with `+` to make it visible to other Rune\nfiles. Struct and object fields and methods are public by default; prefix a\nmember with `-` when it should stay private.\n\nBlocks return their final expression:\n\n```rune\nsum(a: Int, b: Int) =\u003e {\n  result := a + b\n  result\n}\n```\n\nPattern bodies are supported for single-parameter functions:\n\n```rune\nfib(n: Int) -\u003e Int =\u003e {\n  0 =\u003e 0\n  1 =\u003e 1\n  _ =\u003e fib(n - 1) + fib(n - 2)\n}\n```\n\nMatch expressions use the same pattern syntax:\n\n```rune\nvalue {\n  true =\u003e \"yes\"\n  false =\u003e \"no\"\n}\n```\n\n## Types\n\nThe built-in scalar types are:\n\n```text\nInt\nString\nChar\nBool\nVoid\nHTMLElement\nWebComponent\n```\n\nStruct types use symbolic object syntax:\n\n```rune\nUser: {\n  id: Int\n  name: String\n  age: Int\n}\n\nmain() =\u003e {\n  user := User {\n    id: 1,\n    name: \"oboard\",\n    age: 22,\n  }\n\n  @io.println(user.name)\n}\n```\n\nMethods live inside type declarations. Inside a method, `.field` means\n`this.field`:\n\n```rune\nUser: {\n  age: Int\n\n  isAdult() -\u003e Bool =\u003e .age \u003e= 18\n}\n```\n\nEnum types use the same declaration shape with integer members:\n\n```rune\nStatus: {\n  Completed = 0\n  Fail = 1\n}\n\nmain() =\u003e {\n  status := Status.Completed\n  @io.println(status == Status.Fail)\n}\n```\n\nAnonymous records are expressions:\n\n```rune\nobj := {\n  name: \"Alice\",\n  age: 30,\n\n  nextAge() =\u003e .age + 1\n  greetText() =\u003e \"Hello, \" + .name\n}\n```\n\n## Type Inference\n\nRune uses a Hindley-Milner-style inference direction with closed anonymous\nrecords. There is intentionally no row polymorphism: two anonymous record types\nonly unify when their fields match as closed types.\n\nFunction values can still be refined by call sites. If a function value only\nuses `x.a` and is called with `{ b, z, a }`, the call site can refine the\nparameter to the full argument shape.\n\nNamed struct arguments are preserved:\n\n```rune\nReturn: {\n  b: Int\n  z: Bool\n  a: Int\n}\n\nfun(flag) =\u003e {\n  (flag {\n    true =\u003e (x: Return) =\u003e {\n      k: x.a + 1,\n    }\n    false =\u003e (y: Return) =\u003e {\n      k: y.b + 1,\n    }\n  })({\n    b: 2,\n    z: false,\n    a: 1,\n  }).k\n}\n```\n\nHere `x` and `y` are typed as `Return`; the anonymous argument is accepted\nbecause it structurally satisfies `Return`, and Go codegen emits a `Return`\nliteral.\n\n## Lambdas\n\nLambda parameters must be parenthesized:\n\n```rune\narr.map((value) =\u003e value * 2)\n```\n\nThis is invalid:\n\n```rune\narr.map(value =\u003e value * 2)\n```\n\nLambda parameter annotations are supported:\n\n```rune\n(value: Int) =\u003e value + 1\n(user: User) =\u003e user.name\n```\n\n## Core Library\n\nCore library calls are declaration-driven. The checker and backend load stubs\nfrom `core/\u003cmodule\u003e/\u003cmodule\u003e.rn`; compiler-invented module calls are rejected.\n\nCurrently included modules:\n\n```text\ncore/array\ncore/bytes\ncore/buffer\ncore/compress\ncore/fs\ncore/go\ncore/io\ncore/iter\ncore/json\ncore/map\ncore/net\ncore/path\ncore/process\ncore/reader\ncore/set\ncore/stringbuffer\ncore/writer\n```\n\nI/O:\n\n```rune\n@io.print(value)\n@io.println(value)\n@io.printf(format, value)\n```\n\nArrays:\n\n```rune\nmain() =\u003e {\n  arr := [1, 2, 3]\n  arr.push(4)\n  arr.each((value) =\u003e @io.println(value))\n  doubled := arr.map((value) =\u003e value * 2)\n  @io.println(doubled[0])\n}\n```\n\nJSON:\n\n```rune\njson := @json.stringify({\n  name: \"Rune\"\n  version: 1\n})\n```\n\nInline Go FFI:\n\n```rune\n@go.import(\"fmt\")\n\nisAdult(age: Int) -\u003e Bool =\u003e @go.expr(\"$age \u003e= 18\")\n\nmain() =\u003e {\n  name := \"oboard\"\n  @go.stmt(\"fmt.Println($name)\")\n  @io.println(isAdult(22))\n}\n```\n\nFFI strings can reference Rune identifiers with `$name`; the Go backend expands\nthem after identifier mangling.\n\n## Go Codegen\n\nRune-defined identifiers are prefixed with `__` in generated Go to avoid\ncollisions with Go keywords and runtime names. Rune `main` becomes `__main`,\nwith a small Go `main` wrapper as the process entrypoint.\n\nAnonymous records are emitted as Go struct literals. Named structs remain named\nGo structs. Function values are emitted as Go function values.\n\n## TypeScript Codegen\n\nThe TypeScript backend emits DOM-oriented TypeScript from the shared IR. It\ndoes not support `@go` FFI. XML elements are Rune expressions and embedded\n`{expr}` children become text nodes unless the expression returns\n`HTMLElement`. A function declared as returning `WebComponent` can return an\nXML literal; the TypeScript backend emits a `CustomElementConstructor`, and\nmatching XML tags create registered custom elements.\n\n```rune\nrender() -\u003e HTMLElement =\u003e {\n  $count := 0\n\n  \u003cdiv\u003e\n    \u003cp\u003eCount: {$count}\u003c/p\u003e\n    \u003cbutton @click={$count++}\u003eClick Me\u003c/button\u003e\n  \u003c/div\u003e\n}\n```\n\nCompile it with:\n\n```sh\nrune ts examples/counter.rn\n```\n\n## REPL\n\nStart an interactive session:\n\n```sh\nrune repl\n```\n\nThe REPL evaluates expressions and definitions through the interpreter path, so\nit does not require a `main` function.\n\n## VSCode\n\nThe VSCode extension in `vscode-rune/` provides:\n\n* TextMate highlighting\n* snippets\n* `rune lsp` integration\n* diagnostics\n* hover\n* completion\n* go to definition\n* rename\n* document symbols\n* formatting\n* inlay hints for inferred function and lambda types\n* Run / Debug code lenses for `main`\n\nFor local development:\n\n```sh\nscripts/dev.sh --vscode\n```\n\nInlay hints show inferred parameter and return types, including anonymous\nlambda types:\n\n```rune\nfun(flag) =\u003e {\n  (flag {\n    true =\u003e (x) =\u003e {\n      k: x.a + 1,\n    }\n    false =\u003e (y) =\u003e {\n      k: y.b + 1,\n    }\n  })({\n    b: 2,\n    z: false,\n    a: 1,\n  }).k\n}\n```\n\nThe editor can display `flag: Bool`, `x: { ... }`, and return hints inline.\n\n## Examples\n\n```sh\nrune run examples/fib.rn\nrune run examples/array.rn\nrune run examples/anonymous_object.rn\nrune run examples/complex_type.rn\nrune run examples/ffi.rn\n```\n\n`examples/complex_type2.rn` is a static type-inference example. It intentionally\ncontains recursive functions that should be checked, not run.\n\n## Design Notes\n\nRune currently prioritizes:\n\n* expression-first syntax\n* deterministic parsing\n* strong editor support\n* shared IR for interpreter and compiler\n* Go backend pragmatism\n* closed record types without row polymorphism\n\nRune intentionally does not yet implement LLVM, a custom VM, GC, JIT, package\nmanager, package imports, nominal interfaces, or classes. Rune traits use\nstructural matching and do not require explicit `impl` declarations.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foboard%2Frune-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foboard%2Frune-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foboard%2Frune-lang/lists"}