runner

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Aug 14, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Examples

Constants

View Source
const DefaultMaxCacheSize = 10000

DefaultMaxCacheSize is the default upper bound on cached entries.

Variables

This section is empty.

Functions

func EnvFromContext added in v0.2.0

func EnvFromContext(ctx context.Context) (map[string]string, bool)

EnvFromContext returns the request-scoped environment attached to contexts auto-injected into registered Go callables.

Types

type Context

type Context struct {
	Get     map[string]string
	Post    map[string]string
	Path    map[string]string
	Cookie  map[string]string
	Server  map[string]string
	Env     map[string]string
	Headers map[string]string
	Argv    []string
	// contains filtered or unexported fields
}

Context carries HTTP request data exposed to PHP as superglobals, header functions, and staged response headers.

Example
package main

import (
	"fmt"
	"net/http"
	"net/http/httptest"

	"github.com/titpetric/phpscript/runner"
)

func main() {
	req := httptest.NewRequest(http.MethodGet, "/users/42?tab=profile", nil)
	req.Header.Set("X-Request-Id", "abc123")
	req.Pattern = "GET /users/{id}"
	req.SetPathValue("id", "42")

	ctx := runner.FromRequest(req)
	ctx.Header("X-Powered-By: phpscript")

	fmt.Println(ctx.Get["tab"])
	fmt.Println(ctx.Path["id"])
	fmt.Println(ctx.Headers["X-Request-Id"])
	fmt.Println(ctx.ResponseHeaders().Get("X-Powered-By"))

}
Output:
profile
42
abc123
phpscript

func FromRequest

func FromRequest(r *http.Request) Context

FromRequest builds a Context from an HTTP request. Query and form values are flattened to their first value (PHP's scalar superglobal shape); path values are pulled out of the matched ServeMux pattern via r.PathValue.

func NewContext

func NewContext() Context

NewContext returns an allocated empty Context value.

func (Context) GetAllHeaders

func (c Context) GetAllHeaders() *model.Array

GetAllHeaders implements PHP getallheaders(): an associative array of the incoming request headers keyed by canonical header name.

func (Context) Header

func (c Context) Header(header string, opts ...any)

Header implements PHP header($header[, $replace[, $code]]): it parses a "Name: value" line and stages it on the response header set. replace controls whether an existing header of the same name is overwritten (default true).

func (Context) Register

func (c Context) Register(rt *Runtime)

Register installs the request-aware PHP functions onto rt and seeds the request superglobals. After this, transpiled PHP can call getallheaders() / header() and read $_GET, $_POST, $_PATH — all backed by this Context.

func (Context) ResponseHeaders

func (c Context) ResponseHeaders() http.Header

ResponseHeaders returns the headers staged by the PHP header() function so a host handler can copy them onto the http.ResponseWriter after execution.

func (Context) ResponseStatus added in v0.2.0

func (c Context) ResponseStatus() int

ResponseStatus returns the status staged by header(), or zero when the host should retain its default status. A Location header defaults to 302 like PHP.

type ExitError

type ExitError struct {
	Code int
}

ExitError is returned when PHP die()/exit() interrupts script execution.

func IsExit

func IsExit(err error) (*ExitError, bool)

IsExit reports whether err was caused by PHP die()/exit().

func (*ExitError) Error

func (e *ExitError) Error() string

Error returns a formatted PHP exit status.

type ExprCache

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

ExprCache stores immutable compiled expression programs by transpiled source and optional flat bytecode by parsed program identity. Expression AST metadata stays runtime-local; flat bytecode retains its source Program for the lifetime of the explicitly shared cache. Cache capacity is bounded to prevent memory leaks.

func NewExprCache

func NewExprCache() *ExprCache

NewExprCache returns an empty compiled expression cache with default capacity (10,000 entries).

func NewExprCacheWithCapacity added in v0.2.1

func NewExprCacheWithCapacity(maxEntries int) *ExprCache

NewExprCacheWithCapacity returns an empty expression cache bounded to maxEntries.

func (*ExprCache) Clear added in v0.2.1

func (c *ExprCache) Clear()

Clear resets the cached compiled expressions.

func (*ExprCache) GetSource

func (c *ExprCache) GetSource(src string) (*vm.Program, bool)

GetSource returns the compiled expression cached for src, if any.

func (*ExprCache) Len added in v0.2.1

func (c *ExprCache) Len() int

Len returns the number of currently cached source expressions.

func (*ExprCache) SetSource added in v0.1.4

func (c *ExprCache) SetSource(src string, prog *vm.Program)

SetSource stores a compiled program for transpiled source. Evicts one item if max capacity is reached.

type FilenameObserver added in v0.2.1

type FilenameObserver interface {
	UpdateFilename(context.Context, string)
}

FilenameObserver optionally receives the entrypoint passed to LoadFile.

type HostPanicError added in v0.2.0

type HostPanicError struct {
	Callable string
	Value    any
}

HostPanicError converts a panic raised by a registered Go constructor, function, or method into the runtime error path. PHP try/catch can therefore handle it like an error returned by the same host callable.

func (*HostPanicError) Error added in v0.2.0

func (e *HostPanicError) Error() string

type IncludeCache

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

IncludeCache stores parsed include/require programs by cleaned filesystem path. Parsed programs are treated as immutable by Runtime.Run/exec: hoisting copies declarations into runtime maps, while statement execution only reads the AST, so cached *model.Program values can be shared safely by callers that do not mutate ASTs themselves. Cache size is bounded to prevent memory leaks.

func NewIncludeCache

func NewIncludeCache() *IncludeCache

NewIncludeCache returns an empty parsed include cache with default capacity (10,000 entries).

func NewIncludeCacheWithCapacity added in v0.2.1

func NewIncludeCacheWithCapacity(maxEntries int) *IncludeCache

NewIncludeCacheWithCapacity returns an empty include cache bounded to maxEntries.

func (*IncludeCache) Clear added in v0.2.1

func (c *IncludeCache) Clear()

Clear resets the cached entries.

func (*IncludeCache) Get

func (c *IncludeCache) Get(path string) (*model.Program, bool)

Get returns the parsed program cached for path, if any.

func (*IncludeCache) Len added in v0.2.1

func (c *IncludeCache) Len() int

Len returns the number of currently cached programs.

func (*IncludeCache) Set

func (c *IncludeCache) Set(path string, prog *model.Program)

Set stores prog for path. Evicts one item if max capacity is reached.

type IncludeFunc

type IncludeFunc func(path string) (*model.Program, error)

IncludeFunc resolves an include/require path to a parsed program. Wiring this from the host keeps the runner free of file-system and parser dependencies.

type IncludeObserver added in v0.2.1

type IncludeObserver interface {
	UpdateIncludedFiles(context.Context, int)
}

IncludeObserver optionally receives the number of files included so far.

type Observer added in v0.2.1

type Observer interface {
	UpdateStatus(context.Context, model.Status)
	Trace(context.Context, string, ...model.Flag) *model.RequestSpan
}

Observer receives lifecycle updates for a Runtime. Implementations must be safe for use by concurrent runtimes.

type Options

type Options struct {
	// RootFS is the filesystem used to load PHP entrypoints and includes.
	RootFS fs.FS `yaml:"-"`

	// Stdin is exposed to scripts as the STDIN stream. A nil reader produces an
	// empty stream; CLI hosts should pass os.Stdin explicitly.
	Stdin io.Reader `yaml:"-"`

	// SAPI provides output for `php_sapi_name`.
	SAPI string `yaml:"-"`

	// WorkDir is the directory inside RootFS used as the script working directory.
	// Empty means the RootFS root.
	WorkDir string `yaml:"work_dir"`

	// WritablePaths optionally restricts filesystem writes. When empty, writes are
	// left to normal OS/user permissions. Enforcement is done by filesystem shims.
	WritablePaths []string `yaml:"writable_paths"`
}

Options configures a Runtime.

type Runtime

type Runtime struct {

	// Env is the environment visible to PHP for this Runtime. New snapshots the
	// host environment so mutations remain local to a single request/runtime.
	Env map[string]string
	// contains filtered or unexported fields
}

Runtime executes parsed PHP statements and evaluates transpiled expressions with registered functions, classes, constructors, and runtime state.

func New

func New(w io.Writer, opts Options) *Runtime

New returns a Runtime that writes echo output to w (defaults to os.Stdout).

func NewFlatStack added in v0.2.0

func NewFlatStack(w io.Writer, opts Options) *Runtime

NewFlatStack returns a Runtime that executes supported programs through the flat bytecode backend and atomically falls back to the interpreter otherwise. Most callers should use flatstack.New, which preserves runner's public API.

func (*Runtime) ClassExists added in v0.1.0

func (rt *Runtime) ClassExists(name string, autoload bool) (bool, error)

ClassExists reports whether a PHP or host-backed class exists. If autoload is true, registered autoloaders are given a chance to define a missing class.

func (*Runtime) Const

func (rt *Runtime) Const(name string) (any, bool)

Const returns a registered constant value and whether it is defined.

func (*Runtime) Context added in v0.0.5

func (rt *Runtime) Context() context.Context

Context returns the configured lifecycle context.

func (*Runtime) DeclaredClasses added in v0.1.0

func (rt *Runtime) DeclaredClasses() []string

DeclaredClasses returns the names of PHP classes and host-backed constructor classes currently available to the runtime. PHP does not guarantee ordering; phpscript sorts the snapshot for deterministic diagnostics.

func (*Runtime) DefinedConstants added in v0.1.0

func (rt *Runtime) DefinedConstants() map[string]any

DefinedConstants returns a stable snapshot of all runtime constants.

func (*Runtime) DefinedFunctions added in v0.1.0

func (rt *Runtime) DefinedFunctions() (internal, user []string)

DefinedFunctions returns stable snapshots of registered host/internal and PHP user-defined function names.

func (*Runtime) Eval

func (rt *Runtime) Eval(e model.Expr, scope *Scope) (any, error)

Eval transpiles e, binds the referenced variables from scope, and runs the resulting program through the expr-lang VM.

func (*Runtime) Exit

func (rt *Runtime) Exit(code int) error

Exit interrupts execution with a PHP exit status.

func (*Runtime) FS

func (rt *Runtime) FS() fs.FS

FS returns the configured source root (or nil).

func (*Runtime) IncludePath added in v0.1.0

func (rt *Runtime) IncludePath() string

IncludePath returns the current SPL include path.

func (*Runtime) IncludedFiles

func (rt *Runtime) IncludedFiles() []string

IncludedFiles returns the cleaned dirFS filenames included by this runtime.

func (*Runtime) Load

func (rt *Runtime) Load(src string) (*model.Program, error)

Load parses PHP source into a program.

func (*Runtime) LoadFile

func (rt *Runtime) LoadFile(path string) (*model.Program, error)

LoadFile reads and parses a PHP file from the runtime source FS.

func (*Runtime) Observe added in v0.2.1

func (rt *Runtime) Observe(observer Observer)

Observe registers an observer and reports that this Runtime is starting.

func (*Runtime) OnError

func (rt *Runtime) OnError(fn func(error))

OnError installs an error handler (register_error_handler). When set, runtime evaluation errors are routed here instead of aborting the caller.

func (*Runtime) PHPInfo added in v0.1.0

func (rt *Runtime) PHPInfo() error

PHPInfo prints a compact phpinfo-style text report for the phpscript runtime. It intentionally reports runtime facts rather than PHP extensions that phpscript does not provide.

func (*Runtime) RegisterAutoloader added in v0.1.0

func (rt *Runtime) RegisterAutoloader(callback any, prepend bool)

RegisterAutoloader appends or prepends a callback to the SPL autoload queue. The callback receives a fully-qualified class name without a leading slash.

func (*Runtime) RegisterClass

func (rt *Runtime) RegisterClass(c *model.Class)

RegisterClass adds a resolved class to the class table so `new Name` works.

func (*Runtime) RegisterConstructor

func (rt *Runtime) RegisterConstructor(name string, ctor any)

RegisterConstructor binds a class name to a Go constructor so `new Name` in PHP instantiates a native Go value. The constructor may take a leading context.Context (auto-injected) and may return a trailing error, which is surfaced to the interpreter as a thrown error. When a direct variable assignment receives a constructed value that implements SetID(string), the runtime passes it the PHP variable name without the leading dollar sign. Example:

rt.RegisterConstructor("Storage", func(ctx context.Context) (Storage, error) { ... }).
// PHP:  $storage = new Storage;   // == storage, err := NewStorage(ctx).

func (*Runtime) RegisterFunc

func (rt *Runtime) RegisterFunc(name string, fn any)

RegisterFunc forwards a Go function (or any callable) into the VM under name. This is the shim mechanism: e.g. rt.RegisterFunc("strlen", func(s string) int { return len(s) }) makes `strlen($x)` work in transpiled code.

func (*Runtime) RegisterShutdown added in v0.2.1

func (rt *Runtime) RegisterShutdown(callback any)

RegisterShutdown appends a callback to run when the current program exits. Shutdown callbacks run in registration order, including after exit or error.

func (*Runtime) Run

func (rt *Runtime) Run(p *model.Program) (err error)

Run executes a whole program in the global scope.

func (*Runtime) SAPI

func (rt *Runtime) SAPI() string

SAPI returns the configured SAPI string.

func (*Runtime) SPLAutoload added in v0.1.0

func (rt *Runtime) SPLAutoload(class string) error

SPLAutoload implements PHP's default autoloader: lowercase the qualified class name and search each include_path entry for class.php.

func (*Runtime) SetConst

func (rt *Runtime) SetConst(name string, val any)

SetConst registers a PHP constant (e.g. define("FOO", 1) or a built-in like T_VARIABLE). Constants are visible in every scope, including inside functions and methods — unlike globals, which PHP confines to the global scope.

func (*Runtime) SetContext

func (rt *Runtime) SetContext(ctx context.Context)

SetContext installs the lifecycle context auto-injected into registered Go callables whose first parameter is a context.Context (constructors, methods, functions). Defaults to context.Background().

func (*Runtime) SetExprCache

func (rt *Runtime) SetExprCache(cache *ExprCache)

SetExprCache installs a source-keyed compiled-program cache that is safe to share across runtimes. AST-specific expression metadata remains runtime-local. Passing nil disables cross-runtime expression caching.

func (*Runtime) SetGlobal

func (rt *Runtime) SetGlobal(name string, val any)

SetGlobal seeds a variable into the global scope before execution. Useful for injecting request data (the README's $_SERVER gray area) or, in tests, an input value.

func (*Runtime) SetIncludeCache

func (rt *Runtime) SetIncludeCache(cache *IncludeCache)

SetIncludeCache installs a shared include cache. A cache must only be shared by runtimes whose include paths resolve within the same source-root namespace. Passing nil disables include caching.

func (*Runtime) SetIncludePath added in v0.1.0

func (rt *Runtime) SetIncludePath(value string) string

SetIncludePath sets the path list used by the default SPL autoloader and returns its previous value.

func (*Runtime) SetIncludeResolver

func (rt *Runtime) SetIncludeResolver(fn IncludeFunc)

SetIncludeResolver installs the include/require resolver.

func (*Runtime) Stdin added in v0.2.0

func (rt *Runtime) Stdin() io.Reader

Stdin returns the input stream configured by the runtime host.

func (*Runtime) Trace added in v0.2.1

func (rt *Runtime) Trace(message string, flags ...model.Flag) *model.RequestSpan

Trace publishes a trace span to registered observers and returns the first mutable span provided by one of them.

func (*Runtime) UpdateFilename added in v0.2.1

func (rt *Runtime) UpdateFilename(filename string)

UpdateFilename publishes the PHP entrypoint to observers that support filename updates.

func (*Runtime) UpdateIncludedFiles added in v0.2.1

func (rt *Runtime) UpdateIncludedFiles(count int)

UpdateIncludedFiles publishes the current number of included files.

func (*Runtime) UpdateStatus added in v0.2.1

func (rt *Runtime) UpdateStatus(status model.Status)

UpdateStatus publishes a lifecycle phase to all registered observers. It is also available to hosts for phases that occur outside PHP execution.

func (*Runtime) WorkDir

func (rt *Runtime) WorkDir() string

WorkDir returns the configured working directory inside the source root.

func (*Runtime) WritablePaths

func (rt *Runtime) WritablePaths() []string

WritablePaths returns the configured writable path whitelist.

type Scope

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

Scope is a flat variable table for one execution frame.

PHP has no block scoping: variables introduced inside if/for/foreach bodies live in the enclosing function scope. Each function call gets a fresh Scope; the file body runs in the global Scope.

There is intentionally no `global` keyword implemented.

func NewScope

func NewScope() *Scope

NewScope returns an empty scope.

func ScopeFromContext added in v0.0.6

func ScopeFromContext(ctx context.Context) (*Scope, bool)

ScopeFromContext returns the active PHP execution frame attached to a context auto-injected into a registered free function.

func (*Scope) Defer added in v0.1.3

func (s *Scope) Defer(callback any)

Defer registers a callback to run when the current PHP execution frame returns. Callbacks run in last-in, first-out order.

func (*Scope) DefinedVars added in v0.1.0

func (s *Scope) DefinedVars() map[string]any

DefinedVars returns a snapshot of PHP-visible variables in this frame. Interpreter bookkeeping slots use a double-underscore prefix and are not PHP variables, so they are omitted.

func (*Scope) Get

func (s *Scope) Get(name string) (any, bool)

Get returns the value of name and whether it is set.

func (*Scope) Set

func (s *Scope) Set(name string, val any)

Set stores name=val.

type Transpiler

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

Transpiler lowers expression AST nodes into type-agnostic expr-lang source that delegates PHP-specific behavior to runtime helpers.

Example
package main

import (
	"fmt"

	"github.com/titpetric/phpscript/model"
	"github.com/titpetric/phpscript/runner"
)

func main() {
	t := runner.NewTranspiler()

	src, vars, err := t.Transpile(&model.Binary{
		Op: ".",
		Left: &model.Var{
			Name: "greeting",
		},
		Right: &model.Lit{
			Value: " world",
		},
	})
	if err != nil {
		fmt.Println(err)
		return
	}

	fmt.Println(src)
	fmt.Println(vars)

}
Output:
__concat(v_greeting, " world")
[greeting]

func NewTranspiler

func NewTranspiler() *Transpiler

NewTranspiler returns a fresh transpiler.

func (*Transpiler) Closures

func (t *Transpiler) Closures() map[string]*model.Closure

Closures returns the anonymous functions collected during the last Transpile, keyed by their env identifier.

func (*Transpiler) Exprs added in v0.0.5

func (t *Transpiler) Exprs() map[string]model.Expr

func (*Transpiler) Transpile

func (t *Transpiler) Transpile(e model.Expr) (src string, vars []string, err error)

Transpile converts e into expr-lang source and returns the source plus the sorted set of variable names it references.

Jump to

Keyboard shortcuts

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