gpp

module
v0.14.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: MIT

README

G++ (gpp)

G++ is a language for authoring richer abstractions while emitting portable, idiomatic Go. It is a strict superset of Go: every valid Go file is a valid G++ file (.gpp), and every G++ construct has a specific Go lowering. Generated packages compile with the standard Go toolchain and may be distributed and consumed without G++ — the same interoperability story Kotlin, Scala, and Clojure have with Java.

<<<<<<< HEAD

v0.14.0 — Multi-Pattern Arms

Driven by rune's elaborate/store rewrite — rigidity and spine classifiers union constructors in one arm:

match t {
case Var(_), Ref(_), Univ(_), Prop:  // one arm, four constructors
	return true
case App(_, _):
	return false
}

Alternatives take only wildcard arguments and the arm cannot bind the value (split the arm to bind); every alternative is its own reachability row, so a redundant alternative is an unreachable-arm error and alternatives count toward exhaustiveness.

v0.13.0 — The Standard Library Grows Nine

Every package extracted from the first whole-system G++ rewrite (envoy-go, ~360k lines): patterns that appeared three-plus times across an L7 proxy, generalized and shipped where every G++ program can reach them.

import "goforge.dev/gpp/std/kleene"    // K3 three-valued logic: All/Any short-circuit, Undetermined absorbs
import "goforge.dev/gpp/std/latch"     // one-shot quiescence rendezvous: Inc/Dec/Trip/Done, lock-free hot path
import "goforge.dev/gpp/std/clock"     // time seam + deterministic Fake: (deadline, insertion-seq) Advance ordering
import "goforge.dev/gpp/std/guarded"   // Guarded[T]/RWGuarded[T]: the mutex owns the value, not a comment
import "goforge.dev/gpp/std/deepmap"   // two-level map with defensive Snapshot, nil-receiver tolerant
import "goforge.dev/gpp/std/retry"     // bounded ctx-aware exponential backoff, last-error surfaced
import "goforge.dev/gpp/std/registry"  // freeze-after-boot sealed registry: post-freeze Register panics
import "goforge.dev/gpp/std/memo"      // compute-once cache: compute outside the lock, first-writer-wins identity
import "goforge.dev/gpp/std/closeonce" // idempotent Close with cached first error

All nine are authored in G++, tested under -race, and consumed in anger: envoy-go's drain manager is a latch, its clock package re-exports std/clock, and its dynamic-metadata bucket embeds a deepmap. No language changes in this release; the toolchain version moves with std per the one-version discipline.

origin/main

v0.11.0 — Deep Structure

The release that arms the rune kernel rewrite: every enum's recursive structure is now derivable, not hand-rolled.

// Self-recursive enums derive deep traversals (descent sees through
// binder wrappers like Scope{Name string; Body Tm} and slices):
for sub := range TmUniverse(t) { … }        // t + all subterms, preorder
t2 := TmTransform(t, simplify)              // bottom-up rewrite, copies slices

// Monomorphic enums derive structural equality with per-variant hooks —
// proof irrelevance is an override on a derived base, not a hand-written
// walk (handled=false falls through to the derived comparison):
irrelevant := TmEqOverrides{Cast: func(x, y Cast) (bool, bool) {
	return TmEqual(x.A, y.A) && TmEqual(x.B, y.B) && TmEqual(x.X, y.X), true
}}
TmEqualWith(a, b, irrelevant)

// std/option joins std/result: Of/Get at the comma-ok boundary,
// IsSome/IsNone, Map, Bind, UnwrapOr, OrElse.

Traversals and equality are nil-tolerant (optional fields like an elective type annotation pass through untouched), func/map/chan content makes equality silently underivable (closures have no structure), and variant doc comments now survive lowering onto the generated structs — generated Go documents itself on pkg.go.dev.

v0.10.0 — The Dogfood Rewrite

goforge.dev/cadence v0.2.0 is authored in G++ — the first external artifact rewritten in the language — and the rewrite drove three features home:

// Derived rapid generators for every enum (emission is demand-driven —
// law tests, or //gpp:derive gen — so rapid never enters go.mod uninvited):
s := GenStrategy(rt)

// Laws quantify over enums, drawn through the derived generator:
type Interpreter[T any] class {
	Serve(host T, r Region, s Strategy, ctx RequestContext) (Tree, error)
	law Fallback(host T, s Strategy) { … }
}
// → every instance gets a generated rapid property; violations shrink
//   to counterexamples like m={-1}

// Operations declare multiple results; tests are G++ too:
//   foo_test.gpp → foo_gpp_test.go (still a _test.go to the go tool)

In cadence, Strategy became a real sum (illegal states unrepresentable), the hand-rolled FallbackHolds died, and the fallback law is now part of the Interpreter class — proven automatically for every interpreter anyone writes.

v0.9.0 — Tooling: LSP, Editors, go generate

No language changes — this release is about living with gpp:

  • gpp lsp ships inside the binary (one version, always in lockstep): diagnostics as you type from the real gen pipeline run in memory, plus hover, goto-definition, and completion delegated to gopls over the generated Go and mapped back through the sourcemap. The server's dispatch layer is authored in gpp itself.
  • Editors: VS Code (marketplace-ready extension), Neovim, Zed, and GoLand/IntelliJ (platform LSP API) — all thin clients of gpp lsp; see editor/.
  • go generate is canonical: gpp init scaffolds //go:generate go tool gpp gen ./...; the workflow is go generate ./... && go build ./..., with the gpp wrapper as convenience.
  • Cross-package hardening: generated files carry a //gpp:v vintage stamp (a newer file tells you the exact upgrade command); marker reconstruction is package-wide; index domains cross packages (Socket[s states.State]); imported Eq propositions unfold their callee's totals; and a missing instance names the transitive package that provides one.

v0.8.0 — Parser Combinators (std/parsec)

import "goforge.dev/gpp/std/parsec"

// A complete arithmetic evaluator: precedence, parens, whitespace.
func grammar() parsec.Parser[int] {
	var expr parsec.Parser[int]
	factor := parsec.Label(parsec.Or(number(), parsec.Between(parsec.Symbol("("), parsec.Defer(&expr), parsec.Symbol(")"))), "expression")
	term := parsec.Chainl1(factor, mulOp())
	expr = parsec.Chainl1(term, addOp())
	return parsec.Then(parsec.Spaces(), parsec.Before(expr, parsec.EOF()))
}

v, err := parsec.RunString(grammar(), "(1+2)*3")   // 9
// errors carry positions and labels:
// 1:3: unexpected '*', expecting expression

Parsec-style consumed/empty semantics: Or commits once a branch has consumed input, Try restores the lookahead — the discipline that keeps performance predictable and errors precise. Input STREAMS from any io.Reader: the buffer retains only what a live Try could rewind to, split UTF-8 runes decode across read boundaries, and a byte-at-a-time reader parses identically to a string (rapid-tested, along with the monad identities, Or associativity, and Try-never-consumes). The library is gpp eating its own cooking: Reply is a gpp enum matched in every combinator, its derived Fold consumes replies without a match, and Run's output rides the v0.4 railway. Also in this release: the linear-value cell is atomic (CompareAndSwap), so even racing double-users get exactly one winner.

v0.7.0 — The Dependent Core

// Length-indexed vectors: the index is real, checked, and erased.
type Vec[T any, n nat] enum {
	Nil() Vec[T, 0]
	Cons(head T, tail Vec[T, n]) Vec[T, n+1]
}

// 0-quantity parameters exist only at check time:
func Head[T any](0 n nat, v Vec[T, n+1]) T {
	match v {
	case Cons(h, t): // Nil is impossible at n+1 — no other arm needed
		return h
	}
}

// Compiler-verified termination; callable in types:
total func Plus(a, b nat) nat {
	if a == 0 { return b }
	return Plus(a-1, b) + 1
}

// Propositional equality, discharged by the decider:
func Cast[T any](0 n nat, 0 m nat, 0 p Eq[n, m], v Vec[T, n]) Vec[T, m] {
	return v
}
w := Cast(1+1, 2, refl, v) // proves 1+1 = 2; erases to the identity

// Linearity — consumed exactly once, statically AND at runtime:
func Process(1 f *os.File) error { return f.Close() }

gpp now carries a real dependent core: quantities (QTT's 0/1/ω plus multiplicity variables), total functions with structural termination and guarded nat subtraction, enums indexed by nats, enum tags (typestate: Socket[Open]), and structured first-order data (Region[Circle(n), n]), a normalization-by-evaluation engine where n+m ≡ m+n is definitional, and a sound linear-arithmetic decider that prunes impossible match arms, discharges refl proofs, and justifies subtraction. Everything erases: indices vanish from the generated Go, exported dependent functions grow precise runtime guards for plain-Go callers, and linear values travel as generated use-once Lin[T] cells that panic on reuse. std/vec ships the length-indexed sequence. Where the decider cannot prove an obligation, the error names both sides and the workaround — stuck-with-guidance, never silent.

v0.6.0 — Folds, Full GADTs, Existentials, Delegation

// Structural GADT result types — any type expression per position:
type Expr[T any] enum {
	Wrap(inner Expr[T]) Expr[[]T]
	Flipped(a A, b B) Duo[B, A]      // cross-position
}

// Bounded existentials, erased at the boundary:
type Row[T any] enum {
	Packed[A fmt.Stringer](x A, tag string)
}

// Every enum derives a one-level fold (opt out: //gpp:derive off):
n := Fold(Some(7), OptionCases[int, string]{
	Some: strconv.Itoa,
	None: func() string { return "-" },
})

// Kotlin-style interface delegation:
type Logged struct {
	inner Store delegate   // Logged implements Store; override by declaring
	log   *log.Logger
}

GADT result arguments are now arbitrary type expressions, resolved by structural unification: possibility filtering, case heads, constructor inference, and refinement all work through composites and cross-position uses, and refinement wraps EVERY mismatched conversion boundary in an arm (naked returns included) — only actual mismatches wrap. Where Go's erasure cannot name a case head (a composite argument matched at a bare type parameter), the arm is a guided error and case _: covers it. Existential type variables must carry an interface bound — Go cannot express a match arm generic in a hidden type — and erase to that bound in fields, constructors, and binders. std/result now ships a derived result.Fold(r, result.ResultCases[T, E, R]{Ok: …, Err: …}).

v0.5.0 — Typeclasses

Lean-flavored classes, named instances, implicit dispatch, and a law-tested algebraic hierarchy — all lowering to plain Go witness structs a Go consumer can call directly:

type Monoid[T any] class {
	Semigroup[T]
	Empty() T
	law LeftId(a T) { return reflect.DeepEqual(Combine(Empty(), a), a) }
}

instance IntAdd Group[int] {
	Combine(a, b int) int { return a + b }
	Empty() int { return 0 }
	Invert(a int) int { return -a }
}

func Accumulate[T Monoid](xs []T) T {
	acc := Empty()
	for _, x := range xs {
		acc = Combine(acc, x)
	}
	return acc
}

Accumulate([]int{1, 2, 3})   // one Monoid[int] instance in scope: found implicitly

A class is an algebraic structure in the mathematical sense: a carrier set (the instantiating type) together with operations on it, satisfying declared laws — a Monoid is the triple (T, Combine, Empty) with associativity and a two-sided identity, and an instance names one concrete such structure. That is why int has TWO monoids, and why implicit resolution refuses to pick between them: with std/algebra imported, Accumulate([]int{…}) is ambiguous between IntAdd (a Group, by subsumption) and IntMul, and the error names both. You disambiguate by naming the structure you mean:

algebra.Accumulate(algebra.IntAdd, []int{2, 3, 4})  // 9  — the additive monoid
algebra.Accumulate(algebra.IntMul, []int{2, 3, 4})  // 24 — the multiplicative monoid

Explicit witnesses subsume exactly like implicit dispatch (v0.6.1): IntAdd is a Group instance, Accumulate wants a Monoid, and the compiler inserts the upcast — you name the structure, never the coercion.

A class lowers to a flat witness struct (Monoid[T] with func fields); an instance to a package value; a class constraint to a leading witness parameter that call sites receive implicitly. Classes embed to form hierarchies (diamonds collapse; upcasts are generated), operations may carry default bodies instances can omit, and a stronger instance satisfies a weaker constraint (a Group[int] instance answers a [T Monoid] call). Ambiguity is a hard error naming the candidates; the escape hatch is calling the lowered signature directly. law members declare boolean properties over the operations, and law tests generate by default for every concrete instance (rapid properties, inherited laws included) with //gpp:laws knobs (off, [int] [string] instantiations for generic instances, gen=, package-level out=). goforge.dev/gpp/std/algebra ships the Magma→Group hierarchy, stock instances, and Accumulate/FoldMap.

v0.4.0 — Typed Failure

Railway-Oriented error handling in the Wlaschin style: a shipped Result[T, E] library, track-aware pipelines, Kleisli composition, postfix ? propagation, and expression-oriented control flow.

import "goforge.dev/gpp/std/result"

// Track-aware |>: once a Result flows, stages lift by shape —
// T→Result binds, T→(U, error) adapts, T→U maps, T→() tees (Ok only),
// dot segments see the raw Result. Err bypasses everything.
n := s |> validate |> strings.TrimSpace |> strconv.Atoi |> audit |> .UnwrapOr(0)

// Kleisli >=>: compose fallible steps; plain steps lift, the rail
// opens at the first step that can fail, Err short-circuits.
pipeline := strings.TrimSpace >=> validate >=> strconv.Atoi >=> save
// (value, error) functions adapt automatically: strconv.Atoi >=> double

// Postfix ?: propagate failure to the enclosing function.
data := os.ReadFile(path)?          // (…, error) enclosing: zero-value early return
n := parse(s)?                      // Result enclosing: returns Err, typed errors preserved

// Expression-oriented if / switch / match — arms are single expressions.
y := if x > 2 { "big" } else { "small" }
grade := switch score {
case 10:
	"A"
default:
	"B"
}
area := match shape {
case Circle(r):
	3.14 * r * r
case Rect(w, h):
	w * h
}

goforge.dev/gpp/std is a nested module with zero dependencies, written in G++ and shipped as generated Go (go get goforge.dev/gpp/std). Result[T any, E error] carries typed failures; Of enters the railway from a Go-shaped (value, error) pair, Unpack leaves it. ? works with Result values, (…, error) calls, and bare errors, in both Go-shaped and Result-shaped functions. Expression forms hoist to statements before their anchor — hoisted sites evaluate before the rest of their statement, in source order — and a match expression gets the full v0.2.0 machinery: exhaustiveness, GADT refinement, nested patterns.

v0.3.0 — Functional Flow

Pipelines, composition, partial application, and placeholders — all lowering to the plain Go you would have written:

total := xs |> Filter(isEven) |> Map(double) |> Sum
// Sum(StackMap(StackFilter(xs, isEven), double))

answer := 21 |> Some |> .Map(double).UnwrapOr(0)

toStr  := double >>> strconv.Itoa      // func(int) string
inc    := add(1, _)                    // partial application
between:= clamp(_, lo, hi)             // placeholder anywhere in a call

x |> f(a) inserts the piped value as the first argument (a placeholder _ picks a different slot); bare-name segments are method-aware: they resolve against the piped value's members — full Go selector semantics plus G++ generic and enum methods — and against functions, constructors, builtins, and conversions in scope. Resolving to both is a hard error naming the two explicit spellings (.Map(f) for the member, Map(_, f) for the function). Multi-result stages follow Go's spread rule ("42" |> strconv.Atoi |> handle when handle(int, error)). >>> composes left-to-right into a capture-once closure, constructor operands included (double >>> Some). Partials capture their callee and fixed arguments exactly once at creation, method receivers bind-time.

v0.2.0 — Algebraic Data Types

Sum types with exhaustive pattern matching, constructor generation, and initial GADT support — lowered to sealed interfaces plus variant structs that plain Go consumes with an ordinary type switch:

// option.gpp
package option

type Option[T any] enum {
	Some(value T)
	None
}

func (o Option[T]) Map[U any](f func(T) U) Option[U] {
	match o {
	case Some(v):
		return Some(f(v))
	case None:
		return None
	}
}

match is exhaustive: a missing variant is a compile error with a witness (non-exhaustive match on Shape: missing Rect(_, _)), checked by Maranget usefulness so nested patterns like Add(Lit(a), Lit(b)) are covered correctly. Constructors infer their type arguments from arguments or the expected type (var o Option[int] = None), auto-wrap into closures in function position (xs.Map(Some)), and qualify (Option[int].None) when a name is genuinely ambiguous. GADT variants may pin their result type — Lit(v int) Expr[int] — excluding impossible arms and refining type parameters inside matching arms (the classic typed interpreter works). Emitted enums carry //gpp:enum///gpp:variant markers, so importing packages get constructors, matching, and exhaustiveness from the committed Go artifact alone.

// emitted
type Option[T any] interface{ isOption(T) }

type Some[T any] struct{ Value T }
func (Some[T]) isOption(T) {}
// … plain-Go consumer:
switch v := o.(type) {
case option.Some[int]:
	fmt.Println(v.Value)
}

v0.1.0 — Generic Methods

Methods may introduce type parameters not present on their receivers:

// stack.gpp
package stack

type Stack[T any] struct{ items []T }

func (s Stack[T]) Map[U any](f func(T) U) Stack[U] {
    out := Stack[U]{items: make([]U, 0, len(s.items))}
    for _, x := range s.items {
        out.items = append(out.items, f(x))
    }
    return out
}

gpp gen emits stack_gpp.go beside the source — committed to your repo, protobuf-style — lowering each generic method to a package-level generic function:

// Code generated by gpp from stack.gpp. DO NOT EDIT.

//gpp:method (Stack[T]) Map[U]
func StackMap[T any, U any](s Stack[T], f func(T) U) Stack[U] { … }

G++ callers keep method syntax — s.Map(strconv.Itoa) — including chained calls, explicit instantiation (s.Map[string](f)), method values (f := s.Map[string]), and promotion through embedded fields. Plain-Go consumers of your published package call stack.StackMap(s, strconv.Itoa). The //gpp:method marker makes the emitted file self-describing, so packages that import yours get method syntax too — even when your package is fetched as ordinary Go with go get.

CLI

# Canonical workflow: the go toolchain drives, gpp only generates.
gpp init                 # scaffold //go:generate wiring (flag: -hook)
go get -tool goforge.dev/gpp/cmd/gpp@latest   # pin gpp in go.mod (Go 1.24+)
go generate ./...        # regenerate *_gpp.go from *.gpp
go build ./...           # plain Go from here (test/vet/run likewise)

# Convenience wrapper: same thing, one word shorter.
gpp gen ./...            # generate *_gpp.go from *.gpp
gpp gen -check ./...     # exit 1 if any generated file is stale (CI)
gpp gen -stage ./...     # regenerate and git-add results (pre-commit)
gpp build|test|run|vet   # generate, then delegate to the go tool
gpp version

Install

go install goforge.dev/gpp/cmd/gpp@latest

The standard library is a separate, dependency-free module:

go get goforge.dev/gpp/std@latest

Keeping generated code fresh

Use the pre-commit framework:

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/brain-fuel/gpp
    rev: v0.1.0
    hooks:
      - id: gpp-gen

When outputs are stale, the first git commit attempt regenerates and stages the fixed files, then aborts (pre-commit's behavior for any hook that modifies files); retry the commit and it passes. gpp-check is a verify-only variant for CI.

Specification

The spec is executable: the Godog/Cucumber feature suite under features/ plus the grammar deltas in spec/ (one EBNF per milestone). Run it with go test ./....

Limitations (by design)

  • A lowered generic method is a function, not a method — it cannot help a type satisfy an interface. This is fundamental to the lowering (Go interfaces cannot express generic methods) and will not change.
  • Uninstantiated generic method values (f := s.Map) are errors, matching Go's rule for uninstantiated generic function values.
  • Match subjects may not start with (, [, {, or <- (those spellings stay valid Go); bind such subjects to a variable first. Literal patterns and guards arrive in a later milestone.
  • v0.2.0 GADT result-type arguments are the enum's own type parameter or a ground named type per position; refinement applies to T-typed returns (use any(x).(T) manually elsewhere).
  • |> and >>> are the lowest-precedence operators; xs |> len > 0 parses as xs |> (len > 0) and gets a parenthesize hint. Placeholders cannot stand for variadic parameters, and _.Method receivers wait for a later milestone.
  • ? and expression if/switch/match lower by hoisting statements, so they cannot appear where an early return or eager evaluation would change semantics: for conditions/post statements, else-if conditions, the right side of &&/||, case values, select communications, assignment left-hand sides, whole deferred/go calls, or package level (each is a guided error).

Roadmap

Version Theme
v0.1.0 Generic methods — shipped
v0.2.0 Algebraic data types, exhaustive matching — shipped
v0.3.0 Pipelines, composition, partial application — shipped
v0.4.0 Typed failure: std/result, railway pipes, Kleisli >=>, postfix ?, expression-oriented control flow — shipped
v0.5.0 Typeclasses: classes, instances, implicit dispatch, laws, std/algebra — shipped
v0.6.0 Folds, structural GADTs, bounded existentials, delegation — shipped
v0.7.0 The dependent core: QTT quantities, total functions, indexed enums, Eq, linearity, std/vec — shipped
v0.8.0 std/parsec: streaming parser combinators — shipped
v0.9.0 Tooling: gpp lsp + four editors, go generate canonical, cross-package hardening — shipped
v0.10.0 The dogfood rewrite: cadence v0.2.0 in G++; derived generators, laws over enums, multi-result ops, G++ tests — shipped
v0.11.0 Deep structure: derived traversals (Children/Universe/Transform), derived structural equality with overrides, std/option, variant doc preservation — shipped
v0.13.0 The standard library grows nine: kleene, latch, clock, guarded, deepmap, retry, registry, memo, closeonce (from the envoy-go rewrite) — shipped
v0.14.0 Multi-pattern match arms — shipped

License

MIT — see LICENSE.

Directories

Path Synopsis
cmd
gpp command
internal
bddtest
Package bddtest hosts the Godog step definitions and per-scenario World for the gpp spec suite.
Package bddtest hosts the Godog step definitions and per-scenario World for the gpp spec suite.
cli
Package cli implements the gpp command-line interface.
Package cli implements the gpp command-line interface.
core
Package core is gpp's dependent type theory (v0.7.0): first-order terms over nat and enum-tag data, normalization by evaluation, definitional equality, a linear-arithmetic decider, structural termination checking, and the QTT quantity semiring.
Package core is gpp's dependent type theory (v0.7.0): first-order terms over nat and enum-tag data, normalization by evaluation, definitional equality, a linear-arithmetic decider, structural termination checking, and the QTT quantity semiring.
diag
Package diag defines gpp's user-facing diagnostics.
Package diag defines gpp's user-facing diagnostics.
directive
Package directive parses and renders gpp directive comments:
Package directive parses and renders gpp directive comments:
emit
Package emit assembles, formats, and writes generated Go files.
Package emit assembles, formats, and writes generated Go files.
gen
Package gen orchestrates generation: it drives parsing, naming, lowering, and emission for every package matched by the CLI's patterns.
Package gen orchestrates generation: it drives parsing, naming, lowering, and emission for every package matched by the CLI's patterns.
lower
Package lower computes and applies the text edits that turn G++ source into Go.
Package lower computes and applies the text edits that turn G++ source into Go.
lsp
The server's dispatch layer, authored in gpp: incoming work is an enum, routing is a match, and extending the server means adding a variant and an arm — the language serving itself.
The server's dispatch layer, authored in gpp: incoming work is an enum, routing is a match, and extending the server means adding a variant and an arm — the language serving itself.
naming
Package naming implements the lowered-name scheme: a lowered function keeps its method's own name when that name is unique in the package, falling back to the receiver-prefixed concatenation when it collides — the same discipline enum variant structs use.
Package naming implements the lowered-name scheme: a lowered function keeps its method's own name when that name is unique in the package, falling back to the receiver-prefixed concatenation when it collides — the same discipline enum variant structs use.
registry
Package registry indexes the generic methods visible to a compilation: those declared in the packages being generated, plus those advertised by dependency packages via //gpp:method markers in their distributed Go.
Package registry indexes the generic methods visible to a compilation: those declared in the packages being generated, plus those advertised by dependency packages via //gpp:method markers in their distributed Go.
resolve
Package resolve rewrites G++ method-syntax uses of generic methods into calls (or closures) over the lowered package-level functions.
Package resolve rewrites G++ method-syntax uses of generic methods into calls (or closures) over the lowered package-level functions.
sourcemap
Package sourcemap maps positions in emitted Go back to .gpp source.
Package sourcemap maps positions in emitted Go back to .gpp source.
syntax
Package syntax parses .gpp source: Go grammar plus G++'s extensions — type parameters on methods (v0.1.0), enum declarations and match statements (v0.2.0).
Package syntax parses .gpp source: Go grammar plus G++'s extensions — type parameters on methods (v0.1.0), enum declarations and match statements (v0.2.0).
syntax/parser
G++ extension nodes and entry points.
G++ extension nodes and entry points.
toolchain
Package toolchain delegates to the standard go tool.
Package toolchain delegates to the standard go tool.
version
Package version is the single source of the toolchain version — a leaf package so both the CLI and the emitter (which stamps generated files) can share it without cycles.
Package version is the single source of the toolchain version — a leaf package so both the CLI and the emitter (which stamps generated files) can share it without cycles.
std module

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL