On this page

Compatibility and limits

Pipit has its own compiler and runtime. It type-checks source as Go 1.27 and supports many Go language features, but does not claim complete compatibility. Check your programs when adopting or upgrading it, especially code that relies on reflection or native interfaces.

Language and packages

The language tests and parity corpus exercise functions, methods, interfaces, generics, closures, slices, maps, channels, goroutines, defer, and panic/recover. The corpus compares interpreted results with native Go. Passing these cases does not imply every combination is supported. Restricted execution also deliberately disables some features; see execution security.

Host package registration makes native symbols available for imports. stdlib.WithStandardLibrary() registers the bundled set; smaller bundles and custom providers are described in Embedding.

The standard-library registry excludes syscall, plugin, runtime/cgo, runtime/race, runtime/trace, and runtime/coverage. The compiler handles unsafe separately. log/syslog is available only on platforms that provide it.

Use pipit symbols list to inspect the CLI's actual registrations. Embedders can inspect stdlib.Exports(); pipit.StandardLibraryPaths() provides package names without linking the symbol tables.

Known limitations

FeatureCurrent behaviour and alternatives
//go:embedRejected. Read data at run time with explicitly granted filesystem access.
Named array, slice, map, channel, or function typesRuntime identity is shared with the underlying type; interface dispatch and formatting through any can select or lose methods. See below.
reflect.Type method valuesTaking rt.Field or rt.FieldByName as a function bypasses source-field interception. Call the methods directly.
Native package variable writesAssignments can mutate the host's variable. Restricted feature sets reject these unsafe operations.
iter.Pull / iter.Pull2Use a parked goroutine. Call stop when abandoning iteration.
runtime.SetFinalizerRegisters no finalizer for interpreted values.
Slice capacityGrowth can differ from the native compiler's allocation policy.
Recovered runtime errorsMessage text follows Go, but %T reports Pipit's error type.
Deep recursionInterpreted frames use more memory. Set call-depth limits for your workload.

Named types and native interfaces

Named structs and named basic types have distinct runtime identities. Named types with array, slice, map, channel, or function underlying types do not. Direct calls where the compiler knows the type can work, while operations on a runtime interface value may not.

For example, sort.Sort(ByAge(people)) can reach the declared methods through a native adapter. A method call on an interface stored in script code can instead reach the last declared type with that underlying runtime type. Similarly, storing a value in any before formatting can lose its String method.

Returned values

Eval returns ordinary integer expressions as int, and explicitly typed numeric values as their declared types. Boxing into any preserves sized numeric types. float32 and complex64 operations round back to single precision after each operation. The named-type limitations above still apply.

Native and browser execution

Native functions may require facilities unavailable in a browser even if their symbols are registered. Browser applications must provide their own worker lifecycle and termination controls; Pipit's interpreter limits do not supply a browser-wide memory limit.

Bytecode compatibility

pipit.BytecodeVersion identifies the schema. Keep producer and consumer versions and host symbols compatible. Persisted bytecode is not a universal portable binary and its schema marker does not authenticate its contents. Recompile from source when upgrading across incompatible versions.

Call-stack inspection

runtime.Caller, runtime.Callers, runtime.CallersFrames, runtime.FuncForPC, runtime.Stack, and runtime/debug stack helpers describe interpreted frames. They report source positions, qualified Go function names, and synthetic program counters that the stack helpers can decode.

Differences from native Go:

  • Extra native runtime-error frames are absent, so fixed Caller(n) offsets can differ.
  • A function value's reflect.Value.Pointer() does not map back through FuncForPC.
  • Interpreted callbacks invoked by native functions see only their own frames.
  • Programs loaded from bytecode have no source positions.

Execution limits

See execution security for resource-limit coverage and native-call limitations. See concurrent use before evaluating source from more than one goroutine.