script

package
v1.7.8-553 Latest Latest
Warning

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

Go to latest
Published: Aug 21, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

Duso Language Module

A lightweight, embeddable scripting language for agent orchestration. Duso is designed for LLM integration and multi-agent workflows.

Features

  • Loosely-typed: Implicit type coercion where sensible
  • Scoping: Use var for explicit local variables, reach outer scope by default
  • Closures: Functions capture and modify variables from outer scope
  • String templates: "Hello {{name}}" syntax for LLM/JSON use cases
  • Multiline strings: Triple quotes ("""...""") for clean multi-line text
  • Functions: First-class with closures, anonymous function expressions
  • Objects with Methods: Lightweight OOP with automatic property access
  • Callable Objects: Objects can act as constructors for blueprints
  • Arrays and Objects: 0-indexed arrays, key-value objects
  • Control Flow: if/elseif/else, while, for (numeric and iterator), break, continue
  • Exception Handling: try/catch blocks
  • Multiline Comments: /* ... */ with nesting support
  • Go Bindings: Register Go functions directly
  • No external dependencies: Go standard library only

Usage

Basic Execution
interp := script.NewInterpreter(false)
output, err := interp.Execute(`
  x = 5
  y = 10
  print(x + y)
`)
if err != nil {
  log.Fatal(err)
}
fmt.Println(output)  // Output: 15
Registering Go Functions
interp.RegisterFunction("add", func(args map[string]interface{}) (interface{}, error) {
  a := args["0"].(float64)
  b := args["1"].(float64)
  return a + b, nil
})

output, err := interp.Execute(`
  result = add(3, 4)
  print(result)
`)
Registering Objects with Methods
interp.RegisterObject("agents", map[string]script.GoFunction{
  "classify": func(args map[string]interface{}) (interface{}, error) {
    input := args["0"].(string)
    return map[string]interface{}{
      "confidence": 0.85,
      "category": "positive",
    }, nil
  },
})

output, err := interp.Execute(`
  result = agents.classify("test input")
  print(result.confidence)
`)

Quick Examples

Variables & Types
x = 5                           // number
name = "Alice"                  // string
flag = true                     // boolean
arr = ["alice", "bob"]          // array (0-indexed)
obj = {timeout: 30, port: 8080} // object
String Templates
name = "Alice"
age = 30
msg = "Hello {{name}}, age {{age}}"
print(msg)  // Output: Hello Alice, age 30

// Templates perfect for JSON/code (no escaping needed!)
json = "{\"user\": \"{{name}}\", \"age\": {{age}}}"
Multiline Strings
// Triple quotes for multiline strings (no escaping needed!)
prompt = """
You are a helpful assistant.
Please respond in JSON format.
Be concise and accurate.
"""
print(prompt)

// Single quotes work too
doc = '''
This is a multiline string
using single quotes.
'''

// Templates work in multiline strings
name = "Bob"
message = """
Hello {{name}}!
This is a multiline string.
It supports {{1 + 1}} template expressions.
"""

// Perfect for JSON (no quote escaping!)
schema = """
{
  "type": "object",
  "properties": {
    "name": {"type": "string"},
    "age": {"type": "number"}
  }
}
"""

Note on Indentation: Multiline strings automatically remove common leading whitespace from all lines. This lets you write naturally indented code in your editor without that indentation appearing in the final string:

code = """
  def hello():
    return "world"
  """

Results in:

def hello():
  return "world"

The common indentation (2 spaces) is removed, but relative indentation (the 2-space indent of the function body) is preserved. This works with any whitespace (spaces or tabs) and is essential for generating code and writing clean prompts.

Functions
function add(x, y)
  return x + y
end

result = add(5, 3)
print(result)  // Output: 8

// Closures
function makeAdder(n)
  function add(x) return x + n end
  return add
end
addFive = makeAdder(5)
print(addFive(10))  // Output: 15

// Function expressions
callback = function(x)
  return x * 2
end
print(callback(5))  // Output: 10
Objects as Constructors
// Create an object blueprint
Config = {timeout: 30, retries: 3}

// Call it to create a new instance with defaults
config1 = Config()

// Call with overrides
config2 = Config(timeout = 60)
print(config2.timeout)  // Output: 60
Objects with Methods
// Objects can have function properties (methods)
agent = {
  name: "Alice",
  skill: 90,
  greet: function(msg)
    print(msg + ", I am " + name + " with skill " + skill)
  end
}

agent.greet("Hello")  // Output: "Hello, I am Alice with skill 90"

// Create instances from blueprint
template = {
  name: "Unknown",
  describe: function()
    print("Name: " + name)
  end
}

instance = template(name = "Bob")
instance.describe()  // Output: "Name: Bob"

Methods automatically have access to object properties - no need for self. prefix.

Control Flow
for i = 1, 10 do print(i) end              // numeric loop
for item in ["a", "b"] do print(item) end  // iterator loop
while x < 10 do x = x + 1 end              // while loop
if x > 5 then print("big") end             // if statement

// Exception handling
try
  risky_operation()
catch (error)
  print("Error: " + error)
end
Comments
// Single-line comment
x = 5  // Inline comment

// Multiline comments with nesting
/* This is a
    multiline comment */

/*
  Outer comment
  /* Nested comment */
  Still in outer comment
*/
Multiple Print Arguments
print("Value:", 42)              // Output: Value: 42
print("Name: " + name)           // Output: Name: Alice

Built-in Functions

Core: print(), input(), len(), type()

Type Conversion: tonumber(), tostring(), tobool()

String: upper(), lower(), substr(), trim(), split(), join(), contains(), replace()

Math: floor(), ceil(), round(), abs(), min(), max(), sqrt(), pow(), clamp()

Array/Object: keys(), values(), sort()

Date/Time: now(), format_time(), parse_time()

Utility: range()

System: exit()

AI Integration: conversation(), claude() (CLI only)

See the Duso documentation for complete reference.

Type Coercion

  • Strings: "x: " + 42"x: 42"
  • Conditions: if 0 is false, if "" is false, if [] is false, if [1] is true
  • Concatenation: Any type + string coerces to string
  • Comparisons: Strings coerce to numbers when compared with numbers: "10" > 5 → true

Examples

See script/examples/ in repository:

  • basic.du - Variables and operators
  • arrays.du - Array operations
  • functions.du - Functions and control flow
  • structures.du - Objects as constructors/blueprints
  • methods.du - Objects with methods and function expressions
  • break-continue.du - Break and continue statements
  • builtins.du - Comprehensive builtin function examples
  • dates.du - Date and time functions (now, format_time, parse_time)
  • sort_custom.du - Custom comparison functions for sort()
  • find_replace.du - String search and replace with contains() and replace()
  • test_var.du - Variable scoping with var keyword and closures
  • templates.du - String template examples
  • multiline.du - Multiline string examples
  • with-include.du - Using include() for shared code
  • file-io.du - Using load() and save() for files
  • multi-file.du - Larger script with multiple files
  • agents.du - Agent orchestration patterns
  • coercion.du - Type coercion
  • print-variants.du - Multiple print styles
  • colors.du - ANSI terminal color codes (include this file for color variables)
  • benchmark.du - Prime number counting performance test
  • fun.du - Interactive conversation with AI agents

Architecture

  • Lexer - Tokenization with string template and multiline string support
  • Parser - Recursive descent parser producing AST
  • Evaluator - Tree-walking interpreter
  • Value System - Runtime value representation
  • Environment - Scope management with closures
  • Builtins - Built-in functions
  • Structures - Template system for objects
  • Public API - script.Interpreter for easy integration

Full Language Reference

See docs/learning-duso.md for a guided tour of the language with examples, or docs/internals.md for architecture details.

Documentation

Overview

ast.go - Duso Abstract Syntax Tree node definitions

This file defines the data structures that represent a parsed Duso program. The parser converts tokens into an AST using these node types.

CORE LANGUAGE COMPONENT: This is part of the minimal core language. The AST is the intermediate representation between source code and evaluation.

Node types include: - Program: Root node containing all statements - Statements: if/elseif/else, while/for loops, function definitions, assignments - Expressions: Binary/unary operations, function calls, literals, variables - Values: Numbers, strings, booleans, arrays, objects, nil - Functions: Function definitions and calls (both user and built-in)

The AST structure enables: - Proper error reporting (statements have source locations) - Correct evaluation order and precedence - Support for all language constructs

environment.go - Duso variable scoping system

This file implements the lexical scoping and variable lookup system for Duso. An Environment is a single scope level, with optional parent scopes forming a scope chain.

CORE LANGUAGE COMPONENT: This is part of the minimal core runtime. Scope management is essential for: - Local variables in functions - Nested scopes (if blocks, function bodies, loops) - Variable shadowing (redefining in inner scopes) - Function closure support

The scoping model is simple and dynamically typed: - Variables are stored as Value structs - Each environment has an optional parent environment - Variable lookup walks up the scope chain - Function scopes prevent assignments from walking to parent (local declarations) - The "self" value provides context for method calls

STORAGE: most scopes (function frames, loop bodies) hold only a handful of variables, so the first smallScopeSize variables live in inline arrays on the struct — creating and using such a scope costs a single allocation and lookups are a short linear scan (with Go's pointer-equality fast path for the shared AST identifier strings). Scopes that outgrow the inline slots spill to the overflow map.

CONCURRENCY INVARIANT: Environments are deliberately unsynchronized. An env tree is only ever touched by one goroutine, with one exception: parallel() branches read parent scopes concurrently. That is safe because parallel() blocks the parent goroutine on wg.Wait() (no writer exists while readers run), and branch writes stop at the branch's own function env via isParallelContext. Anything that would share an env tree across goroutines in a new way must revisit this.

lexer.go - Duso language tokenizer

This file implements the lexer (scanner/tokenizer) that converts source code strings into a stream of tokens. It is the first stage of compilation, before parsing.

CORE LANGUAGE COMPONENT: This is part of the minimal core language. It is required for all script execution, both in embedded applications and the CLI.

The lexer handles: - Character-by-character reading from source code - Token identification (keywords, operators, literals, identifiers) - Line and column tracking for error reporting - String and number literal parsing - Comment handling

registry.go - Global builtin function registry

This file maintains the global registry of builtin functions. The registry is populated once at startup by the host (runtime package or CLI). Each evaluator gets a copy of the map for lock-free function lookups.

resolver.go - Compile-time slot resolution for function parameters

After parsing, resolveProgram walks the AST and annotates Identifier nodes that provably refer to a parameter of the enclosing function with a slot index. Parameters occupy the first inline storage slots of the function environment in declaration order (both call paths guarantee this), so an annotated identifier reads e.env.fnScope.vals[slot] directly instead of walking the scope chain with string compares.

CORE LANGUAGE COMPONENT: This is part of the minimal core runtime.

The resolver is deliberately conservative: it annotates a use only when the dynamic path would provably produce the same result, because local lookup wins over self properties and parent scopes for both reads and writes (see Environment.Get/Set). Anything ambiguous stays un-annotated and takes the existing name-based path. Punt rules:

  • only parameters are slotted; they are bound before the body runs no matter how they were supplied (positional, named, or default)
  • a parameter shadowed anywhere in the function body — by a var declaration, a for-loop variable, a catch variable, or a nested function definition name — is not slotted at all
  • identifiers inside named-argument expressions are never slotted: object constructors evaluate them in a temp scope where earlier named args are visible (see callObject)
  • parameter default expressions are never slotted (evaluated in the closure environment, not the function environment)
  • nested function bodies get their own scope; outer parameters are not slottable inside them (closure capture stays name-based)
  • a parameter named "self" is never slotted (Get special-cases the name)
  • only the first smallScopeSize parameters get slots (inline storage)

value.go - Duso runtime type system

This file defines the core value types and runtime representation for all Duso data. Every value computed during script execution is represented as a Value struct.

CORE LANGUAGE COMPONENT: This is part of the minimal core runtime. All values in Duso scripts map to one of these types: - NIL: Absence of a value (uninitialized variables) - NUMBER: Floating-point numbers (no integer type) - STRING: Text values - BOOL: True/false - ARRAY: Ordered lists of values (indexed by numbers) - OBJECT: Maps/tables (key-value pairs with string keys) - FUNCTION: Callable functions (either Go or Duso functions)

This type system is simple and dynamically typed to match Duso's design goal of being easy to embed and learn.

Index

Constants

This section is empty.

Variables

View Source
var NoPos = Position{Line: 0, Column: 0}

NoPos represents an unknown or invalid position

Functions

func ArgKey

func ArgKey(i int) string

ArgKey returns the args-map key for positional argument i

func ClearRequestContext

func ClearRequestContext(gid uint64)

ClearRequestContext removes a request context from goroutine-local storage

func CopyBuiltins

func CopyBuiltins() map[string]GoFunction

CopyBuiltins returns a copy of the global builtin registry. Called once per evaluator so it can have lock-free lookups.

func CopyFastBuiltins

func CopyFastBuiltins() map[string]GoFunctionFast

CopyFastBuiltins returns a copy of the fast builtin registry.

func DecodeValue

func DecodeValue(buf []byte) (any, []byte, error)

DecodeValue decodes one value from buf, returning it with the remaining bytes.

func DeepCopyAny

func DeepCopyAny(val any) any

DeepCopyAny performs deep copy on any type (for scope boundaries)

func EncodeValue

func EncodeValue(buf []byte, v any) ([]byte, error)

EncodeValue appends the binary encoding of v to buf and returns the extended buffer. v is an any-tree of the kind a datastore holds.

Functions cannot be encoded and are elided rather than raising an error, matching the deep_copy() builtin exactly: a function becomes nil, and a function stored as an object value has its key dropped entirely.

func FormatErrorWithStack

func FormatErrorWithStack(err *DusoError) string

FormatErrorWithStack formats a DusoError with full stack trace for I/O queuing. This matches the format used by DusoError.Error() but is reusable.

func GetAllBuiltinNames

func GetAllBuiltinNames() []string

GetAllBuiltinNames returns a sorted list of all registered builtin function names.

func GetGoroutineID

func GetGoroutineID() uint64

GetGoroutineID extracts the current goroutine ID from the stack trace

func GetKeywords

func GetKeywords() map[string]TokenType

GetKeywords returns the keywords map for introspection (e.g., for syntax generation)

func IsReservedName

func IsReservedName(name string) bool

IsReservedName checks if a name conflicts with keywords

func RegisterBuiltin

func RegisterBuiltin(name string, fn GoFunction)

RegisterBuiltin registers a builtin function in the global registry. This is called by the host (runtime package or CLI) during initialization.

func RegisterBuiltinFast

func RegisterBuiltinFast(name string, fn GoFunctionFast)

RegisterBuiltinFast registers a fast-path variant for an existing builtin.

func ResolveScriptPath

func ResolveScriptPath(requestedPath, callingScriptFilename string) string

ResolveScriptPath resolves a script path relative to a calling script's directory. If the path is absolute or special (/EMBED/, /STORE/), returns it unchanged. If the path is relative, resolves it relative to the calling script's directory. Example: ResolveScriptPath("./worker.du", "/path/to/bees/bees.du")

returns "/path/to/bees/worker.du"

func ResolveScriptPathFromDir

func ResolveScriptPathFromDir(requestedPath, scriptDir string) string

ResolveScriptPathFromDir resolves a script path relative to a given directory. If the path is absolute or special (/EMBED/, /STORE/), returns it unchanged. If the path is relative, resolves it relative to the given directory. Example: ResolveScriptPathFromDir("./worker.du", "/path/to/bees")

returns "/path/to/bees/worker.du"

func SetDatastoreQueueAppender

func SetDatastoreQueueAppender(appender DatastoreQueueAppender)

SetDatastoreQueueAppender sets the global datastore queue appender callback. Called by runtime.RegisterBuiltins() to wire up I/O routing.

func SetRequestContextWithData

func SetRequestContextWithData(gid uint64, ctx *RequestContext, spawnedData any)

SetRequestContextWithData stores a request context with optional spawned context data

func UnescapeString

func UnescapeString(s string) string

UnescapeString processes escape sequences in a string, preserving UTF-8 Uses rune-based iteration to handle multi-byte characters correctly

func ValueForDisplay

func ValueForDisplay(val Value) string

ValueForDisplay converts a value to a display string for print/output. Strings are printed as-is without quotes (for readability). Other types use Duso syntax so arrays/objects display correctly.

func ValueSize

func ValueSize(v any) int64

ValueSize reports the approximate encoded size of a value in bytes, matching what EncodeValue would produce closely enough to enforce a limit against.

It exists so a size cap can be checked without encoding first: encoding a 500MB value to discover it is too big has already done the damage. The walk is O(n) in the value, but every datastore write already deep-copies the value, so this adds a second pass over data that was being traversed anyway — and for the case that actually matters, a large binary, it is O(1).

func ValueToDusoString

func ValueToDusoString(val Value) string

ValueToDusoString converts any Value to a Duso-parsable string representation. This is used for tostring(), templates, and any place Duso syntax is needed. The result is valid Duso syntax that can be parsed back with parse().

func ValueToInterface

func ValueToInterface(v Value) any

ValueToInterface converts a Value to interface{} for Go interop. This is used to convert script values to Go types for external functions. For arrays, returns *[]Value directly to allow in-place mutations by builtins.

Types

type ArrayLiteral

type ArrayLiteral struct {
	Elements []Node
}

type AssignStatement

type AssignStatement struct {
	Pos              Position
	Target           Node // Can be Identifier, IndexExpr, or PropertyAccess
	Value            Node
	IsVarDeclaration bool // true if "var x = ..." syntax
}

type BinaryExpr

type BinaryExpr struct {
	Pos   Position
	Op    TokenType
	Left  Node
	Right Node
}

type BinaryValue

type BinaryValue struct {
	Data     *[]byte          // Pointer to immutable binary data
	Metadata map[string]Value // filename, content_type, size, etc.
}

BinaryValue represents immutable binary data (e.g., files, images)

type BoolLiteral

type BoolLiteral struct {
	Value bool
}

type BracketInfo

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

BracketInfo tracks opening brackets for better error messages

type BreakIteration

type BreakIteration struct{}

BreakIteration is used to signal a break from a loop (for future use)

func (*BreakIteration) Error

func (e *BreakIteration) Error() string

type BreakStatement

type BreakStatement struct {
	Pos Position
}

type BreakpointError

type BreakpointError struct {
	FilePath  string
	Position  Position
	CallStack []CallFrame
	Env       *Environment // Current environment at breakpoint for scope access
	Message   string       // Optional message from breakpoint()/watch() call
}

BreakpointError signals debug breakpoint hit and captures call stack for display

func (*BreakpointError) Error

func (e *BreakpointError) Error() string

type CallExpr

type CallExpr struct {
	Pos       Position
	Func      Node
	Arguments []Node
	NamedArgs map[string]Node // For function(name = value) style calls
	// contains filtered or unexported fields
}

type CallFrame

type CallFrame struct {
	FunctionName string
	FilePath     string
	Position     Position
}

CallFrame represents a function call in the execution stack

type CircularDetector

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

CircularDetector tracks module loading stack to detect circular dependencies

func (*CircularDetector) Pop

func (c *CircularDetector) Pop()

Pop removes the most recent path from the detector's loading stack

func (*CircularDetector) Push

func (c *CircularDetector) Push(path string) error

Push adds a path to the detector's loading stack

type CodeValue

type CodeValue struct {
	Source   string
	Program  *Program         // parsed AST, immutable
	Metadata map[string]Value // optional user metadata from parse(src, meta)
}

CodeValue represents pre-parsed code (source + AST + optional metadata)

type CompoundAssignStatement

type CompoundAssignStatement struct {
	Pos      Position
	Target   Node      // Can be Identifier, IndexExpr, or PropertyAccess
	Operator TokenType // TOK_PLUSASSIGN, TOK_MINUSASSIGN, etc.
	Value    Node
}

type ComputedKeyPair

type ComputedKeyPair struct {
	KeyExpr   Node
	ValueExpr Node
}

type ContinueIteration

type ContinueIteration struct{}

ContinueIteration is used to signal a continue in a loop (for future use)

func (*ContinueIteration) Error

func (e *ContinueIteration) Error() string

type ContinueStatement

type ContinueStatement struct {
	Pos Position
}

type DatastoreQueueAppender

type DatastoreQueueAppender func(datastore, queue, eventType string, data any, pid int) error

DatastoreQueueAppender is a callback for appending to an I/O queue in a datastore. Set by the runtime package during initialization to enable I/O routing. Parameters: datastore name, queue key, event type ("out", "err", "exit"), data value, PID

type DebugEvent

type DebugEvent struct {
	Error           error            // The error that occurred (BreakpointError or runtime error)
	Message         string           // Error message (for runtime errors without DusoError wrapper)
	FilePath        string           // File where error occurred
	Position        Position         // Position in file
	CallStack       []CallFrame      // Script call stack at error point
	InvocationStack *InvocationFrame // Chain of script invocations that led here
	Env             *Environment     // Environment at time of error
	ResumeChan      chan bool        // Signal to resume execution after REPL
}

DebugEvent represents a debug event (breakpoint or error) that occurred in a child script It's queued for the main process to handle via REPL

type DebugHandler

type DebugHandler func(*DebugEvent)

DebugHandler is a callback function that handles debug events (breakpoints, errors). It receives the debug event and is responsible for: - Displaying the event to the user (via chosen I/O mechanism) - Opening a debug session (REPL, HTTP interface, etc.) - Sending a resume signal when the user is done debugging

type DebugManager

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

DebugManager handles debug events sequentially. Scripts call Wait() synchronously and block until the user responds. The manager processes each event from its queue one-by-one, opening the REPL and waiting for user input before resuming the caller.

When -stdin-port is used, the debug REPL's stdin/stdout automatically goes through the HTTP transport (no special HTTP debug server needed).

func GetDebugManager

func GetDebugManager() *DebugManager

GetDebugManager returns the global debug manager instance

func (*DebugManager) Wait

func (dm *DebugManager) Wait(event *DebugEvent, interpreter *Interpreter)

Wait blocks until the user responds to the debug event. This is called synchronously by ExecuteScript when a breakpoint is hit.

type DusoError

type DusoError struct {
	Message   any // The error message/thrown value (any type, NOT deep copied at throw time)
	FilePath  string
	Position  Position
	CallStack []CallFrame
}

DusoError represents an error with position information and call stack

func (*DusoError) Error

func (e *DusoError) Error() string

type ElseifClause

type ElseifClause struct {
	Condition Node
	Then      []Node
}

type Environment

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

Environment represents a scope for variables

func NewChildEnvironment

func NewChildEnvironment(parent *Environment) *Environment

NewChildEnvironment creates a child environment with a parent scope

func NewChildEnvironmentWithSelf

func NewChildEnvironmentWithSelf(parent *Environment, self Value) *Environment

NewChildEnvironmentWithSelf creates a child environment with a parent scope and self

func NewEnvironment

func NewEnvironment() *Environment

NewEnvironment creates a new root environment

func NewFunctionEnvironment

func NewFunctionEnvironment(parent *Environment) *Environment

NewFunctionEnvironment creates a function scope that blocks variable assignment walk-up

func NewFunctionEnvironmentWithSelf

func NewFunctionEnvironmentWithSelf(parent *Environment, self Value) *Environment

NewFunctionEnvironmentWithSelf creates a function scope with self binding

func (*Environment) Define

func (e *Environment) Define(name string, value Value)

Define creates a new variable in the current scope

func (*Environment) Get

func (e *Environment) Get(name string) (Value, error)

Get retrieves a variable, walking up the parent chain if necessary

func (*Environment) IsParameter

func (e *Environment) IsParameter(name string) bool

IsParameter checks if a name is a function parameter Fast path for common names (bit test), slow path for uncommon (map lookup)

func (*Environment) MarkParameter

func (e *Environment) MarkParameter(name string)

MarkParameter marks a name as a function parameter (can't be shadowed with var) Uses bit flags for common names, map for uncommon (memory optimization)

func (*Environment) Set

func (e *Environment) Set(name string, value Value) error

Set updates a variable, checking self properties first, then walking up the parent chain Parallel context blocks assignment walk-up to parent: parent scope becomes read-only

func (*Environment) SetLocal

func (e *Environment) SetLocal(name string, value Value) error

SetLocal updates a variable only in the current scope

func (*Environment) SetParallelContext

func (e *Environment) SetParallelContext(isParallel bool)

SetParallelContext marks this environment as part of a parallel() block When true, assignments don't walk up to parent scope (parent scope is read-only)

type ErrorValue

type ErrorValue struct {
	Message Value  // the value passed to throw(), or runtime error message string
	Stack   string // formatted string: file:line:col + call stack
}

ErrorValue represents a first-class error value (message + stack trace string)

type Evaluator

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

func NewEvaluator

func NewEvaluator() *Evaluator

NewEvaluator creates a new evaluator

func (*Evaluator) CallFunction

func (e *Evaluator) CallFunction(fn Value, args map[string]Value) (Value, error)

CallFunction calls a Duso function with the given arguments This delegates to callScriptFunction or callGoFunction based on the function type

func (*Evaluator) Eval

func (e *Evaluator) Eval(node Node) (Value, error)

Eval evaluates a node

func (*Evaluator) EvalModule

func (e *Evaluator) EvalModule(prog *Program) (Value, error)

EvalModule evaluates a program in an isolated module scope and returns the result. This is used by require() to load modules in isolation - the module's variables don't leak into the caller's scope. The last expression value becomes the module's export.

func (*Evaluator) EvalTemplateLiteral

func (e *Evaluator) EvalTemplateLiteral(template string) (string, error)

EvalTemplateLiteral evaluates a template string with embedded expressions

func (*Evaluator) EvaluateTemplate

func (e *Evaluator) EvaluateTemplate(templateStr string, bindings map[string]Value) (string, error)

EvaluateTemplate evaluates a template string with provided variable bindings. The template string can contain {{ }} expressions that are evaluated in the context of the provided bindings. Returns the evaluated template as a string.

Example:

bindings := map[string]Value{
  "name": NewString("World"),
  "count": NewNumber(42),
}
result, err := evaluator.EvaluateTemplate("Hello {{name}}, count: {{count}}", bindings)
// result = "Hello World, count: 42"

func (*Evaluator) GetContext

func (e *Evaluator) GetContext() *ExecContext

GetContext returns the execution context (FilePath, CallStack, Position info)

func (*Evaluator) GetEnv

func (e *Evaluator) GetEnv() *Environment

GetEnv returns the current environment for variable inspection

func (*Evaluator) GetEnvironment

func (e *Evaluator) GetEnvironment() *Environment

GetEnvironment returns the current evaluation environment

func (*Evaluator) GetGoFunctions

func (e *Evaluator) GetGoFunctions() map[string]GoFunction

GetGoFunctions returns a copy of the registered Go functions

func (*Evaluator) GetWatchCache

func (e *Evaluator) GetWatchCache() map[string]Value

GetWatchCache returns the watch cache map for debug watch() expressions

func (*Evaluator) IsParallelContext

func (e *Evaluator) IsParallelContext() bool

IsParallelContext returns true if executing in a parallel() block

func (*Evaluator) ParseExpression

func (e *Evaluator) ParseExpression(exprStr string) (Node, error)

ParseExpression parses a string expression into an AST node

func (*Evaluator) RegisterFunction

func (e *Evaluator) RegisterFunction(name string, fn GoFunction)

RegisterFunction registers a Go function

func (*Evaluator) RegisterObject

func (e *Evaluator) RegisterObject(name string, methods map[string]GoFunction)

RegisterObject registers an object with methods

func (*Evaluator) ReqCtx

func (e *Evaluator) ReqCtx() *RequestContext

ReqCtx returns the request context attached to this evaluator, or nil.

func (*Evaluator) SetEnvironment

func (e *Evaluator) SetEnvironment(env *Environment)

SetEnvironment sets the evaluation environment

func (*Evaluator) SetExecutionFilePath

func (e *Evaluator) SetExecutionFilePath(filePath string)

SetExecutionFilePath sets the FilePath in the execution context for error reporting

func (*Evaluator) SetParallelContext

func (e *Evaluator) SetParallelContext(isParallel bool)

SetParallelContext sets whether the evaluator is executing in a parallel() block

func (*Evaluator) SetReqCtx

func (e *Evaluator) SetReqCtx(rc *RequestContext)

SetReqCtx attaches the per-execution request context to this evaluator. Evaluators are per-execution (HTTP handler, spawn, run), so this is safe to read without locking from builtins invoked during that execution.

type ExecContext

type ExecContext struct {
	FilePath  string
	CallStack []CallFrame
}

ExecContext tracks execution state including file path and call stack

func NewExecContext

func NewExecContext(filePath string) *ExecContext

NewExecContext creates a new execution context with the given file path

func (*ExecContext) Depth

func (ctx *ExecContext) Depth() int

Depth returns the current call stack depth

func (*ExecContext) PopCall

func (ctx *ExecContext) PopCall()

PopCall removes the last function call from the stack

func (*ExecContext) PushCall

func (ctx *ExecContext) PushCall(name, file string, pos Position)

PushCall adds a function call to the stack

type ExitExecution

type ExitExecution struct {
	Values []any
}

ExitExecution is used to signal exit() with optional return values

func (*ExitExecution) Error

func (e *ExitExecution) Error() string

type ForStatement

type ForStatement struct {
	Pos       Position
	Var       string
	Start     Node
	End       Node
	Step      Node // Can be nil for iterator-based for loops
	Iterator  Node // Non-nil for "for item in array" loops
	Body      []Node
	IsNumeric bool // true for numeric for, false for iterator-based
	// contains filtered or unexported fields
}

type FunctionCaller

type FunctionCaller interface {
	// CallFunction calls a Duso function with the given arguments
	CallFunction(fn Value, args map[string]Value) (Value, error)

	// EvalTemplateLiteral evaluates a template string and returns the result
	EvalTemplateLiteral(template string) (string, error)

	// GetEnvironment returns the current evaluation environment
	GetEnvironment() *Environment

	// IsParallelContext returns true if executing in a parallel() block
	IsParallelContext() bool
}

FunctionCaller is an interface for invoking Duso functions and accessing evaluation context. This interface decouples Builtins from directly depending on Evaluator, allowing callback-based builtins (map, filter, reduce, etc.) to work without circular dependencies.

type FunctionDef

type FunctionDef struct {
	Pos        Position
	Name       string
	Parameters []*Parameter
	Body       []Node
	// contains filtered or unexported fields
}

type FunctionExpr

type FunctionExpr struct {
	Parameters []*Parameter
	Body       []Node
	// contains filtered or unexported fields
}

type GoFunction

type GoFunction func(evaluator *Evaluator, args map[string]any) (any, error)

func GetBuiltin

func GetBuiltin(name string) GoFunction

GetBuiltin retrieves a single builtin function by name, or nil if not found.

type GoFunctionFast

type GoFunctionFast func(evaluator *Evaluator, args []Value) (Value, error)

GoFunctionFast is the fast-path builtin signature: evaluated positional args in, Value out, no interface{} marshalling. See RegisterBuiltinFast.

type IOConfig

type IOConfig struct {
	Datastore string // Name of the datastore to use
	Queue     string // Key in the datastore where I/O events are appended
	Out       bool   // Route print() output to the queue
	Err       bool   // Route error() and runtime errors to the queue
	Exit      bool   // Route exit code to the queue
	PID       int    // Process ID (set by spawn/run, used in queue entries)
}

IOConfig specifies where a spawned/run process should route its I/O When set, print/error/exit output goes to a datastore queue instead of stdout/stderr

type Identifier

type Identifier struct {
	Pos  Position
	Name string
	// contains filtered or unexported fields
}

type IfStatement

type IfStatement struct {
	Pos       Position
	Condition Node
	Then      []Node
	Elseifs   []*ElseifClause
	Else      []Node
}

type IndexExpr

type IndexExpr struct {
	Pos    Position
	Object Node
	Index  Node
}

type Interpreter

type Interpreter struct {

	// I/O routing configuration (optional, set at spawn/run time)
	IOConfig *IOConfig // If set, print/error/exit route to datastore instead of default handlers

	// Host-provided capabilities (for builtins that need host services)
	ScriptLoader func(path string) ([]byte, error)           // Loads scripts for spawn/run (required for those builtins)
	FileReader   func(path string) ([]byte, error)           // Reads files for load/readfile (required for those builtins)
	FileWriter   func(path, content string) error            // Writes files for save/writefile (required for those builtins)
	FileStatter  func(path string) int64                     // Gets file modification time for caching (used by http_server)
	DirReader    func(path string) ([]map[string]any, error) // Lists directory contents, supports /EMBED/ and /STORE/ (used by http_server)
	OutputWriter func(msg string) error                      // Outputs messages for print/error/debug (required for those builtins)
	InputReader  func(prompt string) (string, error)         // Reads input from user (required for input() builtin)
	EnvReader    func(varname string) string                 // Reads environment variables (used by env() builtin)
	// contains filtered or unexported fields
}

Interpreter is the public API for executing Duso scripts.

CORE INTERPRETER - This is suitable for both embedded Go applications and CLI usage. It uses only the core language runtime with no external dependencies.

To extend with CLI features (file I/O, module loading), see pkg/cli/register.go

func GetExecutionInterpreter

func GetExecutionInterpreter(gid uint64) *Interpreter

GetExecutionInterpreter retrieves the interpreter for the current execution Returns nil if no RequestContext is available

func NewInterpreter

func NewInterpreter() *Interpreter

NewInterpreter creates a new interpreter instance.

This creates a minimal interpreter with only the core Duso language features. Use this in embedded Go applications, then optionally register custom functions with RegisterFunction() or CLI features with pkg/cli.RegisterFunctions().

func (*Interpreter) AppendToIOQueue

func (i *Interpreter) AppendToIOQueue(eventType string, data any, pid int) error

AppendToIOQueue appends an I/O event to the configured datastore queue. eventType should be one of: "out", "err", "exit" The entry includes the PID for sorting/filtering in shared queues. This is called by the I/O handler functions to route output to a datastore. Returns nil if no IOConfig is set (I/O routing not enabled).

func (*Interpreter) CacheProgram

func (i *Interpreter) CacheProgram(key string, program *Program)

CacheProgram stores a pre-parsed program in the cache with the given key. Used by http_server to cache inline code handlers from parse().

func (*Interpreter) EvalInContext

func (i *Interpreter) EvalInContext(source string) (string, error)

EvalInContext evaluates code in the current evaluator context. Used by the debug REPL to maintain variable scope and evaluator state. Unlike Execute(), this preserves all evaluator state without reinitializing.

func (*Interpreter) EvalInEnvironment

func (i *Interpreter) EvalInEnvironment(source string, env *Environment) (string, error)

EvalInEnvironment evaluates code in a specific environment context. This is used by the debug REPL to evaluate expressions in the scope where the breakpoint occurred.

func (*Interpreter) EvalProgram

func (i *Interpreter) EvalProgram(program *Program) (Value, error)

EvalProgram evaluates a pre-parsed program in the current scope. This is used by include() when the AST is already cached. Unlike ExecuteModuleProgram, this executes in the current environment so variables and functions are available after execution.

func (*Interpreter) Execute

func (i *Interpreter) Execute(source string) (string, error)

Execute executes script source code

func (*Interpreter) ExecuteFile

func (i *Interpreter) ExecuteFile(path string) (string, error)

ExecuteFile executes a script file

func (*Interpreter) ExecuteModule

func (i *Interpreter) ExecuteModule(source string) (Value, error)

ExecuteModule executes script source in an isolated module scope and returns the result value. This is used by require() to load modules in isolation. The module's variables don't leak into the caller's scope. The last expression value (or explicit return) is the export.

func (*Interpreter) ExecuteModuleProgram

func (i *Interpreter) ExecuteModuleProgram(program *Program) (Value, error)

ExecuteModuleProgram executes a pre-parsed program in an isolated module scope. This is used by require() when the AST is already cached. The module's variables don't leak into the caller's scope. The last expression value (or explicit return) is the export.

Creates a fresh evaluator for each module to ensure per-execution isolation (no sharing of evaluator state across concurrent requests).

func (*Interpreter) ExecuteNode

func (i *Interpreter) ExecuteNode(node Node) error

ExecuteNode executes a single AST node. Used by debugger for statement-by-statement execution. Maintains evaluator state between calls.

func (*Interpreter) GetCallStack

func (i *Interpreter) GetCallStack() []CallFrame

GetCallStack returns the current call stack for debugging

func (*Interpreter) GetDebugEventChan

func (i *Interpreter) GetDebugEventChan() chan *DebugEvent

GetDebugEventChan returns the channel for receiving debug events from child scripts

func (*Interpreter) GetDebugHandler

func (i *Interpreter) GetDebugHandler() DebugHandler

GetDebugHandler retrieves the currently registered debug handler.

func (*Interpreter) GetDebugSessionMutex

func (i *Interpreter) GetDebugSessionMutex() *sync.Mutex

GetDebugSessionMutex returns the mutex that serializes debug REPL sessions. Only one debug REPL should be active at a time to prevent multiple readers on stdin.

func (*Interpreter) GetEvaluator

func (i *Interpreter) GetEvaluator() *Evaluator

GetEvaluator returns the internal evaluator instance (for advanced use). This is primarily used by CLI functions that need access to registered Go functions.

func (*Interpreter) GetFilePath

func (i *Interpreter) GetFilePath() string

GetFilePath returns the current file path for error reporting

func (*Interpreter) GetModuleCache

func (i *Interpreter) GetModuleCache(path string) (Value, int64, bool)

GetModuleCache retrieves a cached module value by absolute path with mtime validation. Returns (value, mtime, found). Caller should validate mtime if caching should expire. Used by require() to implement module caching with file change detection.

func (*Interpreter) GetScriptDir

func (i *Interpreter) GetScriptDir() string

GetScriptDir returns the directory of the main script.

func (*Interpreter) ParseScript

func (i *Interpreter) ParseScript(path string) (*Program, error)

ParseScript parses a script file with AST caching, using the interpreter's ScriptLoader. This is used by spawn(), run(), and HTTP handlers to avoid re-parsing the same script.

The cache is validated using file modification time: - If the file hasn't changed, the cached AST is returned - If the file is newer, it's re-parsed and the cache is updated - For /EMBED/ files, the cached AST is always returned

This requires ScriptLoader and FileStatter to be set on the interpreter.

func (*Interpreter) ParseScriptFile

func (i *Interpreter) ParseScriptFile(path string, readFile func(string) ([]byte, error), getMtime func(string) int64) (*Program, error)

ParseScriptFile reads and parses a script file with AST caching and mtime checking. This is the centralized script loader used by require(), include(), and main script execution.

The cache is validated using file modification time: - If the file hasn't changed since caching, the cached AST is returned - If the file is newer, it's re-parsed and the cache is updated - For /EMBED/ files, the cached AST is always returned (embedded files don't change)

This function requires a FileReadFunc to be provided for reading files. It's typically called from pkg/cli with an appropriate file reader.

func (*Interpreter) QueueDebugEvent

func (i *Interpreter) QueueDebugEvent(event *DebugEvent)

QueueDebugEvent sends a debug event to the main process (non-blocking due to buffered channel)

func (*Interpreter) RegisterDebugHandler

func (i *Interpreter) RegisterDebugHandler(handler DebugHandler)

RegisterDebugHandler registers a handler function to be called when debug events occur. The handler is responsible for displaying the event to the user and managing the debug session. This allows the runtime to be I/O-agnostic while delegating user interaction to the handler.

Example (console debugging):

interp.RegisterDebugHandler(func(event *DebugEvent) {
    handleConsoleDebugEvent(interp, event)
})

The handler will be called from the debug event listener goroutine.

func (*Interpreter) RegisterFunction

func (i *Interpreter) RegisterFunction(name string, fn GoFunction) error

RegisterFunction registers a custom Go function callable from Duso scripts.

This is how embedded applications extend Duso with domain-specific functionality. For CLI-specific functions (load, save, include), see pkg/cli.

func (*Interpreter) RegisterObject

func (i *Interpreter) RegisterObject(name string, methods map[string]GoFunction) error

RegisterObject registers an object with methods (e.g., "agents" with methods like "classify")

func (*Interpreter) Reset

func (i *Interpreter) Reset()

Reset resets the environment

func (*Interpreter) SetFilePath

func (i *Interpreter) SetFilePath(path string)

SetFilePath sets the current file path for error reporting

func (*Interpreter) SetModuleCache

func (i *Interpreter) SetModuleCache(path string, value Value, mtime int64)

SetModuleCache stores a module value in the cache by absolute path with its mtime. Used by require() to cache module results so they're only loaded once.

func (*Interpreter) SetScriptDir

func (i *Interpreter) SetScriptDir(dir string)

SetScriptDir sets the directory of the main script for relative path resolution. Used by run() and spawn() to resolve relative script paths when loading from embedded files.

type InvocationFrame

type InvocationFrame struct {
	Filename string           // Script filename
	Line     int              // Line number where invocation happened
	Col      int              // Column number
	Reason   string           // "http_route", "spawn", etc.
	Details  map[string]any   // Additional context (method, path, etc.)
	Parent   *InvocationFrame // Previous frame in chain
}

InvocationFrame represents a single level in the call stack

type Lexer

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

func NewLexer

func NewLexer(source string) *Lexer

func NewLexerAt

func NewLexerAt(source string, startLine int, startCol int) *Lexer

NewLexerAt creates a lexer with a starting line and column position Used for parsing template expressions within strings

func (*Lexer) NextToken

func (l *Lexer) NextToken() Token

func (*Lexer) Tokenize

func (l *Lexer) Tokenize() ([]Token, error)

type LintAnalyzer

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

LintAnalyzer performs static analysis on a Duso AST

func NewLintAnalyzer

func NewLintAnalyzer(program *Program, filename string) *LintAnalyzer

NewLintAnalyzer creates a new analyzer

func (*LintAnalyzer) Analyze

func (a *LintAnalyzer) Analyze() []*LintDiagnostic

Analyze performs all linting checks

type LintDiagnostic

type LintDiagnostic struct {
	Message  string
	Severity int // 0=error, 1=warning
	Line     int
	Column   int
}

LintDiagnostic represents a linting issue

type LintScope

type LintScope struct {
	Parent     *LintScope
	Symbols    map[string]*SymbolInfo
	IsFunction bool
}

LintScope represents a lexical scope (function, block, etc.)

type ModuleCacheEntry

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

ModuleCacheEntry holds a cached module result with its modification time

type NilLiteral

type NilLiteral struct{}

type Node

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

Node is the interface that all AST nodes must implement

type NumberLiteral

type NumberLiteral struct {
	Value float64
}

type ObjectLiteral

type ObjectLiteral struct {
	StaticPairs   map[string]Node
	ComputedPairs []*ComputedKeyPair
}

type Parameter

type Parameter struct {
	Name    string // Parameter name
	Default Node   // Default value expression (nil if no default)
}

Parameter represents a function parameter with optional default value

type ParseCacheEntry

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

ParseCacheEntry holds a cached parsed AST with its modification time

type Parser

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

func NewParser

func NewParser(tokens []Token) *Parser

func NewParserWithFile

func NewParserWithFile(tokens []Token, filePath string) *Parser

NewParserWithFile creates a parser with an explicit file path for error reporting

func (*Parser) Parse

func (p *Parser) Parse() (*Program, error)

func (*Parser) ParseTemplateString

func (p *Parser) ParseTemplateString(template string, pos Position) (Node, error)

ParseTemplateString parses a template string containing {{ }} expressions

type Position

type Position struct {
	Line   int
	Column int
}

Position represents a location in source code

func (Position) IsValid

func (p Position) IsValid() bool

IsValid returns true if the position has valid line/column information

type PostIncrementStatement

type PostIncrementStatement struct {
	Pos      Position
	Target   Node      // Can be Identifier, IndexExpr, or PropertyAccess
	Operator TokenType // TOK_INCREMENT or TOK_DECREMENT
}

type Program

type Program struct {
	Statements []Node
}

Program is the root node of an AST

type PropertyAccess

type PropertyAccess struct {
	Pos      Position
	Object   Node
	Property string
}

type RegexLiteral

type RegexLiteral struct {
	Pattern string
}

type RegexValue

type RegexValue struct {
	Pattern  string         // Original pattern source
	Compiled *regexp.Regexp // Compiled regex
}

RegexValue represents a compiled regular expression pattern

type RequestContext

type RequestContext struct {
	Data             any                // Generic context data (spawn/run data or HTTP request/response functions)
	Frame            *InvocationFrame   // Root invocation frame for this context
	ExitChan         chan any           // Channel to receive exit value from script
	ProcessCtx       context.Context    // Process context for cancellation (kill support)
	Interpreter      *Interpreter       // Reference to shared global interpreter (read-only)
	Evaluator        *Evaluator         // Fresh evaluator for this execution's environment
	CircularDetector *CircularDetector  // Tracks circular dependency detection for require() calls
	IOConfig         *IOConfig          // Per-execution I/O routing config
	OutputWriter     func(string) error // Per-execution output writer (may route to datastore)
	// contains filtered or unexported fields
}

RequestContext holds context data for any spawned/invoked script Used for spawn() calls, run() calls, and HTTP handlers

func CurrentRequestContext

func CurrentRequestContext(e *Evaluator) (*RequestContext, bool)

CurrentRequestContext returns the request context for the current execution. It prefers the evaluator-attached context (set by ExecuteScript), which avoids the goroutine-ID lookup (runtime.Stack costs ~3µs per call); evaluators without one (main script, module eval, parallel branches) fall back to the goroutine-local registration.

func GetRequestContext

func GetRequestContext(gid uint64) (*RequestContext, bool)

GetRequestContext retrieves a request context from goroutine-local storage

type ReturnStatement

type ReturnStatement struct {
	Pos   Position
	Value Node // Can be nil
}

type ReturnValue

type ReturnValue struct {
	Value Value
}

ReturnValue is used to signal a return from a function

func (*ReturnValue) Error

func (e *ReturnValue) Error() string

type ScriptExecutionResult

type ScriptExecutionResult struct {
	Value any   // The exit value or nil
	Error error // Any error that occurred
}

ScriptExecutionResult holds the result of script execution

func ExecuteScript

func ExecuteScript(
	program Node,
	interpreter *Interpreter,
	invocationFrame *InvocationFrame,
	requestContext *RequestContext,
	timeoutCtx context.Context,
) *ScriptExecutionResult

ExecuteScript executes a parsed script with proper exception handling. Used by run(), spawn(), and HTTP handlers to unify script execution and error handling.

type ScriptFunction

type ScriptFunction struct {
	Name       string
	FilePath   string // File where function was defined (for error reporting)
	Parameters []*Parameter
	Body       []Node
	Closure    *Environment
	// contains filtered or unexported fields
}

type StringLiteral

type StringLiteral struct {
	Value string
}

type SymbolInfo

type SymbolInfo struct {
	Name     string
	Scope    *LintScope
	Position Position
	Used     bool
	Kind     string // "function", "parameter", "variable"
}

SymbolInfo tracks a definition (function or variable)

type TemplateLiteral

type TemplateLiteral struct {
	Pos   Position
	Parts []Node // Alternating TextPart and expression nodes
}

type TernaryExpr

type TernaryExpr struct {
	Pos       Position
	Condition Node
	TrueExpr  Node
	FalseExpr Node
}

type TextPart

type TextPart struct {
	Value string
}

type Token

type Token struct {
	Type   TokenType
	Value  string
	Line   int
	Column int
}

func (Token) String

func (t Token) String() string

type TokenType

type TokenType int
const (
	// Special
	TOK_EOF TokenType = iota
	TOK_ERROR
	TOK_COMMENT

	// Literals
	TOK_NUMBER
	TOK_STRING
	TOK_TILDE_STRING
	TOK_TRUE
	TOK_FALSE
	TOK_NIL
	TOK_IDENT

	// Keywords
	TOK_IF
	TOK_THEN
	TOK_ELSE
	TOK_ELSEIF
	TOK_END
	TOK_WHILE
	TOK_DO
	TOK_FOR
	TOK_IN
	TOK_FUNCTION
	TOK_RETURN
	TOK_BREAK
	TOK_CONTINUE
	TOK_TRY
	TOK_CATCH
	TOK_AND
	TOK_OR
	TOK_NOT
	TOK_VAR
	TOK_RAW

	// Operators
	TOK_PLUS
	TOK_MINUS
	TOK_STAR
	TOK_SLASH
	TOK_PERCENT
	TOK_EQUAL
	TOK_NOTEQUAL
	TOK_LT
	TOK_GT
	TOK_LTE
	TOK_GTE
	TOK_ASSIGN
	TOK_PLUSASSIGN
	TOK_MINUSASSIGN
	TOK_STARASSIGN
	TOK_SLASHASSIGN
	TOK_MODASSIGN
	TOK_INCREMENT
	TOK_DECREMENT

	// Delimiters
	TOK_LPAREN
	TOK_RPAREN
	TOK_LBRACKET
	TOK_RBRACKET
	TOK_LBRACE
	TOK_RBRACE
	TOK_COMMA
	TOK_DOT
	TOK_COLON
	TOK_QUESTION
)

func LookupKeyword

func LookupKeyword(ident string) TokenType

func (TokenType) String

func (t TokenType) String() string

String returns a human-readable name for the TokenType

type TryStatement

type TryStatement struct {
	Pos        Position
	Block      []Node
	CatchVar   string
	CatchBlock []Node
}

type UnaryExpr

type UnaryExpr struct {
	Pos     Position
	Op      TokenType
	Operand Node
}

type Value

type Value struct {
	Type ValueType
	Num  float64 // inline storage for VAL_NUMBER — keeps arithmetic off the heap
	Data any
}

func DeepCopy

func DeepCopy(v Value) Value

DeepCopy creates a deep copy of a Value, recursively copying arrays and objects

func InterfaceToValue

func InterfaceToValue(i any) Value

InterfaceToValue converts Go any to script values. This is used to convert Go values to script Values for builtins.

func NewArray

func NewArray(elements []Value) Value

func NewBinary

func NewBinary(data []byte) Value

func NewBool

func NewBool(b bool) Value

func NewCode

func NewCode(src string, prog *Program, meta map[string]Value) Value

func NewErrorValue

func NewErrorValue(msg Value, stack string) Value

func NewFunction

func NewFunction(fn *ScriptFunction) Value

func NewGoFunction

func NewGoFunction(fn GoFunction) Value

func NewNil

func NewNil() Value

Constructors

func NewNumber

func NewNumber(n float64) Value

func NewObject

func NewObject(obj map[string]Value) Value

func NewRegex

func NewRegex(pattern string, compiled *regexp.Regexp) Value

func NewString

func NewString(s string) Value

func (Value) AsArray

func (v Value) AsArray() []Value

func (Value) AsArrayPtr

func (v Value) AsArrayPtr() *[]Value

AsArrayPtr returns a pointer to the array for in-place mutations

func (Value) AsBinary

func (v Value) AsBinary() *BinaryValue

func (Value) AsBool

func (v Value) AsBool() bool

func (Value) AsCode

func (v Value) AsCode() *CodeValue

func (Value) AsErrorVal

func (v Value) AsErrorVal() *ErrorValue

func (Value) AsNumber

func (v Value) AsNumber() float64

Getters

func (Value) AsObject

func (v Value) AsObject() map[string]Value

func (Value) AsRegex

func (v Value) AsRegex() *RegexValue

func (Value) AsString

func (v Value) AsString() string

func (Value) IsArray

func (v Value) IsArray() bool

func (Value) IsBinary

func (v Value) IsBinary() bool

func (Value) IsBool

func (v Value) IsBool() bool

func (Value) IsCode

func (v Value) IsCode() bool

func (Value) IsError

func (v Value) IsError() bool

func (Value) IsFunction

func (v Value) IsFunction() bool

func (Value) IsNil

func (v Value) IsNil() bool

Type checking

func (Value) IsNumber

func (v Value) IsNumber() bool

func (Value) IsObject

func (v Value) IsObject() bool

func (Value) IsRegex

func (v Value) IsRegex() bool

func (Value) IsString

func (v Value) IsString() bool

func (Value) IsTruthy

func (v Value) IsTruthy() bool

Truthiness

func (Value) String

func (v Value) String() string

String representation

type ValueRef

type ValueRef struct {
	Val Value
}

ValueRef wraps a Value so it can pass through the any interface without losing type info

type ValueType

type ValueType int
const (
	VAL_NIL ValueType = iota
	VAL_NUMBER
	VAL_STRING
	VAL_BOOL
	VAL_ARRAY
	VAL_OBJECT
	VAL_FUNCTION
	VAL_CODE   // pre-parsed code (source + AST + metadata)
	VAL_ERROR  // first-class error value (message + stack string)
	VAL_BINARY // immutable binary data (files, images, etc.)
	VAL_REGEX  // compiled regular expression pattern
)

func (ValueType) String

func (vt ValueType) String() string

String returns a human-readable name for the ValueType

type WhileStatement

type WhileStatement struct {
	Pos       Position
	Condition Node
	Body      []Node
}

Jump to

Keyboard shortcuts

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