pawscript

package
v0.2.9-alpha-r3 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2025 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// Tau is the circle constant (2*pi) - the superior circle constant
	Tau = 6.283185307179586476925286766559005768394338798750211641949889184615632812572417997256069650684234
	// E is Euler's number
	E = math.E // 2.718281828459045235360287471352662497757247093699959574966...
	// Root2 is the square root of 2
	Root2 = math.Sqrt2 // 1.41421356237309504880168872420969807856967187537694...
	// Root3 is the square root of 3
	Root3 = 1.7320508075688772935274463415058723669428052538103806280558
	// Root5 is the square root of 5
	Root5 = 2.2360679774997896964091736687747632440588203494105043021130
	// Phi is the golden ratio (1 + sqrt(5)) / 2
	Phi = math.Phi // 1.61803398874989484820458683436563811772030917980576...
	// Ln2 is the natural logarithm of 2
	Ln2 = math.Ln2 // 0.693147180559945309417232121458176568075500134360255254120...
)

Mathematical constants - using Go's float64 precision

View Source
const (
	StringStorageThreshold = 200 // characters - strings larger than this become StoredString
	BlockStorageThreshold  = 500 // characters - blocks larger than this become StoredBlock
)

Storage thresholds - values larger than these are stored as objects

View Source
const ScopeMarker = "\x00SCOPE\x00"

ScopeMarker is the special marker for scope operator :: Used to distinguish module::item from named argument syntax

View Source
const UndefinedMarker = "\x00UNDEFINED\x00"

UndefinedMarker is the legacy string marker for undefined values Kept for backward compatibility - new code should use ActualUndefined{} instead

Variables

This section is empty.

Functions

func ANSIClearMode

func ANSIClearMode(mode string) string

ANSIClearMode returns ANSI clear sequence for different modes

func ANSIClearScreen

func ANSIClearScreen() string

ClearScreen returns ANSI code to clear screen

func ANSIColor

func ANSIColor(fg, bg int, bold, blink, underline, invert bool) string

ANSIColor generates ANSI escape sequence for colors and attributes fg, bg: CGA color numbers (0-15), -1 for default/unchanged bold, blink, underline, invert: attribute flags

func ANSIColorPreserving

func ANSIColorPreserving(fg, currentBG int, bold, blink, underline, invert bool) string

ANSIColorPreserving generates ANSI color sequence while preserving existing background This is used when only foreground is specified

func ANSIHideCursor

func ANSIHideCursor() string

HideCursor returns ANSI code to hide cursor

func ANSIMoveCursor

func ANSIMoveCursor(row, col int) string

MoveCursor returns ANSI code to position cursor

func ANSIMoveRelative

func ANSIMoveRelative(h, v int) string

MoveCursorRelative returns ANSI codes for relative movement

func ANSIReset

func ANSIReset() string

ANSIReset returns the ANSI reset sequence

func ANSISetCursorShape

func ANSISetCursorShape(shape string, blink string) string

SetCursorShape returns ANSI code for cursor shape Shapes: 0=default, 1=blinking block, 2=steady block, 3=blinking underline, 4=steady underline, 5=blinking bar, 6=steady bar Blink: "true"/"fast" = blinking, "false" = steady

func ANSIShowCursor

func ANSIShowCursor() string

ShowCursor returns ANSI code to show cursor

func CGAToANSIBG

func CGAToANSIBG(cga int) int

CGAToANSIBG converts CGA color (0-15) to ANSI background code

func CGAToANSIFG

func CGAToANSIFG(cga int) int

CGAToANSIFG converts CGA color (0-15) to ANSI foreground code

func ChannelClose

func ChannelClose(ch *StoredChannel) error

ChannelClose closes a channel or subscriber

func ChannelDisconnect

func ChannelDisconnect(ch *StoredChannel, subscriberID int) error

ChannelDisconnect disconnects a specific subscriber from a channel

func ChannelGetSize

func ChannelGetSize(ch *StoredChannel) (width, height int)

ChannelGetSize returns the terminal dimensions for the channel Falls back to system terminal if channel is nil or has no terminal capabilities

func ChannelGetTerminalType

func ChannelGetTerminalType(ch *StoredChannel) string

ChannelGetTerminalType returns the terminal type for the channel Falls back to system terminal if channel is nil or has no terminal capabilities

func ChannelIsOpened

func ChannelIsOpened(ch *StoredChannel) bool

ChannelIsOpened checks if a channel or subscriber is still open

func ChannelIsRedirected

func ChannelIsRedirected(ch *StoredChannel) bool

ChannelIsRedirected returns true if the channel's output is being redirected Falls back to system terminal if channel is nil or has no terminal capabilities

func ChannelIsTerminal

func ChannelIsTerminal(ch *StoredChannel) bool

ChannelIsTerminal returns true if the channel represents an interactive terminal Falls back to system terminal if channel is nil or has no terminal capabilities

func ChannelLen

func ChannelLen(ch *StoredChannel) int

ChannelLen returns the number of unread messages for a channel/subscriber

func ChannelRecv

func ChannelRecv(ch *StoredChannel) (int, interface{}, error)

ChannelRecv receives a message from a channel Returns (senderID, value, error) Advances read pointer and cleans up fully-consumed messages

func ChannelSend

func ChannelSend(ch *StoredChannel, value interface{}) error

ChannelSend sends a message to a channel If sender is the main channel (ID 0), broadcasts to all subscribers If sender is a subscriber, sends only to main channel

func ChannelSupportsANSI

func ChannelSupportsANSI(ch *StoredChannel) bool

ChannelSupportsANSI returns true if the channel's terminal supports ANSI escape codes Falls back to system terminal if channel is nil or has no terminal capabilities

func ChannelSupportsColor

func ChannelSupportsColor(ch *StoredChannel) bool

ChannelSupportsColor returns true if the channel's terminal supports color Falls back to system terminal if channel is nil or has no terminal capabilities

func CleanupTerminal

func CleanupTerminal()

CleanupTerminal restores the terminal to its original state. This should be called when the program exits to ensure the terminal is left in a usable state (proper newline handling, echo enabled, etc.)

func FormatValueColored

func FormatValueColored(value interface{}, pretty bool, cfg DisplayColorConfig, ps *PawScript) string

FormatValueColored formats any PawScript value with ANSI colors in PSL format This is the exported version that can be used by CLI tools

func GetTempDirectory

func GetTempDirectory() string

GetTempDirectory returns the system temp directory

func GetTerminalType

func GetTerminalType() string

GetTerminalType returns the terminal type from TERM environment variable

func GetWorkingDirectory

func GetWorkingDirectory() (string, error)

GetWorkingDirectory returns the current working directory

func IsRedirected

func IsRedirected() bool

IsRedirected checks if stdout is being redirected (piped or file)

func IsTerminal

func IsTerminal() bool

IsTerminal checks if stdout is a terminal

func JSONToStoredList

func JSONToStoredList(value interface{}, childrenKey string, mergeChildren interface{}, executor *Executor) interface{}

JSONToStoredList converts a parsed JSON value to a StoredList structure. - Arrays become lists with positional items only - Objects become lists with named args only - Special handling for _children (or custom childrenKey):

  • mergeChildren == nil: omit children entirely
  • mergeChildren == false: keep as separate named key with positional-only list
  • mergeChildren == true (default): merge children into positional args of parent
  • mergeChildren == int64(0): array_1 mode - index 0 object becomes named args, rest become positional

func LogLevelToString

func LogLevelToString(level LogLevel) string

LogLevelToString converts a LogLevel to its string name

func ParseColorName

func ParseColorName(name string) int

ParseColorName converts a color name or number to CGA color index (0-15) Returns -1 for invalid/default

func ParseCommand

func ParseCommand(commandStr string) (string, []interface{}, map[string]interface{})

ParseCommand parses a single command into name and arguments

func SerializePSL

func SerializePSL(config PSLMap) string

SerializePSL serializes a PSLMap to PSL format string Uses the same format as PawScript's list serialization

func SerializePSLList

func SerializePSLList(list PSLList) string

SerializePSLList serializes a PSLList to PSL format string

func SerializePSLPretty

func SerializePSLPretty(config PSLMap) string

SerializePSLPretty serializes a PSLMap to PSL format with pretty indentation Each named argument on its own line for readability

func SupportsANSI

func SupportsANSI() bool

SupportsANSI returns true if the terminal likely supports ANSI escape codes

func SupportsColor

func SupportsColor() bool

SupportsColor returns true if the terminal likely supports color

Types

type ActualUndefined

type ActualUndefined struct{}

ActualUndefined represents the undefined value as a proper type This replaces the old UndefinedMarker string approach for cleaner type handling

func (ActualUndefined) String

func (u ActualUndefined) String() string

type ArgParseError

type ArgParseError struct {
	Message string
}

ArgParseError represents an error that occurred during argument parsing It can be included in the returned args slice and detected by the executor

type BoolStatus

type BoolStatus bool

BoolStatus represents a boolean success/failure status

type BraceCoordinator

type BraceCoordinator struct {
	Evaluations       []*BraceEvaluation
	CompletedCount    int
	TotalCount        int
	HasFailure        bool
	FirstFailureError string
	OriginalString    string
	SubstitutionCtx   *SubstitutionContext
	ResumeCallback    func(finalString string, success bool) Result
}

BraceCoordinator manages parallel brace evaluation

type BraceEvaluation

type BraceEvaluation struct {
	Location  *BraceLocation
	TokenID   string      // Token ID if async, empty if sync
	Result    interface{} // Result value when completed
	State     *ExecutionState
	IsAsync   bool
	Completed bool
	Failed    bool
	Error     string
	Position  *SourcePosition // Position of the content inside the brace (for error reporting)
}

BraceEvaluation tracks the evaluation state of a single brace expression

type BraceLocation

type BraceLocation struct {
	StartPos         int
	EndPos           int
	Content          string
	StartLine        int
	StartColumn      int
	PositionInParent *SourcePosition
	IsUnescape       bool // true if ${...}, false if {...}
}

BraceLocation tracks the position of a brace expression in the source string

type BreakResult

type BreakResult struct {
	Levels int
}

BreakResult signals that a loop should be exited Levels indicates how many loop levels to break out of (1 = innermost)

type BubbleEntry

type BubbleEntry struct {
	Content    interface{}   // The PawScript value
	Microtime  int64         // Microseconds since epoch when created
	Memo       string        // Optional memo string
	StackTrace []interface{} // Optional stack trace (nil if trace was false)
	Flavors    []string      // All flavors this bubble belongs to (for cross-referencing)
}

BubbleEntry represents a single bubble in the bubble system Bubbles are out-of-band values that accumulate and "bubble up" through the call stack

type ChannelMessage

type ChannelMessage struct {
	SenderID   int
	Value      interface{}
	ConsumedBy map[int]bool // Track which subscribers have read this message
}

ChannelMessage represents a message in a channel buffer

type CommandSequence

type CommandSequence struct {
	Type               string // "sequence", "conditional", "or"
	RemainingCommands  []*ParsedCommand
	CurrentIndex       int
	TotalCommands      int
	OriginalCommand    string
	Timestamp          time.Time
	InheritedResult    interface{}
	HasInheritedResult bool
	Position           *SourcePosition
}

CommandSequence represents suspended command execution

type Config

type Config struct {
	Debug                bool
	DefaultTokenTimeout  time.Duration
	EnableSyntacticSugar bool
	AllowMacros          bool
	ShowErrorContext     bool
	ContextLines         int
	OptLevel             OptimizationLevel // AST caching level (default: OptimizeBasic)
	Stdin                io.Reader         // Custom stdin reader (default: os.Stdin)
	Stdout               io.Writer         // Custom stdout writer (default: os.Stdout)
	Stderr               io.Writer         // Custom stderr writer (default: os.Stderr)
	FileAccess           *FileAccessConfig // File system access control (nil = unrestricted)
	ScriptDir            string            // Directory containing the script being executed
}

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns default configuration

type Context

type Context struct {
	Args      []interface{}
	RawArgs   []string               // Original argument strings before resolution (for diagnostics)
	NamedArgs map[string]interface{} // Named arguments (key: value)
	Position  *SourcePosition

	ParsedCommand *ParsedCommand // Source parsed command (for block caching)
	// contains filtered or unexported fields
}

Context is passed to command handlers

func (*Context) ClaimObjectReference

func (c *Context) ClaimObjectReference(objectID int)

ClaimObjectReference claims ownership of an object to prevent garbage collection

func (*Context) ClearResult

func (c *Context) ClearResult()

ClearResult clears the result value

func (*Context) GetMacroContext

func (c *Context) GetMacroContext() *MacroContext

GetMacroContext returns the current macro context for stack traces

func (*Context) GetModuleEnv

func (c *Context) GetModuleEnv() *ModuleEnvironment

GetModuleEnv returns the module environment from the current execution state This can be used to capture the environment for deferred callback execution

func (*Context) GetOrParseBlock

func (c *Context) GetOrParseBlock(argIndex int, blockStr string) ([]*ParsedCommand, string)

GetOrParseBlock returns cached parsed commands for a block argument at the given index, or parses the block string if not cached. Returns nil and error string if parsing fails.

func (*Context) GetResult

func (c *Context) GetResult() interface{}

GetResult gets the current result value

func (*Context) GetVariable

func (c *Context) GetVariable(name string) (interface{}, bool)

GetVariable retrieves a variable from the current execution state

func (*Context) HasResult

func (c *Context) HasResult() bool

HasResult checks if a result value exists

func (*Context) LogError

func (c *Context) LogError(cat LogCategory, message string)

LogError logs a command error with position, routing through execution state channels

func (*Context) LogWarning

func (c *Context) LogWarning(cat LogCategory, message string)

LogWarning logs a command warning with position, routing through execution state channels

func (*Context) NewStoredListWithRefs

func (c *Context) NewStoredListWithRefs(items []interface{}, namedArgs map[string]interface{}) StoredList

NewStoredListWithRefs creates a StoredList and claims references to any nested object markers

func (*Context) RequestToken

func (c *Context) RequestToken(cleanup func(string)) string

RequestToken requests an async completion token

func (*Context) ResolveHashArg

func (c *Context) ResolveHashArg(name string) interface{}

ResolveHashArg resolves a hash-prefixed symbol through the lookup chain: 1. Local variables 2. ObjectsModule (module's copy-on-write object layer) 3. ObjectsInherited (inherited objects like io::#out) Returns nil if not found

func (*Context) ResumeToken

func (c *Context) ResumeToken(tokenID string, status bool) bool

ResumeToken resumes execution with a token

func (*Context) SetModuleObject

func (c *Context) SetModuleObject(name string, value interface{})

SetModuleObject sets a value in the current module's ObjectsModule (copy-on-write layer). This allows commands to override inherited objects for the current module context.

func (*Context) SetResult

func (c *Context) SetResult(value interface{})

SetResult sets the formal result value

func (*Context) StoreObject

func (c *Context) StoreObject(value interface{}, typeName string) int

StoreObject stores an object and returns its ID Deprecated: Use RegisterObject instead for new code

type ContinueResult

type ContinueResult struct {
	Levels int
}

ContinueResult signals that a loop should skip to the next iteration Levels indicates how many loop levels to skip (1 = innermost)

type DisplayColorConfig

type DisplayColorConfig struct {
	Reset   string
	Key     string
	String  string
	Int     string
	Float   string
	True    string
	False   string
	Nil     string
	Bracket string
	Colon   string
	Symbol  string
	Object  string
	Bytes   string
}

DisplayColorConfig holds ANSI color codes for colored output

func DefaultDisplayColors

func DefaultDisplayColors() DisplayColorConfig

DefaultDisplayColors returns the default color configuration

func ParseDisplayColorConfig

func ParseDisplayColorConfig(colorArg interface{}, executor *Executor) DisplayColorConfig

ParseDisplayColorConfig extracts color configuration from a list, using defaults for unspecified colors

type EarlyReturn

type EarlyReturn struct {
	Status    BoolStatus
	Result    interface{}
	HasResult bool
}

EarlyReturn represents early termination from a block

type ExecutionState

type ExecutionState struct {

	// InBraceExpression is true when executing inside a brace expression {...}
	// Commands can check this to return values instead of emitting side effects to #out
	InBraceExpression bool
	// contains filtered or unexported fields
}

ExecutionState manages the result state during command execution

func NewExecutionState

func NewExecutionState() *ExecutionState

NewExecutionState creates a new execution state

func NewExecutionStateFrom

func NewExecutionStateFrom(parent *ExecutionState) *ExecutionState

NewExecutionStateFrom creates a child state inheriting from parent Used for macro calls - starts with fresh result and nil bubbleMap (lazy-created if needed)

func NewExecutionStateFromSharedVars

func NewExecutionStateFromSharedVars(parent *ExecutionState) *ExecutionState

NewExecutionStateFromSharedVars creates a child that shares variables but has its own result storage This is used for braces that need isolated result storage but shared variable scope Bubbles survive into and out of brace expressions (shared bubbleMap)

func (*ExecutionState) AddBubble

func (s *ExecutionState) AddBubble(flavor string, content interface{}, trace bool, memo string)

AddBubble adds a new bubble entry to the bubble map If trace is true, includes the current stack trace

func (*ExecutionState) AddBubbleMultiFlavor

func (s *ExecutionState) AddBubbleMultiFlavor(flavors []string, content interface{}, trace bool, memo string)

AddBubbleMultiFlavor adds the SAME bubble entry to multiple flavors This allows the same entry to be found under different flavor keys, enabling efficient "burst" operations that can remove from all related flavors

func (*ExecutionState) ClaimObjectReference

func (s *ExecutionState) ClaimObjectReference(objectID int)

ClaimObjectReference takes ownership of an object reference This increments the reference count in the global store and tracks it locally If this state already owns the object, this is a no-op (idempotent)

func (*ExecutionState) ClearResult

func (s *ExecutionState) ClearResult()

ClearResult clears the result value

func (*ExecutionState) CreateChild

func (s *ExecutionState) CreateChild() *ExecutionState

CreateChild creates a child state that inherits current result

func (*ExecutionState) DeleteVariable

func (s *ExecutionState) DeleteVariable(name string)

DeleteVariable removes a variable from the current scope

func (*ExecutionState) ExtractObjectReferences

func (s *ExecutionState) ExtractObjectReferences(value interface{}) []int

ExtractObjectReferences scans a value for object markers and returns their IDs

func (*ExecutionState) GetAllFlavorNames

func (s *ExecutionState) GetAllFlavorNames() []string

GetAllFlavorNames returns all flavor names that currently have bubbles

func (*ExecutionState) GetBubbleMap

func (s *ExecutionState) GetBubbleMap() map[string][]*BubbleEntry

GetBubbleMap returns a copy of the bubble map for inspection

func (*ExecutionState) GetBubblesForFlavors

func (s *ExecutionState) GetBubblesForFlavors(flavors []string) []*BubbleEntry

GetBubblesForFlavors returns all unique bubbles from the specified flavors, sorted by microtime (oldest first). Duplicates are removed.

func (*ExecutionState) GetLastBraceFailureCount

func (s *ExecutionState) GetLastBraceFailureCount() int

GetLastBraceFailureCount returns the count of brace expressions that returned false in the last command

func (*ExecutionState) GetLastStatus

func (s *ExecutionState) GetLastStatus() bool

GetLastStatus returns the last command status

func (*ExecutionState) GetResult

func (s *ExecutionState) GetResult() interface{}

GetResult returns the current result value

func (*ExecutionState) GetVariable

func (s *ExecutionState) GetVariable(name string) (interface{}, bool)

GetVariable gets a variable from the current scope

func (*ExecutionState) HasResult

func (s *ExecutionState) HasResult() bool

HasResult checks if a result value exists

func (*ExecutionState) MergeBubbles

func (s *ExecutionState) MergeBubbles(child *ExecutionState)

MergeBubbles merges bubbles from a child state into this state Called when a macro returns to concatenate child's bubbles onto parent's

func (*ExecutionState) Recycle

func (s *ExecutionState) Recycle(ownsVariables, ownsBubbleMap bool)

Recycle returns the state and its maps to the object pools for reuse. Call this when the state is no longer needed (e.g., after macro execution). ownsVariables indicates whether this state owns its variables map (true for macro states, false for brace states that share variables with parent). ownsBubbleMap indicates whether this state owns its bubbleMap (true for macro states, false for brace states that share bubbleMap with parent).

func (*ExecutionState) ReleaseAllReferences

func (s *ExecutionState) ReleaseAllReferences()

ReleaseAllReferences releases all owned object references Called when context ends (normally or via early return)

func (*ExecutionState) ReleaseObjectReference

func (s *ExecutionState) ReleaseObjectReference(objectID int)

ReleaseObjectReference releases ownership of an object reference This decrements the reference count and may free the object

func (*ExecutionState) RemoveBubble

func (s *ExecutionState) RemoveBubble(entry *BubbleEntry)

RemoveBubble removes a bubble entry from ALL flavors it belongs to Uses the Flavors field on the entry to find all flavor lists to remove from

func (*ExecutionState) SetLastBraceFailureCount

func (s *ExecutionState) SetLastBraceFailureCount(count int)

SetLastBraceFailureCount sets the count of brace expressions that returned false

func (*ExecutionState) SetLastStatus

func (s *ExecutionState) SetLastStatus(status bool)

SetLastStatus sets the last command status

func (*ExecutionState) SetResult

func (s *ExecutionState) SetResult(value interface{})

SetResult sets the result value

func (*ExecutionState) SetResultWithoutClaim

func (s *ExecutionState) SetResultWithoutClaim(value interface{})

SetResultWithoutClaim sets result without claiming ownership Used when transferring ownership from child contexts

func (*ExecutionState) SetVariable

func (s *ExecutionState) SetVariable(name string, value interface{})

SetVariable sets a variable in the current scope

func (*ExecutionState) Snapshot

func (s *ExecutionState) Snapshot() (interface{}, bool)

Snapshot returns a snapshot of the current state

func (*ExecutionState) String

func (s *ExecutionState) String() string

String returns a string representation for debugging

type Executor

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

Executor handles command execution

func NewExecutor

func NewExecutor(logger *Logger) *Executor

NewExecutor creates a new command executor

func (*Executor) AddOrphanedBubbles

func (e *Executor) AddOrphanedBubbles(bubbleMap map[string][]*BubbleEntry)

AddOrphanedBubbles merges bubbles from an abandoned fiber into orphanedBubbles The references are transferred (not released) - caller must NOT release them after this call

func (*Executor) ApplyTemplate

func (e *Executor) ApplyTemplate(template *SubstitutionTemplate, ctx *SubstitutionContext) (string, bool)

ApplyTemplate executes a pre-parsed substitution template with the given context Returns the substituted string and a flag indicating if async processing is needed

func (*Executor) ApplyTemplateTyped

func (e *Executor) ApplyTemplateTyped(template *SubstitutionTemplate, ctx *SubstitutionContext) (interface{}, bool, bool)

ApplyTemplateTyped evaluates a single-expression template and returns the typed value directly. This avoids the round-trip through string markers for brace expressions, tilde variables, and dollar args. Returns (value, isTyped, isAsync):

  • isTyped=true means value is the typed result (use directly)
  • isTyped=false means fall back to string-based ApplyTemplate
  • isAsync=true means async coordination is needed

func (*Executor) ClearOrphanedBubbles

func (e *Executor) ClearOrphanedBubbles()

ClearOrphanedBubbles clears the orphaned bubbles map Should be called after retrieving and processing orphaned bubbles

func (*Executor) Execute

func (e *Executor) Execute(commandStr string, args ...interface{}) Result

Execute executes a command string

func (*Executor) ExecuteParsedCommands

func (e *Executor) ExecuteParsedCommands(
	commands []*ParsedCommand,
	state *ExecutionState,
	substitutionCtx *SubstitutionContext,
	lineOffset, columnOffset int,
) Result

ExecuteParsedCommands executes pre-parsed commands with the given state and context This is the cached-command equivalent of ExecuteWithState

func (*Executor) ExecuteStoredMacro

func (e *Executor) ExecuteStoredMacro(
	macro *StoredMacro,
	executeCallback func(commands string, state *ExecutionState, ctx *SubstitutionContext) Result,
	args []interface{},
	namedArgs map[string]interface{},
	state *ExecutionState,
	invocationPosition *SourcePosition,
	parentState *ExecutionState,
) Result

ExecuteStoredMacro executes a StoredMacro object directly

func (*Executor) ExecuteWithState

func (e *Executor) ExecuteWithState(
	commandStr string,
	state *ExecutionState,
	substitutionCtx *SubstitutionContext,
	filename string,
	lineOffset, columnOffset int,
) Result

ExecuteWithState executes with explicit state and substitution context

func (*Executor) ForceCleanupToken

func (e *Executor) ForceCleanupToken(tokenID string)

ForceCleanupToken forces cleanup of a token

func (*Executor) GetCommand

func (e *Executor) GetCommand(name string) (Handler, bool)

GetCommand retrieves a command handler by name

func (*Executor) GetFiberCount

func (e *Executor) GetFiberCount() int

GetFiberCount returns the number of currently running fibers

func (*Executor) GetMaxIterations

func (e *Executor) GetMaxIterations() int

GetMaxIterations returns the maximum loop iterations setting 0 or negative means unlimited

func (*Executor) GetOptimizationLevel

func (e *Executor) GetOptimizationLevel() OptimizationLevel

GetOptimizationLevel returns the current AST caching level

func (*Executor) GetOrCacheBlockArg

func (e *Executor) GetOrCacheBlockArg(cmd *ParsedCommand, argIndex int, blockStr string, filename string) []*ParsedCommand

GetOrCacheBlockArg returns cached parsed commands for a block argument, or parses and caches them. This is called by loop commands (while, for, repeat, fizz) to cache their body blocks. If the block contains $N patterns, it cannot be cached and nil is returned (caller should parse fresh). If cmd is nil (not from cached macro), nil is returned and caller should parse fresh.

func (*Executor) GetOrParseMacroCommands

func (e *Executor) GetOrParseMacroCommands(macro *StoredMacro, filename string) ([]*ParsedCommand, error)

GetOrParseMacroCommands returns cached parsed commands for a macro, or parses and caches them If caching is disabled (OptimizeNone), it parses fresh each time The returned commands can be executed with ExecuteParsedCommands

func (*Executor) GetOrphanedBubbles

func (e *Executor) GetOrphanedBubbles() map[string][]*BubbleEntry

GetOrphanedBubbles returns the current orphaned bubbles map Does NOT clear the map - caller should call ClearOrphanedBubbles after processing

func (*Executor) GetSuspendedFibers

func (e *Executor) GetSuspendedFibers() map[int]string

GetSuspendedFibers returns a map of fiberID -> tokenID for all suspended fibers

func (*Executor) GetTokenStatus

func (e *Executor) GetTokenStatus() map[string]interface{}

GetTokenStatus returns information about active tokens

func (*Executor) NewBlock

func (e *Executor) NewBlock(s string) ObjectRef

NewBlock creates a new stored block and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewBytes

func (e *Executor) NewBytes(data []byte) ObjectRef

NewBytes creates a new stored bytes object and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewChannel

func (e *Executor) NewChannel(bufferSize int) ObjectRef

NewChannel creates a new stored channel and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewCommand

func (e *Executor) NewCommand(cmd StoredCommand) ObjectRef

NewCommand creates a new stored command and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewFiber

func (e *Executor) NewFiber(fh *FiberHandle) ObjectRef

NewFiber creates a new stored fiber and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewFile

func (e *Executor) NewFile(file *StoredFile) ObjectRef

NewFile creates a new stored file and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewList

func (e *Executor) NewList(items []interface{}, namedArgs map[string]interface{}) ObjectRef

NewList creates a new stored list and returns its ObjectRef. Claims nested refs for any ObjectRefs in items or namedArgs. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewMacro

func (e *Executor) NewMacro(macro StoredMacro) ObjectRef

NewMacro creates a new stored macro and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewString

func (e *Executor) NewString(s string) ObjectRef

NewString creates a new stored string and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewStruct

func (e *Executor) NewStruct(ss StoredStruct) ObjectRef

NewStruct creates a new stored struct and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) NewStructArray

func (e *Executor) NewStructArray(ss StoredStruct) ObjectRef

NewStructArray creates a new stored struct array and returns its ObjectRef. Returns ObjectRef with refcount=0 - caller must claim ownership.

func (*Executor) ParseSubstitutionTemplate

func (e *Executor) ParseSubstitutionTemplate(str string, filename string) *SubstitutionTemplate

ParseSubstitutionTemplate parses a string into a SubstitutionTemplate for efficient runtime substitution This pre-computes all substitution points so runtime only needs to iterate and fill in values

func (*Executor) PopAndResumeCommandSequence

func (e *Executor) PopAndResumeCommandSequence(tokenID string, status bool) bool

PopAndResumeCommandSequence pops and resumes a command sequence

func (*Executor) PreCacheCommandTemplates

func (e *Executor) PreCacheCommandTemplates(cmd *ParsedCommand, filename string)

PreCacheCommandTemplates pre-parses substitution templates for a command's arguments

func (*Executor) PushCommandSequence

func (e *Executor) PushCommandSequence(
	tokenID string,
	seqType string,
	remainingCommands []*ParsedCommand,
	currentIndex int,
	originalCommand string,
	state *ExecutionState,
	position *SourcePosition,
) error

PushCommandSequence pushes a command sequence onto a token

func (*Executor) RefClaim

func (e *Executor) RefClaim(ref ObjectRef)

RefClaim increments the reference count for an object. Safe to call with zero-value ObjectRef (no-op). This is the ONLY function that should be used to claim object references.

func (*Executor) RefRelease

func (e *Executor) RefRelease(ref ObjectRef)

RefRelease decrements the reference count for an object. When refcount reaches 0, releases nested refs and marks for ID reuse. Safe to call with zero-value ObjectRef (no-op). This is the ONLY function that should be used to release object references.

func (*Executor) RegisterCommand

func (e *Executor) RegisterCommand(name string, handler Handler)

RegisterCommand registers a command handler

func (*Executor) RegisterObject

func (e *Executor) RegisterObject(value interface{}, objType ObjectType) ObjectRef

RegisterObject stores a new object and returns its ObjectRef The object is stored with refcount=0 - caller must claim ownership For lists: automatically claims refs to all nested items (ensures proper cleanup on free)

func (*Executor) RequestBraceCoordinatorToken

func (e *Executor) RequestBraceCoordinatorToken(
	evaluations []*BraceEvaluation,
	originalString string,
	substitutionCtx *SubstitutionContext,
	resumeCallback func(finalString string, success bool) Result,
	state *ExecutionState,
	position *SourcePosition,
) string

RequestBraceCoordinatorToken creates a token for coordinating parallel brace evaluation

func (*Executor) RequestCompletionToken

func (e *Executor) RequestCompletionToken(
	cleanupCallback func(string),
	parentTokenID string,
	timeout time.Duration,
	state *ExecutionState,
	position *SourcePosition,
) string

RequestCompletionToken requests a new completion token for async operations If timeout <= 0, no timeout is set (token relies on explicit completion)

func (*Executor) ResumeBraceEvaluation

func (e *Executor) ResumeBraceEvaluation(coordinatorToken, childToken string, result interface{}, success bool)

ResumeBraceEvaluation is called when a child brace evaluation completes

func (*Executor) SetFallbackHandler

func (e *Executor) SetFallbackHandler(handler func(string, []interface{}, map[string]interface{}, *ExecutionState, *SourcePosition) Result)

SetFallbackHandler sets a fallback handler for unknown commands

func (*Executor) SetMaxIterations

func (e *Executor) SetMaxIterations(max int)

SetMaxIterations sets the maximum loop iterations 0 or negative values mean unlimited iterations

func (*Executor) SetOptimizationLevel

func (e *Executor) SetOptimizationLevel(level OptimizationLevel)

SetOptimizationLevel sets the AST caching level

func (*Executor) SetRootState

func (e *Executor) SetRootState(state *ExecutionState)

SetRootState sets the root execution state for error routing fallback

func (*Executor) SpawnFiber

func (e *Executor) SpawnFiber(macro *StoredMacro, args []interface{}, namedArgs map[string]interface{}, parentModuleEnv *ModuleEnvironment) *FiberHandle

SpawnFiber spawns a new fiber to execute a macro parentModuleEnv allows the fiber to inherit commands from the parent context

func (*Executor) UnregisterCommand

func (e *Executor) UnregisterCommand(name string) bool

UnregisterCommand unregisters a command

func (*Executor) WaitForAllFibers

func (e *Executor) WaitForAllFibers()

WaitForAllFibers blocks until all child fibers complete

func (*Executor) WaitForFiber

func (e *Executor) WaitForFiber(fiber *FiberHandle) (interface{}, error)

WaitForFiber blocks until the specified fiber completes

type FiberHandle

type FiberHandle struct {
	ID             int
	State          *ExecutionState
	SuspendedOn    string                    // tokenID if suspended, "" if running
	ResumeChan     chan ResumeData           // Channel for resuming suspended fiber
	Result         interface{}               // Final result when fiber completes
	Error          error                     // Error if fiber failed
	CompleteChan   chan struct{}             // Closed when fiber completes
	Completed      bool                      // True when fiber has finished
	FinalBubbleMap map[string][]*BubbleEntry // Preserved bubbleMap after fiber completion
	BubbleUpMap    map[string][]*BubbleEntry // Early bubble staging area (for fiber_bubble)
	// contains filtered or unexported fields
}

FiberHandle represents a running fiber (lightweight thread)

type FileAccessConfig

type FileAccessConfig struct {
	ReadRoots  []string // Directories allowed for read access (empty = no access)
	WriteRoots []string // Directories allowed for write access (empty = no access)
	ExecRoots  []string // Directories allowed for exec command (empty = no access)
}

FileAccessConfig controls file system access permissions

type FizzContinuation

type FizzContinuation struct {
	BodyBlock          string            // The fizz body
	CachedBodyCmds     []*ParsedCommand  // Cached full parsed body for reuse across iterations
	RemainingBodyCmds  []*ParsedCommand  // Commands remaining in current iteration after yield
	BodyCmdIndex       int               // Which command in body yielded
	ContentVarName     string            // Variable name for bubble content
	MetaVarName        string            // Variable name for bubble metadata (optional)
	HasMetaVar         bool              // Whether meta variable is being used
	Flavors            []string          // Flavors being iterated
	CurrentBubbleIndex int               // Current position in bubble list
	Bubbles            []*BubbleEntry    // List of bubbles being iterated
	State              *ExecutionState   // Execution state at time of yield
	ParentContinuation *FizzContinuation // For nested fizz loops
}

FizzContinuation stores state for resuming a fizz loop after yield

type ForContinuation

type ForContinuation struct {
	BodyBlock         string           // The for body
	CachedBodyCmds    []*ParsedCommand // Cached full parsed body for reuse across iterations
	RemainingBodyCmds []*ParsedCommand // Commands remaining in current iteration after yield
	BodyCmdIndex      int              // Which command in body yielded
	IterationNumber   int              // Current iteration number (1-based for iter:)
	IterVar           string           // Variable for iteration value
	IterNumVar        string           // Variable for iter: (iteration number)
	IndexVar          string           // Variable for index: (0-based index)
	KeyVar            string           // Variable for key (key-value iteration)
	ValueVar          string           // Variable for value (key-value iteration)
	UnpackVars        []string         // Variables for unpack mode
	// Iterator state
	IteratorToken      string           // Token marker for the iterator
	IteratorType       string           // "range", "list", "keys", "generator", "channel", "structarray"
	IsDescending       bool             // Whether iterating in descending order
	State              *ExecutionState  // Execution state at time of yield
	ParentContinuation *ForContinuation // For nested for loops
	// Numeric range state
	RangeStart   float64 // Start value for numeric range
	RangeEnd     float64 // End value for numeric range
	RangeStep    float64 // Step value for numeric range
	RangeCurrent float64 // Current value in numeric range
}

ForContinuation stores state for resuming a for loop after yield

type Handler

type Handler func(*Context) Result

Handler is a function that handles a command

type IOChannelConfig

type IOChannelConfig struct {
	// Standard channels - if nil, defaults will be created using DefaultStdin/Stdout/Stderr
	Stdin  *StoredChannel // Read-only channel for input
	Stdout *StoredChannel // Write-only channel for standard output
	Stderr *StoredChannel // Write-only channel for error output
	Stdio  *StoredChannel // Bidirectional channel (read from stdin, write to stdout)

	// Default streams to use when creating default channels (if nil, uses os.Stdin/Stdout/Stderr)
	DefaultStdin  io.Reader
	DefaultStdout io.Writer
	DefaultStderr io.Writer

	// Additional custom channels - will be registered with their map keys as names
	// Example: {"#mylog": logChannel} would create io::#mylog
	CustomChannels map[string]*StoredChannel
}

IOChannelConfig allows host applications to provide custom IO channel handlers Any nil channel will use the default OS-backed implementation

type ItemMetadata

type ItemMetadata struct {
	// Original module name as registered/loaded from disk or stdlib
	OriginalModuleName string

	// For macros/objects: source location where defined/exported
	// For commands: empty
	SourceFile   string
	SourceLine   int
	SourceColumn int

	// For commands: "standard" (stdlib) or "host" (registered by host app)
	// For macros/objects: empty
	RegistrationSource string

	// The module name it was IMPORTed from (may differ if renamed via MODULE)
	ImportedFromModule string

	// The original item name in the library (before any rename via IMPORT)
	OriginalName string

	// The item type: "command", "macro", "object"
	ItemType string
}

ItemMetadata tracks comprehensive metadata about an item in the registry

type IteratorState

type IteratorState struct {
	Type     string     // "each", "pair", "range", or "rng"
	ListID   int        // Object ID of the list being iterated
	Index    int        // Current position (for "each")
	Keys     []string   // Keys to iterate (for "pair")
	KeyIndex int        // Current key position (for "pair")
	Rng      *rand.Rand // Random number generator (for "rng")
	// Range iterator fields
	RangeStart   float64 // Start value (for "range")
	RangeEnd     float64 // End value (for "range")
	RangeStep    float64 // Step value (for "range")
	RangeCurrent float64 // Current value (for "range")
	RangeStarted bool    // Whether iteration has started (for "range")
}

IteratorState stores state for Go-backed iterators (each, pair, range, rng)

type KeyInputManager

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

KeyInputManager handles raw keyboard input, parsing escape sequences and providing both key events and line assembly

func NewKeyInputManager

func NewKeyInputManager(inputReader io.Reader, echoWriter io.Writer, debugFn func(string)) *KeyInputManager

NewKeyInputManager creates a new key input manager inputReader can be any io.Reader (os.Stdin, io.PipeReader, etc.) echoWriter is where to echo typed characters (typically os.Stdout or a pipe) If inputReader is os.Stdin and is a terminal, raw mode will be enabled

func (*KeyInputManager) GetKeysChannel

func (m *KeyInputManager) GetKeysChannel() *StoredChannel

GetKeysChannel returns the channel for reading parsed key events

func (*KeyInputManager) GetLinesChannel

func (m *KeyInputManager) GetLinesChannel() *StoredChannel

GetLinesChannel returns the channel for reading assembled lines

func (*KeyInputManager) IsManagingStdin

func (m *KeyInputManager) IsManagingStdin() bool

IsManagingStdin returns true if this manager is managing the terminal stdin This is used by REPLs to determine if they should delegate input handling. Returns true if either: - Manager directly manages terminal (input is os.Stdin) - Manager reads from a terminal-backed channel (e.g., #in wrapping stdin)

func (*KeyInputManager) IsRunning

func (m *KeyInputManager) IsRunning() bool

IsRunning returns true if the manager is currently running

func (*KeyInputManager) SetLineEchoWriter

func (m *KeyInputManager) SetLineEchoWriter(w io.Writer)

SetLineEchoWriter sets the writer to use for echo during line read mode This is used when input comes from a channel (not os.Stdin directly) but we still want echo during {read} operations

func (*KeyInputManager) SetTerminalBacked

func (m *KeyInputManager) SetTerminalBacked(backed bool)

SetTerminalBacked marks this manager as reading from a terminal-backed channel. This is used when input comes through a channel that wraps stdin, so the manager knows to signal REPLs to delegate input handling even though it's not directly reading from os.Stdin.

func (*KeyInputManager) Start

func (m *KeyInputManager) Start() error

Start begins reading from input and processing keys

func (*KeyInputManager) Stop

func (m *KeyInputManager) Stop() error

Stop stops reading and restores terminal state

type Library

type Library map[string]ModuleSection

Library is a two-level structure: moduleName -> itemName -> ModuleItem

type ListTypeInfo

type ListTypeInfo struct {
	Type         string // "empty", "nil", "undefined", specific type, or "mixed"
	Solid        bool   // true if no nil/undefined values
	Serializable bool   // true if all values are serializable
}

ListTypeInfo holds type tracking information for a collection of values

func NewEmptyTypeInfo

func NewEmptyTypeInfo() ListTypeInfo

NewEmptyTypeInfo returns initial type info for an empty collection

type LogCategory

type LogCategory string

LogCategory represents the subsystem generating the message

const (
	CatNone     LogCategory = ""         // Uncategorized
	CatParse    LogCategory = "parse"    // Parser errors
	CatCommand  LogCategory = "command"  // Command execution
	CatVariable LogCategory = "variable" // Variable operations (get/set)
	CatArgument LogCategory = "argument" // Argument validation
	CatIO       LogCategory = "io"       // I/O operations (read/exec)
	CatNetwork  LogCategory = "network"  // Network operations
	CatMacro    LogCategory = "macro"    // Macro operations
	CatAsync    LogCategory = "async"    // Async/token operations
	CatMemory   LogCategory = "memory"   // Memory/refcounting
	CatMath     LogCategory = "math"     // Arithmetic operations
	CatList     LogCategory = "list"     // List operations
	CatString   LogCategory = "string"   // String operations
	CatType     LogCategory = "type"     // Type operations
	CatFlow     LogCategory = "flow"     // Flow control (while, if, ret)
	CatSystem   LogCategory = "system"   // System/module operations
	CatApp      LogCategory = "app"      // Application specific
	CatUser     LogCategory = "user"     // User generated/custom
)

func AllLogCategories

func AllLogCategories() []LogCategory

AllLogCategories returns a slice of all defined log categories (excluding CatNone)

func LogCategoryFromString

func LogCategoryFromString(name string) (LogCategory, bool)

LogCategoryFromString converts a string name to a LogCategory Returns CatNone if the string is not a valid category name

type LogConfig

type LogConfig struct {
	ErrorLog  *LogFilter // Filter for #err output
	DebugLog  *LogFilter // Filter for #debug output
	BubbleLog *LogFilter // Filter for bubble capture
}

LogConfig holds the three log filter systems (error_logging, debug_logging, bubble_logging) ErrorLog controls what goes to #err; DebugLog controls what goes to #debug BubbleLog controls what gets captured as bubbles (flavor = level_category) A message can pass multiple filters and appear in multiple outputs

func NewLogConfig

func NewLogConfig() *LogConfig

NewLogConfig creates a new LogConfig with default settings ErrorLog defaults to showing Warn and above; DebugLog defaults to showing nothing BubbleLog defaults to capturing nothing (must be explicitly enabled) Force threshold: ErrorLog keeps Fatal (mandatory stderr), DebugLog/BubbleLog have None (so fatal errors aren't forced to debug/bubble outputs - they'll bubble up anyway)

func (*LogConfig) Copy

func (c *LogConfig) Copy() *LogConfig

Copy creates a deep copy of the LogConfig for COW semantics

type LogFilter

type LogFilter struct {
	Default    LogLevel                 // Threshold for categories not in the map
	Categories map[LogCategory]LogLevel // Per-category thresholds
	Floor      LogLevel                 // Global floor: nothing below this ever shows
	Force      LogLevel                 // Global force: everything at/above this always shows
}

LogFilter controls which log messages pass through to an output channel A message passes the filter if:

  • Level >= Force (always pass), OR
  • Level >= Floor AND Level >= threshold (where threshold is Categories[cat] if exists, else Default)

func NewLogFilter

func NewLogFilter(defaultLevel LogLevel) *LogFilter

NewLogFilter creates a new LogFilter with sensible defaults

func (*LogFilter) Copy

func (f *LogFilter) Copy() *LogFilter

Copy creates a deep copy of the LogFilter for COW semantics

func (*LogFilter) Passes

func (f *LogFilter) Passes(level LogLevel, cat LogCategory) bool

Passes checks if a message with the given level and category passes this filter

func (*LogFilter) PassesAny

func (f *LogFilter) PassesAny(level LogLevel, cats []LogCategory) bool

PassesAny checks if a message passes the filter for ANY of the given categories This allows a message to be tagged with multiple categories (e.g., CatCommand + CatMath) and pass if any of those categories' thresholds are met

type LogLevel

type LogLevel int

LogLevel represents the severity of a log message (higher value = higher severity)

const (
	LevelTrace  LogLevel = iota // Detailed tracing (requires enabled + category)
	LevelInfo                   // Informational messages (requires enabled + category)
	LevelDebug                  // Development debugging (requires enabled + category)
	LevelNotice                 // Notable events (always shown)
	LevelWarn                   // Warnings (always shown)
	LevelError                  // Runtime errors (always shown)
	LevelFatal                  // Parse/unknown command errors (always shown)
)
const LevelNone LogLevel = LevelFatal + 1

LevelNone represents "off" - threshold higher than any level, so nothing passes

func LogLevelFromString

func LogLevelFromString(name string) LogLevel

LogLevelFromString converts a string name to a LogLevel Returns -1 if the string is not a valid level name

type Logger

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

Logger handles logging for PawScript

func NewLogger

func NewLogger(enabled bool) *Logger

NewLogger creates a new logger with default stdout/stderr

func NewLoggerWithWriters

func NewLoggerWithWriters(enabled bool, stdout, stderr io.Writer) *Logger

NewLoggerWithWriters creates a new logger with custom writers

func (*Logger) ClearOutputContext

func (l *Logger) ClearOutputContext()

ClearOutputContext clears the output context (reverts to direct io.Writer)

func (*Logger) CommandError

func (l *Logger) CommandError(cat LogCategory, cmdName, message string, position *SourcePosition)

CommandError logs a command execution error with category

func (*Logger) CommandWarning

func (l *Logger) CommandWarning(cat LogCategory, cmdName, message string, position *SourcePosition)

CommandWarning logs a command warning with category

func (*Logger) Debug

func (l *Logger) Debug(format string, args ...interface{})

Debug logs a debug message (no position)

func (*Logger) DebugCat

func (l *Logger) DebugCat(cat LogCategory, format string, args ...interface{})

DebugCat logs a categorized debug message

func (*Logger) DebugMulti

func (l *Logger) DebugMulti(cats []LogCategory, format string, args ...interface{})

DebugMulti logs a debug message with multiple categories

func (*Logger) DebugWithState

func (l *Logger) DebugWithState(cat LogCategory, message string, state *ExecutionState, executor *Executor)

DebugWithState logs a debug message using the given execution state for channel resolution

func (*Logger) DisableCategory

func (l *Logger) DisableCategory(cat LogCategory)

DisableCategory disables debug logging for a specific category

func (*Logger) EnableAllCategories

func (l *Logger) EnableAllCategories()

EnableAllCategories enables all categories for debug logging

func (*Logger) EnableCategory

func (l *Logger) EnableCategory(cat LogCategory)

EnableCategory enables debug logging for a specific category

func (*Logger) Error

func (l *Logger) Error(format string, args ...interface{})

Error logs an error message (no position)

func (*Logger) ErrorCat

func (l *Logger) ErrorCat(cat LogCategory, format string, args ...interface{})

ErrorCat logs a categorized error message

func (*Logger) ErrorMulti

func (l *Logger) ErrorMulti(cats []LogCategory, format string, args ...interface{})

ErrorMulti logs an error with multiple categories

func (*Logger) ErrorWithPosition

func (l *Logger) ErrorWithPosition(cat LogCategory, message string, position *SourcePosition, context []string)

ErrorWithPosition logs an error with position information

func (*Logger) ErrorWithState

func (l *Logger) ErrorWithState(cat LogCategory, message string, state *ExecutionState, executor *Executor)

ErrorWithState logs an error message using the given execution state for channel resolution

func (*Logger) Fatal

func (l *Logger) Fatal(format string, args ...interface{})

Fatal logs a fatal error message (no position) - use ParseError or UnknownCommandError for positioned errors

func (*Logger) FatalCat

func (l *Logger) FatalCat(cat LogCategory, format string, args ...interface{})

FatalCat logs a categorized fatal error message

func (*Logger) FatalWithState

func (l *Logger) FatalWithState(cat LogCategory, message string, state *ExecutionState, executor *Executor)

FatalWithState logs a fatal error message using the given execution state for channel resolution

func (*Logger) GetStderr

func (l *Logger) GetStderr() io.Writer

GetStderr returns the stderr writer

func (*Logger) GetStdout

func (l *Logger) GetStdout() io.Writer

GetStdout returns the stdout writer

func (*Logger) Info

func (l *Logger) Info(format string, args ...interface{})

Info logs an informational message (no position)

func (*Logger) InfoCat

func (l *Logger) InfoCat(cat LogCategory, format string, args ...interface{})

InfoCat logs a categorized informational message

func (*Logger) InfoMulti

func (l *Logger) InfoMulti(cats []LogCategory, format string, args ...interface{})

InfoMulti logs an info message with multiple categories

func (*Logger) InfoWithState

func (l *Logger) InfoWithState(cat LogCategory, message string, state *ExecutionState, executor *Executor)

InfoWithState logs an info message using the given execution state for channel resolution

func (*Logger) IsCategoryEnabled

func (l *Logger) IsCategoryEnabled(cat LogCategory) bool

IsCategoryEnabled checks if a category is enabled

func (*Logger) Log

func (l *Logger) Log(level LogLevel, cat LogCategory, message string, position *SourcePosition, context []string)

Log is the unified logging method

func (*Logger) LogMulti

func (l *Logger) LogMulti(level LogLevel, cats []LogCategory, message string, position *SourcePosition, context []string)

LogMulti is like Log but accepts multiple categories A message passes a filter if ANY of its categories pass that filter's threshold The first category in the list is used for the message prefix

func (*Logger) LogWithState

func (l *Logger) LogWithState(level LogLevel, cat LogCategory, message string, position *SourcePosition, context []string, state *ExecutionState, executor *Executor)

LogWithState logs a message using the given execution state for channel resolution This is useful when you want to log with a specific state context

func (*Logger) Notice

func (l *Logger) Notice(format string, args ...interface{})

Notice logs a notable event (no position) - always shown, less severe than warning

func (*Logger) NoticeCat

func (l *Logger) NoticeCat(cat LogCategory, format string, args ...interface{})

NoticeCat logs a categorized notice message

func (*Logger) NoticeMulti

func (l *Logger) NoticeMulti(cats []LogCategory, format string, args ...interface{})

NoticeMulti logs a notice with multiple categories

func (*Logger) NoticeWithState

func (l *Logger) NoticeWithState(cat LogCategory, message string, state *ExecutionState, executor *Executor)

NoticeWithState logs a notice message using the given execution state for channel resolution

func (*Logger) ParseError

func (l *Logger) ParseError(message string, position *SourcePosition, context []string)

ParseError logs a parse error (always visible)

func (*Logger) SetEnabled

func (l *Logger) SetEnabled(enabled bool)

SetEnabled enables or disables debug logging

func (*Logger) SetOutputContext

func (l *Logger) SetOutputContext(ctx *OutputContext)

SetOutputContext sets the output context for channel-based logging This should be called when entering a new execution scope

func (*Logger) Trace

func (l *Logger) Trace(format string, args ...interface{})

Trace logs a detailed trace message (no position)

func (*Logger) TraceCat

func (l *Logger) TraceCat(cat LogCategory, format string, args ...interface{})

TraceCat logs a categorized trace message

func (*Logger) TraceMulti

func (l *Logger) TraceMulti(cats []LogCategory, format string, args ...interface{})

TraceMulti logs a trace message with multiple categories

func (*Logger) TraceWithState

func (l *Logger) TraceWithState(cat LogCategory, message string, state *ExecutionState, executor *Executor)

TraceWithState logs a trace message using the given execution state for channel resolution

func (*Logger) UnknownCommandError

func (l *Logger) UnknownCommandError(commandName string, position *SourcePosition, context []string)

UnknownCommandError logs an unknown command error (always visible)

func (*Logger) Warn

func (l *Logger) Warn(format string, args ...interface{})

Warn logs a warning message (no position)

func (*Logger) WarnCat

func (l *Logger) WarnCat(cat LogCategory, format string, args ...interface{})

WarnCat logs a categorized warning message

func (*Logger) WarnMulti

func (l *Logger) WarnMulti(cats []LogCategory, format string, args ...interface{})

WarnMulti logs a warning with multiple categories

func (*Logger) WarnWithState

func (l *Logger) WarnWithState(cat LogCategory, message string, state *ExecutionState, executor *Executor)

WarnWithState logs a warning message using the given execution state for channel resolution

func (*Logger) WithContext

func (l *Logger) WithContext(state *ExecutionState, executor *Executor) *Logger

WithContext returns a copy of the logger with the given output context This is useful for creating a logger bound to a specific execution state

type MacroContext

type MacroContext struct {
	MacroName        string
	DefinitionFile   string
	DefinitionLine   int
	DefinitionColumn int
	InvocationFile   string
	InvocationLine   int
	InvocationColumn int
	ParentMacro      *MacroContext
}

MacroContext tracks macro invocation chain for error reporting

type MacroDefinition

type MacroDefinition struct {
	Name             string
	Commands         string
	DefinitionFile   string
	DefinitionLine   int
	DefinitionColumn int
	Timestamp        time.Time
}

MacroDefinition stores a macro definition

type ModuleEnvironment

type ModuleEnvironment struct {

	// Current default module name for exports
	DefaultName string

	// Library layers (two-level: module -> items)
	LibraryInherited  Library // Read-only reference from parent
	LibraryRestricted Library // Copy-on-write, starts pointing to Inherited

	// Command registry layers
	CommandRegistryInherited map[string]Handler // Reference from parent
	CommandRegistryModule    map[string]Handler // Copy-on-write

	// Macro registry layers
	MacrosInherited map[string]*StoredMacro // Reference from parent
	MacrosModule    map[string]*StoredMacro // Copy-on-write

	// Object storage layers (for #-prefixed exports)
	ObjectsInherited map[string]interface{} // Reference from parent
	ObjectsModule    map[string]interface{} // Copy-on-write

	// Module exports (accumulated during execution)
	ModuleExports Library

	// Item metadata tracking (keyed by local name)
	ItemMetadataInherited map[string]*ItemMetadata // Reference from parent
	ItemMetadataModule    map[string]*ItemMetadata // Copy-on-write

	// Log configuration layers (controls what goes to #err and #out)
	LogConfigInherited *LogConfig // Reference from parent
	LogConfigModule    *LogConfig // Copy-on-write

	// Cache invalidation: incremented when MacrosModule or CommandRegistryModule is modified
	// Used by ParsedCommand to know when cached handler resolutions are stale
	RegistryGeneration uint64
	// contains filtered or unexported fields
}

ModuleEnvironment encapsulates the module system state

func NewChildModuleEnvironment

func NewChildModuleEnvironment(parent *ModuleEnvironment) *ModuleEnvironment

NewChildModuleEnvironment creates a child environment inheriting from parent

func NewMacroModuleEnvironment

func NewMacroModuleEnvironment(parent *ModuleEnvironment) *ModuleEnvironment

NewMacroModuleEnvironment creates an environment for a macro definition This captures the current state with copy-on-write isolation: - Inherited layers point to parent's current Module layers - Module layers share the same reference (COW ensures isolation on modification) - ModuleExports starts blank; caller merges exports into their LibraryInherited after execution

func NewModuleEnvironment

func NewModuleEnvironment() *ModuleEnvironment

NewModuleEnvironment creates a new module environment All registry pairs (Inherited/Module) start pointing to the same map instance. They only diverge via copy-on-write when modifications are made.

func (*ModuleEnvironment) CopyCommandRegistry

func (env *ModuleEnvironment) CopyCommandRegistry()

CopyCommandRegistry is an alias for EnsureCommandRegistryCopied for backward compatibility.

func (*ModuleEnvironment) CopyLibraryInherited

func (env *ModuleEnvironment) CopyLibraryInherited()

CopyLibraryInherited performs copy-on-write for LibraryInherited This is used by LIBRARY "forget" to modify Inherited without affecting Restricted

func (*ModuleEnvironment) CopyLibraryRestricted

func (env *ModuleEnvironment) CopyLibraryRestricted()

CopyLibraryRestricted performs copy-on-write for LibraryRestricted

func (*ModuleEnvironment) CopyMacroRegistry

func (env *ModuleEnvironment) CopyMacroRegistry()

CopyMacroRegistry is an alias for EnsureMacroRegistryCopied for backward compatibility.

func (*ModuleEnvironment) CopyObjectRegistry

func (env *ModuleEnvironment) CopyObjectRegistry()

CopyObjectRegistry is an alias for EnsureObjectRegistryCopied for backward compatibility.

func (*ModuleEnvironment) EnsureCommandRegistryCopied

func (env *ModuleEnvironment) EnsureCommandRegistryCopied()

EnsureCommandRegistryCopied performs copy-on-write for CommandRegistryModule. Creates an isolated copy so modifications don't affect the original shared map.

func (*ModuleEnvironment) EnsureLogConfigCopied

func (env *ModuleEnvironment) EnsureLogConfigCopied()

EnsureLogConfigCopied performs copy-on-write for LogConfigModule. Creates an isolated copy so modifications don't affect the original shared config.

func (*ModuleEnvironment) EnsureMacroRegistryCopied

func (env *ModuleEnvironment) EnsureMacroRegistryCopied()

EnsureMacroRegistryCopied performs copy-on-write for MacrosModule. Creates an isolated copy so modifications don't affect the original shared map.

func (*ModuleEnvironment) EnsureMetadataRegistryCopied

func (env *ModuleEnvironment) EnsureMetadataRegistryCopied()

EnsureMetadataRegistryCopied performs copy-on-write for ItemMetadataModule. Creates an isolated copy so modifications don't affect the original shared map.

func (*ModuleEnvironment) EnsureObjectRegistryCopied

func (env *ModuleEnvironment) EnsureObjectRegistryCopied()

EnsureObjectRegistryCopied performs copy-on-write for ObjectsModule. Creates an isolated copy so modifications don't affect the original shared map.

func (*ModuleEnvironment) GetCommand

func (env *ModuleEnvironment) GetCommand(name string) (Handler, bool)

GetCommand looks up a command from the module's command registry. CommandRegistryModule and CommandRegistryInherited start as the same map instance and only diverge via COW. A nil handler value means the command was REMOVEd. If name contains ScopeMarker (::), performs scoped lookup in Library instead.

func (*ModuleEnvironment) GetLogConfig

func (env *ModuleEnvironment) GetLogConfig() *LogConfig

GetLogConfig returns the effective log config for this module environment

func (*ModuleEnvironment) GetLogConfigForModification

func (env *ModuleEnvironment) GetLogConfigForModification() *LogConfig

GetLogConfigForModification returns the log config ready for modification (triggers COW if needed) Caller must hold the lock

func (*ModuleEnvironment) GetMacro

func (env *ModuleEnvironment) GetMacro(name string) (*StoredMacro, bool)

GetMacro looks up a macro from the module's macro registry. MacrosModule and MacrosInherited start as the same map instance and diverge via COW. A nil macro value means the macro was explicitly REMOVEd. If name contains ScopeMarker (::), performs scoped lookup in Library instead.

func (*ModuleEnvironment) GetObject

func (env *ModuleEnvironment) GetObject(name string) (interface{}, bool)

GetObject looks up a #-prefixed object from the module's object registry. ObjectsModule and ObjectsInherited start as the same map instance and diverge via COW. A nil object value means the object was explicitly REMOVEd.

func (*ModuleEnvironment) MergeExportsInto

func (env *ModuleEnvironment) MergeExportsInto(target *ModuleEnvironment)

MergeExportsInto merges this environment's ModuleExports into another environment's LibraryInherited This is used to persist module exports between executions

func (*ModuleEnvironment) PopulateDefaultImports

func (env *ModuleEnvironment) PopulateDefaultImports()

PopulateDefaultImports copies all commands and objects from LibraryInherited into CommandRegistryInherited and ObjectsInherited, making them directly callable. Also populates ItemMetadataInherited with metadata for each item. This should be called after all commands are registered via RegisterCommandInModule.

func (*ModuleEnvironment) PopulateIOModule

func (env *ModuleEnvironment) PopulateIOModule(config *IOChannelConfig, executor *Executor)

PopulateIOModule creates native IO channels and registers them in the io module Creates: io::#stdin/#in, io::#stdout/#out, io::#stderr/#err, io::#stdio/#io If config is provided, uses custom channels; otherwise creates default OS-backed channels If executor is provided, channels are stored in storedObjects for proper ID tracking

func (*ModuleEnvironment) PopulateOSModule

func (env *ModuleEnvironment) PopulateOSModule(scriptArgs []string, scriptDir string)

PopulateOSModule creates the os module with script arguments as #args Creates: os::#args (StoredList containing script arguments) Named args include: os:, arch:, script_dir: (directory containing the script)

func (*ModuleEnvironment) RegisterCommandToModule

func (env *ModuleEnvironment) RegisterCommandToModule(name string, handler Handler)

RegisterCommandToModule registers a command handler to the module environment

type ModuleItem

type ModuleItem struct {
	Type  string      // "command", "macro", "object"
	Value interface{} // Handler, *StoredMacro, or stored object value
}

ModuleItem represents an exported item from a module (command, macro, or object)

type ModuleSection

type ModuleSection map[string]*ModuleItem // itemName -> ModuleItem

ModuleSection holds all items exported under a module name

type ObjectRef

type ObjectRef struct {
	Type ObjectType
	ID   int
}

ObjectRef is the internal representation of a reference to a stored object. It is lightweight (just type + ID) and passed around instead of marker strings.

func ExtractObjectRef

func ExtractObjectRef(value interface{}) ObjectRef

ExtractObjectRef extracts an ObjectRef from any value. Handles ObjectRef directly, marker strings (Symbol/string), and returns zero-value ObjectRef for non-reference values.

func ParseObjectRef

func ParseObjectRef(marker string) ObjectRef

ParseObjectRef parses a legacy marker string into an ObjectRef. Returns zero-value ObjectRef if parsing fails.

func (ObjectRef) IsValid

func (ref ObjectRef) IsValid() bool

IsValid returns true if this is a valid object reference (not zero value)

func (ObjectRef) String

func (ref ObjectRef) String() string

String returns a human-readable representation of the ObjectRef. This is used when formatting lists for display. Format matches how Symbol markers are displayed: <type id>

func (ObjectRef) ToMarker

func (ref ObjectRef) ToMarker() string

ToMarker converts to the legacy marker string format. This should ONLY be used at code substitution boundaries.

type ObjectType

type ObjectType int

ObjectType identifies the type of a stored object

const (
	ObjNone ObjectType = iota // Zero value - invalid/no reference
	ObjList
	ObjString
	ObjBlock
	ObjBytes
	ObjChannel
	ObjFiber
	ObjCommand
	ObjMacro
	ObjStruct
	ObjStructArray
	ObjFile
	ObjToken // Async completion token with lifecycle management
)

func ObjectTypeFromString

func ObjectTypeFromString(s string) ObjectType

ObjectTypeFromString converts a string to ObjectType

func (ObjectType) String

func (t ObjectType) String() string

String returns the string representation of an ObjectType

type OptimizationLevel

type OptimizationLevel int

Config holds configuration for PawScript OptimizationLevel controls AST caching behavior

const (
	OptimizeNone  OptimizationLevel = 0 // -O0: No caching, always re-parse
	OptimizeBasic OptimizationLevel = 1 // -O1: Cache macro bodies and loop bodies (default)
)

type OutputContext

type OutputContext struct {
	State    *ExecutionState
	Executor *Executor
}

OutputContext provides the necessary context for channel-based output routing This allows the logger to resolve #out/#err channels through the proper hierarchy

func NewOutputContext

func NewOutputContext(state *ExecutionState, executor *Executor) *OutputContext

NewOutputContext creates a new OutputContext from an ExecutionState

func (*OutputContext) ResolveChannel

func (oc *OutputContext) ResolveChannel(channelName string) *StoredChannel

ResolveChannel resolves a channel name (like "#out" or "#err") through the hierarchy: 1. Local macro/execution context variables 2. Module's ObjectsModule (copy-on-write layer) 3. Root ObjectsInherited (where io::#out etc. live) Returns nil if no channel found (caller should fall back to system console)

func (*OutputContext) WriteToDebug

func (oc *OutputContext) WriteToDebug(message string) error

WriteToDebug writes a message to the resolved #debug channel or falls back to system stdout #debug is separate from #out to allow independent redirection of debug/log output

func (*OutputContext) WriteToErr

func (oc *OutputContext) WriteToErr(message string) error

WriteToErr writes a message to the resolved #err channel or falls back to system stderr

func (*OutputContext) WriteToOut

func (oc *OutputContext) WriteToOut(message string) error

WriteToOut writes a message to the resolved #out channel or falls back to system stdout

type PSLConfig

type PSLConfig = PSLMap

PSLConfig is an alias for PSLMap (deprecated name, use PSLMap)

type PSLList

type PSLList []interface{}

PSLList holds an ordered list of positional items

func ParsePSLList

func ParsePSLList(input string) (PSLList, error)

ParsePSLList parses a PSL format string into a PSLList

type PSLMap

type PSLMap map[string]interface{}

PSLMap holds a map of named items from a PSL structure Keys are strings, values can be strings, ints, floats, bools, nil, or nested structures

func ParsePSL

func ParsePSL(input string) (PSLMap, error)

ParsePSL parses a PSL format string into a PSLMap Uses the existing PawScript parser

func (PSLMap) GetBool

func (m PSLMap) GetBool(key string, defaultVal bool) bool

GetBool returns a bool value from PSLMap, with default fallback

func (PSLMap) GetFloat

func (m PSLMap) GetFloat(key string, defaultVal float64) float64

GetFloat returns a float64 value from PSLMap, with default fallback

func (PSLMap) GetInt

func (m PSLMap) GetInt(key string, defaultVal int) int

GetInt returns an int value from PSLMap, with default fallback

func (PSLMap) GetItems

func (m PSLMap) GetItems(key string) []interface{}

GetItems returns the positional items from a list value, or nil if not found/not a list

func (PSLMap) GetString

func (m PSLMap) GetString(key string, defaultVal string) string

GetString returns a string value from PSLMap, with default fallback

func (PSLMap) Set

func (m PSLMap) Set(key string, value interface{})

Set sets a value in the PSLMap

type ParenGroup

type ParenGroup string

ParenGroup represents a value that was originally in parentheses This preserves the original form for $* substitution

func (ParenGroup) String

func (p ParenGroup) String() string

type ParsedCommand

type ParsedCommand struct {
	Command         string
	Arguments       []interface{}
	NamedArgs       map[string]interface{} // Named arguments (key: value)
	Position        *SourcePosition
	OriginalLine    string
	Separator       string                      // "none", ";", "&", "|"
	ChainType       string                      // "none", "chain" (~>), "chain_append" (~~>), "assign" (=>)
	CachedBlockArgs map[int][]*ParsedCommand    // Pre-parsed block arguments (for blocks without $N substitution)
	CachedBraces    map[string][]*ParsedCommand // Pre-parsed brace expressions by content string
	ArgTemplates    []*SubstitutionTemplate     // Pre-parsed substitution templates for string arguments
	CommandTemplate *SubstitutionTemplate       // Pre-parsed template for command name (if it has substitutions)

	// Handler caching: resolved command/macro handlers to avoid map lookups
	// These are populated on first execution and reused if CachedEnv/CachedGeneration match
	ResolvedHandler  Handler            // Cached command handler (nil if macro or unresolved)
	ResolvedMacro    *StoredMacro       // Cached macro (nil if command or unresolved)
	CachedEnv        *ModuleEnvironment // Environment we resolved against
	CachedGeneration uint64             // RegistryGeneration when we resolved

	// OriginalCmd points to the original ParsedCommand when this is a position-adjusted copy
	// Cache operations should target OriginalCmd to persist across copies
	OriginalCmd *ParsedCommand
}

ParsedCommand represents a parsed command with metadata

type Parser

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

Parser handles parsing with position tracking

func NewParser

func NewParser(source, filename string) *Parser

NewParser creates a new parser

func (*Parser) GetSourceMap

func (p *Parser) GetSourceMap() *SourceMap

GetSourceMap returns the source map

func (*Parser) NormalizeKeywords

func (p *Parser) NormalizeKeywords(source string) string

NormalizeKeywords replaces 'then' with '&', 'else' with '|', and 'not' with '!' when they are standalone words but skips content inside parentheses (which may be stored as data rather than executed)

func (*Parser) ParseCommandSequence

func (p *Parser) ParseCommandSequence(commandStr string) ([]*ParsedCommand, error)

ParseCommandSequence parses a command string into individual commands

func (*Parser) RemoveComments

func (p *Parser) RemoveComments(source string) string

RemoveComments removes comments while preserving position mapping

type PawScript

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

PawScript is the main PawScript interpreter

func New

func New(config *Config) *PawScript

New creates a new PawScript interpreter

func (*PawScript) Cleanup

func (ps *PawScript) Cleanup()

Cleanup releases all resources held by the interpreter. Call this when the host application is done with the interpreter. After calling Cleanup, the interpreter should not be used.

func (*PawScript) ClearMacros

func (ps *PawScript) ClearMacros() int

ClearMacros clears all macros from the root module environment

func (*PawScript) Configure

func (ps *PawScript) Configure(config *Config)

Configure updates the configuration

func (*PawScript) CreateRestrictedSnapshot

func (ps *PawScript) CreateRestrictedSnapshot() *ModuleEnvironment

CreateRestrictedSnapshot creates a restricted environment snapshot This captures the current state with copy-on-write isolation, similar to what a macro definition would capture. Use with ExecuteWithEnvironment to run scripts in a restricted/isolated environment.

func (*PawScript) DefineMacro

func (ps *PawScript) DefineMacro(name, commandSequence string) bool

DefineMacro defines a new macro in the root module environment

func (*PawScript) DeleteMacro

func (ps *PawScript) DeleteMacro(name string) bool

DeleteMacro deletes a macro from the root module environment

func (*PawScript) Execute

func (ps *PawScript) Execute(commandString string, args ...interface{}) Result

Execute executes a command string using the persistent root state. Variables, macros, and objects persist across calls for REPL and host application use. Call Cleanup() to explicitly release resources when done with the interpreter.

This method blocks until the command completes, including any async operations like msleep. This is the intuitive, default behavior matching script execution. Use ExecuteAsync() if you need to handle async tokens manually.

func (*PawScript) ExecuteAsync

func (ps *PawScript) ExecuteAsync(commandString string) Result

ExecuteAsync executes a command string without waiting for async operations. If the command initiates async operations (like msleep), this returns a TokenResult immediately. The caller is responsible for handling the token, either by calling WaitForToken() or managing it through their own async flow.

Most callers should use Execute() instead for simpler blocking semantics.

func (*PawScript) ExecuteFile

func (ps *PawScript) ExecuteFile(commandString, filename string) Result

ExecuteFile executes a script file with proper filename tracking. Uses the persistent root state so variables, macros, and objects persist. If the script contains async operations (like msleep), this function waits for the entire script to complete before returning and merging exports.

func (*PawScript) ExecuteInRoot

func (ps *PawScript) ExecuteInRoot(commandString string) Result

ExecuteInRoot executes a command string directly in the root environment. Any IMPORT, macro definitions, or other changes persist directly to root. Use this when you need changes to be visible to all subsequent Execute() calls.

func (*PawScript) ExecuteMacro

func (ps *PawScript) ExecuteMacro(name string) Result

ExecuteMacro executes a macro by name from the root module environment. Uses the persistent root state so variables and objects persist.

func (*PawScript) ExecuteWithEnvironment

func (ps *PawScript) ExecuteWithEnvironment(commandString string, env *ModuleEnvironment, filename string, lineOffset, columnOffset int) Result

ExecuteWithEnvironment executes a command string using a specific module environment This allows running scripts in a restricted/isolated environment created by CreateRestrictedSnapshot. Exports from this execution are NOT merged into root. Optional source location parameters help track the origin of the code for error messages.

func (*PawScript) FlushIO

func (ps *PawScript) FlushIO()

FlushIO waits for any pending output on stdout and stderr to be written. This should be called before printing prompts or completion messages to ensure all previous output has been displayed.

func (*PawScript) ForceCleanupToken

func (ps *PawScript) ForceCleanupToken(tokenID string)

ForceCleanupToken forces cleanup of a token

func (*PawScript) GetConfig

func (ps *PawScript) GetConfig() *Config

GetConfig returns the current configuration

func (*PawScript) GetFiberCount

func (ps *PawScript) GetFiberCount() int

GetFiberCount returns the number of currently active fibers. Returns 0 if no fibers are running.

func (*PawScript) GetKeyInputKeysChannel

func (ps *PawScript) GetKeyInputKeysChannel() *StoredChannel

GetKeyInputKeysChannel returns the keys channel from the active KeyInputManager, or nil if no manager is active. This allows REPLs to read parsed key events (like "Up", "Enter", "a", "M-x") instead of raw bytes from stdin.

func (*PawScript) GetMacro

func (ps *PawScript) GetMacro(name string) *string

GetMacro returns the commands for a macro from the root module environment

func (*PawScript) GetResultValue

func (ps *PawScript) GetResultValue() interface{}

GetResultValue returns the last execution result value (for REPL)

func (*PawScript) GetRootState

func (ps *PawScript) GetRootState() *ExecutionState

GetRootState returns the persistent root execution state. This allows host applications to inspect or manipulate the execution environment.

func (*PawScript) GetTokenStatus

func (ps *PawScript) GetTokenStatus() map[string]interface{}

GetTokenStatus returns information about active tokens

func (*PawScript) HasActiveKeyInputManager

func (ps *PawScript) HasActiveKeyInputManager() bool

HasActiveKeyInputManager returns true if a KeyInputManager is currently active This is used by REPLs to check if they should read from the manager's channel instead of directly from stdin

func (*PawScript) HasLibraryModule

func (ps *PawScript) HasLibraryModule(moduleName string) bool

HasLibraryModule checks if a module exists in the library. Use this to check before calling ImportModuleToRoot to avoid error logging.

func (*PawScript) HasMacro

func (ps *PawScript) HasMacro(name string) bool

HasMacro checks if a macro exists in the root module environment

func (*PawScript) ImportModuleToRoot

func (ps *PawScript) ImportModuleToRoot(moduleName string) bool

ImportModuleToRoot imports all items from a module directly into the root environment. This makes the items available to all subsequent Execute() calls without needing IMPORT.

func (*PawScript) IsKeyInputManagerOnStdin

func (ps *PawScript) IsKeyInputManagerOnStdin() bool

IsKeyInputManagerOnStdin returns true if the active KeyInputManager is reading from stdin (the terminal). This helps REPLs know when to delegate input handling to the manager.

func (*PawScript) ListMacros

func (ps *PawScript) ListMacros() []string

ListMacros returns a list of all macro names from the root module environment

func (*PawScript) NewExecutionStateFromRoot

func (ps *PawScript) NewExecutionStateFromRoot() *ExecutionState

NewExecutionStateFromRoot creates an execution state that inherits from root module environment

func (*PawScript) RegisterBasicMathLib

func (ps *PawScript) RegisterBasicMathLib()

RegisterBasicMathLib registers basic math and comparison commands Modules: basicmath, cmp

func (*PawScript) RegisterBitwiseLib

func (ps *PawScript) RegisterBitwiseLib()

RegisterBitwiseLib registers bitwise operation commands Module: bitwise

func (*PawScript) RegisterChannelsLib

func (ps *PawScript) RegisterChannelsLib()

RegisterChannelsLib registers channel-related commands Module: channels

func (*PawScript) RegisterCommand

func (ps *PawScript) RegisterCommand(name string, handler Handler)

RegisterCommand registers a command handler (legacy - adds to CommandRegistryInherited directly)

func (*PawScript) RegisterCommandInModule

func (ps *PawScript) RegisterCommandInModule(moduleName, cmdName string, handler Handler)

RegisterCommandInModule registers a command handler in a specific module within LibraryInherited

func (*PawScript) RegisterCommands

func (ps *PawScript) RegisterCommands(commands map[string]Handler)

RegisterCommands registers multiple command handlers

func (*PawScript) RegisterCoreLib

func (ps *PawScript) RegisterCoreLib()

RegisterCoreLib registers core language commands Modules: core, macros, flow, debug

func (*PawScript) RegisterFibersLib

func (ps *PawScript) RegisterFibersLib()

RegisterFibersLib registers fiber-related commands Module: fibers

func (*PawScript) RegisterFilesLib

func (ps *PawScript) RegisterFilesLib()

RegisterFilesLib registers file system commands Module: files

func (*PawScript) RegisterGeneratorLib

func (ps *PawScript) RegisterGeneratorLib()

RegisterGeneratorLib registers generator and coroutine commands Module: core

func (*PawScript) RegisterMathLib

func (ps *PawScript) RegisterMathLib()

RegisterMathLib registers the auxiliary math library with trigonometric functions and mathematical constants. This library is NOT auto-imported - users must explicitly use IMPORT math to access these functions. Module: math

func (*PawScript) RegisterObjectInModule

func (ps *PawScript) RegisterObjectInModule(moduleName, objName string, value interface{})

RegisterObjectInModule registers an object (like #stdin) in a specific module within LibraryInherited

func (*PawScript) RegisterStandardLibrary

func (ps *PawScript) RegisterStandardLibrary(scriptArgs []string)

RegisterStandardLibrary registers all standard library commands This is the main entry point for setting up the PawScript standard library Uses custom IO channels from ps.config if set, otherwise defaults to OS-backed channels

func (*PawScript) RegisterStandardLibraryWithIO

func (ps *PawScript) RegisterStandardLibraryWithIO(scriptArgs []string, ioConfig *IOChannelConfig)

RegisterStandardLibraryWithIO registers all standard library commands with custom IO channels If ioConfig is nil, uses default OS-backed channels If specific channels in ioConfig are nil, defaults are used for those channels

Example usage with custom channels:

config := &pawscript.IOChannelConfig{
	Stdout: myCustomStdout,  // Custom stdout handler
	// Stdin, Stderr, Stdio will use defaults
	CustomChannels: map[string]*pawscript.StoredChannel{
		"#mylog": myLogChannel,
	},
}
ps.RegisterStandardLibraryWithIO(args, config)

func (*PawScript) RegisterSystemLib

func (ps *PawScript) RegisterSystemLib(scriptArgs []string)

RegisterSystemLib registers OS, IO, and system commands Modules: os, io, sys

func (*PawScript) RegisterTypesLib

func (ps *PawScript) RegisterTypesLib()

RegisterTypesLib registers string and list manipulation commands Modules: strlist, str

func (*PawScript) RequestToken

func (ps *PawScript) RequestToken(cleanupCallback func(string), parentToken string, timeout time.Duration) string

RequestToken requests an async completion token

func (*PawScript) ResolveValue

func (ps *PawScript) ResolveValue(val interface{}) interface{}

ResolveValue resolves ObjectRefs and other markers to their actual values. This is useful for displaying values in a human-readable format.

func (*PawScript) ResumeToken

func (ps *PawScript) ResumeToken(tokenID string, status bool) bool

ResumeToken resumes execution with a token

func (*PawScript) SetContextLines

func (ps *PawScript) SetContextLines(lines int)

SetContextLines sets the number of context lines for error reporting

func (*PawScript) SetErrorContextEnabled

func (ps *PawScript) SetErrorContextEnabled(enabled bool)

SetErrorContextEnabled enables or disables error context reporting

func (*PawScript) SetFallbackHandler

func (ps *PawScript) SetFallbackHandler(handler func(string, []interface{}) Result)

SetFallbackHandler sets a fallback handler for unknown commands

func (*PawScript) SetInheritedObject

func (ps *PawScript) SetInheritedObject(moduleName, objectName string, value interface{})

SetInheritedObject sets or overrides an object in the ObjectsInherited map. This is useful for overriding default channels like #out, #in, #err at runtime. The moduleName parameter is currently ignored - objects are set at the root level.

func (*PawScript) StopKeyInputManager

func (ps *PawScript) StopKeyInputManager() error

StopKeyInputManager stops the active KeyInputManager and restores stdin to line mode if it was in raw mode. This should be called when the REPL wants to take back control of stdin.

func (*PawScript) WaitForToken

func (ps *PawScript) WaitForToken(tokenID string) bool

WaitForToken waits for an async token to complete and returns the result status. This is used by REPLs to wait for async commands like msleep before returning to the prompt. Returns true if the operation succeeded, false otherwise.

type PawScriptError

type PawScriptError struct {
	Message  string
	Position *SourcePosition
	Context  []string
}

PawScriptError represents an error with position information

func (*PawScriptError) Error

func (e *PawScriptError) Error() string

type QuotedString

type QuotedString string

QuotedString represents a value that was originally quoted This preserves the original form for $* substitution

func (QuotedString) String

func (q QuotedString) String() string

type REPL

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

REPL provides an interactive Read-Eval-Print Loop for PawScript

func NewREPL

func NewREPL(config REPLConfig, output func(string)) *REPL

NewREPL creates a new REPL instance

func NewREPLWithInterpreter

func NewREPLWithInterpreter(ps *PawScript, output func(string)) *REPL

NewREPLWithInterpreter creates a REPL with an existing PawScript interpreter

func (*REPL) GetHistory

func (r *REPL) GetHistory() []string

GetHistory returns the command history

func (*REPL) GetPawScript

func (r *REPL) GetPawScript() *PawScript

GetPawScript returns the underlying PawScript interpreter

func (*REPL) HandleInput

func (r *REPL) HandleInput(data []byte) bool

HandleInput processes input bytes from the terminal Returns true if the REPL should exit

func (*REPL) HandleKeyEvent

func (r *REPL) HandleKeyEvent(key string) bool

HandleKeyEvent processes a named key event (from KeyInputManager) This allows the REPL to be used with KeyInputManager's keys channel Returns true if the REPL should exit

func (*REPL) IsBusy

func (r *REPL) IsBusy() bool

IsBusy returns whether the REPL is currently executing a command When busy, terminal input should go to stdin channels instead of the REPL

func (*REPL) IsRunning

func (r *REPL) IsRunning() bool

IsRunning returns whether the REPL is active

func (*REPL) ReadLine

func (r *REPL) ReadLine() (string, bool)

ReadLine waits for and returns complete input from the readline. Returns the input string and true, or empty string and false if quit/interrupted. Must be called after StartReadline().

func (*REPL) ResetLine

func (r *REPL) ResetLine()

ResetLine clears the current input and shows a fresh prompt. Useful for the CLI to reset state between commands.

func (*REPL) SaveHistory

func (r *REPL) SaveHistory()

SaveHistory saves the command history to file

func (*REPL) SetBackgroundRGB

func (r *REPL) SetBackgroundRGB(red, green, blue uint8)

SetBackgroundRGB sets the background color to determine prompt colors Uses brightness calculation: if brightness > 0.5, uses dark brown instead of yellow

func (*REPL) SetFlush

func (r *REPL) SetFlush(flush func())

SetFlush sets the flush callback that is called after outputting a newline but before executing a command. This is important for GUI terminals that use asynchronous output (like glib.IdleAdd) - the flush callback should process pending events to ensure the newline is displayed before blocking execution.

func (*REPL) SetPSLColors

func (r *REPL) SetPSLColors(colors DisplayColorConfig)

SetPSLColors sets the colors used for PSL result display

func (*REPL) SetTerminalWidth

func (r *REPL) SetTerminalWidth(width int)

SetTerminalWidth sets the terminal width for horizontal scrolling calculations For GUI terminals, this should be called when the logical width changes

func (*REPL) Start

func (r *REPL) Start()

Start begins the REPL session

func (*REPL) StartReadline

func (r *REPL) StartReadline()

StartReadline begins a readline-only session where input is collected but not executed. Use ReadLine() to wait for complete input. The output function is used for prompts and editing feedback.

func (*REPL) Stop

func (r *REPL) Stop()

Stop ends the REPL session

type REPLConfig

type REPLConfig struct {
	Debug        bool
	Unrestricted bool
	OptLevel     int
	ShowBanner   bool             // Whether to show the startup banner
	IOConfig     *IOChannelConfig // Optional IO channels (for GUI terminals)
}

REPLConfig configures the REPL behavior

type RepeatContinuation

type RepeatContinuation struct {
	BodyBlock          string              // The repeat body
	CachedBodyCmds     []*ParsedCommand    // Cached full parsed body for reuse across iterations
	RemainingBodyCmds  []*ParsedCommand    // Commands remaining in current iteration after yield
	BodyCmdIndex       int                 // Which command in body yielded
	CurrentIteration   int                 // Current iteration number (0-based)
	TotalIterations    int                 // Total number of iterations
	CounterVar         string              // Optional variable name for iteration counter
	Results            []interface{}       // Results collected so far
	Failures           []interface{}       // Failed iteration numbers so far
	State              *ExecutionState     // Execution state at time of yield
	ParentContinuation *RepeatContinuation // For nested repeat loops
}

RepeatContinuation stores state for resuming a repeat loop after yield

type Result

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

Result represents the result of command execution (either a status or async token)

type ResumeData

type ResumeData struct {
	TokenID string
	Status  bool
	Result  interface{}
}

ResumeData contains information for resuming a suspended fiber

type SegmentType

type SegmentType int

SegmentType identifies the kind of segment in a substitution template

const (
	SegmentLiteral    SegmentType = iota // Plain text, no substitution needed
	SegmentTildeVar                      // ~varname or ?varname
	SegmentDollarArg                     // $1, $2, etc.
	SegmentDollarStar                    // $* (all args as comma-separated)
	SegmentDollarAt                      // $@ (all args as list)
	SegmentDollarHash                    // $# (arg count)
	SegmentBrace                         // {...} expression
)

type SourceMap

type SourceMap struct {
	Filename              string
	OriginalLines         []string
	TransformedToOriginal map[int]*SourcePosition
}

SourceMap maps transformed positions to original positions

func NewSourceMap

func NewSourceMap(source, filename string) *SourceMap

NewSourceMap creates a new source map

func (*SourceMap) AddMapping

func (sm *SourceMap) AddMapping(transformedPos int, originalPos *SourcePosition)

AddMapping adds a position mapping

func (*SourceMap) GetOriginalPosition

func (sm *SourceMap) GetOriginalPosition(transformedPos int) *SourcePosition

GetOriginalPosition gets the original position for a transformed position

type SourcePosition

type SourcePosition struct {
	Line         int
	Column       int
	Length       int
	OriginalText string
	Filename     string
	MacroContext *MacroContext
}

SourcePosition tracks the position of code in source files

type StoredBlock

type StoredBlock string

StoredBlock represents a large code block stored outside the argument flow Blocks (ParenGroup) exceeding BlockStorageThreshold are stored as objects and passed by reference

func (StoredBlock) String

func (s StoredBlock) String() string

type StoredBytes

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

StoredBytes represents an immutable byte array All operations return new StoredBytes instances (copy-on-write) Slicing shares the backing array for memory efficiency When elements are extracted, they are converted to int64

func NewStoredBytes

func NewStoredBytes(data []byte) StoredBytes

NewStoredBytes creates a new StoredBytes from a byte slice

func NewStoredBytesFromInts

func NewStoredBytesFromInts(values []int64) StoredBytes

NewStoredBytesFromInts creates StoredBytes from int64 values Values are masked to byte range (0-255)

func StoredBytesFromString

func StoredBytesFromString(s string) (StoredBytes, error)

FromString creates StoredBytes from a string (low-ASCII only) Returns error if any character is >= 128

func (StoredBytes) Append

func (sb StoredBytes) Append(value int64) StoredBytes

Append returns a new StoredBytes with the byte appended (O(n) copy-on-write) Value is masked to byte range

func (StoredBytes) AppendBytes

func (sb StoredBytes) AppendBytes(other StoredBytes) StoredBytes

AppendBytes returns a new StoredBytes with other bytes appended

func (StoredBytes) Compact

func (sb StoredBytes) Compact() StoredBytes

Compact returns a new StoredBytes with a new backing array Use this to free memory if you've sliced a large byte array

func (StoredBytes) Concat

func (sb StoredBytes) Concat(other StoredBytes) StoredBytes

Concat returns a new StoredBytes with bytes from both (O(n+m) copy)

func (StoredBytes) Data

func (sb StoredBytes) Data() []byte

Data returns the underlying byte slice (direct reference)

func (StoredBytes) Get

func (sb StoredBytes) Get(index int) int64

Get returns the byte at the given index as int64 Returns 0 if index is out of bounds

func (StoredBytes) Len

func (sb StoredBytes) Len() int

Len returns the number of bytes

func (StoredBytes) Prepend

func (sb StoredBytes) Prepend(value int64) StoredBytes

Prepend returns a new StoredBytes with the byte prepended (O(n) copy-on-write) Value is masked to byte range

func (StoredBytes) Slice

func (sb StoredBytes) Slice(start, end int) StoredBytes

Slice returns a new StoredBytes with bytes from start to end (end exclusive) Shares the backing array for memory efficiency (O(1) time, O(1) space)

func (StoredBytes) String

func (sb StoredBytes) String() string

String returns a hex string representation with spaces every 4 bytes Format: <08AEC7FF 0810CD00 24EE>

func (StoredBytes) ToASCIIString

func (sb StoredBytes) ToASCIIString() string

ToASCIIString converts bytes to string (for display/debugging)

func (StoredBytes) ToInt64

func (sb StoredBytes) ToInt64() int64

ToInt64 converts the bytes to an int64 (big-endian) Used when bytes are coerced to a number

type StoredChannel

type StoredChannel struct {
	BufferSize       int
	Messages         []ChannelMessage
	Subscribers      map[int]*StoredChannel // Map of subscriber ID to subscriber endpoint
	NextSubscriberID int
	IsClosed         bool
	IsSubscriber     bool           // True if this is a subscriber endpoint
	SubscriberID     int            // ID of this subscriber (0 for main channel)
	ParentChannel    *StoredChannel // Reference to parent if this is a subscriber
	CustomSend       *StoredMacro   // Optional custom send handler
	CustomRecv       *StoredMacro   // Optional custom recv handler
	CustomClose      *StoredMacro   // Optional custom close handler
	Timestamp        time.Time
	// Native function handlers for Go-backed channels (stdio, etc.)
	// If set, these are called instead of the buffer-based operations
	NativeSend  func(interface{}) error     // Native send handler
	NativeRecv  func() (interface{}, error) // Native receive handler
	NativeClose func() error                // Native close handler
	NativeLen   func() int                  // Native length handler (for Go channel backing)
	NativeFlush func() error                // Native flush handler (waits for pending output)
	// Terminal capabilities associated with this channel
	// Allows channels to report their own ANSI/color/size support
	// If nil, system terminal capabilities are used as fallback
	Terminal *TerminalCapabilities
	// PasteBuffer holds complete lines from bracketed paste that haven't been read yet
	// When a multi-line paste arrives, complete lines are stored here for subsequent reads
	PasteBuffer []string
	// PartialPaste holds the last segment of a paste that didn't end with a newline
	// This becomes the starting content for the next read, allowing user to continue typing
	PartialPaste string
	// PasteNotified is set when readkey returns "Paste" to avoid returning it multiple times
	// Cleared when read is called
	PasteNotified bool
	// contains filtered or unexported fields
}

StoredChannel represents a bidirectional communication channel with pub-sub support Supports both native (Go-backed) and custom (macro-backed) channels

func ChannelSubscribe

func ChannelSubscribe(ch *StoredChannel) (*StoredChannel, error)

ChannelSubscribe creates a new subscriber endpoint for a channel

func NewChannelSubscriber

func NewChannelSubscriber(parent *StoredChannel, id int) *StoredChannel

NewChannelSubscriber creates a subscriber endpoint for a channel

func NewStoredChannel

func NewStoredChannel(bufferSize int) *StoredChannel

NewStoredChannel creates a new channel with optional buffer size

func (*StoredChannel) Flush

func (ch *StoredChannel) Flush() error

Flush waits for any pending output to be written. If NativeFlush is set, it calls that handler. Returns nil if no flush handler is set.

func (*StoredChannel) GetTerminalCapabilities

func (ch *StoredChannel) GetTerminalCapabilities() *TerminalCapabilities

GetTerminalCapabilities returns terminal capabilities for this channel Falls back through: this channel -> parent channel -> system terminal

func (*StoredChannel) SetTerminalCapabilities

func (ch *StoredChannel) SetTerminalCapabilities(caps *TerminalCapabilities)

SetTerminalCapabilities sets terminal capabilities for this channel Multiple channels can share the same capabilities pointer

func (*StoredChannel) String

func (ch *StoredChannel) String() string

String returns a string representation for debugging

type StoredCommand

type StoredCommand struct {
	CommandName string
	Handler     Handler
	Timestamp   time.Time
}

StoredCommand represents a built-in or registered command stored as a reference-counted object This allows commands to be treated as first-class values

func NewStoredCommand

func NewStoredCommand(name string, handler Handler) StoredCommand

NewStoredCommand creates a new StoredCommand

func (StoredCommand) String

func (sc StoredCommand) String() string

String returns a string representation for debugging

type StoredFile

type StoredFile struct {
	File     *os.File // The underlying OS file handle
	Path     string   // Original path used to open the file
	Mode     string   // "r", "w", "a", "rw"
	IsClosed bool
	// contains filtered or unexported fields
}

StoredFile represents an open file handle Files act like channels for read/write but support additional operations

func NewStoredFile

func NewStoredFile(file *os.File, path, mode string) *StoredFile

NewStoredFile creates a new file handle

func (*StoredFile) Close

func (f *StoredFile) Close() error

Close closes the file handle

func (*StoredFile) Flush

func (f *StoredFile) Flush() error

Flush flushes the file buffers

func (*StoredFile) ReadAll

func (f *StoredFile) ReadAll() (string, error)

ReadAll reads the entire remaining content of the file

func (*StoredFile) ReadBytes

func (f *StoredFile) ReadBytes(n int) ([]byte, error)

ReadBytes reads up to n bytes from the file If n <= 0, reads all remaining bytes

func (*StoredFile) ReadLine

func (f *StoredFile) ReadLine() (string, error)

ReadLine reads a single line from the file

func (*StoredFile) Seek

func (f *StoredFile) Seek(offset int64, whence int) (int64, error)

Seek moves the file position

func (*StoredFile) String

func (f *StoredFile) String() string

String returns a string representation for debugging

func (*StoredFile) Tell

func (f *StoredFile) Tell() (int64, error)

Tell returns the current file position

func (*StoredFile) Truncate

func (f *StoredFile) Truncate() error

Truncate truncates the file at the current position

func (*StoredFile) Write

func (f *StoredFile) Write(s string) error

Write writes a string to the file

func (*StoredFile) WriteBytes

func (f *StoredFile) WriteBytes(data []byte) error

WriteBytes writes raw bytes to the file

type StoredList

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

StoredList represents an immutable list of values with optional named arguments All operations return new StoredList instances (copy-on-write) Slicing shares the backing array for memory efficiency Named arguments (key-value pairs) are stored separately from positional items

Type tracking fields are maintained for both positional items (arr) and named args (map): - Type: "empty" (nothing added), "nil", a specific type name, or "mixed" - Solid: true if no nil/undefined values have been added - Serializable: true if all values are serializable types

func NewStoredListWithNamed

func NewStoredListWithNamed(items []interface{}, namedArgs map[string]interface{}) StoredList

NewStoredListWithNamed creates a new StoredList with both positional items and named arguments Type info is computed without executor (markers won't be fully resolved)

func NewStoredListWithRefs

func NewStoredListWithRefs(items []interface{}, namedArgs map[string]interface{}, executor *Executor) StoredList

NewStoredListWithRefs creates a new StoredList with type info computed via executor NOTE: Does NOT claim refs - that's now done by setListResult when registering This allows sliced/derived lists to share items without double-claiming

func NewStoredListWithoutRefs

func NewStoredListWithoutRefs(items []interface{}) StoredList

NewStoredListWithoutRefs creates a new StoredList from a slice of items WARNING: Does NOT claim references to nested object markers - use NewStoredListWithRefs if the list contains channel/list markers that need to stay alive

func (StoredList) Append

func (pl StoredList) Append(item interface{}) StoredList

Append returns a new StoredList with the item appended (O(n) copy-on-write) Preserves named arguments from the original list Type info is updated incrementally based on the new item

func (StoredList) ArrSerializable

func (pl StoredList) ArrSerializable() bool

ArrSerializable returns true if all positional items are serializable types

func (StoredList) ArrSolid

func (pl StoredList) ArrSolid() bool

ArrSolid returns true if no nil/undefined values are in the positional items

func (StoredList) ArrType

func (pl StoredList) ArrType() string

ArrType returns the type of positional items: "empty", "nil", "undefined", a specific type, or "mixed"

func (StoredList) Compact

func (pl StoredList) Compact() StoredList

Compact returns a new StoredList with a new backing array Use this to free memory if you've sliced a large list Preserves named arguments and type info from the original list

func (StoredList) Concat

func (pl StoredList) Concat(other StoredList) StoredList

Concat returns a new StoredList with items from both lists (O(n+m) copy) Named arguments are merged, with keys from 'other' replacing keys from 'pl' when both contain the same key Type info is merged from both lists

func (StoredList) Get

func (pl StoredList) Get(index int) interface{}

Get returns the item at the given index (0-based) Returns nil if index is out of bounds

func (StoredList) Items

func (pl StoredList) Items() []interface{}

Items returns a copy of the underlying items slice

func (StoredList) Len

func (pl StoredList) Len() int

Len returns the number of positional items in the list (excludes named arguments)

func (StoredList) MapSerializable

func (pl StoredList) MapSerializable() bool

MapSerializable returns true if all named arg values are serializable types

func (StoredList) MapSolid

func (pl StoredList) MapSolid() bool

MapSolid returns true if no nil/undefined values are in the named args

func (StoredList) MapType

func (pl StoredList) MapType() string

MapType returns the type of named arg values: "empty", "nil", "undefined", a specific type, or "mixed"

func (StoredList) NamedArgs

func (pl StoredList) NamedArgs() map[string]interface{}

NamedArgs returns the named arguments map (direct reference, not a copy) Returns nil if there are no named arguments

func (StoredList) Prepend

func (pl StoredList) Prepend(item interface{}) StoredList

Prepend returns a new StoredList with the item prepended (O(n) copy-on-write) Preserves named arguments from the original list Type info is updated incrementally based on the new item

func (StoredList) Slice

func (pl StoredList) Slice(start, end int) StoredList

Slice returns a new StoredList with items from start to end (end exclusive) Shares the backing array for memory efficiency (O(1) time, O(1) space) Preserves named arguments and type info from the original list (Type info is conservative - slice might be more specific but we preserve parent's info)

func (StoredList) String

func (pl StoredList) String() string

String returns a string representation for debugging Named arguments appear before positional items

type StoredMacro

type StoredMacro struct {
	Commands         string
	CachedCommands   []*ParsedCommand // Lazily populated parsed form (nil until first use)
	DefinitionFile   string
	DefinitionLine   int
	DefinitionColumn int
	Timestamp        time.Time
	ModuleEnv        *ModuleEnvironment // Captured module environment
	IsForward        bool               // True if this is an unresolved forward declaration
}

StoredMacro represents a macro stored as a reference-counted object This can be either a named macro (registered in the macro system) or anonymous

func NewStoredMacro

func NewStoredMacro(commands string, position *SourcePosition) StoredMacro

NewStoredMacro creates a new StoredMacro

func NewStoredMacroWithEnv

func NewStoredMacroWithEnv(commands string, position *SourcePosition, moduleEnv *ModuleEnvironment) StoredMacro

NewStoredMacroWithEnv creates a new StoredMacro with captured environment

func (StoredMacro) String

func (sm StoredMacro) String() string

String returns a string representation for debugging

type StoredObject

type StoredObject struct {
	Value    interface{} // The actual object (StoredList, etc.)
	Type     ObjectType  // Object type (ObjList, ObjString, etc.)
	RefCount int         // Number of contexts holding references
	Hash     uint64      // Content hash for immutable types (0 for mutable)
	Deleted  bool        // Marked for ID reuse when true
}

StoredObject represents a reference-counted stored object

type StoredString

type StoredString string

StoredString represents a large string stored outside the argument flow Strings exceeding StringStorageThreshold are stored as objects and passed by reference

func (StoredString) String

func (s StoredString) String() string

type StoredStruct

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

StoredStruct represents an instance of a struct or struct array The definition is now a StoredList, referenced by its object ID

func NewStoredStruct

func NewStoredStruct(defID int, size int) StoredStruct

NewStoredStruct creates a new single struct instance

func NewStoredStructArray

func NewStoredStructArray(defID int, size int, n int) StoredStruct

NewStoredStructArray creates a new struct array with n elements

func NewStoredStructFromData

func NewStoredStructFromData(defID int, data []byte, recordSize int, length int) StoredStruct

NewStoredStructFromData creates a struct from existing data (for nested structs)

func (StoredStruct) Compact

func (ss StoredStruct) Compact() StoredStruct

Compact returns a new struct array with a fresh backing array

func (StoredStruct) Data

func (ss StoredStruct) Data() []byte

Data returns the underlying byte slice for this struct/array

func (StoredStruct) DefID

func (ss StoredStruct) DefID() int

DefID returns the object ID of the struct definition list

func (StoredStruct) Get

func (ss StoredStruct) Get(index int) StoredStruct

Get returns the struct at index i (for arrays) Returns a single struct that shares the backing array

func (StoredStruct) GetBytesAt

func (ss StoredStruct) GetBytesAt(fieldOffset, fieldLength int) ([]byte, bool)

GetBytesAt returns raw bytes at the given offset and length

func (StoredStruct) IsArray

func (ss StoredStruct) IsArray() bool

IsArray returns true if this is a struct array

func (StoredStruct) Len

func (ss StoredStruct) Len() int

Len returns the number of elements (-1 for single struct)

func (StoredStruct) RecordSize

func (ss StoredStruct) RecordSize() int

RecordSize returns the size of each record

func (StoredStruct) SetBytesAt

func (ss StoredStruct) SetBytesAt(fieldOffset int, value []byte, maxLen int) bool

SetBytesAt sets raw bytes at the given offset

func (StoredStruct) Slice

func (ss StoredStruct) Slice(start, end int) StoredStruct

Slice returns a new struct array with elements from start to end (end exclusive) Shares the backing array for memory efficiency

func (StoredStruct) String

func (ss StoredStruct) String() string

String returns a human-readable representation

func (StoredStruct) ZeroPadAt

func (ss StoredStruct) ZeroPadAt(fieldOffset, startPos, fieldLength int)

ZeroPadAt zero-pads from the given position to the end of the field

type SubstitutionContext

type SubstitutionContext struct {
	Args           []interface{}
	ExecutionState *ExecutionState
	// ParentContext was assigned but never read - removed to reduce struct size
	MacroContext        *MacroContext
	CurrentLineOffset   int
	CurrentColumnOffset int
	Filename            string // Filename for error reporting
	// BraceFailureCount tracks how many brace expressions returned false status during substitution
	// This is separate from ExecutionState.lastStatus which tracks the main command's status
	// If > 0, assignment should propagate failure status
	BraceFailureCount int
	// BracesEvaluated tracks how many brace expressions were evaluated during substitution
	// Used to know whether to update lastBraceFailureCount (only if braces were present)
	BracesEvaluated int
	// CurrentParsedCommand is the current command being executed (for block caching)
	CurrentParsedCommand *ParsedCommand
	// CapturedModuleEnv is the macro's captured environment (for handler caching)
	// This is the environment commands should be cached against, not the child execution environment
	CapturedModuleEnv *ModuleEnvironment
}

SubstitutionContext provides context for macro argument substitution

type SubstitutionResult

type SubstitutionResult struct {
	Value      string // The substituted string (when not failed/async)
	Failed     bool   // True if brace evaluation failed
	AsyncToken string // Non-empty if async coordination is needed
}

SubstitutionResult represents the result of command string substitution This replaces the old PAWS marker strings for cleaner type handling

func (SubstitutionResult) IsAsync

func (r SubstitutionResult) IsAsync() bool

IsAsync returns true if this result requires async coordination

type SubstitutionTemplate

type SubstitutionTemplate struct {
	Segments     []TemplateSegment
	HasDollarSub bool // true if any $N, $*, $@, $# segments (requires MacroContext)
	HasTildeSub  bool // true if any ~var segments
	HasBraceSub  bool // true if any {...} segments
	IsSingleExpr bool // true if template is a single expression (can be evaluated typed)
}

SubstitutionTemplate is a pre-parsed template for efficient runtime substitution Instead of scanning strings at runtime, we iterate through pre-computed segments

type SuspendResult

type SuspendResult struct{}

SuspendResult signals that a new suspension token should be created with the remaining commands in the current sequence

type Symbol

type Symbol string

Symbol represents a bare identifier (unquoted, non-keyword) This preserves the original form and allows type detection

func (Symbol) String

func (s Symbol) String() string

type TemplateSegment

type TemplateSegment struct {
	Type       SegmentType
	Literal    string           // For SegmentLiteral: the text
	VarName    string           // For SegmentTildeVar: variable name
	IsQuestion bool             // For SegmentTildeVar: true if ? (existence check)
	ArgNum     int              // For SegmentDollarArg: 1-based argument number
	InQuote    bool             // For SegmentDollarArg: true if inside double quotes
	BraceAST   []*ParsedCommand // For SegmentBrace: pre-parsed commands
	BraceRaw   string           // For SegmentBrace: original content (for cache key)
	IsUnescape bool             // For SegmentBrace: true if ${...} (splat mode)
}

TemplateSegment represents one piece of a pre-parsed substitution template

type TerminalCapabilities

type TerminalCapabilities struct {

	// Terminal type and detection
	TermType      string // e.g., "xterm-256color", "gui-console"
	IsTerminal    bool   // true if this is an interactive terminal
	IsRedirected  bool   // true if output is being redirected (piped/file)
	SupportsANSI  bool   // true if ANSI escape codes are supported
	SupportsColor bool   // true if color output is supported
	ColorDepth    int    // 0=none, 8=basic, 16=extended, 256=256color, 24=truecolor

	// Screen dimensions
	Width  int // columns
	Height int // rows

	// Input capabilities
	SupportsInput bool // true if this channel can receive input
	EchoEnabled   bool // true if input should be echoed (duplex mode)
	LineMode      bool // true if input is line-buffered, false for raw/char mode

	// Custom metadata (for host-provided channels)
	Metadata map[string]interface{}
	// contains filtered or unexported fields
}

TerminalCapabilities holds terminal capabilities that can be associated with a channel This allows different channels (e.g., system stdout vs gui_console) to report their own capabilities independently

func DetectSystemTerminalCapabilities

func DetectSystemTerminalCapabilities() *TerminalCapabilities

DetectSystemTerminalCapabilities creates capabilities by detecting the system terminal

func GetSystemTerminalCapabilities

func GetSystemTerminalCapabilities() *TerminalCapabilities

GetSystemTerminalCapabilities returns the detected system terminal capabilities

func NewTerminalCapabilities

func NewTerminalCapabilities() *TerminalCapabilities

NewTerminalCapabilities creates a new capabilities struct with defaults

func (*TerminalCapabilities) Clone

Clone creates a copy of the terminal capabilities

func (*TerminalCapabilities) GetSize

func (tc *TerminalCapabilities) GetSize() (width, height int)

GetSize returns the terminal dimensions

func (*TerminalCapabilities) SetSize

func (tc *TerminalCapabilities) SetSize(width, height int)

SetSize updates the terminal dimensions

type TerminalState

type TerminalState struct {

	// Sticky cursor parameters
	XBase  int // leftmost column value (default 1)
	YBase  int // topmost row value (default 1)
	Rows   int // total rows in region (default 24)
	Cols   int // total cols in region (default 80)
	Indent int // columns reserved on left
	Head   int // rows reserved on top

	// Current cursor position (relative to xbase/ybase after indent/head)
	X int
	Y int

	// Cursor appearance
	Visible bool   // cursor visibility
	Shape   string // "underline", "block", "bar", "half"
	Blink   string // "false", "true", "fast"
	Color   int    // cursor color number

	// Behavior
	Free   bool // true = can move into margin/head areas
	Duplex bool // true = echo input to terminal (default true)

	// Screen tracking
	ScreenRows int // detected physical rows
	ScreenCols int // detected physical cols

	// Clear tracking
	HasCleared bool // true if clear was last output operation

	// Color tracking (for preserving background when only foreground changes)
	CurrentFG int // current foreground color (-1 = default)
	CurrentBG int // current background color (-1 = default)

	// Attribute tracking
	Bold      bool
	AttrBlink bool // named differently to avoid conflict with cursor Blink
	Underline bool
	Invert    bool
	// contains filtered or unexported fields
}

TerminalState holds cursor position and terminal configuration

func NewTerminalState

func NewTerminalState() *TerminalState

NewTerminalState creates a new terminal state with defaults

func (*TerminalState) ClampPosition

func (ts *TerminalState) ClampPosition()

ClampPosition ensures cursor is within bounds based on Free setting

func (*TerminalState) GetPhysicalX

func (ts *TerminalState) GetPhysicalX() int

GetPhysicalX returns the physical column on screen

func (*TerminalState) GetPhysicalY

func (ts *TerminalState) GetPhysicalY() int

GetPhysicalY returns the physical row on screen

func (*TerminalState) ResetTerminal

func (ts *TerminalState) ResetTerminal()

ResetTerminal performs a full terminal reset This is equivalent to 'tput reset' - resets all attributes and state

func (*TerminalState) SetDuplex

func (ts *TerminalState) SetDuplex(enabled bool) error

SetDuplex enables or disables terminal echo (duplex mode) When duplex is true (default), typed characters are echoed to the screen When duplex is false, typed characters are not echoed (for password entry, etc.)

type TildeLocation

type TildeLocation struct {
	StartPos     int    // Position of the ~ or ?
	EndPos       int    // Position of last char of varname (or semicolon if present)
	VarName      string // The variable name (without ~ or ? or ;)
	HasSemicolon bool   // true if terminated by explicit semicolon
	IsQuestion   bool   // true if this is a ? (existence check) expression, false for ~ (value)
}

TildeLocation tracks the position of a tilde or question variable reference in a string

type TokenData

type TokenData struct {
	StringID           string      // External string ID for host API (e.g., "fiber-0-token-5")
	ObjectID           int         // Internal object ID in storedObjects
	Completed          bool        // True when async operation has finished
	FinalStatus        bool        // Success/failure status when completed
	FinalResult        interface{} // Result value when completed
	CommandSequence    *CommandSequence
	ParentToken        string
	Children           map[string]bool
	CleanupCallback    func(string)
	CancelFunc         context.CancelFunc
	ChainedToken       string
	Timestamp          time.Time
	ExecutionState     *ExecutionState
	SuspendedResult    interface{}
	HasSuspendedResult bool
	Position           *SourcePosition
	BraceCoordinator   *BraceCoordinator    // For coordinating parallel brace evaluation
	InvertStatus       bool                 // If true, invert the success status when this token completes
	FiberID            int                  // ID of the fiber that created this token
	WaitChan           chan ResumeData      // For synchronous blocking (e.g., in while loops)
	SubstitutionCtx    *SubstitutionContext // For generator macro argument substitution
	WhileContinuation  *WhileContinuation   // For resuming while loops after yield
	ForContinuation    *ForContinuation     // For resuming for loops after yield
	RepeatContinuation *RepeatContinuation  // For resuming repeat loops after yield
	FizzContinuation   *FizzContinuation    // For resuming fizz loops after yield
	IteratorState      *IteratorState       // For Go-backed iterators (each, pair)
	ParentState        *ExecutionState      // For macro async: parent state for deferred result transfer
}

TokenData stores information about an active token Tokens are now stored as regular objects (ObjToken) with integer IDs, while maintaining a string ID for external communication (host API, serialization). Tokens use reference counting for lifecycle: executor claims a ref on creation, releases it on completion. Scripts can hold additional refs to query status later.

type TokenResult

type TokenResult string

TokenResult represents an async token

type UnpackTarget

type UnpackTarget struct {
	Type    string // "positional", "named_same", "named_different"
	Key     string // For named extractions
	VarName string // Variable name to store into
}

UnpackTarget represents a single unpacking target with its type and names

type WhileContinuation

type WhileContinuation struct {
	ConditionBlock     string           // The while condition (re-evaluated each iteration)
	BodyBlock          string           // The full while body
	CachedBodyCmds     []*ParsedCommand // Cached full parsed body for reuse across iterations
	RemainingBodyCmds  []*ParsedCommand // Commands remaining in current iteration after yield
	BodyCmdIndex       int              // Which command in body yielded
	IterationCount     int              // Current iteration number
	State              *ExecutionState  // Execution state at time of yield
	SubstitutionCtx    *SubstitutionContext
	ParentContinuation *WhileContinuation // For nested while loops - outer loop's state
}

WhileContinuation stores state for resuming a while loop after yield

type YieldResult

type YieldResult struct {
	Value              interface{}
	TokenID            string              // Token to update (empty = use #token from state)
	WhileContinuation  *WhileContinuation  // Optional - set when yielding from inside while loop
	RepeatContinuation *RepeatContinuation // Optional - set when yielding from inside repeat loop
	ForContinuation    *ForContinuation    // Optional - set when yielding from inside for loop
	FizzContinuation   *FizzContinuation   // Optional - set when yielding from inside fizz loop
}

YieldResult represents yielding a value from a generator The executor catches this and updates the token's remaining commands

Directories

Path Synopsis
cmd
exec_examples command
paw command
pawgui command
pawgui - PawScript with Fyne GUI support A drop-in replacement for paw with additional GUI capabilities
pawgui - PawScript with Fyne GUI support A drop-in replacement for paw with additional GUI capabilities
pawgui-gtk command
pawgui-gtk - GTK3-based GUI for PawScript with custom terminal emulator Cross-platform: works on Linux, macOS, and Windows
pawgui-gtk - GTK3-based GUI for PawScript with custom terminal emulator Cross-platform: works on Linux, macOS, and Windows
pawgui-qt command
pawgui-qt - Qt-based GUI for PawScript with custom terminal emulator Cross-platform: works on Linux, macOS, and Windows
pawgui-qt - Qt-based GUI for PawScript with custom terminal emulator Cross-platform: works on Linux, macOS, and Windows
token_example command
pkg
pawgui
Package pawgui provides shared functionality for PawScript GUI implementations.
Package pawgui provides shared functionality for PawScript GUI implementations.
purfecterm
Package purfecterm provides the core terminal emulation logic shared between GUI toolkit implementations (GTK, Qt, etc.).
Package purfecterm provides the core terminal emulation logic shared between GUI toolkit implementations (GTK, Qt, etc.).

Jump to

Keyboard shortcuts

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