Documentation
¶
Index ¶
- Constants
- func Bindings() []func(*Runtime)
- func EnvFromContext(ctx context.Context) (map[string]string, bool)
- func RegisterBinding(installer func(*Runtime))
- type Context
- type ExitError
- type ExprCache
- type FilenameObserver
- type HostPanicError
- type IncludeCache
- type IncludeFunc
- type IncludeObserver
- type Observer
- type Options
- type Runtime
- func (rt *Runtime) ClassExists(name string, autoload bool) (bool, error)
- func (rt *Runtime) Const(name string) (any, bool)
- func (rt *Runtime) Context() context.Context
- func (rt *Runtime) DeclaredClasses() []string
- func (rt *Runtime) DefinedConstants() map[string]any
- func (rt *Runtime) DefinedFunctions() (internal, user []string)
- func (rt *Runtime) Eval(e model.Expr, scope *Scope) (any, error)
- func (rt *Runtime) Exit(code int) error
- func (rt *Runtime) FS() fs.FS
- func (rt *Runtime) IncludePath() string
- func (rt *Runtime) IncludedFiles() []string
- func (rt *Runtime) Load(src string) (*model.Program, error)
- func (rt *Runtime) LoadFile(path string) (*model.Program, error)
- func (rt *Runtime) Observe(observer Observer)
- func (rt *Runtime) OnError(fn func(error))
- func (rt *Runtime) PHPInfo() error
- func (rt *Runtime) RegisterAutoloader(callback any, prepend bool)
- func (rt *Runtime) RegisterClass(c *model.Class)
- func (rt *Runtime) RegisterConstructor(name string, ctor any)
- func (rt *Runtime) RegisterFunc(name string, fn any)
- func (rt *Runtime) RegisterShutdown(callback any)
- func (rt *Runtime) Run(p *model.Program) (err error)
- func (rt *Runtime) SAPI() string
- func (rt *Runtime) SPLAutoload(class string) error
- func (rt *Runtime) SetConst(name string, val any)
- func (rt *Runtime) SetContext(ctx context.Context)
- func (rt *Runtime) SetExprCache(cache *ExprCache)
- func (rt *Runtime) SetGlobal(name string, val any)
- func (rt *Runtime) SetIncludeCache(cache *IncludeCache)
- func (rt *Runtime) SetIncludePath(value string) string
- func (rt *Runtime) SetIncludeResolver(fn IncludeFunc)
- func (rt *Runtime) Stdin() io.Reader
- func (rt *Runtime) Trace(message string, flags ...model.Flag) *model.RequestSpan
- func (rt *Runtime) UpdateFilename(filename string)
- func (rt *Runtime) UpdateIncludedFiles(count int)
- func (rt *Runtime) UpdateStatus(status model.Status)
- func (rt *Runtime) WorkDir() string
- func (rt *Runtime) WritablePaths() []string
- type Scope
- type Transpiler
Examples ¶
Constants ¶
const DefaultMaxCacheSize = 10000
DefaultMaxCacheSize is the default upper bound on cached entries.
Variables ¶
This section is empty.
Functions ¶
func Bindings ¶ added in v0.2.4
func Bindings() []func(*Runtime)
Bindings returns the contributed installers in registration order.
func EnvFromContext ¶ added in v0.2.0
EnvFromContext returns the request-scoped environment attached to contexts auto-injected into registered Go callables.
func RegisterBinding ¶ added in v0.2.4
func RegisterBinding(installer func(*Runtime))
RegisterBinding contributes a runtime installer, which stdlib.Register runs on every Runtime it sets up. Binding packages call it from their init() (see stdlib/ps/init.go), so a package is wired in by importing it — the way a program imports a database/sql driver. The registry lives here, in the leaf package that owns Runtime, so that stdlib can blank-import its subpackages without the two importing each other.
Installers run in registration order, before the bindings a host passes to stdlib.Register directly.
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 ¶
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 RequestContext ¶ added in v0.2.2
RequestContext returns the request data registered on a runtime context. It is intended for request-aware Go bindings such as session management.
func (Context) AddResponseHeader ¶ added in v0.2.2
AddResponseHeader appends a response header without replacing existing values. It is useful for headers such as Set-Cookie that may occur more than once in a response.
func (Context) GetAllHeaders ¶
GetAllHeaders implements PHP getallheaders(): an associative array of the incoming request headers keyed by canonical header name.
func (Context) Header ¶
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 ¶
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 ¶
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
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.
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
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.
type FilenameObserver ¶ added in v0.2.1
FilenameObserver optionally receives the entrypoint passed to LoadFile.
type HostPanicError ¶ added in v0.2.0
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.
type IncludeFunc ¶
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
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 NewFlatStack ¶ added in v0.2.0
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
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) DeclaredClasses ¶ added in v0.1.0
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
DefinedConstants returns a stable snapshot of all runtime constants.
func (*Runtime) DefinedFunctions ¶ added in v0.1.0
DefinedFunctions returns stable snapshots of registered host/internal and PHP user-defined function names.
func (*Runtime) Eval ¶
Eval transpiles e, binds the referenced variables from scope, and runs the resulting program through the expr-lang VM.
func (*Runtime) IncludePath ¶ added in v0.1.0
IncludePath returns the current SPL include path.
func (*Runtime) IncludedFiles ¶
IncludedFiles returns the cleaned dirFS filenames included by this runtime.
func (*Runtime) Observe ¶ added in v0.2.1
Observe registers an observer and reports that this Runtime is starting.
func (*Runtime) OnError ¶
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
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
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 ¶
RegisterClass adds a resolved class to the class table so `new Name` works.
func (*Runtime) RegisterConstructor ¶
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 ¶
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
RegisterShutdown appends a callback to run when the current program exits. Shutdown callbacks run in registration order, including after exit or error.
func (*Runtime) SPLAutoload ¶ added in v0.1.0
SPLAutoload implements PHP's default autoloader: lowercase the qualified class name and search each include_path entry for class.php.
func (*Runtime) SetConst ¶
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 ¶
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 ¶
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 ¶
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
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
Stdin returns the input stream configured by the runtime host.
func (*Runtime) Trace ¶ added in v0.2.1
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
UpdateFilename publishes the PHP entrypoint to observers that support filename updates.
func (*Runtime) UpdateIncludedFiles ¶ added in v0.2.1
UpdateIncludedFiles publishes the current number of included files.
func (*Runtime) UpdateStatus ¶ added in v0.2.1
UpdateStatus publishes a lifecycle phase to all registered observers. It is also available to hosts for phases that occur outside PHP execution.
func (*Runtime) WritablePaths ¶
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 ScopeFromContext ¶ added in v0.0.6
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
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
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.
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 (*Transpiler) Calls ¶ added in v0.2.5
func (t *Transpiler) Calls() []string
Calls returns the function names the last Transpile emitted as bare env identifiers, deduplicated and in first-use order. Like Idents, it aliases the transpiler's own storage.
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. It is nil when the expression has none.
func (*Transpiler) Exprs ¶ added in v0.0.5
func (t *Transpiler) Exprs() map[string]model.Expr
Exprs returns the sub-expressions marked for deferred evaluation during the last Transpile. It is nil when the expression has none.
func (*Transpiler) Idents ¶ added in v0.2.5
func (t *Transpiler) Idents() []string
Idents returns the expr identifiers of the variables collected during the last Transpile, positionally matching its vars result.
func (*Transpiler) Reset ¶ added in v0.2.5
func (t *Transpiler) Reset()
Reset clears the state collected by the last Transpile, keeping the backing arrays of the variable slices.
func (*Transpiler) Transpile ¶
Transpile converts e into expr-lang source and returns the source plus the set of variable names it references, in first-use order.
The returned slice aliases the transpiler's own storage; copy it (or use Idents, which is kept in step with it) before the transpiler is reused.