Documentation
¶
Overview ¶
Package perl embeds the Perl interpreter — compiled to wasm and transpiled to pure Go — behind a sandboxed, multi-instance API. Each Perl value is an isolated interpreter: its own memory, filesystem view, and environment. No cgo, no system perl.
Index ¶
- func Adopt[T PerlValue](c *Perl, v T) (T, error)
- func As[T PerlValue](v Value) (T, error)
- func ExitCode(err error) (int, bool)
- func ExtractStdlib() (string, error)
- type ArrayValue
- func (v ArrayValue) Index(ctx context.Context, i int) (Value, error)
- func (v ArrayValue) Kind() Kind
- func (v ArrayValue) Len(ctx context.Context) (int, error)
- func (v ArrayValue) Push(ctx context.Context, vals ...Value) error
- func (v ArrayValue) Ref() RefValue
- func (v ArrayValue) SetIndex(ctx context.Context, i int, val Value) error
- func (v ArrayValue) Values(ctx context.Context) ([]Value, error)
- type CodeValue
- type Config
- type FS
- type File
- type GlobValue
- type GoFunc
- type HashValue
- func (v HashValue) Delete(ctx context.Context, key string) error
- func (v HashValue) Get(ctx context.Context, key string) (Value, bool, error)
- func (v HashValue) Keys(ctx context.Context) ([]string, error)
- func (v HashValue) Kind() Kind
- func (v HashValue) Ref() RefValue
- func (v HashValue) Set(ctx context.Context, key string, val Value) error
- type IOValue
- type Kind
- type MemFS
- type Pair
- type Perl
- func (p *Perl) AddInc(ctx context.Context, dirs ...string) error
- func (p *Perl) AddXSDir(dir string) error
- func (p *Perl) Bind(name string, fn GoFunc) error
- func (p *Perl) BindClass(name string, methods map[string]GoFunc) error
- func (p *Perl) Call(ctx context.Context, name string, args ...Value) ([]Value, error)
- func (p *Perl) Clone() (*Perl, error)
- func (p *Perl) Close() error
- func (p *Perl) Eval(ctx context.Context, src string) (Result, error)
- func (p *Perl) NewArray(ctx context.Context, vals ...Value) (ArrayValue, error)
- func (p *Perl) NewHash(ctx context.Context, pairs ...Pair) (HashValue, error)
- func (p *Perl) RunFile(ctx context.Context, path string, incDirs []string, args []string) error
- type PerlError
- type PerlValue
- type RefValue
- func (v RefValue) Can(ctx context.Context, method string) (bool, error)
- func (v RefValue) Class() (string, bool)
- func (v RefValue) Deref(ctx context.Context) (Value, error)
- func (v RefValue) Equal(o RefValue) bool
- func (v RefValue) Isa(ctx context.Context, class string) (bool, error)
- func (v RefValue) Kind() Kind
- func (v RefValue) MethodCall(ctx context.Context, method string, args ...Value) ([]Value, error)
- type Result
- type ScalarType
- type ScalarValue
- type Value
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Adopt ¶ added in v0.2.0
Adopt returns v as seen by c, a clone of the instance v was obtained from. Cloning copies the guest memory wholesale — the handle registry included — so a reference obtained in the prototype BEFORE its first Clone designates the same (copied) value in every clone under the same handle. Scalars are instance-free and pass through unchanged.
func As ¶ added in v0.2.0
As extracts the concrete type T from v, for call sites that know the expected type up front; a kind mismatch is an error, never a panic. For runtime inspection use a type switch over the concrete types instead.
func ExitCode ¶ added in v0.2.0
ExitCode reports whether err (from Eval, Call, or RunFile) is the guest terminating itself with a Perl-level exit(), and returns the exit status. An embedder running a whole script typically forwards the status to os.Exit after Closing the instance — a Call-surfaced exit leaves the interpreter cleanly unwound, so Close still flushes PerlIO and runs END blocks. (An exit during Eval reaches the host as a raw wasi proc_exit instead; that instance should only be Closed.)
func ExtractStdlib ¶
ExtractStdlib unpacks the embedded standard library into a temporary directory (once per process) and returns its path. The result is cached, so repeated calls — e.g. one per Interpreter — are cheap. The returned directory is the value to pass as Config.StdlibDir (it becomes @INC via perl_new).
Types ¶
type ArrayValue ¶ added in v0.2.0
type ArrayValue struct {
// contains filtered or unexported fields
}
ArrayValue is a Perl array (AV), viewed through the reference that reached Go. Operations run real Perl element accesses, so ties and overloads behave as in plain Perl; a die comes back as *PerlError.
func (ArrayValue) Index ¶ added in v0.2.0
Index returns $array[i] (Perl indexing: negative counts from the end).
func (ArrayValue) Len ¶ added in v0.2.0
func (v ArrayValue) Len(ctx context.Context) (int, error)
Len returns scalar @array.
func (ArrayValue) Push ¶ added in v0.2.0
func (v ArrayValue) Push(ctx context.Context, vals ...Value) error
Push appends vals to the array. An ArrayValue or HashValue among vals flattens into its contents, exactly like push @a, @b, %h in Perl.
func (ArrayValue) Ref ¶ added in v0.2.0
func (v ArrayValue) Ref() RefValue
Ref returns the reference to this array (\@a).
type CodeValue ¶ added in v0.2.0
type CodeValue struct {
// contains filtered or unexported fields
}
CodeValue is a Perl subroutine (CV), viewed through the code reference that reached Go.
func (CodeValue) Call ¶ added in v0.2.0
Call invokes the subroutine in list context and returns its return list. An ArrayValue or HashValue among args flattens into the argument list, exactly like f(@a, %h) in Perl; pass Ref() to pass the reference itself. A die comes back as *PerlError.
func (CodeValue) CallScalar ¶ added in v0.2.0
CallScalar invokes the subroutine in scalar context and returns its single result.
type Config ¶
type Config struct {
// StdlibDir is the path INSIDE the instance's filesystem (Config.FS)
// holding the Perl standard library (the assembled lib/ tree); it
// becomes @INC via perl_new. Empty defaults to "/" — right for the
// library default and for NewStdlibMemFS. An instance on the host
// filesystem (fs.NewHostFS) points this at a host directory, e.g. the
// one ExtractStdlib returns.
StdlibDir string
// Env is the environment the guest sees (%ENV). nil means an empty
// environment — the host process os.Environ() is NOT leaked.
Env []string
// Dial is the outbound-connection whitelist. It is called before each
// connect with the network ("tcp"), the host NAME the guest asked for
// (empty when it connected to a literal address), the resolved
// dotted-quad IP, and the port; returning false denies the connection.
// Receiving both the name and the IP lets policy match them jointly, and
// the connection is made to the exact approved IP (no DNS rebinding).
// FAIL-CLOSED: a nil Dial denies ALL outbound connections.
Dial func(network, host, ip string, port int) bool
// Resolve is the name-resolution whitelist. It is called with the host
// being resolved before each lookup; returning false denies it.
// FAIL-CLOSED: a nil Resolve denies ALL lookups (so a hostname
// connection needs both Resolve and Dial; a literal-IP connection needs
// only Dial).
Resolve func(host string) bool
// Stdin, when non-nil, backs the guest's fd 0 (STDIN). Defaults to an
// empty stream (the host process stdin is NOT used).
Stdin io.Reader
// Stdout, when non-nil, receives the guest's fd 1 writes (os-level
// stdout). Note: Perl-level print output is also captured into
// Result.Stdout by the bridge; Stdout here is the raw fd sink.
Stdout io.Writer
// Stderr, when non-nil, receives the guest's fd 2 writes.
Stderr io.Writer
// MaxMemoryBytes, when > 0, caps this instance's wasm linear memory.
// A guest allocation that would grow memory past this limit fails
// (memory.grow returns -1) instead of growing the host process unbounded.
// Rounded down to a multiple of the 64 KiB wasm page size; values below
// the module's initial memory are ignored.
MaxMemoryBytes int
// MemoryReserveBytes, when > 0, is the initial linear-memory slice
// capacity reserved for this instance. Reserving capacity up front makes
// boot-time grows zero-copy reslices, dropping a freshly-booted
// instance's resident memory. The reservation is virtual address space,
// not resident memory. Only consulted when the instance boots privately;
// an instance built on the copy-on-write process snapshot maps the
// snapshot instead. When 0, a default headroom is used.
MemoryReserveBytes int
// Exec is the subprocess whitelist. It is called before every process
// spawn with the executable path and full argv; returning false denies
// the spawn. Spawning runs a HOST binary, so a sandbox that allows
// subprocess should set this to a strict allow-list. FAIL-CLOSED: a nil
// Exec denies ALL spawns.
Exec func(path string, argv []string) bool
// FS, when non-nil, is the filesystem backend this instance sees as its
// entire guest filesystem ("/"). Every file operation is routed to it, so
// giving two instances separate FS values isolates them completely.
//
// The go-perl/fs package provides the backends: fs.NewMemFS (private
// in-memory), fs.NewHostFS (pass-through to the operating system's
// filesystem - how the perl command behaves, and what gperl uses),
// fs.DirFS (the host filesystem scoped to one directory), or any other
// fs.FS implementation.
//
// When nil, the instance gets a PRIVATE in-memory filesystem
// pre-loaded with the standard library (NewStdlibMemFS), so a library
// embedding never touches the host disk unless explicitly asked to.
FS FS
}
Config configures a new Perl instance created by New. The zero value is a usable, FULLY SANDBOXED interpreter: a private in-memory filesystem pre-loaded with the embedded standard library, an empty environment (the host process env is not leaked), sandboxed stdio, and every capability hook denying — no outbound connections, no name resolution, no subprocess spawns. Each capability is granted explicitly by setting its field.
type FS ¶
FS is the read/write filesystem backend a Perl instance is given via Config.FS. It is a write-capable superset of io/fs.FS; implementations live in the go-perl/fs package.
type GlobValue ¶ added in v0.2.0
type GlobValue struct {
// contains filtered or unexported fields
}
GlobValue is a typeglob (GV) — a filehandle in most user code. Opaque for now: it can be inspected, held, and passed back to Perl; operations are added as needs arise.
type GoFunc ¶ added in v0.2.0
GoFunc is a Go function callable from Perl. args is the Perl call's argument list as typed Values (references arrive as handle-bearing Values); the returned slice becomes the Perl call's return list. Returning an error makes the Perl call die with the error text.
fn may call back into the instance (Eval, Call, value operations) — the invoke lock is released for the callback's duration, and a nested entry from the handler's own goroutine is safe. What deadlocks is HOST-side lock cycles: a handler that blocks on something only the code that initiated the outer call can provide (a mutex it holds, a channel it will only service after the call returns) waits forever. Keep handlers self-contained or hand work to other goroutines without waiting on the outer caller.
type HashValue ¶ added in v0.2.0
type HashValue struct {
// contains filtered or unexported fields
}
HashValue is a Perl hash (HV), viewed through the reference that reached Go. Operations run real Perl accesses, so ties behave as in plain Perl.
type IOValue ¶ added in v0.2.0
type IOValue struct {
// contains filtered or unexported fields
}
IOValue is a filehandle body (IO). Opaque for now, like GlobValue.
type Kind ¶ added in v0.2.0
type Kind uint8
Kind is the runtime kind of a Value, one level finer than the concrete type for scalars (mirroring reflect.Value.Kind): a ScalarValue reports which representation its scalar holds, every other concrete type reports its single kind.
const ( // KindUndef is an undefined scalar (SV: undef). KindUndef Kind = iota // KindBool is a core boolean scalar (SV: !!1 / !!0). KindBool // KindInt is an integer scalar (SV: IV). KindInt // KindFloat is a floating-point scalar (SV: NV). KindFloat // KindString is a string scalar (SV: PV — a byte string). KindString // KindRef is a reference (RV). KindRef // KindArray is an array (AV). KindArray // KindHash is a hash (HV). KindHash // KindCode is a subroutine (CV). KindCode // KindGlob is a typeglob (GV). KindGlob // KindIO is a filehandle body (IO). KindIO )
type MemFS ¶
MemFS is an in-memory read/write FS (see the go-perl/fs package).
func NewStdlibMemFS ¶
NewStdlibMemFS returns an in-memory filesystem pre-loaded with the embedded Perl standard library at the root, ready to back an Interpreter:
fs := perl.NewStdlibMemFS()
interp, _ := perl.NewInterpreter(perl.Config{FS: fs}) // StdlibDir = "/"
Each call returns an independent FS, so interpreters built from separate NewStdlibMemFS() values share no filesystem state. This is also the filesystem an instance gets by default (Config with a nil FS).
type Perl ¶ added in v0.2.0
type Perl struct {
// contains filtered or unexported fields
}
Perl is one isolated Perl interpreter instance.
func New ¶ added in v0.2.0
New builds a fresh Perl instance, applies the sandbox config, and returns it ready to Eval. When the config permits, the instance is mapped copy-on-write from a process-wide snapshot of an already-initialized interpreter, so construction is cheap and the instances share the read-only bulk of their memory.
func (*Perl) AddInc ¶ added in v0.2.0
AddInc prepends dirs to the instance's @INC, so `use`/`require` resolve modules from them (a vendored local/lib/perl5 tree, an application's lib directory). Paths cross via the function bridge, so no Perl-source quoting is involved.
func (*Perl) AddXSDir ¶ added in v0.2.0
AddXSDir registers the native XS modules in dir with the instance, the way AddInc registers a module tree. Each <Module-Name>.so in dir (the package separator spelled "-", the `gperl xs build` output naming) is registered under its module name; the architecture-specific project layout is dir = local/xs/<goos>_<goarch> (see the xs package's ArchTag). Registration is cheap (each module boots lazily on first `use`), and a missing directory simply registers nothing.
The loader itself lives in the go-perl/xs package; using AddXSDir from a binary that links neither psgi nor gperl requires importing it (`import _ "github.com/goccy/go-perl/xs"`).
func (*Perl) Bind ¶ added in v0.2.0
Bind makes fn callable from Perl as the subroutine name (fully qualified, or defined into main:: when unqualified). The Perl side sees an ordinary sub: arguments arrive in Go as typed Values, the returned slice becomes the return list, and a Go error — or a contained panic — becomes a Perl die. Binding the same name again replaces the sub (the previous function is unreferenced but its id stays allocated).
func (*Perl) BindClass ¶ added in v0.2.0
BindClass defines a Perl class whose methods are implemented in Go: each entry becomes the sub name::method, so Perl's own method resolution — inheritance via @ISA, class methods, SUPER:: — applies unchanged. Every method receives the invocant as args[0]: the class name (a string scalar) for a class-method call, the blessed instance (a RefValue) for an instance call.
Unless methods defines "new", a default constructor is provided:
sub new { my $class = shift; bless { @_ }, $class }
so instances are ordinary Perl hash-based objects (readable from Go through the value operations, extensible by subclassing in Perl). A Go method that needs per-instance Go state can key a Go-side map by an id stored in the hash.
func (*Perl) Call ¶ added in v0.2.0
Call invokes the named Perl subroutine in list context and returns its return list. name is a fully qualified sub name ("My::App::handler") or a main:: sub name ("handler"). An ArrayValue or HashValue among args flattens into the argument list, exactly like f(@a, %h) in Perl (pass Ref() to pass the reference itself). A Perl-level die (including calling a sub that does not exist) is returned as a *PerlError; other errors are host/transport failures or a context cancellation, which behaves exactly like Eval's.
func (*Perl) Clone ¶ added in v0.2.0
Clone returns a new instance mapped copy-on-write from this instance's CURRENT state: every module compiled and every value that exists in p exists in the clone, and from here the two diverge privately, sharing the read-only bulk of their memory.
Take clones at rest — between requests, never while an Eval/Call is running in p. The first Clone builds the image (a full memory copy); subsequent clones of the same instance reuse it, so p must not run anything between clones of one batch either. The clone inherits p's configuration (filesystem, environment, hooks) and its Go bindings.
func (*Perl) Close ¶ added in v0.2.0
Close finalizes the instance. The Perl must not be used afterward: every later Eval/Call errors, and outstanding *Ref handles become inert (their finalizers only touch host-side state). Idempotent.
func (*Perl) Eval ¶ added in v0.2.0
Eval compiles and runs src in this instance's persistent package (its main::) and returns the structured result. A Perl-level die is reported via Result.Error (*PerlError), not as Eval's own error; a Go error indicates a host/transport failure (a wasm trap, encoding problem, ...) or a context cancellation.
Cancelling ctx while the eval runs stops it at the next Perl opcode (the interpreter runs a pluggable run loop that tests a host-writable flag; see perl-wasm's bridge) and Eval returns ctx.Err(). A single long-running opcode — a pathological regex, a big sort — is not preempted until it returns to the run loop.
func (*Perl) NewArray ¶ added in v0.2.0
NewArray materialises a fresh array in the guest holding vals (one crossing) and returns it. An ArrayValue or HashValue among vals flattens, like [@a, %h]; pass Ref() to nest a reference.
func (*Perl) NewHash ¶ added in v0.2.0
NewHash materialises a fresh hash in the guest holding pairs (one crossing) and returns it.
func (*Perl) RunFile ¶ added in v0.2.0
RunFile executes the Perl program at path — a guest path against Config.FS when one is set, a host path otherwise — with incDirs prepended to @INC and args as @ARGV. The program's output goes to the instance's configured stdio (not captured), and its package state persists on the instance afterwards.
An uncaught die comes back as *PerlError; a Perl-level exit() comes back as the error ExitCode recognizes, after which the instance must only be Closed. Both conventions let a command-line front end translate the outcome into a process exit status.
type PerlError ¶ added in v0.2.0
type PerlError struct {
Message string
}
PerlError is a Perl-level die surfaced by Eval, Call, and the value operations: Message holds $@.
type PerlValue ¶ added in v0.2.0
type PerlValue interface {
ScalarValue | RefValue | ArrayValue | HashValue | CodeValue | GlobValue | IOValue
}
PerlValue enumerates the concrete Value types, as the constraint behind the typed extraction path (As and friends).
type RefValue ¶ added in v0.2.0
type RefValue struct {
// contains filtered or unexported fields
}
RefValue is a reference (RV): a handle to a Perl reference held alive in the interpreter's registry. Identity is preserved — the same Perl reference always surfaces with the same handle, and sending it back dereferences to the same referent.
func (RefValue) Can ¶ added in v0.2.0
Can reports $ref->can(method) — whether the class provides the method.
func (RefValue) Class ¶ added in v0.2.0
Class returns the package the reference is blessed into, and whether it is blessed at all.
func (RefValue) Deref ¶ added in v0.2.0
Deref dereferences the reference — the reflect.Value.Elem analog:
\$x -> the ScalarValue $x (or a fresh RefValue for a ref-to-ref) \@a -> the ArrayValue @a \%h -> the HashValue %h \&f -> the CodeValue &f \*g -> the GlobValue *g
Aggregate derefs are view constructions (no guest call); a scalar deref reads the referent from the guest.
func (RefValue) Equal ¶ added in v0.2.0
Equal reports whether two references designate the same Perl reference. The guest deduplicates handles by referent address, so identity comparison is handle comparison.
func (RefValue) Isa ¶ added in v0.2.0
Isa reports $ref->isa(class) — whether the reference's class is or inherits from class.
func (RefValue) MethodCall ¶ added in v0.2.0
MethodCall invokes $ref->method(args...) in list context and returns the return list, dispatched by Perl's own method resolution (inheritance, AUTOLOAD). A die comes back as *PerlError.
type Result ¶ added in v0.2.0
type Result struct {
// Value is the evaluated expression's value (the last statement, in
// scalar context), valid when Error is nil. See Value for the Perl
// coercions its accessors apply.
Value Value
// Error is non-nil when the eval died: a Perl-level die/croak or a
// compile error, carrying $@ as a *PerlError.
Error error
// Stdout / Stderr capture what the eval printed to STDOUT / STDERR
// (the bridge redirects both onto in-memory scalars for the duration).
Stdout string
Stderr string
}
Result is the outcome of one Eval: the expression's value and the Perl-level error state. A die/croak/compile error is a fact ABOUT the evaluation, so it lives here as Error (*PerlError, $@'s text), not in Eval's own error return — that one reports host and transport failures.
type ScalarType ¶ added in v0.2.0
ScalarType constrains the Go types ValueOf accepts as one Perl scalar.
type ScalarValue ¶ added in v0.2.0
type ScalarValue struct {
// contains filtered or unexported fields
}
ScalarValue is one Perl scalar: undef, a boolean, an integer, a float, or a byte string. The accessors coerce the way Perl itself would, totally — they never panic. Kind reports which representation the scalar holds.
func ValueOf ¶ added in v0.2.0
func ValueOf[T ScalarType](v T) ScalarValue
ValueOf builds the scalar for a Go value: a bool crosses as a Perl core boolean, integers as IVs, floats as NVs, a string as a utf8 character string, and a []byte as a raw byte string.
func (ScalarValue) Bool ¶ added in v0.2.0
func (v ScalarValue) Bool() bool
Bool applies Perl truth: undef, "", "0", and zero are false, everything else is true.
func (ScalarValue) Bytes ¶ added in v0.2.0
func (v ScalarValue) Bytes() []byte
Bytes is the scalar's raw byte string: for a string scalar the exact PV bytes (no re-encoding), otherwise the bytes of String().
func (ScalarValue) Float ¶ added in v0.2.0
func (v ScalarValue) Float() float64
Float numifies the scalar the way Perl does (a leading numeric prefix counts, anything else is 0).
func (ScalarValue) Int ¶ added in v0.2.0
func (v ScalarValue) Int() int64
Int numifies the scalar the way Perl does and truncates toward zero.
func (ScalarValue) Kind ¶ added in v0.2.0
func (v ScalarValue) Kind() Kind
Kind reports the scalar's representation: KindUndef, KindBool, KindInt, KindFloat, or KindString.
func (ScalarValue) String ¶ added in v0.2.0
func (v ScalarValue) String() string
String is the scalar's string form, as Perl would stringify it (a boolean true is "1", false is ""; undef is "").
type Value ¶ added in v0.2.0
type Value interface {
Kind() Kind
// contains filtered or unexported methods
}
Value is any Perl value. Sealed: the concrete types — ScalarValue, RefValue, ArrayValue, HashValue, CodeValue, GlobValue, IOValue — are the only implementations, so a type switch over them is exhaustive.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
gperl
command
gperl is the perl-meets-go command for go-perl: it runs Perl programs on the embedded (wasm2go-transpiled) interpreter with go-style tooling.
|
gperl is the perl-meets-go command for go-perl: it runs Perl programs on the embedded (wasm2go-transpiled) interpreter with go-style tooling. |
|
Package fs provides the filesystem backends a Perl instance runs on.
|
Package fs provides the filesystem backends a Perl instance runs on. |
|
Package gperl is the library behind the gperl command: the perl-meets-go toolchain for go-perl.
|
Package gperl is the library behind the gperl command: the perl-meets-go toolchain for go-perl. |
|
Package internal holds the machinery under the public go-perl API: the generated wasm2go binding (perl.go), the per-instance bridge transport, the copy-on-write snapshot/clone plumbing, and the native-XS hook surface the xs subpackage drives.
|
Package internal holds the machinery under the public go-perl API: the generated wasm2go binding (perl.go), the per-instance bridge transport, the copy-on-write snapshot/clone plumbing, and the native-XS hook surface the xs subpackage drives. |
|
Package psgi serves PSGI Perl web applications from Go's net/http.
|
Package psgi serves PSGI Perl web applications from Go's net/http. |
|
Package xs loads host-native XS modules — shared libraries compiled with an ordinary C compiler against go-perl's XS SDK headers (sdk/include) — into a running Perl instance.
|
Package xs loads host-native XS modules — shared libraries compiled with an ordinary C compiler against go-perl's XS SDK headers (sdk/include) — into a running Perl instance. |