starlarkbridge

package
v0.1.0-dev.20260820235215 Latest Latest
Warning

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

Go to latest
Published: Aug 20, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package starlarkbridge bridges the Go framework and Starlark scripts.

It converts values in both directions, exposes provider receivers as Starlark globals, and runs scripts through a per-session Runtime that borrows the op.RuntimeEnvironment.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewGoReceiver

func NewGoReceiver(value any) (starlark.HasAttrs, error)

NewGoReceiver wraps a Go value as a starlark surface bound to its receiver type.

The bridge resolves the receiver type via op.ResolveReceiverType from `value`'s reflect type — using the announced type (with its `MethodMetadata`: parameter names, property `Modifiers`) when one is registered, and deriving via reflection otherwise — and returns a goReceiver carrying that type plus the wrapped instance. Routing through the same env-free resolver the projection path uses means an ad-hoc wrap of a registered type carries its metadata, rather than a bare reflection-derived surface. NewGoReceiver is the ad-hoc wrapper where the type must be inferred from the value; the Runtime builds its provider modules through [newGoReceiver] directly.

Parameters:

  • `value`: the Go value to wrap.

Returns:

  • [`starlark.HasAttrs`]: the bound starlark surface, ready for [goReceiver.AttrNames] / [goReceiver.Attr] / [goReceiver.Type].
  • `error`: non-nil if a receiver type cannot be resolved from `value`'s reflect type.

func NewProvider

func NewProvider(receiverType op.ReceiverType, instance any) starlark.HasAttrs

NewProvider wraps a Go provider instance as a starlark surface bound to the supplied receiver type.

The provider variant of NewGoReceiver: the caller has already produced (or looked up) the matching op.ReceiverType and passes it explicitly, skipping the type derivation step. The receiver's converter is derived from the instance's environment when the instance is an env-bearing provider. The generated module tests call it.

Parameters:

  • `receiverType`: the provider receiver type descriptor.
  • `instance`: the Go provider instance.

Returns:

func NoSuchAttrError

func NoSuchAttrError(typeName, attr string) error

NoSuchAttrError returns a starlark-style "no such attribute" error for a given type and attribute name.

Centralized so the wording and quoting stay consistent across the bridge.

Parameters:

  • `typeName`: the receiver type's name.
  • `attr`: the missing attribute name.

Returns:

func StarlarkToGoTyped

func StarlarkToGoTyped(env *op.RuntimeEnvironment, sv starlark.Value, target reflect.Type) (any, error)

StarlarkToGoTyped converts a starlark.Value into a value of the declared Go target type.

The cascade: starlark None short-circuits to nil; otherwise [converter.toGo] produces an `any` value in its natural Go shape, then op.Convert routes through registered converters and Resource constructors to land on `target`. The environment's op.ReceiverRegistry is consulted for Resource construction.

This is the public façade over [converter]; external callers convert through it rather than naming the type.

Parameters:

  • `env`: the runtime environment the [converter] is built from; its registry is consulted by op.Convert.
  • `sv`: the starlark value to convert.
  • `target`: the declared Go target type.

Returns:

  • `any`: the converted Go value (nil for starlark None).
  • `error`: non-nil if conversion fails.

Types

type Invoker

type Invoker interface {

	// CallStarlark invokes callable with the given Go arguments on a fresh Starlark thread and returns its result as a
	// native Go value.
	//
	// Each positional and keyword argument is converted to Starlark, the call runs on a thread minted for this
	// invocation (Starlark threads are not safe for concurrent reuse, so a per-call — hence per-goroutine — thread is
	// the only correct choice), and the result is converted back to Go. Keyword arguments are passed in sorted-name
	// order for determinism.
	//
	// Parameters:
	//   - `callable`: the Starlark callable to invoke.
	//   - `args`: the positional arguments, as native Go values; nil for none.
	//   - `kwargs`: the keyword arguments, as native Go values; nil for none.
	//
	// Returns:
	//   - `any`: the call's result as a native Go value.
	//   - `error`: non-nil when an argument or the result cannot be converted, or the call itself fails.
	CallStarlark(callable starlark.Callable, args []any, kwargs map[string]any) (any, error)
}

Invoker is the provider-facing surface for calling a Starlark callable from Go.

A provider that captured a Starlark callable — e.g. function.Resource holding a *starlark.Function reducer — builds its own Invoker via NewInvoker and calls through it. The Invoker takes native Go arguments and returns a native Go result, owning every Go↔Starlark conversion and the per-goroutine thread discipline, so providers stay Go-native and re-roll neither.

func NewInvoker

func NewInvoker() Invoker

NewInvoker returns a new Invoker over an env-free converter.

The invoker path performs no environment-dependent conversion — toStarlark and toNaturalGo never read the converter's environment — so no runtime environment is needed. Each consumer builds its own instance rather than sharing one through a registry.

Returns:

  • `Invoker`: a ready-to-use invoker over an env-free converter.

type Projector

type Projector interface {
	Project(target reflect.Type) (any, error)
}

Projector is implemented by starlark.Values that know how to project themselves into a Go target type.

Projector is the bridge's contract for "given a target type, give me a Go value of that type." The wrapper implements it by running op.Convert's cascade on its wrapped Go instance. Plan-time references (Promise, Invocation) implement it by selecting one of their legal handles based on the target type — for example, Promise projects to *Promise, op.PromiseBinding, or itself-as-interface depending on what the caller wants.

The slot-fill dispatch type-asserts against this interface to detect any starlark.Value with a Go-side projection path, regardless of mechanism. The interface is the contract; concrete types choose how to satisfy it.

type Runtime

type Runtime struct {
	// contains filtered or unexported fields
}

Runtime manages a Starlark scripting runtime.

It constructs providers as Starlark globals from the selected modules and provides the @devlore// module loader.

func NewRuntime

func NewRuntime(env *op.RuntimeEnvironment, options ...RuntimeOption) *Runtime

NewRuntime creates a fully initialized runtime that borrows the supplied op.RuntimeEnvironment.

The runtime does NOT own the env's lifetime — the caller (typically an op.Plan closure, a tool session-owner like [star.Application], or a wrapper that explicitly built the env) constructs the env, passes it here for the duration of starlark work, and is responsible for `defer env.Close()`. Providers are constructed and cached as the predeclared starlark globals from the env's selected `Modules`.

Parameters:

  • `env`: the runtime environment to borrow. The full module set is exposed as starlark globals.
  • `options`: zero or more RuntimeOption that narrow or otherwise configure this runtime's predeclared surface. Example: DenyAttributes. They are applied in order before the surface is built.

Returns:

  • `*Runtime`: the initialized runtime borrowing the supplied env.

func (*Runtime) Environment

func (rt *Runtime) Environment() *op.RuntimeEnvironment

Environment returns the runtime environment context.

Returns:

  • `*op.RuntimeEnvironment`: the environment.

func (*Runtime) Invoke

func (rt *Runtime) Invoke(script, root string) (result starlark.StringDict, err error)

Invoke executes a starlark script.

Script loading is confined to root via os.OpenRoot — relative load calls cannot escape. The `@devlore//` module loader resolves provider names from the registry. Dry-run mode is read from the tool's [application.Application] (carried on the shared op.RuntimeEnvironment); the caller does not pass it per-invocation.

Parameters:

  • `script`: path to the script file, relative to root.
  • `root`: filesystem root for script loading (confined via os.OpenRoot).

Returns:

  • `[starlark.StringDict]`: the script's global bindings after execution.
  • `error`: non-nil if the script fails to load or execute.

func (*Runtime) Modules

func (rt *Runtime) Modules() []op.ProviderReceiverType

Modules returns the selected modules.

Returns:

  • `[]op.ProviderReceiverType`: the module list.

func (*Runtime) NewModule

func (rt *Runtime) NewModule(name string) (starlark.Value, bool)

NewModule constructs a new starlark.Value for the named provider.

Parameters:

  • `name`: the provider name to build.

Returns:

  • `starlark.Value`: the constructed starlark.Value, or nil if not found.
  • `bool`: true if the provider was found in the selected modules.

func (*Runtime) Predeclared

func (rt *Runtime) Predeclared() starlark.StringDict

Predeclared returns the cached predeclared starlark globals dict built from the selected modules.

Returns:

  • `starlark.StringDict`: the predeclared globals.

type RuntimeOption

type RuntimeOption func(*Runtime)

RuntimeOption configures a Runtime at construction time.

An option is a closure that mutates the partially built runtime; NewRuntime invokes each in order after allocating the runtime and before building its predeclared surface. The type is exported so callers can pass options, but its safety rests on `Runtime`'s unexported fields: an option authored outside this package receives the *Runtime yet can reach only its exported methods, so only this package can write an option that actually configures internal state.

func DenyAttributes

func DenyAttributes(global string, names ...string) RuntimeOption

DenyAttributes hides the named attributes on a predeclared top-level global, for this runtime only.

The underlying provider's Go methods are untouched — only this runtime's starlark projection of `global` is narrowed. A denied attribute is neither callable ([filteredReceiver.Attr] returns an error) nor advertised (omitted from [filteredReceiver.AttrNames]). Repeated calls for the same global union their name sets. The mechanism is generic and tool-agnostic: the bridge enforces "this runtime hides these names"; the calling tool owns the policy of which names, and why.

Parameters:

  • `global`: the predeclared top-level global whose attribute surface is narrowed (e.g. `"plan"`).
  • `names`: the attribute names to hide on that global.

Returns:

  • `RuntimeOption`: an option that records the denial, applied by NewRuntime.

Jump to

Keyboard shortcuts

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