Skip to content

package codegen

import "github.com/cloudboss/unobin/pkg/codegen"

Package codegen generates Go source for compiled factories and UB libraries.

It emits main.go for a factory binary and package files for imported UB libraries. Generated code embeds typed syntax bodies, resolved import tables, and compile-extracted Go library metadata that the runtime needs during plan, apply, validate, and refresh.

Functions

func ContentRevision

func ContentRevision(dir string) (string, error)

ContentRevision returns a short content-addressable revision for the generated library in dir. It hashes every Go source file plus go.mod and go.sum in sorted path order, so the result is a stable fingerprint of the factory source, the inlined UB libraries, and the full pinned Go dependency set that go.sum records. The compiled binary itself is excluded; only build inputs contribute. Run it after `go mod tidy` so go.sum is present.

func EncodeNode

func EncodeNode(n lang.Node) (string, error)

EncodeNode renders a parsed `lang` AST node as a Go expression that constructs an equivalent value. The expression evaluates to the matching `lang` pointer type (`*lang.File` for a File, `*lang.Field` for a Field, the matching `*lang.X` for any expression node).

Source positions are not encoded; the produced node has zero Span values. The encoder handles every plain expression node and every `TypeExpr` node; callers must not pass a node kind the parser does not produce as part of a body.

func EncodeSyntaxFactoryBody

func EncodeSyntaxFactoryBody(n syntax.FactoryBody) (string, error)

EncodeSyntaxFactoryBody renders a typed factory or composite body as a Go expression. Source positions are omitted; runtime graph extraction only needs declaration names, selectors, and expression bodies.

func EncodeSyntaxFactoryBodyWithSpans

func EncodeSyntaxFactoryBodyWithSpans(
    n syntax.FactoryBody,
    spanName SyntaxSpanNamer,
) (string, error)

EncodeSyntaxFactoryBodyWithSpans renders a body while preserving source spans.

func Generate

func Generate(in Input) ([]byte, error)

Generate produces the formatted Go source for the factory binary's main.go. The result is the bytes a caller writes to disk and feeds through `go build`.

func GenerateLibrary

func GenerateLibrary(
    packageID string,
    library program.Library,
    packagePaths map[string]string,
) ([]byte, error)

func GenerateUBLibrary

func GenerateUBLibrary(
    alias string,
    syntaxBodies map[string]map[string]syntax.FactoryBody,
    imports map[string]map[string]map[string]string,
    goSpecs map[string]GoLibrarySpecs,
) ([]byte, error)

GenerateUBLibrary produces the Go source for a UB library's generated package. The package's name is alias; it exports a `Library()` function returning a `*runtime.Library` whose composites are split into one map per kind (ResourceComposites, DataComposites, ActionComposites). syntaxBodies are keyed by kind and then composite name; each generated registration uses SyntaxBody.

imports maps each composite's kind and name to its resolved import table: the composite's body's own imports block, with each declared alias mapped to the Go import path of the package that supplies it. The generated source emits one Go-level import per unique path and renders a per-composite `Libraries` map binding each composite-local alias to the corresponding package's `Library()`. Pass nil or an empty map when a composite has no imports.

goSpecs maps a Go import path to the specs its types declare. A bound library with specs is constructed once in `Library()`, has its Constraints and Defaults attached, and every binding of that path shares the instance, so a composite-internal node resolves the same spec data a root import of the library would.

func GenerateUBLibraryPackage

func GenerateUBLibraryPackage(
    packageID string,
    libraryName string,
    syntaxBodies map[string]map[string]syntax.FactoryBody,
    imports map[string]map[string]map[string]string,
    goSpecs map[string]GoLibrarySpecs,
    sourceFiles map[string]syntax.SourceFileSpec,
) ([]byte, error)

GenerateUBLibraryPackage produces a UB library package whose Go package identifier can differ from the runtime library name.

func GenerateUBLibraryPackageWithAssets

func GenerateUBLibraryPackageWithAssets(
    packageID string,
    libraryName string,
    syntaxBodies map[string]map[string]syntax.FactoryBody,
    imports map[string]map[string]map[string]string,
    goSpecs map[string]GoLibrarySpecs,
    sourceFiles map[string]syntax.SourceFileSpec,
    assetSetIDs map[string]map[string]string,
) ([]byte, error)

GenerateUBLibraryPackageWithAssets includes the captured asset-set ID for each composite body.

func GenerateUBLibraryPackageWithAssetsAndConfigSchemas

func GenerateUBLibraryPackageWithAssetsAndConfigSchemas(
    packageID string,
    libraryName string,
    syntaxBodies map[string]map[string]syntax.FactoryBody,
    imports map[string]map[string]map[string]string,
    goSpecs map[string]GoLibrarySpecs,
    sourceFiles map[string]syntax.SourceFileSpec,
    assetSetIDs map[string]map[string]string,
    libraryConfigSchemas map[string]map[string]map[string]runtime.LibraryConfigSchema,
) ([]byte, error)

GenerateUBLibraryPackageWithAssetsAndConfigSchemas includes the captured asset-set IDs and resolved library-config schemas for each composite body.

func WriteSource

func WriteSource(
    dir string,
    in Input,
    goVersion, unobinVersion string,
    importVersions map[string]string,
    replaces Replaces,
) ([]filechange.Change, error)

WriteSource lays out a generated binary's source tree in dir, ready for `go build` to consume. It writes:

<dir>/main.go                 // From Generate.
<dir>/internal/<id>/<id>.go   // From Input.UBPackages.
<dir>/go.mod                  // With the right require statements.
<dir>/go.sum                  // Reset for Go dependency resolution.

Source and captured assets are owned outputs. Go may edit module files during dependency resolution; regeneration replaces them with the current requirements. Directories from earlier versions without a manifest require a fresh output path.

goVersion is the Go toolchain version to declare. unobinVersion is the version of `github.com/cloudboss/unobin` the generated binary depends on. importVersions maps each library's Go import path to the version constraint to require for callers that have not set Input.GoModules. replaces maps a module path to a local path to substitute via `replace`.

Types

type GeneratedImports

type GeneratedImports struct {
    GoImports  map[string]string
    UBImports  map[string]string
    UBPackages map[string][]byte
}

func GenerateImports

func GenerateImports(imports *program.Imports, factoryName string) (*GeneratedImports, error)

type GoLibrarySpecs

type GoLibrarySpecs = program.LibrarySpec

GoLibrarySpecs holds one Go library's compile-extracted spec data, keyed by "\.\" the way runtime.Library stores it. The dev CLI gathers it from the library's source; codegen embeds it in generated code so the runtime can look it up at plan and apply.

type Input

type Input struct {
    FactoryBody   syntax.FactoryBody
    FactorySource syntax.SourceFileSpec
    // Body is a test convenience for callers that have a small source fragment.
    Body           string
    LibraryPath    string
    FactoryName    string
    BuildProfile   program.BuildProfile
    AssetBundle    []byte
    HasAssets      bool
    RootAssetSetID string
    GoImports      map[string]string
    GoModules      map[string]string
    UBImports      map[string]string
    // UBPackages contains generated UB-library source keyed by its local package ID.
    UBPackages map[string][]byte
    // GoConstraints maps a Go-library alias to its types' cross-field
    // constraints (kebab type name -> specs), gathered by the dev CLI
    // from the library's source. codegen attaches them to the library in
    // the generated main.go so the plan can check each node against them.
    GoConstraints map[string]map[string][]lang.ConstraintSpec
    // GoDefaults maps a Go-library alias to its types' declared input
    // defaults, gathered the same way and attached the same way, so the
    // runtime can fill them into evaluated bodies.
    GoDefaults map[string]map[string][]lang.DefaultSpec
    // GoSchemas maps a Go-library alias to schema metadata the compiled
    // runtime needs after compile-time checks, such as sensitive fields.
    GoSchemas map[string]*runtime.LibrarySchema
    // LibraryConfigSchemas maps library-config paths to schemas resolved by
    // source analysis, including schema packages not listed in imports.
    LibraryConfigSchemas map[string]runtime.LibraryConfigSchema
}

Input bundles everything codegen needs to produce a factory binary's `main.go`. FactoryBody is the typed factory body the binary executes. LibraryPath is the binary's library-path identity, the same form Go libraries use; the operator's stack file asserts the same value under `factory.pin.library-path` and plan, refresh, and validate refuse on mismatch. An empty LibraryPath disables that identity check. The version and content-revision are not generated here; compile stamps them into the built binary with -ldflags so the generated source stays a pure function of the factory content. GoImports maps each Go-library alias the source uses to the Go import path that supplies it (e.g., `"std" -> "github.com/cloudboss/unobin-library-std"`). GoModules maps each required Go module path to the selected version for go.mod. A Go package import below a module appears only in GoImports. UBImports maps each UB-library alias to the local Go import path of the package that compile generated for it (typically `\/internal/\`).

type Replaces

type Replaces map[string]string

Replaces maps a library path to a local filesystem path to substitute at build time, used in the generated `go.mod`'s replace directives. The value is typically the absolute path to a local checkout. An empty map means no replace directives.

type ScaffoldInput

type ScaffoldInput struct {
    OutDir        string
    TypeName      string
    Force         bool
    UnobinVersion string
}

type ScaffoldOutput

type ScaffoldOutput struct {
    OutDir string
    Files  []filechange.Change
}

func ScaffoldFactory

func ScaffoldFactory(input ScaffoldInput) (*ScaffoldOutput, error)

func ScaffoldLibrary

func ScaffoldLibrary(input ScaffoldInput) (*ScaffoldOutput, error)

type SyntaxSpanNamer

type SyntaxSpanNamer func(parse.Span) string

SyntaxSpanNamer names a compact generated expression for one source span.