Skip to content

martianoff/gala

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,019 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GALA

Build Release GitHub release (latest SemVer) License Go Bazel PRs Welcome

GALA Logo

GALA (Go Alternative LAnguage) is a modern programming language that transpiles to Go. It brings sealed types, pattern matching, immutability by default, and functional collections to the Go ecosystem -- without sacrificing Go's performance, tooling, or library compatibility.

Try GALA in your browser!

sealed type Shape {
    case Circle(Radius float64)
    case Rectangle(Width float64, Height float64)
}

func area(s Shape) string = s match {
    case Circle(r)       => f"circle area: ${3.14159 * r * r}%.2f"
    case Rectangle(w, h) => f"rect area: ${w * h}%.2f"
}

What is GALA?

GALA gives you Scala-like expressiveness -- sealed types, exhaustive pattern matching, Option[T]/Either[A,B]/Try[T] monads, immutable collections -- in a concise, readable syntax that compiles to a single native binary. GALA is fully Go-compatible: every Go library works out of the box.


Key Features

Sealed types and exhaustive pattern matching -- Define closed type hierarchies. The compiler rejects incomplete matches.

sealed type Result[T any] {
    case Ok(Value T)
    case Err(Message string)
}

val msg = result match {
    case Ok(v)    => s"got $v"
    case Err(msg) => s"error: $msg"
}

Immutability by default -- val and := are immutable. Structs auto-generate Copy() and Equal().

struct Config(Host string, Port int)
val updated = config.Copy(Port = 8080)

Expression functions -- Single-expression functions skip braces and return.

func square(x int) int = x * x
func max(a int, b int) int = if (a > b) a else b

Default parameters and named arguments -- Skip boilerplate. Defaults are evaluated at each call site; named arguments can appear in any order.

func connect(host string, port int = 8080, tls bool = true) Connection

connect("localhost")                  // port=8080, tls=true
connect("localhost", tls = false)     // port=8080, tls=false
connect(host = "db", port = 5432)     // tls=true

Lambda type inference -- Parameter types and method type parameters are inferred from context.

val list = ListOf(1, 2, 3)
val doubled = list.Map((x) => x * 2)
val sum = list.FoldLeft(0, (acc, x) => acc + x)

Monads -- Option[T], Either[A,B], Try[T], Future[T] with Map, FlatMap, Recover, and pattern matching.

val name = user.Name
    .Map((n) => strings.ToUpper(n))
    .GetOrElse("ANONYMOUS")

Functional collections -- Immutable List, Array, HashMap, HashSet, TreeSet, TreeMap with Map, Filter, FoldLeft, Collect, and more.

val nums = ArrayOf(1, 2, 3, 4, 5)
val evens = nums.Filter((x) => x % 2 == 0)
val evenDoubled = nums.Collect({ case n if n % 2 == 0 => n * 2 })

Tuples with destructuring -- Up to Tuple5, with pattern matching and concise syntax.

val pair = (1, "hello")
val (x, y) = pair

Read-only pointers -- ConstPtr[T] prevents accidental mutation through pointers.

val data = 42
val ptr = &data       // ConstPtr[int], not *int
val value = *ptr      // OK: read
// *ptr = 100         // compile error: cannot write through ConstPtr

String interpolation -- s"..." with auto-inferred format verbs and f"..." with explicit format specs. No imports needed.

val name = "Alice"
val age = 30
Println(s"$name is $age years old")       // Alice is 30 years old
Println(f"Pi = ${3.14159}%.2f")           // Pi = 3.14
Println(s"${nums.MkString(", ")}")        // 1, 2, 3

Zero-reflection JSON codec -- Codec[T] uses the compiler-generated StructMeta[T] intrinsic for fully typed serialization with no reflection, no struct tags, and pattern matching support.

struct Person(FirstName string, LastName string, Age int)

val codec = Codec[Person](SnakeCase())
val jsonStr = codec.Encode(Person("Alice", "Smith", 30)).Get()
// {"first_name":"Alice","last_name":"Smith","age":30}

val decoded = codec.Decode(jsonStr)       // Try[Person]
val name = jsonStr match {
    case codec(p) => p.FirstName          // pattern matching!
    case _        => "unknown"
}

Regex with pattern matching -- Compile-safe regex with extractors that destructure capture groups directly in match.

val dateRegex = regex.MustCompile("(\\d{4})-(\\d{2})-(\\d{2})")

"2024-01-15" match {
    case dateRegex(Array(year, month, day)) => s"$year/$month/$day"
    case _ => "not a date"
}

Full Go interop -- Use any Go library. Go function return types are automatically inferred from the Go SDK, and multi-return (T, error) patterns are wrapped into Try[T].

Fast compilation -- Analysis caching and batch transpilation make multi-file packages compile up to 16x faster. Profile bottlenecks with GALA_PROFILE=1.


Quick Start

New to GALA? Try it instantly in the browser playground — no install. Or follow the full Getting Started guide.

1. Install

Download a pre-built binary from Releases, rename it to gala (or gala.exe on Windows), and add it to your PATH.

GALA transpiles to Go, so it needs Go 1.25+ on your PATH to compile programs. Install Go first if you don't have it.

Or build from source:

git clone https://github.com/martianoff/gala.git && cd gala
bazel build //cmd/gala:gala

Verify the install:

gala version

2. Create a project

mkdir hello && cd hello
gala mod init example.com/hello

Write main.gala:

package main

struct Person(Name string, Age int)

func greet(p Person) string = p match {
    case Person(name, age) if age < 18 => s"Hey, $name!"
    case Person(name, _)               => s"Hello, $name"
}

func main() {
    Println(greet(Person("Alice", 25)))
}

3. Run

gala run main.gala     # Transpile + compile + run
gala build             # Build project to a binary
gala test              # Run tests

# Or with Bazel (for larger projects)
bazel build //... && bazel test //...

Need help? Ask in GitHub Discussions.


GALA vs Go

Pattern Matching vs Switch

GALAGo
val msg = shape match {
    case Circle(r)      => f"r=$r%.1f"
    case Rectangle(w,h) => f"$w%.0fx$h%.0f"
    case Point()        => "point"
}
var msg string
switch shape._variant {
case Shape_Circle:
    msg = fmt.Sprintf("r=%.1f", shape.Radius.Get())
case Shape_Rectangle:
    msg = fmt.Sprintf("%fx%f", shape.Width.Get(), shape.Height.Get())
case Shape_Point:
    msg = "point"
}

Option Handling vs nil Checks

GALAGo
val name = user.Name
    .Map((n) => strings.ToUpper(n))
    .GetOrElse("ANONYMOUS")
name := "ANONYMOUS"
if user.Name != nil {
    name = strings.ToUpper(*user.Name)
}

Immutable Structs vs Manual Copying

GALAGo
struct Config(Host string, Port int)
val updated = config.Copy(Port = 8080)
type Config struct {
    Host string
    Port int
}
updated := Config{Host: config.Host, Port: 8080}

Default Parameters vs Option Structs

GALAGo
func connect(
    host string,
    port int = 8080,
    tls bool = true,
) Connection

connect("localhost", tls = false)
type ConnectOptions struct {
    Host string
    Port int
    TLS  *bool
}

func Connect(opts ConnectOptions) Connection {
    if opts.Port == 0 { opts.Port = 8080 }
    if opts.TLS == nil {
        t := true; opts.TLS = &t
    }
    // ...
}
Connect(ConnectOptions{Host: "localhost", TLS: ptrBool(false)})

Error Handling: Try vs if-err

GALAGo
val result = divide(10, 2)
    .Map((x) => x * 2)
    .FlatMap((x) => divide(x, 3))
    .Recover((e) => 0)
result, err := divide(10, 2)
if err != nil {
    result = 0
} else {
    result = result * 2
    result, err = divide(result, 3)
    if err != nil {
        result = 0
    }
}

Standard Library

Types

Type Description
Option[T] Optional values -- Some(value) / None()
Either[A, B] Disjoint union -- Left(a) / Right(b)
Try[T] Failable computation -- Success(value) / Failure(err)
Future[T] Async computation with Map, FlatMap, Zip, Await
Tuple[A, B] Pairs and triples with (a, b) syntax
ConstPtr[T] Read-only pointer with auto-deref field access
IO[T] Lazy, composable effect type -- Suspend, Map, FlatMap, Recover

JSON, Regex, IO

Type Description
Codec[T] Zero-reflection JSON codec with Encode, Decode, Rename, Omit, pattern matching
Regex Compiled regex with Matches, FindFirst, FindAll, ReplaceAll, pattern matching
IO[T] Lazy effect -- separates description from execution, re-runs on every .Run()

Collections

Type Kind Key Operations Best for
List[T] Immutable O(1) prepend, O(n) index Recursive processing, prepend-heavy workloads
Array[T] Immutable O(1) random access General-purpose indexed sequences
HashMap[K,V] Immutable O(1) lookup Functional key-value storage
HashSet[T] Immutable O(1) membership Unique element collections
TreeSet[T] Immutable O(log n) sorted ops Ordered unique elements, range queries
TreeMap[K,V] Immutable O(log n) sorted ops Sorted key-value storage, range queries

All collections support Map, Filter, FoldLeft, ForEach, Exists, Find, Collect, MkString, Sorted, SortWith, SortBy, and more.

TreeMap[K,V] is a Red-Black tree that maintains entries in sorted key order. It provides MinKey, MaxKey, Range(from, to), RangeFrom, RangeTo, and conversion to HashMap, Go maps, or sorted arrays.

Mutable variants of all collection types are available in collection_mutable for performance-sensitive code.


Showcase

Project Description
GALA Playground Web-based playground (try it live) -- write and run GALA code in the browser with 9 built-in examples
State Machine Example State machines with sealed types + pattern matching -- order FSM, traffic light, vending machine (with Go comparison)
Log Analyzer Structured log parsing with Go stdlib interop (strings, strconv, fmt) + functional pipelines (FoldLeft, Filter, AppendAll) (with Go comparison)
GALA Server Immutable HTTP server library with builder-pattern configuration, route groups, filters, and pattern matching -- written entirely in GALA
GALA TUI Elm-architecture TUI framework -- immutable widgets, differential renderer, async runtime, fuzzy command palette, markdown, mouse, themes -- written entirely in GALA
GALA Team Multi-agent Claude CLI orchestrator -- a Team Lead delegates to Engineers and QAs, reviews their work, and hands you a PR for sign-off -- written entirely in GALA with gala_tui

Dependency Management

gala mod init github.com/user/project
gala mod add github.com/example/utils@v1.2.3
gala mod add github.com/google/uuid@v1.6.0 --go
gala mod tidy

IDE Support

GALA ships with a GoLand/IntelliJ plugin and an LSP server (gala lsp) for editor-agnostic support.

GoLand / IntelliJ IDEA

  1. Install GALA CLI: Download from releases and add to PATH
  2. Install plugin: GoLand > Settings > Plugins > Install from Disk > select gala-intellij-plugin.zip from releases
  3. Restart GoLand — the LSP server starts automatically when a .gala file is opened

Plugin Features (local, no LSP needed)

  • Full ANTLR-based parser with complete PSI tree
  • Syntax highlighting (keywords, types, strings, comments, operators, built-in functions, std types)
  • Semantic annotator (built-in types, std types, built-in functions, string interpolation)
  • Code folding (blocks, sealed types, imports)
  • Brace matching
  • Structure view (functions, types, sealed types with cases)
  • Comment/uncomment
  • 12 live templates (func, val, var, match, if, for, sealed, struct, lambda, main, println, sinterp)
  • Color settings page

LSP Features (via gala lsp)

  • Real-time diagnostics (parse errors, transpilation errors, unused variables, match exhaustiveness)
  • Hover (type signatures with fields, methods, sealed cases, built-in function docs)
  • Go to Definition (cross-file via analyzer metadata, local declarations, pattern bindings, named arg fields)
  • Find References (same-file occurrences)
  • Completion (type-aware dot completion, named arg fields, sealed case patterns with destructuring, keywords, built-ins)
  • Inlay hints (type inference from transpiler's VarTypes for all declarations)
  • Document symbols (types, functions, sealed variants)
  • Debounced analysis (500ms) to prevent noise while typing

VS Code

Add to .vscode/settings.json:

{
  "lsp.servers": {
    "gala": {
      "command": "gala",
      "args": ["lsp"],
      "filetypes": ["gala"]
    }
  }
}

Neovim

require('lspconfig.configs').gala = {
  default_config = {
    cmd = { 'gala', 'lsp' },
    filetypes = { 'gala' },
    root_dir = require('lspconfig.util').root_pattern('gala.mod', '.git'),
  },
}
require('lspconfig').gala.setup({})

Installation

Pre-built Binaries

Download from Releases:

Platform Binary
Linux (x64) gala-linux-amd64
Linux (ARM64) gala-linux-arm64
macOS (x64) gala-darwin-amd64
macOS (Apple Silicon) gala-darwin-arm64
Windows (x64) gala-windows-amd64.exe

After downloading, rename the binary to gala (or gala.exe on Windows) and add it to your PATH.

Prerequisite: GALA needs Go 1.25+ on your PATH to compile programs. Install Go before running gala build or gala run.

Build from Source

git clone https://github.com/martianoff/gala.git
cd gala
bazel build //cmd/gala:gala

Using Bazel (Recommended)

load("//:gala.bzl", "gala_binary", "gala_library")

gala_binary(
    name = "myapp",
    src = "main.gala",
)

Get Lines of Code

cloc --vcs=git --read-lang-def=gala_cloc.def .

Documentation


Contributing

Contributions are welcome. Please ensure:

  1. bazel build //... passes
  2. bazel test //... passes
  3. New features include examples in examples/
  4. Documentation is updated for grammar/feature changes

License

License

Apache License 2.0. See LICENSE for details.

About

GALA (Go Alternative LAnguage) -- a modern functional programming language that transpiles to Go. Sealed types, pattern matching, immutability by default, monads (Option, Either, Try, Future), and full Go interop. Built with Go, ANTLR4, Bazel and Claude.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors