{"id":44927517,"url":"https://github.com/i2y/konpeito","last_synced_at":"2026-03-14T02:19:41.011Z","repository":{"id":338923347,"uuid":"1158568561","full_name":"i2y/konpeito","owner":"i2y","description":"A gradually typed Ruby subset compiler with Hindley-Milner type inference, dual LLVM/JVM backends, and seamless Java interop.","archived":false,"fork":false,"pushed_at":"2026-03-08T16:29:45.000Z","size":14405,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-08T19:02:41.129Z","etag":null,"topics":["jvm","llvm","mruby","raylib","ruby","skija"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/i2y.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","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-02-15T15:37:14.000Z","updated_at":"2026-03-08T16:29:49.000Z","dependencies_parsed_at":"2026-02-22T09:01:18.600Z","dependency_job_id":null,"html_url":"https://github.com/i2y/konpeito","commit_stats":null,"previous_names":["i2y/konpeito"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/i2y/konpeito","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2y%2Fkonpeito","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2y%2Fkonpeito/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2y%2Fkonpeito/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2y%2Fkonpeito/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/i2y","download_url":"https://codeload.github.com/i2y/konpeito/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/i2y%2Fkonpeito/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30372127,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T21:41:54.280Z","status":"online","status_checked_at":"2026-03-11T02:00:07.027Z","response_time":84,"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":["jvm","llvm","mruby","raylib","ruby","skija"],"created_at":"2026-02-18T05:12:09.101Z","updated_at":"2026-03-11T05:05:12.100Z","avatar_url":"https://github.com/i2y.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Konpeito\n\n\u003e *Konpeito (konpeitō) — Japanese sugar crystals. Crystallizing Ruby into native code.*\n\nA gradually typed Ruby compiler with Hindley-Milner type inference, dual LLVM/JVM backends, and seamless Java interop.\n\nWrite ordinary Ruby. Konpeito infers types automatically, compiles to fast native code, and falls back to dynamic dispatch where it can't resolve statically — with a warning so you always know.\n\n## How It Works\n\nKonpeito uses a three-tier type resolution strategy:\n\n1. **HM inference** resolves most types automatically — no annotations needed. Like Crystal, but for Ruby.\n2. **RBS annotations** add precision where needed. Optional type hints that help the compiler optimize further.\n3. **Dynamic fallback** handles the rest. Unresolved calls compile to runtime dispatch (LLVM: `rb_funcallv`, JVM: `invokedynamic`), and the compiler warns you.\n\nAdding an RBS signature promotes a dynamic fallback to static dispatch. The compiler tells you where the boundaries are — fix them if you want, or leave them dynamic. Your call.\n\n## What Gets Compiled\n\nKonpeito compiles your `.rb` source files into native code. Understanding the boundary between compiled and non-compiled code is key:\n\n**Compiled (native code):**\n- All `.rb` files you pass to `konpeito build`\n- Files resolved via `require` / `require_relative` at compile time (when source is available on the load path via `-I`)\n- Within compiled code: type-resolved operations become native CPU instructions; unresolved operations fall back to `rb_funcallv` (CRuby's dynamic dispatch) with a compiler warning\n\n**Not compiled (loaded at runtime by CRuby):**\n- Installed gems referenced by `require` — the compiler detects these and emits `rb_require` calls so CRuby loads them at runtime\n- Standard libraries (`json`, `net/http`, `fileutils`, etc.) — same treatment\n- Any Ruby code running in the host CRuby process outside the compiled extension\n\nThe compiled extension and CRuby coexist in the same process. Native code calls CRuby C API functions (`rb_define_class`, `rb_funcallv`, `rb_ary_push`, etc.), so compiled code can freely create Ruby objects, call Ruby methods, and interact with any loaded gem. The speed gain comes from the parts where Konpeito resolves types and emits native instructions instead of going through Ruby's method dispatch.\n\nThis leads to two usage patterns:\n\n### Pattern 1: Extension Library\n\nCompile performance-critical code into a CRuby extension (`.bundle` / `.so`). Your main application stays as regular Ruby and loads the compiled code via `require`:\n\n```ruby\n# math.rb — compiled by Konpeito\nmodule MyMath\n  def self.sum_up_to(n)\n    total = 0\n    i = 1\n    while i \u003c= n\n      total += i\n      i += 1\n    end\n    total\n  end\nend\n```\n\n```bash\nkonpeito build math.rb   # → math.bundle\n```\n\n```ruby\n# app.rb — regular Ruby, NOT compiled\nrequire_relative \"math\"\nputs MyMath.sum_up_to(10_000_000)   # calls into compiled native code\n```\n\nYour code can `require` installed gems freely. The compiler compiles your code and emits runtime `require` calls for the gems, so everything works together at runtime:\n\n```ruby\n# my_app.rb — compiled by Konpeito\nrequire \"kumiki\"     # gem — loaded at runtime by CRuby\ninclude Kumiki\n\nclass MyComponent \u003c Component\n  # ... your code is compiled natively\n  # ... calls to kumiki methods go through rb_funcallv (dynamic dispatch)\nend\n```\n\nThis is the pattern shown in [Hello World](#hello-world) below.\n\n### Pattern 2: Whole Application\n\nCompile an entire Ruby application including framework code — the compiler traces all `require` statements on the load path specified by `-I` and compiles everything into a single extension:\n\n```bash\nkonpeito build -I /path/to/kumiki/lib counter.rb   # → counter.bundle (971 KB)\nruby -r ./counter -e \"\"                             # load and run\n```\n\nThe difference from Pattern 1: framework code (kumiki) is also compiled, enabling direct dispatch, monomorphization, and inlining across the entire codebase. Without `-I`, only your code is compiled (~50 KB) and the framework is loaded at runtime — this still works, but method calls into the framework go through dynamic dispatch.\n\nSee [Tutorial](docs/tutorial.md) for step-by-step walkthroughs of both patterns with working examples.\n\n## Quick Start\n\n### Prerequisites\n\nRuby 4.0+ is required. Java 21+ is needed for the JVM backend. LLVM 20 is needed only for the CRuby native backend.\n\n```bash\ngem install konpeito\n```\n\n**JVM backend** (recommended — standalone JARs, Castella UI, Java interop):\n```bash\n# macOS\nbrew install openjdk@21\n\n# Ubuntu / Debian\nsudo apt install openjdk-21-jdk\n\n# Fedora\nsudo dnf install java-21-openjdk-devel\n\n# Windows (MSYS2 / MinGW)\nwinget install EclipseAdoptium.Temurin.21.JDK\n```\n\n**CRuby native backend** (optional — C extensions):\n```bash\ngem install ruby-llvm\n\n# macOS\nbrew install llvm@20\nln -sf /opt/homebrew/opt/llvm@20/lib/libLLVM-20.dylib /opt/homebrew/lib/\n\n# Ubuntu / Debian\nsudo apt install llvm-20 clang-20\n\n# Fedora\nsudo dnf install llvm20 clang20\n\n# Windows (MSYS2 / MinGW)\nwinget install LLVM.LLVM\n```\n\n### Hello World\n\nWrite a small Ruby file:\n\n```ruby\n# math.rb\nmodule MyMath\n  def self.add(a, b)\n    a + b\n  end\n\n  def self.sum_up_to(n)\n    total = 0\n    i = 1\n    while i \u003c= n\n      total = total + i\n      i = i + 1\n    end\n    total\n  end\nend\n```\n\nCompile and use it from Ruby:\n\n```bash\nkonpeito build math.rb          # produces math.bundle (macOS), math.so (Linux), or math.dll (Windows)\n```\n\n```ruby\nrequire_relative \"math\"\nputs MyMath.add(3, 4)        # =\u003e 7\nputs MyMath.sum_up_to(100)   # =\u003e 5050\n```\n\n### CLI Overview\n\n```bash\nkonpeito build src/main.rb                          # compile to CRuby extension\nkonpeito build --target jvm -o app.jar src/main.rb  # compile to standalone JAR\nkonpeito run src/main.rb                            # build and run in one step\nkonpeito check src/main.rb                          # type check only (no codegen)\nkonpeito init my_project                            # scaffold a new project\nkonpeito test                                       # run project tests\nkonpeito fmt                                        # format source files\nkonpeito watch src/main.rb                          # auto-recompile on changes\nkonpeito doctor                                     # check your environment\n```\n\nFor detailed options and examples, see [CLI Reference](docs/cli-reference.md).\n\n## Features\n\n- **HM Type Inference** — Types are inferred automatically. No annotations needed for most code.\n- **Gradual Typing** — Static where possible, dynamic where necessary. The compiler shows you the boundary.\n- **Flow Typing** — Type narrowing via `if x.nil?`, `case/in Integer`, boolean guards, and more.\n- **Unboxed Arithmetic** — Integer and Float operations compile to native CPU instructions, skipping Ruby's method dispatch entirely.\n- **Loop Optimizations** — LICM, inlined iterators (`each`, `map`, `reduce`, `times`), and LLVM O2 passes.\n- **CRuby C Extensions** — Output plugs directly into your existing Ruby app via `require`.\n- **JVM Backend** — Generate standalone `.jar` files that run on any Java 21+ VM.\n- **Java Interop** — Call Java libraries directly with full type safety. Java type information flows into HM inference automatically.\n- **Native Data Structures** — `NativeArray[T]`, `NativeHash[K,V]`, `StaticArray[T,N]`, `Slice[T]`, `@struct` value types for high-performance data handling.\n- **C Interop** — Call external C libraries with `%a{cfunc}` / `%a{ffi}`, plus built-in HTTP (libcurl), Crypto (OpenSSL), and Compression (zlib) modules.\n- **SIMD Vectorization** — `%a{simd}` compiles vector types to LLVM vector instructions.\n- **Operator Overloading** — Define `+`, `-`, `*`, `==`, `\u003c=\u003e`, etc. on your own classes with full type inference.\n- **Pattern Matching** — Full `case/in` support with array, hash, guard, and capture patterns.\n- **Modern Ruby Syntax** — `_1`/`_2` numbered params, `it`, endless methods, `class \u003c\u003c self`, safe navigation (`\u0026.`), and more.\n- **Concurrency** — Fiber, Thread, Mutex, ConditionVariable, SizedQueue, and Ractor (with `Ractor::Port`, `Ractor.select`, `Ractor[:key]` local storage, `name:`, `monitor`/`unmonitor`). JVM Ractor uses Virtual Threads for scheduling but does not enforce object isolation — objects are shared by reference, unlike CRuby's strict isolation model.\n- **Built-in Tooling** — Formatter (`fmt`), debug info (`-g`), and profiling (`--profile`).\n- **Castella UI** — A reactive GUI framework for the JVM backend (see below).\n\n## Supported Ruby Syntax\n\nKonpeito supports most Ruby 4.0 syntax:\n\n| Category | Supported |\n|----------|-----------|\n| Literals | Integer, Float, String, Symbol, Array, Hash, Regexp, Range, Heredoc, nil/true/false |\n| String interpolation | `\"Hello #{name}\"` |\n| Variables | Local, `@instance`, `@@class`, `$global` |\n| Control flow | `if`/`unless`, `while`/`until`, `for`, `case`/`when`, `case`/`in`, `break`, `next`, `return` |\n| Methods \u0026 OOP | Classes, modules, inheritance, `super`, `attr_accessor`, method visibility (`private`/`protected`) |\n| Blocks \u0026 closures | `yield`, `block_given?`, Proc, Lambda, `\u0026blk` |\n| Pattern matching | Literals, arrays, hashes, guards (`if`), captures (`=\u003e`), pins (`^`), rest (`*`) |\n| Exceptions | `begin`/`rescue`/`else`/`ensure`, custom exception classes |\n| Modern syntax | `_1`/`_2` numbered params, `it`, endless methods, `class \u003c\u003c self`, `\u0026.` safe navigation |\n| Operators | Full overloading (`+`, `-`, `*`, `==`, `\u003c=\u003e`, etc.), compound assignment (`+=`, `\\|\\|=`, `\u0026\u0026=`) |\n| Arguments | Keyword args, rest args (`*args`), keyword rest (`**kwargs`), splat (`foo(*arr)`) |\n| Concurrency | Fiber, Thread, Mutex, ConditionVariable, SizedQueue, Ractor (JVM) |\n| Misc | `alias`, `defined?`, open classes, multi-assignment, `%w`/`%i` literals |\n\n### Not Supported (by design)\n\n- `eval`, `instance_eval`, `class_eval`\n- `define_method`, `method_missing`\n- `ObjectSpace`, `Binding`\n- Dynamic `require`/`load` (variable-based require)\n\nFor the complete specification, see [Language Specification](docs/language-specification.md).\n\n## JVM Backend\n\nKonpeito can also compile to JVM bytecode, producing standalone JAR files:\n\n```bash\nkonpeito build --target jvm -o app.jar main.rb\n# or compile and run immediately:\nkonpeito build --target jvm --run main.rb\n```\n\nThe JVM backend supports seamless Java interop — call Java libraries directly from your Ruby code without writing any glue. Java type information is introspected from the classpath and fed into HM inference, so calling Java APIs is type-safe without annotations.\n\n## Castella UI\n\nA reactive GUI framework for the JVM backend, powered by [JWM](https://github.com/HumbleUI/JWM) + [Skija](https://github.com/HumbleUI/Skija).\n\n### DSL\n\nRuby's block syntax becomes a UI DSL — `column`, `row`, `text`, `button` etc. nest naturally with keyword arguments. A plain Ruby method is a reusable component.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/dashboard.png\" alt=\"Analytics Dashboard\" width=\"720\" /\u003e\n\u003c/p\u003e\n\n```ruby\ndef view\n  column(padding: 20.0, spacing: 16.0) {\n    row(spacing: 12.0) {\n      text(\"Analytics Dashboard\", font_size: 26.0, bold: true)\n      spacer\n      button(\"Refresh\", width: 90.0) {}\n    }.fixed_height(40.0)\n\n    # KPI Cards — extract a method, and it's a reusable component\n    row(spacing: 12.0) {\n      kpi_card(\"Revenue\", \"$48,250\", \"+12.5%\", $theme.accent)\n      kpi_card(\"Users\",   \"3,842\",   \"+8.1%\",  $theme.success)\n      kpi_card(\"Orders\",  \"1,205\",   \"-2.3%\",  $theme.error)\n    }\n\n    # Charts, tables, and layouts compose with blocks\n    row(spacing: 12.0) {\n      column(expanding_width: true, bg_color: $theme.bg_primary, border_radius: 10.0, padding: 14.0) {\n        bar_chart(labels, data, [\"Revenue\", \"Costs\"]).title(\"Monthly Overview\").fixed_height(220.0)\n      }\n      column(expanding_width: true, bg_color: $theme.bg_primary, border_radius: 10.0, padding: 14.0) {\n        data_table(headers, widths, rows).fixed_height(200.0)\n      }\n    }\n  }\nend\n\n# A Ruby method is a reusable component\ndef kpi_card(label, value, change, color)\n  column(spacing: 6.0, bg_color: $theme.bg_primary, border_radius: 10.0, padding: 16.0, expanding_width: true) {\n    text(label, font_size: 12.0, color: $theme.text_secondary)\n    text(value, font_size: 24.0, bold: true)\n    text(change, font_size: 13.0, color: color)\n  }\nend\n```\n\n### Reactive State\n\n`state(0)` creates an observable value, and the UI re-renders automatically when it changes:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/counter.png\" alt=\"Counter App\" width=\"320\" /\u003e\n\u003c/p\u003e\n\n```ruby\nclass Counter \u003c Component\n  def initialize\n    super\n    @count = state(0)\n  end\n\n  def view\n    column(padding: 16.0, spacing: 8.0) {\n      text \"Count: #{@count}\", font_size: 32.0, align: :center\n      row(spacing: 8.0) {\n        button(\" - \") { @count -= 1 }\n        button(\" + \") { @count += 1 }\n      }\n    }\n  end\nend\n```\n\nAn OOP-style API (`Column(...)`, `Row(...)`) is also available. Available widgets: `Text`, `Button`, `TextInput`, `MultilineText`, `Column`, `Row`, `Image`, `Checkbox`, `Slider`, `ProgressBar`, `Tabs`, `DataTable`, `TreeView`, `BarChart`, `LineChart`, `PieChart`, `Markdown`, and more.\n\n### Style Composition\n\nStyles are first-class objects — store them in variables and compose with `+`:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/style_composition.png\" alt=\"Style Composition\" width=\"480\" /\u003e\n\u003c/p\u003e\n\n```ruby\ncard = Style.new.bg_color($theme.bg_primary).border_radius(10.0).padding(16.0)\ngreen_card = card + Style.new.border_color($theme.success)\n\ncolumn(spacing: 12.0) {\n  container(card)       { text \"Default card\" }\n  container(green_card) { text \"Green border variant\" }\n}\n```\n\n### Calculator Demo\n\nA port of the original Python Castella calculator. Flex layout, button kinds (`KIND_DANGER`, `KIND_WARNING`, `KIND_SUCCESS`), reactive `state()`, and class methods called from instance method callbacks — all in ~130 lines:\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/screenshots/calc.png\" alt=\"Calculator\" width=\"320\" /\u003e\n\u003c/p\u003e\n\n```ruby\nclass Calc \u003c Component\n  def initialize\n    super\n    @display = state(\"0\")\n    @lhs = 0.0\n    @current_op = \"\"\n    @is_refresh = true\n  end\n\n  # --- Calculator logic ---\n\n  def press_number(label)\n    if @display.value == \"0\" || @is_refresh\n      @display.set(label)\n    else\n      @display.set(@display.value + label)\n    end\n    @is_refresh = false\n  end\n\n  def press_dot\n    if @is_refresh\n      @display.set(\"0.\")\n      @is_refresh = false\n      return\n    end\n    if !@display.value.include?(\".\")\n      @display.set(@display.value + \".\")\n    end\n  end\n\n  def all_clear\n    @display.set(\"0\")\n    @lhs = 0.0\n    @current_op = \"\"\n    @is_refresh = true\n  end\n\n  def self.calc(lhs, op, rhs)\n    if op == \"+\"\n      lhs + rhs\n    elsif op == \"-\"\n      lhs - rhs\n    elsif op == \"\\u00D7\"\n      lhs * rhs\n    elsif op == \"\\u00F7\"\n      if rhs == 0.0\n        0.0\n      else\n        lhs / rhs\n      end\n    else\n      rhs\n    end\n  end\n\n  def self.format_result(val)\n    if val == val.to_i.to_f\n      val.to_i.to_s\n    else\n      val.to_s\n    end\n  end\n\n  def press_operator(new_op)\n    rhs = @display.value.to_f\n    if @current_op != \"\"\n      result = Calc.calc(@lhs, @current_op, rhs)\n      @display.set(Calc.format_result(result))\n      @lhs = result\n    else\n      @lhs = rhs\n    end\n    if new_op == \"=\"\n      @current_op = \"\"\n    else\n      @current_op = new_op\n    end\n    @is_refresh = true\n  end\n\n  # --- View ---\n\n  def view\n    grid = Style.new.spacing(4.0)\n    btn  = Style.new.font_size(32.0)\n    op   = btn + Style.new.kind(KIND_WARNING)\n    ac   = btn + Style.new.kind(KIND_DANGER).flex(3)\n    eq   = btn + Style.new.kind(KIND_SUCCESS)\n    wide = btn + Style.new.flex(2)\n\n    column(spacing: 4.0, padding: 4.0) {\n      text @display.value, font_size: 48.0, align: :right, kind: KIND_INFO, height: 72.0\n      row(grid) {\n        button(\"AC\", ac) { all_clear }\n        button(\"\\u00F7\", op) { press_operator(\"\\u00F7\") }\n      }\n      row(grid) {\n        button(\"7\", btn) { press_number(\"7\") }\n        button(\"8\", btn) { press_number(\"8\") }\n        button(\"9\", btn) { press_number(\"9\") }\n        button(\"\\u00D7\", op) { press_operator(\"\\u00D7\") }\n      }\n      row(grid) {\n        button(\"4\", btn) { press_number(\"4\") }\n        button(\"5\", btn) { press_number(\"5\") }\n        button(\"6\", btn) { press_number(\"6\") }\n        button(\"-\", op) { press_operator(\"-\") }\n      }\n      row(grid) {\n        button(\"1\", btn) { press_number(\"1\") }\n        button(\"2\", btn) { press_number(\"2\") }\n        button(\"3\", btn) { press_number(\"3\") }\n        button(\"+\", op) { press_operator(\"+\") }\n      }\n      row(grid) {\n        button(\"0\", wide) { press_number(\"0\") }\n        button(\".\", btn) { press_dot }\n        button(\"=\", eq) { press_operator(\"=\") }\n      }\n    }\n  end\nend\n\nframe = JWMFrame.new(\"Castella Calculator\", 320, 480)\napp = App.new(frame, Calc.new)\napp.run\n```\n\n## Performance\n\nKonpeito targets compute-heavy, typed loops where unboxed arithmetic and backend optimizations can make a meaningful difference. Actual speedups depend heavily on the workload, input data, and hardware — the numbers below are from one specific environment and should be taken as rough indicators, not guarantees.\n\n### LLVM Backend (CRuby Extension)\n\nTypical speedup ranges observed on our test machine (vs Ruby YJIT):\n\n- **Numeric loops** (arithmetic, counters, reductions): often **5–80x** faster, depending on how much of the loop body can be fully unboxed\n- **Native data structures** (NativeArray, StaticArray): **~10–60x** faster for tight element-access loops\n- **Iterator inlining** (each, map, reduce, times): **~7–50x** faster with typed arrays or ranges\n\nThese figures reflect native-internal performance — the loop itself runs entirely inside compiled code. Cross-boundary calls (Ruby ↔ native) see smaller gains due to interop overhead.\n\n**Where Konpeito is slower:** Pattern matching (`case/in`) is currently **~2–3x slower** than YJIT — Ruby's VM is highly optimized for this. String operations (NativeString) are also slower than CRuby's mature string implementation due to conversion overhead. Workloads that are I/O-bound, rely heavily on dynamic features, or hit areas where YJIT already excels may see no benefit or even regressions.\n\n### JVM Backend (Standalone JAR)\n\nFor numeric workloads, the JVM backend typically shows **~30–60x** speedups over Ruby YJIT, benefiting from HotSpot's JIT on top of Konpeito's static type resolution. I/O-bound or polymorphic code will see less improvement.\n\n\u003e **Test environment:** Apple M4 Max, Ruby 4.0.1 + YJIT, Java 21.0.10 (HotSpot), macOS 15. Results will vary on different hardware and configurations.\n\n## Documentation\n\n### User Guides\n\n- **[Getting Started](docs/getting-started.md)** — Installation, Hello World, first project, Castella UI tutorial\n- **[Tutorial](docs/tutorial.md)** — Extension library and whole-application compilation patterns\n- **[CLI Reference](docs/cli-reference.md)** — All commands, options, and configuration\n- **[API Reference](docs/api-reference.md)** — Castella UI widgets, native data structures, standard library\n\n### Architecture \u0026 Design\n\n- **[Architecture](docs/architecture.md)** — Full compiler pipeline, design philosophy, and roadmap\n- **[JVM Backend](docs/architecture-jvm.md)** — Dual-backend strategy, JVM codegen, Java interop\n- **[Castella UI](docs/castella-ui.md)** — GUI framework design and widget reference\n- **[Native Stdlib Proposal](docs/native-stdlib-proposal.md)** — NativeArray, StaticArray, Slice, and friends\n- **[Language Specification](docs/language-specification.md)** — Supported syntax, type system rules, backend behavior\n- **[RBS Requirements](docs/rbs-requirements-en.md)** — When you need RBS files and when you don't\n\n## Requirements\n\n| Dependency | Version | Required for |\n|---|---|---|\n| Ruby | 4.0.1+ | Always |\n| Java | 21+ | JVM backend |\n| LLVM | 20 | CRuby native backend |\n| ruby-llvm gem | ~\u003e 20.1 | CRuby native backend |\n| Platform | macOS (ARM64/x64), Linux (x64/ARM64), Windows (x64, MSYS2/MinGW) | — |\n\n## Built with AI\n\nThis project was developed collaboratively between a human director ([Yasushi Itoh](https://github.com/i2y)) and [Claude Code](https://claude.com/claude-code) by Anthropic. The human set the vision, made design decisions, and guided the direction; the AI wrote the implementation. It's an experiment in what's possible when human judgment meets AI capability.\n\n## Status\n\nKonpeito is in an early stage. Bugs and undocumented limitations should be expected. Actively improving — bug reports and feedback are very welcome.\n\nBoth LLVM and JVM backends are tested against the project's conformance test suite covering core language features (control flow, classes, blocks, exceptions, pattern matching, concurrency, etc.). The LLVM backend has been successfully used to compile and run [kumiki](https://github.com/i2y/kumiki)'s `all_widgets_demo.rb` — a non-trivial reactive GUI application with 20+ widget types — as a CRuby extension.\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for setup instructions and guidelines.\n\nThe core principle: **no ambiguous behavior**. If the compiler can't determine a type, it falls back to dynamic dispatch with a warning — never guesses heuristically. Adding RBS promotes the fallback to static dispatch.\n\n## License\n\n[MIT](LICENSE) — Copyright (c) 2026 Yasushi Itoh\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi2y%2Fkonpeito","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fi2y%2Fkonpeito","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fi2y%2Fkonpeito/lists"}