model

package
v0.2.5 Latest Latest
Warning

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

Go to latest
Published: Aug 16, 2026 License: MIT Imports: 7 Imported by: 0

Documentation

Overview

Package model holds the shared data structures (AST, runtime values, class metadata) used by both the parser and the runner packages.

The split is deliberate: parser/ produces these structures from PHP source, runner/ consumes them. Neither package depends on the other; they only share model/.

Index

Constants

This section is empty.

Variables

View Source
var SpanType = struct {
	Database Flag
	Internal Flag
	External Flag
	Template Flag
	Cache    Flag
	HTTP     Flag
}{
	Database: "database",
	Internal: "internal",
	External: "external",
	Template: "template",
	Cache:    "cache",
	HTTP:     "http",
}

SpanType contains the conventional span type names.

Functions

func IsCollection added in v0.2.5

func IsCollection(v any) bool

IsCollection reports whether v is array-like from PHP's point of view: an *Array or a native Go slice or map. Strings and structs are not, matching is_array().

func LenValues added in v0.2.5

func LenValues(v any) (int, bool)

LenValues reports a collection's entry count and whether v was a collection at all. It backs count(): a non-collection reports (0, false) so callers can apply PHP's "count of a scalar" behaviour themselves.

func RangeValues added in v0.2.5

func RangeValues(v any, fn func(key, val any) bool)

RangeValues iterates a collection in order, calling fn for each key/value pair until fn returns false. It accepts:

*Array          insertion order, hybrid int64/string keys (a list-mode
                Array walks its []any directly, with no map lookup)
slice, array    int64 keys in index order
map             key order is Go's (unordered), keys as declared

Anything else, nil included, iterates zero times — PHP's foreach over a non-array warns and continues rather than failing.

func WithRequest added in v0.2.1

func WithRequest(ctx context.Context, request *Request) context.Context

func WithSpanFilename added in v0.2.1

func WithSpanFilename(ctx context.Context, filename string) context.Context

WithSpanFilename associates spans created from ctx with the active source file.

func WithSpanLine added in v0.2.1

func WithSpanLine(ctx context.Context, line int) context.Context

WithSpanLine associates spans created from ctx with the active source line.

Types

type Array

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

Array is PHP's ordered hash map. It preserves insertion order and allows both integer and string keys, so it doubles as list and dictionary.

It has two internal representations and switches between them by itself:

list mode  values live in `list`, the key of element i is int64(i).
           `keys` and `values` are nil, so the array costs one slice.
map mode   `values` holds key->value and `keys` holds insertion order.

A new array starts in list mode, which is what `$a[] = v` (Append) and a PHP list literal produce, and stays there for as long as every key so far is the dense sequence 0,1,...,n-1. The first key that breaks the invariant — a string key, a negative or sparse integer, an int that is not an int64 — promotes the array to map mode, permanently. See promote.

Nothing about the observable behaviour differs between the two modes; list mode exists only so that the common case does not allocate a map[any]any, a key slice, and an interface box per key. Keys are still treated as opaque: an Array never normalises "1" to 1 (its callers do, see runner.normalizeKey), and only an int64 key advances the append index.

func NewArray

func NewArray() *Array

NewArray returns an empty ordered array.

func NewArraySize added in v0.2.5

func NewArraySize(n int) *Array

NewArraySize returns an empty ordered array with room for n entries. Building an array of known size through it avoids the backing slice's growth reallocations (a 5-entry array grows 1->2->4->8), which is most of what an *Array costs while it stays in list mode.

func ToArray added in v0.2.5

func ToArray(v any) *Array

ToArray returns v as an *Array, converting a native collection if needed and passing an existing *Array through untouched. Use it at the point where PHP semantics genuinely require an array (mutation, `$a[] = v`), not to normalise arguments — RangeValues reads every shape without allocating.

func (*Array) Append

func (a *Array) Append(val any)

Append adds val at the next integer index (PHP `$a[] = v`).

func (*Array) Clear added in v0.0.7

func (a *Array) Clear()

Clear removes all entries and resets list indexing, returning the array to list mode.

func (*Array) Get

func (a *Array) Get(key any) (any, bool)

Get returns the value for key and whether it existed.

func (*Array) Keys

func (a *Array) Keys() []any

Keys returns keys in insertion order. A list-mode array materialises them on each call, since it does not store them.

func (*Array) Len

func (a *Array) Len() int

Len reports the number of entries.

func (*Array) Map added in v0.2.1

func (a *Array) Map() map[string]any

Map returns the array as a string-keyed map for Go APIs that accept named values. PHP integer keys are represented by their decimal string form.

func (*Array) Range

func (a *Array) Range(fn func(key, val any) bool)

Range iterates entries in insertion order.

func (*Array) Set

func (a *Array) Set(key, val any)

Set assigns key=val, appending the key if new.

type ArrayItem

type ArrayItem struct {
	Key Expr
	Val Expr
}

ArrayItem is one entry of an ArrayLit. Key is nil for list-style entries.

type ArrayItemValue

type ArrayItemValue struct {
	Key any
	Val any
}

ArrayItemValue is a runtime (already-evaluated) array entry, the value-level counterpart of the ArrayItem AST node. The transpiled __array/__pair helpers produce these. Key is nil for list-style appends.

type ArrayLit

type ArrayLit struct {
	Items []ArrayItem
}

ArrayLit is `array(...)`, `[...]` or `{...}` (map/list literal).

type Assign

type Assign struct {
	Target Expr // Var, PropAccess or Index
	Op     string
	Value  Expr
}

Assign is `Target = Value`. Op may be "=", ".=", "+=", "[]=" (append). expr-lang cannot mutate, so assignment is handled entirely by the runner.

type AssignExpr

type AssignExpr struct {
	Target Expr
	Op     string
	Value  Expr
	Line   int
}

AssignExpr is assignment used as an expression, e.g. the PHP idiom `if (($x = f()) !== false)`. The README forbids assignment in conditions, but minitpl relies on it, so it is supported with Var/Index/Prop targets. As a statement it is lowered to *Assign by the parser.

type Binary

type Binary struct {
	Op    string
	Left  Expr
	Right Expr
}

Binary is an infix operator. Op covers arithmetic (+ - * / %), string concat ("."), comparison (== != === !== < <= > >=) and logical (&& ||).

type Break

type Break struct{}

Break exits the nearest loop or switch.

type Call

type Call struct {
	Name     string
	Fallback string
	Args     []Expr
	Bare     bool // exit/die used without parentheses
}

Call is a free-function call: `name(args...)`.

Name is the primary (possibly namespace-qualified) function name. Fallback is the global-namespace name to try if Name is undefined — PHP resolves an unqualified call inside a namespace by first looking in the current namespace and then falling back to the global function of the same short name. Fallback is "" for calls that need no fallback (the common, non-namespaced case), in which case the call resolves as a bare env identifier exactly as before.

type Cast

type Cast struct {
	Type string
	X    Expr
}

Cast is a type cast like `(bool)$x`, `(int)$x`, `(string)$x`, `(array)$x`.

type Catch

type Catch struct {
	Var  string
	Body []Stmt
}

Catch is one `catch (...) { ... }` clause. Var is the bound variable name (without `$`); the caught error is assigned to it so `echo $e` prints it.

type Class

type Class struct {
	Name    string
	Fields  []Field
	Consts  []Field // class constants (Name + value Expr)
	Methods map[string]*FuncDecl
}

Class is the resolved, runnable form of a ClassDecl: field defaults plus a method table keyed by method name.

type ClassConst

type ClassConst struct {
	Class string
	Name  string
}

ClassConst is `Class::NAME` / `self::NAME` class-constant access.

type ClassDecl

type ClassDecl struct {
	Name     string
	Abstract bool
	Fields   []Field
	Consts   []Field // class constants (Name + value Expr), referenced as Class::NAME
	Methods  []*FuncDecl
}

ClassDecl is a trimmed-down class: fields + methods + class constants, no inheritance. Abstract is tolerated (parsed) but not enforced (README omits abstract classes; minitpl's Hook is abstract only to declare constants).

type Closure

type Closure struct {
	Params []Param
	Body   []Stmt
}

Closure is an anonymous function expression `function($a,$b){ ... }`. minitpl uses one as the usort() comparator. `use (...)` capture is not supported (the engine's closures capture nothing).

type Continue

type Continue struct{}

Continue restarts the nearest loop.

type Echo

type Echo struct {
	Args []Expr
}

Echo writes the evaluated arguments to the output buffer.

type Expr

type Expr interface {
	Node
	// contains filtered or unexported methods
}

Expr is an expression: something that evaluates to a value. Expressions are the unit the runner transpiles into go-expr (expr-lang) source and evaluates through the embedded VM.

func UnwrapParenthesized added in v0.2.0

func UnwrapParenthesized(e Expr) Expr

UnwrapParenthesized returns the expression inside any explicit grouping. Consumers that inspect expression shape rather than evaluate it should use this so parentheses remain semantically transparent.

type ExprStmt

type ExprStmt struct {
	X Expr
}

ExprStmt is an expression evaluated for its side effects (e.g. a method call).

type ExtendedDatabaseProvider added in v0.2.1

type ExtendedDatabaseProvider interface {
	List() []string
	Register(string, string)
}

ExtendedDatabaseProvider extends database providers with listing and registration.

type Field

type Field struct {
	Name       string
	Default    Expr   // nil if none
	Visibility string // "public", "protected", "private", or ""
}

Field is a class property declaration (also reused for class constants).

type Flag added in v0.2.1

type Flag string

Flag configures a span. Unrecognized values select the span type so PHP callers can pass plain strings without a separate conversion API.

const (
	OpenSpan  Flag = "open"
	CloseSpan Flag = "close"
)

type For

type For struct {
	Init Stmt
	Cond Expr
	Post Stmt
	Body []Stmt
}

For is `for (Init; Cond; Post) { Body }`. `while` is parsed into a For with nil Init/Post.

type Foreach

type Foreach struct {
	Source    Expr
	KeyTarget Expr // nil if not captured
	ValTarget Expr
	KeyVar    string // deprecated: use KeyTarget
	ValVar    string // deprecated: use ValTarget
	Body      []Stmt
}

Foreach is `foreach (Source as [KeyTarget =>] ValTarget) { Body }`.

type Func

type Func struct {
	Decl *FuncDecl
	Go   any // an arbitrary Go func, invoked via reflection by the runtime
}

Func is a callable value: either a user-defined PHP function (Decl set) or a host Go function (Go set). Registered host functions use Go.

type FuncDecl

type FuncDecl struct {
	Class      string // "" for free functions
	Name       string
	Filename   string
	Params     []Param
	Body       []Stmt
	Visibility string // "public", "protected", "private", or ""
	Static     bool
	Abstract   bool // declaration only; Body is empty
}

FuncDecl is a free function or a class method declared with the `function Class::method()` syntax described in the README.

type If

type If struct {
	Cond Expr
	Then []Stmt
	Else []Stmt // may itself contain a single nested *If for elseif chains
}

If is `if (Cond) { Then } elseif... else { Else }`.

type Include

type Include struct {
	Path          Expr
	Keyword       string // include, include_once, require, or require_once
	Once          bool
	Parenthesized bool
}

Include pulls in another file (include / include_once / require). PHP allows include constructs both as standalone statements and as value-producing expressions.

type Index

type Index struct {
	Base  Expr
	Index Expr
}

Index is `Base[Index]` element access.

type InlineHTML

type InlineHTML struct {
	Text string
}

InlineHTML is raw text outside of <?php ... ?> tags. It is emitted verbatim.

type ListExpr

type ListExpr struct {
	Elems []Expr
}

ListExpr is `list($a, $b, ...)`, valid only as an assignment target. Elements may be nil for skipped positions (`list(, $b)`).

type Lit

type Lit struct {
	Value any
}

Lit is a literal scalar: nil, bool, int64, float64 or string.

type MethodCall

type MethodCall struct {
	Base   Expr
	Method string
	Args   []Expr
}

MethodCall is `Base->method(args...)` or `Base.method(args...)`.

type New

type New struct {
	Class string
	Args  []Expr
}

New is `new ClassName` / `new ClassName(args...)`.

type Node

type Node interface {
	// contains filtered or unexported methods
}

Node is the root interface for every AST element.

type Object

type Object struct {
	Class *Class
	Props map[string]any
	ID    string
}

Object is a class instance: a property bag plus a pointer back to its class. Because methods live on the Class (resolved by the runtime), an Object passed into expr-lang exposes its Props for `$obj->field` style access.

func NewObject

func NewObject(c *Class) *Object

NewObject builds an instance with field defaults applied.

func (*Object) SetID added in v0.2.1

func (o *Object) SetID(id string)

SetID records the PHP variable receiving this constructed object.

type Param

type Param struct {
	Name    string
	Default Expr // nil if required
}

Param is a single function parameter with an optional default value.

type Parenthesized added in v0.2.0

type Parenthesized struct {
	X Expr
}

Parenthesized preserves explicit grouping from the source expression.

type Program

type Program struct {
	Stmts     []Stmt
	Namespace string // set when the file declares `namespace Name;`
	// SourceSpans records original statement lines when Program came from the
	// parser. Consumers may ignore it; the formatter uses it to retain a single
	// intentional blank line between statements.
	SourceSpans map[Stmt]SourceSpan
}

Program is the top-level result of parsing a single PHP file.

type PropAccess

type PropAccess struct {
	Base Expr
	Name string
}

PropAccess is field access. The README allows both `$obj->field` and the new `obj.field` notation; both parse to this node.

type Request added in v0.2.1

type Request struct {
	ID             string         `json:"request_id"`
	Status         Status         `json:"status"`
	Request        string         `json:"request"`
	Hostname       string         `json:"hostname"`
	Filename       string         `json:"filename,omitempty"`
	IncludedFiles  int            `json:"included_files"`
	Method         string         `json:"method"`
	URI            string         `json:"uri"`
	Protocol       string         `json:"protocol"`
	RemoteAddress  string         `json:"remote_address"`
	UserAgent      string         `json:"user_agent,omitempty"`
	StartedAt      time.Time      `json:"started_at"`
	UpdatedAt      time.Time      `json:"updated_at"`
	Duration       time.Duration  `json:"duration_ns"`
	ResponseStatus int            `json:"response_status,omitempty"`
	ResponseBytes  int64          `json:"response_bytes"`
	HeapDelta      int64          `json:"heap_delta_bytes"`
	AllocatedBytes uint64         `json:"allocated_bytes"`
	Allocations    uint64         `json:"allocations"`
	GCCycles       uint32         `json:"gc_cycles"`
	GCPause        time.Duration  `json:"gc_pause_ns"`
	Spans          []*RequestSpan `json:"spans,omitempty"`

	MemStats  runtime.MemStats `json:"-"`
	ChangedAt time.Time        `json:"-"`
}

Request describes an active or recently completed request.

func (*Request) AppendSpan added in v0.2.1

func (r *Request) AppendSpan(at time.Time, message string, flags ...Flag) *RequestSpan

func (*Request) StartSpan added in v0.2.1

func (r *Request) StartSpan(ctx context.Context, name string) Span

StartSpan starts a named span attached to the request.

type RequestSpan added in v0.2.1

type RequestSpan struct {
	ID         int            `json:"id"`
	Time       time.Time      `json:"time"`
	Duration   time.Duration  `json:"duration_ns,omitempty"`
	Type       Flag           `json:"type"`
	Filename   string         `json:"filename,omitempty"`
	Line       int            `json:"line,omitempty"`
	Message    template.HTML  `json:"message"`
	Attributes map[string]any `json:"attributes,omitempty"`
	Error      string         `json:"error,omitempty"`
	Open       bool           `json:"open,omitempty"`
	Close      bool           `json:"close,omitempty"`
}

RequestSpan is one timestamped event in a request.

func StartSpan added in v0.2.1

func StartSpan(ctx context.Context, message string, flags ...Flag) *RequestSpan

StartSpan appends an event to the request in ctx and returns it so callers can add measurements after the observed work completes. The type defaults to internal; any other string flag selects a custom type.

func (*RequestSpan) End added in v0.2.1

func (s *RequestSpan) End()

End records the span duration once.

func (*RequestSpan) RecordError added in v0.2.1

func (s *RequestSpan) RecordError(err error)

RecordError records an error on the span.

func (*RequestSpan) SetAttribute added in v0.2.1

func (s *RequestSpan) SetAttribute(key string, value any)

SetAttribute records an attribute on the span.

func (*RequestSpan) SetDuration added in v0.2.1

func (s *RequestSpan) SetDuration(duration time.Duration)

SetDuration replaces the measured span duration.

func (*RequestSpan) SetFilename added in v0.2.1

func (s *RequestSpan) SetFilename(filename string)

SetFilename records the source filename associated with the span.

func (*RequestSpan) SetLine added in v0.2.1

func (s *RequestSpan) SetLine(line int)

SetLine records the source line associated with the span.

func (*RequestSpan) SetMessage added in v0.2.1

func (s *RequestSpan) SetMessage(message string)

SetMessage replaces the span message.

func (*RequestSpan) SetTime added in v0.2.1

func (s *RequestSpan) SetTime(started time.Time)

SetTime replaces the span start time.

func (*RequestSpan) SetType added in v0.2.1

func (s *RequestSpan) SetType(spanType Flag)

SetType replaces the span type.

type RequestStatistic added in v0.2.1

type RequestStatistic struct {
	Request               string        `json:"request"`
	Hostname              string        `json:"hostname"`
	Filename              string        `json:"filename,omitempty"`
	AverageIncludedFiles  float64       `json:"average_included_files"`
	Count                 uint64        `json:"count"`
	Share                 float64       `json:"share_percent"`
	AverageDuration       time.Duration `json:"average_duration_ns"`
	AverageResponseBytes  uint64        `json:"average_response_bytes"`
	AverageAllocatedBytes uint64        `json:"average_allocated_bytes"`

	TotalDuration      time.Duration `json:"-"`
	TotalResponseBytes uint64        `json:"-"`
	TotalAllocated     uint64        `json:"-"`
	TotalIncluded      uint64        `json:"-"`
}

RequestStatistic aggregates one method and URI in the rolling window.

type Return

type Return struct {
	Value Expr // may be nil
}

Return exits the current function with an optional value.

type RouteAnnotation added in v0.2.0

type RouteAnnotation struct {
	Method string
	Path   string
}

RouteAnnotation is one // @route declaration found in a PHP source file.

type SourceSpan added in v0.2.0

type SourceSpan struct {
	Start int
	End   int
}

SourceSpan is the inclusive source-line range occupied by a statement.

type Span added in v0.2.1

type Span interface {
	End()
	SetMessage(string)
	SetFilename(string)
	SetLine(int)
	SetTime(time.Time)
	SetDuration(time.Duration)
	SetType(Flag)
	SetAttribute(string, any)
	RecordError(error)
}

Span describes a mutable timed operation.

type Status added in v0.2.1

type Status string

Status describes the current phase of a Runtime. The one-character values follow the scoreboard convention used by servers such as lighttpd.

const (
	StatusWaiting    Status = "_"
	StatusStarting   Status = "s"
	StatusReading    Status = "R"
	StatusProcessing Status = "P"
	StatusWriting    Status = "W"
	StatusKeepalive  Status = "K"
	StatusClosing    Status = "C"
	StatusError      Status = "E"
)

type Stmt

type Stmt interface {
	Node
	// contains filtered or unexported methods
}

Stmt is a statement: something executed for its side effects (echo, control flow, assignment, declarations). Statements are interpreted directly by the runner because expr-lang has no concept of statements, loops or mutation.

type Switch

type Switch struct {
	Cond    Expr
	Cases   []SwitchCase
	Default []Stmt
}

Switch is `switch (Cond) { case V: ...; default: ... }`. Case bodies fall through unless they break (PHP semantics); the runner handles break/return.

type SwitchCase

type SwitchCase struct {
	Value Expr
	Body  []Stmt
}

SwitchCase is one `case Value:` arm of a Switch.

type Ternary

type Ternary struct {
	Cond Expr
	Then Expr
	Else Expr
}

Ternary is `Cond ? Then : Else`.

type Throw

type Throw struct {
	X Expr
}

Throw raises an exception. The VM has no exception model; it surfaces as a runtime error (sufficient for minitpl's error-path `throw`s, which the happy compile path never hits).

type Tracer added in v0.2.1

type Tracer interface {
	StartSpan(context.Context, string) Span
}

Tracer starts named spans.

type Try

type Try struct {
	Body    []Stmt
	Catches []Catch
	Finally []Stmt
}

Try is `try { Body } catch (Type $var) { ... } finally { ... }`. The VM has no exception class hierarchy, so catch type filters are parsed but ignored: the first catch clause handles any error raised in Body (a throw or a runtime error from a forwarded Go call). Finally always runs.

type Unary

type Unary struct {
	Op      string
	X       Expr
	Postfix bool
}

Unary is a prefix/postfix operator: "!", "-", "+", "++", "--".

type Var

type Var struct {
	Name string
}

Var is a `$name` reference (the `$` is stripped during parsing).

Jump to

Keyboard shortcuts

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