lua

package
v1.2.1 Latest Latest
Warning

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

Go to latest
Published: Oct 16, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package lua is apogee's Lua 5.5 VM, in pure Go and built for real-time use, with a JIT compiler on linux and darwin, arm64 and amd64. It began as a port of the C Lua VM from https://www.lua.org/, by way of Shopify/go-lua. The standard libraries are in package stdlib.

Example

A host registers Go functions, loads a script, and calls the script's functions from Go, here once a frame.

package main

import (
	"fmt"
	"log"

	"github.com/matjam/apogee/lua"
	"github.com/matjam/apogee/stdlib"
)

func main() {
	l := lua.NewState()
	stdlib.Open(l)

	// A Go function the script can call.
	l.Register("greet", func(l *lua.State) int {
		l.PushString("hello, " + l.Arg[string](1))
		return 1
	})

	if err := l.DoString(`
		count = 0
		function frame(t)
		  count = count + 1
		  return greet("frame " .. count), t * 2
		end`); err != nil {
		log.Fatal(err)
	}

	for t := range 3 {
		l.Global("frame")
		l.PushNumber(float64(t))
		if err := l.ProtectedCall(1, 2, 0); err != nil {
			log.Fatal(err)
		}
		message, _ := l.ToString(-2)
		doubled, _ := l.ToNumber(-1)
		fmt.Println(message, doubled)
		l.Pop(2)
	}
}
Output:
hello, frame 1 0
hello, frame 2 2
hello, frame 3 4

Index

Examples

Constants

View Source
const (
	HookCall, MaskCall = iota, 1 << iota
	HookReturn, MaskReturn
	HookLine, MaskLine
	HookCount, MaskCount
	HookTailCall, MaskTailCall
)

Debug.Event and SetDebugHook mask argument values.

View Source
const (
	// RegistryIndex is the pseudo-index for the registry table.
	RegistryIndex = firstPseudoIndex

	// RegistryIndexMainThread is the registry index for the main thread of the
	// State. (The main thread is the one created together with the State.)
	RegistryIndexMainThread = iota

	// RegistryIndexGlobals is the registry index for the global environment.
	RegistryIndexGlobals
)

Lua provides a registry, a predefined table, that can be used by any Go code to store whatever Lua values it needs to store. The registry table is always located at pseudo-index RegistryIndex, which is a valid index. Any Go library can store data into this table, but it should take care to choose keys that are different from those used by other libraries, to avoid collisions. Typically, you should use as key a string containing your library name, or a light userdata object in your code, or any Lua object created by your code. As with global names, string keys starting with an underscore followed by uppercase letters are reserved for Lua.

The integer keys in the registry are used by the reference mechanism and by some predefined values. Therefore, integer keys should not be used for other purposes.

When you create a new Lua state, its registry comes with some predefined values. These predefined values are indexed with integer keys defined as constants.

View Source
const (
	VersionMajor  = 5
	VersionMinor  = 5
	VersionNumber = 505
	VersionString = "Lua " + string('0'+VersionMajor) + "." + string('0'+VersionMinor)
)
View Source
const (
	GCPMinorMul   = iota // generational mode: minor collection frequency
	GCPMajorMinor        // generational mode: shift from major to minor
	GCPMinorMajor        // generational mode: shift from minor to major
	GCPPause             // collect when the heap reaches this percentage of the last
	GCPStepMul           // incremental mode: the collector's speed
	GCPStepSize          // incremental mode: bytes per step

)

Collector parameters for GCParam, as lua_gc's LUA_GCP values. apogee's collector uses only GCPPause; it keeps the others for collectgarbage.

View Source
const MinStack = 20

MinStack is the minimum Lua stack available to a Go function.

View Source
const MultipleReturns = -1

MultipleReturns is the argument for argCount or resultCount in ProtectedCall and Call.

View Source
const Signature = chunk.Signature

Signature is the mark for precompiled code ('<esc>Lua').

Variables

View Source
var (
	ErrSyntax       = errors.New("syntax error")
	ErrMemory       = errors.New("memory error")
	ErrErrorHandler = errors.New("error within the error handler")
	ErrFile         = errors.New("file error")
)

Errors introduced by the Lua VM.

Functions

func BaseIPairs added in v1.1.1

func BaseIPairs(l *State) int

BaseIPairs is ipairs, a Go closure whose upvalue is its iterator, so that it returns the same function each time, which indexes the value with metamethods, as Lua 5.4's does.

func BaseIPairsIterator added in v1.1.1

func BaseIPairsIterator(l *State) int

BaseIPairsIterator is the iterator ipairs returns: the index after the second argument and the table's value there, with metamethods, or nil where that value is nil.

func BaseNext added in v1.1.1

func BaseNext(l *State) int

BaseNext is next: the key after the second argument in the table, and its value, or nil after the last.

func BasePairs added in v1.1.1

func BasePairs(l *State) int

BasePairs is pairs, a Go closure whose upvalue is next, which it returns, so it returns the same function each time, unless __pairs says otherwise.

func BaseSetMetatable added in v1.1.1

func BaseSetMetatable(l *State) int

BaseSetMetatable is setmetatable, which the standard library registers. Compiled code sets the metatable of a table that has none itself, when the new one's shape has never held __gc or __mode (shape.collects).

func MathAbs added in v1.1.0

func MathAbs(l *State) int

MathAbs is math.abs, keeping an integer an integer.

func MathCeil added in v1.1.0

func MathCeil(l *State) int

MathCeil is math.ceil: an integer's value, or a float rounded up, as an integer when one holds it.

func MathFloor added in v1.1.0

func MathFloor(l *State) int

MathFloor is math.floor: an integer's value, or a float rounded down, as an integer when one holds it.

func MathMax added in v1.1.0

func MathMax(l *State) int

MathMax is math.max: the first argument no other is greater than, keeping its type.

func MathMin added in v1.1.0

func MathMin(l *State) int

MathMin is math.min: the first argument no other is less than, keeping its type.

func UpValueIndex

func UpValueIndex(i int) int

UpValueIndex returns the pseudo-index that represents the i-th upvalue of the running function.

https://www.lua.org/manual/5.5/manual.html#lua_upvalueindex

Types

type ArgType

type ArgType interface {
	float64 | float32 | int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64 | string | bool
}

ArgType lists the Go types Arg can convert a Lua argument to.

type BufferElement

type BufferElement interface {
	float64 | float32 | int32 | uint8
}

BufferElement is the element type of a buffer.

type ComparisonOperator

type ComparisonOperator int

A ComparisonOperator is an op argument for Compare.

const (
	OpEq ComparisonOperator = iota // Compares for equality (==).
	OpLT                           // Compares for less than (<).
	OpLE                           // Compares for less or equal (<=).
)

Valid ComparisonOperator values for Compare.

type Debug

type Debug struct {
	Event int

	// Name is a reasonable name for the given function. Because functions in
	// Lua are first-class values, they do not have a fixed name. Some functions
	// can be the value of multiple global variables, while others can be stored
	// only in a table field. The Info function checks how the function was
	// called to find a suitable name. If it cannot find a name, then Name is "".
	Name string

	// NameKind explains the name field. The value of NameKind can be "global",
	// "local", "method", "field", "upvalue", or "" (the empty string), according
	// to how the function was called. (Lua uses the empty string when no other
	// option seems to apply.)
	NameKind string

	// What is the string "Lua" if the function is a Lua function, "Go" if it is
	// a Go function, "main" if it is the main part of a chunk.
	//
	// With the environment variable APOGEE_GO_AS_C=1 when a state is created,
	// its debug information calls Go functions "C", with the source "=[C]",
	// as C Lua's does for its C functions, for scripts and tests that expect
	// that.
	What string

	// Source is the source of the chunk that created the function. If Source
	// starts with a '@', it means that the function was defined in a file where
	// the file name follows the '@'. If Source starts with a '=', the remainder
	// of its contents describe the source in a user-dependent manner. Otherwise,
	// the function was defined in a string where Source is that string.
	Source string

	// ShortSource is a "printable" version of source, to be used in error messages.
	ShortSource string

	// CurrentLine is the current line where the given function is executing.
	// When no line information is available, CurrentLine is set to -1.
	CurrentLine int

	// LineDefined is the line number where the definition of the function starts.
	LineDefined int

	// LastLineDefined is the line number where the definition of the function ends.
	LastLineDefined int

	// UpValueCount is the number of upvalues of the function.
	UpValueCount int

	// ParameterCount is the number of fixed parameters of the function (always 0
	// for Go functions).
	ParameterCount int

	// IsVarArg is true if the function is a vararg function (always true for Go
	// functions).
	IsVarArg bool

	// IsTailCall is true if this function invocation was called by a tail call.
	// In this case, the caller of this level is not in the stack.
	IsTailCall bool

	// ExtraArgs, filled by option 't', is how many __call metamethods the
	// call went through, each adding the called value as an argument.
	ExtraArgs int

	// FirstTransfer and TransferCount, filled by option 'r', are the
	// values a call or return hook can see: the parameters or results,
	// as indices Local takes. They are 0 outside such a hook.
	FirstTransfer, TransferCount int
	// contains filtered or unexported fields
}

A Debug carries different pieces of information about a function or an activation record. Stack fills only the private part of this structure, for later use. To fill the other fields of a Debug with useful information, call Info.

type Frame

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

A Frame identifies an activation record. It is returned by State.Frame and passed to State.Info; its zero value identifies none.

type Function

type Function func(state *State) int

A Function is a Go function intended to be called from Lua.

Example
package main

import (
	"fmt"

	"github.com/matjam/apogee/lua"
)

// averageAndSum receives a variable number of numerical arguments and returns their average and sum.
func averageAndSum(l *lua.State) int {
	n := l.Top() // Number of arguments.
	var sum float64
	for i := 1; i <= n; i++ {
		f, ok := l.ToNumber(i)
		if !ok {
			l.PushString("incorrect argument")
			l.Error()
		}
		sum += f
	}
	l.PushNumber(sum / float64(n)) // First result.
	l.PushNumber(sum)              // Second result.
	return 2                       // Result count.
}

func main() {
	l := lua.NewState()
	l.Register("averageAndSum", averageAndSum)
	l.Global("averageAndSum")
	l.PushNumber(2)
	l.PushNumber(4)
	l.Call(2, 2)
	avg, _ := l.ToNumber(-2)
	sum, _ := l.ToNumber(-1)
	fmt.Println(avg, sum)
}
Output:
3 6

type GCOption

type GCOption int

A GCOption is an operation for GC.

const (
	GCStop         GCOption = iota // stop automatic Lua collections
	GCRestart                      // restart them
	GCCollect                      // run a full collection
	GCCount                        // the Go heap in use, in kilobytes
	GCCountBytes                   // the remainder of GCCount, in bytes
	GCStep                         // GC(GCStep, n): do n bytes' worth of work; returns 1 if that finished a collection
	GCIsRunning                    // 1 if automatic collections are on
	GCGenerational                 // switch to generational mode; returns the previous mode
	GCIncremental                  // switch to incremental mode; returns the previous mode
	GCParam                        // GC(GCParam, p, v): returns parameter p, then sets it to v if v >= 0
)

Valid GCOption values, as lua_gc's options.

type Hook

type Hook func(state *State, activationRecord Debug)

A Hook is a callback function that can be registered with SetHook to trace various VM events.

type Integer

type Integer interface {
	~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
}

Integer lists the Go integer types PushInteger takes.

type NumberFunction

type NumberFunction interface {
	func(float64) float64 |
		func(float64, float64) float64 |
		func(float64, float64, float64) float64 |
		func(float64, float64, float64, float64) float64 |
		func(float64) |
		func(float64, float64) |
		func(float64, float64, float64) |
		func(float64, float64, float64, float64)
}

NumberFunction lists the plain Go function types that PushNumberFunction accepts: up to four float64 arguments, returning one float64 or nothing.

type Operator

type Operator int

An Operator is an op argument for Arith.

const (
	OpAdd        Operator = iota // Performs addition (+).
	OpSub                        // Performs subtraction (-).
	OpMul                        // Performs multiplication (*).
	OpMod                        // Performs modulo (%).
	OpPow                        // Performs exponentiation (^).
	OpDiv                        // Performs float division (/).
	OpIDiv                       // Performs floor division (//).
	OpBAnd                       // Performs bitwise and (&).
	OpBOr                        // Performs bitwise or (|).
	OpBXor                       // Performs bitwise exclusive or (~).
	OpShl                        // Performs left shift (<<).
	OpShr                        // Performs right shift (>>).
	OpUnaryMinus                 // Performs mathematical negation (unary -).
	OpBNot                       // Performs bitwise not (unary ~).
)

Valid Operator values for Arith.

type Option

type Option func(*State)

An Option configures a State created by NewState.

func WithoutFinalizers added in v1.2.0

func WithoutFinalizers() Option

WithoutFinalizers turns __gc finalizers off: the State never calls a __gc metamethod, in a collection or at Close. A metatable with __gc can still be set; its __gc is ignored, as C Lua ignores a __gc added after the metatable was set. Files the io library opens are then closed only by file:close, io.close or os.exit.

A host that runs untrusted scripts wants this: a finalizer runs outside the calls the host makes, with hooks off, so neither a count hook nor Interrupt can stop one that never returns, and Close waits for it.

func WithoutJIT

func WithoutJIT() Option

WithoutJIT turns the JIT off, so the State only interprets.

type RegistryFunction

type RegistryFunction struct {
	Name     string
	Function Function
}

A RegistryFunction is used for arrays of functions to be registered by SetFunctions. Name is the function name and Function is the function.

type RuntimeError

type RuntimeError string

A RuntimeError is an error raised internally by the Lua VM or through Error.

func (RuntimeError) Error

func (r RuntimeError) Error() string

type State

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

A State is an opaque structure representing per thread Lua state.

func NewState

func NewState(options ...Option) *State

NewState creates a new thread running in a new, independent state.

https://www.lua.org/manual/5.5/manual.html#lua_newstate

func (*State) AbsIndex

func (l *State) AbsIndex(index int) int

AbsIndex converts the acceptable index index to an absolute index (that is, one that does not depend on the stack top).

https://www.lua.org/manual/5.5/manual.html#lua_absindex

func (*State) Allocated

func (l *State) Allocated() int

Allocated returns the bytes the state and its threads have allocated since SetAllocationLimit, or since NewState, as the limit counts them.

func (*State) Arg

func (l *State) Arg[T ArgType](index int) T

Arg returns the Go function argument at index as a T, converting it as CheckNumber, CheckInteger or CheckString would: an integer type takes an integer, or a float or numeral with an integral value, converted as a C cast would. For bool it returns the value's truth, as ToBoolean does. It raises a Lua error when the argument cannot convert.

func (*State) ArgumentCheck

func (l *State) ArgumentCheck(cond bool, index int, extraMessage string)

ArgumentCheck checks whether cond is true. If not, raises an error with a standard message.

func (*State) ArgumentError

func (l *State) ArgumentError(argCount int, extraMessage string)

ArgumentError raises an error with a standard message that includes extraMessage as a comment.

This function never returns. It is an idiom to use it in Go functions as

l.ArgumentError(args, "message")
panic("unreachable")

func (*State) Arith

func (l *State) Arith(op Operator)

Arith performs an arithmetic operation over the two values (or one, in case of negation) at the top of the stack, with the value at the top being the second operand, ops these values and pushes the result of the operation. The function follows the semantics of the corresponding Lua operator (that is, it may call metamethods).

https://www.lua.org/manual/5.5/manual.html#lua_arith

func (*State) AtPanic

func (l *State) AtPanic(panicFunction Function) Function

AtPanic sets a new panic function and returns the old one.

func (*State) Call

func (l *State) Call(argCount, resultCount int)

Call calls a function. To do so, use the following protocol: first, the function to be called is pushed onto the stack; then, the arguments to the function are pushed in direct order - that is, the first argument is pushed first. Finally, call Call. argCount is the number of arguments that you pushed onto the stack. All arguments and the function value are popped from the stack when the function is called.

The results are pushed onto the stack when the function returns. The number of results is adjusted to resultCount, unless resultCount is MultipleReturns. In this case, all results from the function are pushed. Lua takes care that the returned values fit into the stack space. The function results are pushed onto the stack in direct order (the first result is pushed first), so that after the call the last result is on the top of the stack.

Any error inside the called function provokes a call to panic().

The following example shows how the host program can do the equivalent to this Lua code:

a = f("how", t.x, 14)

Here it is in Go:

l.Global("f")       // Function to be called.
l.PushString("how") // 1st argument.
l.Global("t")       // Table to be indexed.
l.Field(-1, "x")    // Push result of t.x (2nd arg).
l.Remove(-2)        // Remove t from the stack.
l.PushInteger(14)   // 3rd argument.
l.Call(3, 1)        // Call f with 3 arguments and 1 result.
l.SetGlobal("a")    // Set global a.

Note that the code above is "balanced": at its end, the stack is back to its original configuration. This is considered good programming practice.

https://www.lua.org/manual/5.5/manual.html#lua_call

func (*State) CallMeta

func (l *State) CallMeta(index int, event string) bool

CallMeta calls a metamethod.

If the object at index has a metatable and this metatable has a field event, this function calls this field passing the object as its only argument. In this case this function returns true and pushes onto the stack the value returned by the call. If there is no metatable or no metamethod, this function returns false (without pushing any value on the stack).

func (*State) CallWithContinuation

func (l *State) CallWithContinuation(argCount, resultCount, context int, continuation Function)

CallWithContinuation is exactly like Call, but allows the called function to yield.

https://www.lua.org/manual/5.5/manual.html#lua_callk

func (*State) Charge

func (l *State) Charge(n int)

Charge counts n bytes against the allocation limit, raising a memory error if they do not fit. A Go function calls it for memory it allocates for Lua that the state cannot see, such as the Go value behind a userdata. n <= 0 counts nothing.

func (*State) CheckAllocation

func (l *State) CheckAllocation(n int)

CheckAllocation raises a memory error if n more bytes would not fit in the allocation limit, without counting them. A Go function calls it before building a large value that pushing will count, such as a string.

func (*State) CheckAny

func (l *State) CheckAny(index int)

CheckAny checks whether the function has an argument of any type (including nil) at position index.

func (*State) CheckInteger

func (l *State) CheckInteger(index int) int64

CheckInteger returns the argument at index as an integer, raising an error if it is not a number, or has no integer representation.

http://www.lua.org/manual/5.5/manual.html#luaL_checkinteger

func (*State) CheckNumber

func (l *State) CheckNumber(index int) float64

func (*State) CheckOption

func (l *State) CheckOption(index int, def string, list []string) int

CheckOption checks that the argument at index is a string in list, or is absent if def, its default, is not "", and returns its position in list. Otherwise it raises an error.

https://www.lua.org/manual/5.5/manual.html#luaL_checkoption

func (*State) CheckStack

func (l *State) CheckStack(size int) bool

CheckStack ensures that there are at least size free stack slots in the stack, and reports whether it could. Unlike the other Check*() functions it doesn't raise an error when the stack can't grow, with one exception: when growing would pass the limit SetAllocationLimit set, it raises the memory error, so that running out of the allocation budget can't be caught as an ordinary failure, such as unpack's "too many results".

https://www.lua.org/manual/5.5/manual.html#lua_checkstack

func (*State) CheckStackWithMessage

func (l *State) CheckStackWithMessage(space int, message string)

func (*State) CheckString

func (l *State) CheckString(index int) string

CheckString checks whether the function argument at index is a string and returns this string.

This function uses ToString to get its result, so all conversions and caveats of that function apply here.

func (*State) CheckType

func (l *State) CheckType(index int, t Type)

CheckType checks whether the function argument at index has type t. See Type for the encoding of types for t.

func (*State) CheckUserData

func (l *State) CheckUserData[T any](index int, name string) T

CheckUserData checks whether the function argument at index is a userdata of the type name (see NewMetaTable) holding a T, and returns it. It raises a Lua error otherwise.

Example

A Go value becomes a Lua object with methods through userdata and a metatable, and is read back with its Go type.

package main

import (
	"log"
	"math"

	"github.com/matjam/apogee/lua"
	"github.com/matjam/apogee/stdlib"
)

func main() {
	type point struct{ x, y float64 }

	l := lua.NewState()
	stdlib.Open(l)

	// The metatable of every point: its __index table holds the methods.
	l.NewMetaTable("point")
	l.NewTable()
	l.SetFunctions([]lua.RegistryFunction{{Name: "norm", Function: func(l *lua.State) int {
		p := l.CheckUserData[*point](1, "point")
		l.PushNumber(math.Hypot(p.x, p.y))
		return 1
	}}}, 0)
	l.SetField(-2, "__index")
	l.Pop(1)

	l.Register("point", func(l *lua.State) int {
		l.PushUserData(&point{l.Arg[float64](1), l.Arg[float64](2)})
		l.SetMetaTableNamed("point")
		return 1
	})

	if err := l.DoString(`print(point(3, 4):norm())`); err != nil {
		log.Fatal(err)
	}
}
Output:
5.0

func (*State) Close

func (l *State) Close()

Close closes the state, as lua_close does: it closes the main thread's pending to-be-closed variables, and then calls the __gc metamethods of every object that has one, newest first, reachable or not. Errors in them are warnings. Nothing may use the state afterwards.

https://www.lua.org/manual/5.5/manual.html#lua_close

func (*State) CloseRunning

func (l *State) CloseRunning()

CloseRunning closes l, the running coroutine, as coroutine.close() does in Lua 5.5: its to-be-closed variables close and its Resume returns, as if it had finished without results, or with the error one raised.

func (*State) CloseThread

func (l *State) CloseThread(from *State) error

CloseThread closes the to-be-closed variables of l, a coroutine that is suspended or dead, as lua_closethread does, and leaves it dead. from is the thread closing it, whose nested calls count against l's limit, or nil. It returns the error that killed l, or one a __close metamethod raised since, with the error value on l's stack; or nil.

func (*State) Compare

func (l *State) Compare(index1, index2 int, op ComparisonOperator) bool

Compare compares two values.

https://www.lua.org/manual/5.5/manual.html#lua_compare

func (*State) Concat

func (l *State) Concat(n int)

Concat concatenates the n values at the top of the stack, pops them, and leaves the result at the top. If n is 1, the result is the single value on the stack (that is, the function does nothing); if n is 0, the result is the empty string. Concatenation is performed following the usual semantic of Lua.

https://www.lua.org/manual/5.5/manual.html#lua_concat

func (*State) Context

func (l *State) Context() (int, bool, error)

Context is called by a continuation function to retrieve the status of the thread and context information. When called in the origin function, it will always return (0, false, nil). When called inside a continuation function, it will return (ctx, shouldYield, err), where ctx is the value that was passed to the callee together with the continuation function.

https://www.lua.org/manual/5.5/manual.html#lua_KFunction

func (*State) Copy

func (l *State) Copy(from, to int)

Copy moves the element at the index from into the valid index to without shifting any element (therefore replacing the value at that position).

https://www.lua.org/manual/5.5/manual.html#lua_copy

func (*State) CountInstructions added in v1.2.0

func (l *State) CountInstructions(n int)

CountInstructions counts n steps of work that a Go function does for Lua as if they were n VM instructions. It advances the count hook that SetHook set with MaskCount, calling the hook when the count runs out, and checks for an Interrupt as a loop does. A Go function that can run for a long time calls it from its loop, so that a hook or Interrupt can stop it as they stop Lua code; string matching calls it as it backtracks. An error the hook raises, or the interrupt's, is raised from here, as if by the Go function. The hook runs at most once per call. n <= 0 counts nothing.

func (*State) CreateTable

func (l *State) CreateTable(arrayCount, recordCount int)

CreateTable creates a new empty table and pushes it onto the stack. arrayCount is a hint for how many elements the table will have as a sequence; recordCount is a hint for how many other elements the table will have. Lua may use these hints to preallocate memory for the the new table. This pre-allocation is useful for performance when you know in advance how many elements the table will have. Otherwise, you can use the function NewTable.

https://www.lua.org/manual/5.5/manual.html#lua_createtable

func (*State) DoFile

func (l *State) DoFile(fileName string) error

DoFile loads and runs the given file.

func (*State) DoString

func (l *State) DoString(s string) error

DoString loads and runs the given string.

func (*State) Dump

func (l *State) Dump(w io.Writer, strip bool) error

Dump dumps a function as a binary chunk. It receives a Lua function on the top of the stack and produces a binary chunk that, if loaded again, results in a function equivalent to the one dumped. With strip set, the chunk has no debug information. It returns an error if the value on the top of the stack is not a Lua function.

http://www.lua.org/manual/5.5/manual.html#lua_dump

func (*State) Error

func (l *State) Error()

Error generates a Lua error. The error message must be on the stack top. The error can be any of any Lua type. This function will panic().

https://www.lua.org/manual/5.5/manual.html#lua_error

func (*State) Errorf

func (l *State) Errorf(format string, a ...any)

Errorf raises an error. The error message format is given by format plus any extra arguments, following the same rules as PushFString. It also adds at the beginning of the message the file name and the line number where the error occurred, if this information is available.

This function never returns. It is an idiom to use it in Go functions as:

l.Errorf(format, args...)
panic("unreachable")

func (*State) Field

func (l *State) Field(index int, name string) Type

Field pushes onto the stack the value table[name], where table is the table on the stack at the given index, and returns its type. This call may trigger a metamethod for the __index event.

https://www.lua.org/manual/5.5/manual.html#lua_getfield

func (*State) FieldInt

func (l *State) FieldInt[T Integer](index int, i T) Type

FieldInt pushes t[i], where t is the value at index, and returns its type. As in Lua, this may trigger a metamethod for the "index" event.

http://www.lua.org/manual/5.5/manual.html#lua_geti

func (*State) FileResult

func (l *State) FileResult(err error, filename string) int

FileResult produces the return values for file-related functions in the standard library (io.open, os.rename, file:seek, etc.).

func (*State) Frame

func (l *State) Frame(level int) (f Frame, ok bool)

Frame gets information about the interpreter runtime stack.

It returns a Frame identifying the activation record of the function executing at a given level. Level 0 is the current running function, whereas level n+1 is the function that has called level n (except for tail calls, which do not count on the stack). When there are no errors, Stack returns true; when called with a level greater than the stack depth, it returns false.

func (*State) GC

func (l *State) GC(what GCOption, args ...int) int

GC controls the collector, as lua_gc does; see the gc.go comment for what a collection does in apogee. It returns -1 for an invalid option, and for any option while a collection or a finalizer runs. GCGenerational and GCIncremental return the previous mode, one of them.

https://www.lua.org/manual/5.5/manual.html#lua_gc

func (*State) Global

func (l *State) Global(name string) Type

Global pushes onto the stack the value of the global name, and returns its type.

https://www.lua.org/manual/5.5/manual.html#lua_getglobal

func (*State) Hook

func (l *State) Hook() Hook

Hook returns the current hook function.

func (*State) HookCount

func (l *State) HookCount() int

HookCount returns the hook count SetHook set.

https://www.lua.org/manual/5.5/manual.html#lua_gethookcount

func (*State) HookMask

func (l *State) HookMask() byte

HookMask returns the current hook mask.

func (*State) Info

func (l *State) Info(what string, frame Frame) (d Debug, ok bool)

Info gets information about a specific function or function invocation.

To get information about a function invocation, the parameter where must be a valid activation record that was filled by a previous call to Stack or given as an argument to a hook (see Hook).

To get information about a function you push it onto the stack and start the what string with the character '>'. (In that case, Info pops the function from the top of the stack.) For instance, to know in which line a function f was defined, you can write the following code:

l.Global("f") // Get global 'f'.
d, _ := l.Info(">S", Frame{})
fmt.Printf("%d\n", d.LineDefined)

Each character in the string what selects some fields of the Debug struct to be filled or a value to be pushed on the stack:

'n': fills in the field Name and NameKind
'S': fills in the fields Source, ShortSource, LineDefined, LastLineDefined, and What
'l': fills in the field CurrentLine
't': fills in the field IsTailCall
'u': fills in the fields UpValueCount, ParameterCount, and IsVarArg
'f': pushes onto the stack the function that is running at the given level
'L': pushes onto the stack a table whose indices are the numbers of the lines that are valid on the function

(A valid line is a line with some associated code, that is, a line where you can put a break point. Non-valid lines include empty lines and comments.)

This function returns false on error (for instance, an invalid option in what).

func (*State) Insert

func (l *State) Insert(index int)

Insert moves the top element into the given valid index, shifting up the elements above this index to open space. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.

https://www.lua.org/manual/5.5/manual.html#lua_insert

func (*State) Interrupt

func (l *State) Interrupt()

Interrupt stops the Lua code running in l's state, on whichever of its threads is running, with the error "interrupted!" at its next loop iteration or tail call, as the standalone lua does on Ctrl-C. Unlike every other method, it may be called from any goroutine. A Go function the code called runs to completion first, and an interrupt that arrives once the outermost call from Go has returned is dropped.

Example

Interrupt, from another goroutine, stops a script that runs too long.

package main

import (
	"fmt"
	"time"

	"github.com/matjam/apogee/lua"
	"github.com/matjam/apogee/stdlib"
)

func main() {
	l := lua.NewState()
	stdlib.Open(l)
	time.AfterFunc(10*time.Millisecond, l.Interrupt)
	if err := l.DoString(`while true do end`); err != nil {
		fmt.Println(err)
		l.Pop(1)
	}
}
Output:
runtime error: [string "while true do end"]:1: interrupted!

func (*State) IsBoolean

func (l *State) IsBoolean(index int) bool

IsBoolean verifies that the value at index is a boolean.

https://www.lua.org/manual/5.5/manual.html#lua_isboolean

func (*State) IsFunction

func (l *State) IsFunction(index int) bool

IsFunction verifies that the value at index is a function, either Go or Lua function.

https://www.lua.org/manual/5.5/manual.html#lua_isfunction

func (*State) IsGoFunction

func (l *State) IsGoFunction(index int) bool

IsGoFunction verifies that the value at index is a Go function.

https://www.lua.org/manual/5.5/manual.html#lua_iscfunction

func (*State) IsInteger

func (l *State) IsInteger(index int) bool

IsInteger verifies that the value at index is an integer: a number with the integer subtype, not a float with an integral value.

http://www.lua.org/manual/5.5/manual.html#lua_isinteger

func (*State) IsLightUserData

func (l *State) IsLightUserData(index int) bool

IsLightUserData verifies that the value at index is a light userdata.

https://www.lua.org/manual/5.5/manual.html#lua_islightuserdata

func (*State) IsNil

func (l *State) IsNil(index int) bool

IsNil verifies that the value at index is nil.

https://www.lua.org/manual/5.5/manual.html#lua_isnil

func (*State) IsNone

func (l *State) IsNone(index int) bool

IsNone verifies that the value at index is not valid.

https://www.lua.org/manual/5.5/manual.html#lua_isnone

func (*State) IsNoneOrNil

func (l *State) IsNoneOrNil(index int) bool

IsNoneOrNil verifies that the value at index is either nil or invalid.

https://www.lua.org/manual/5.5/manual.html#lua_isnoneornil

func (*State) IsNumber

func (l *State) IsNumber(index int) bool

IsNumber verifies that the value at index is a number, or a string convertible to one.

http://www.lua.org/manual/5.5/manual.html#lua_isnumber

func (*State) IsString

func (l *State) IsString(index int) bool

IsString verifies that the value at index is a string, or a number (which is always convertible to a string).

https://www.lua.org/manual/5.5/manual.html#lua_isstring

func (*State) IsTable

func (l *State) IsTable(index int) bool

IsTable verifies that the value at index is a table.

https://www.lua.org/manual/5.5/manual.html#lua_istable

func (*State) IsThread

func (l *State) IsThread(index int) bool

IsThread verifies that the value at index is a thread.

https://www.lua.org/manual/5.5/manual.html#lua_isthread

func (*State) IsUserData

func (l *State) IsUserData(index int) bool

IsUserData verifies that the value at index is a userdata.

https://www.lua.org/manual/5.5/manual.html#lua_isuserdata

func (*State) IsYieldable

func (l *State) IsYieldable() bool

IsYieldable reports whether l can yield: it is a coroutine, and no Go call without a continuation, nor a metamethod call from Go, is running.

https://www.lua.org/manual/5.5/manual.html#lua_isyieldable

func (*State) Len

func (l *State) Len(index int) int64

Len returns the length of the value at index as an integer, as the # operator computes it, metamethods included.

http://www.lua.org/manual/5.5/manual.html#luaL_len

func (*State) Length

func (l *State) Length(index int)

Length of the value at index; it is equivalent to the # operator in Lua. The result is pushed on the stack.

https://www.lua.org/manual/5.5/manual.html#lua_len

func (*State) Load

func (l *State) Load(r io.Reader, chunkName string, mode string) error

Load loads a Lua chunk, without running it. If there are no errors, it pushes the compiled chunk as a Lua function on top of the stack. Otherwise, it pushes an error message.

https://www.lua.org/manual/5.5/manual.html#lua_load

func (*State) LoadBuffer

func (l *State) LoadBuffer(b, name, mode string) error

func (*State) LoadFile

func (l *State) LoadFile(fileName, mode string) error

func (*State) LoadString

func (l *State) LoadString(s string) error

func (*State) Local

func (l *State) Local(frame Frame, n int) (string, bool)

Local gets a local variable of the function running in frame: it pushes the variable's value and returns its name. Parameter 1 is the first local, then the other locals in the order they are declared, while they are active. Negative n are the varargs, named "(vararg)", and the function's other slots are named "(temporary)", or "(C temporary)" in a Go function, as in Lua 5.4.

With the zero Frame, Local instead returns the name of parameter n of the Lua function on the top of the stack, and pushes nothing.

Local returns false, pushing nothing, if there is no such variable.

https://www.lua.org/manual/5.5/manual.html#lua_getlocal

func (*State) MetaField

func (l *State) MetaField(index int, event string) Type

MetaField pushes onto the stack the field event from the metatable of the object at index, and returns its type. If the object does not have a metatable, or if the metatable does not have this field, it returns TypeNil and pushes nothing.

https://www.lua.org/manual/5.5/manual.html#luaL_getmetafield

func (*State) MetaTable

func (l *State) MetaTable(index int) bool

MetaTable pushes onto the stack the metatable of the value at index. If the value at index does not have a metatable, the function returns false and nothing is put onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_getmetatable

func (*State) MetaTableNamed

func (l *State) MetaTableNamed(name string)

func (*State) NewLibrary

func (l *State) NewLibrary(functions []RegistryFunction)

func (*State) NewLibraryTable

func (l *State) NewLibraryTable(functions []RegistryFunction)

func (*State) NewMetaTable

func (l *State) NewMetaTable(name string) bool

NewMetaTable returns false if the registry already has the key name. Otherwise, creates a new table to be used as a metatable for userdata, adds it to the registry with key name, and returns true.

In both cases it pushes onto the stack the final value associated with name in the registry.

func (*State) NewTable

func (l *State) NewTable()

NewTable creates a new empty table and pushes it onto the stack. It is equivalent to l.CreateTable(0, 0).

https://www.lua.org/manual/5.5/manual.html#lua_newtable

func (*State) NewThread

func (l *State) NewThread() *State

NewThread creates a thread, pushes it onto the stack, and returns it. The thread shares l's global state and hook, with its own stack.

https://www.lua.org/manual/5.5/manual.html#lua_newthread

func (*State) Next

func (l *State) Next(index int) bool

Next pops a key from the stack and pushes a key-value pair from the table at index, while the table has next elements. If there are no more elements, nothing is pushed on the stack and Next returns false.

A typical traversal looks like this:

// Table is on top of the stack (index -1).
l.PushNil() // Add nil entry on stack (need 2 free slots).
for l.Next(-2) {
	key := l.CheckString(-2)
	val := l.CheckString(-1)
	l.Pop(1) // Remove val, but need key for the next iter.
}

https://www.lua.org/manual/5.5/manual.html#lua_next

func (*State) OptInteger

func (l *State) OptInteger(index int, def int64) int64

OptInteger is CheckInteger, returning def for an absent or nil argument.

func (*State) OptNumber

func (l *State) OptNumber(index int, def float64) float64

func (*State) OptString

func (l *State) OptString(index int, def string) string

OptString returns the string at index if it is a string. If this argument is absent or is nil, returns def. Otherwise, raises an error.

func (*State) Pop

func (l *State) Pop(n int)

Pop pops n elements from the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pop

func (*State) ProtectedCall

func (l *State) ProtectedCall(argCount, resultCount, errorFunction int) error

ProtectedCall calls a function in protected mode. Both argCount and resultCount have the same meaning as in Call. If there are no errors during the call, ProtectedCall behaves exactly like Call.

However, if there is any error, ProtectedCall catches it, pushes a single value on the stack (the error message), and returns an error. Like Call, ProtectedCall always removes the function and its arguments from the stack.

If errorFunction is 0, then the error message returned on the stack is exactly the original error message. Otherwise, errorFunction is the stack index of an error handler (in the Lua C, message handler). This cannot be a pseudo-index in the current implementation. In case of runtime errors, this function will be called with the error message and its return value will be the message returned on the stack by ProtectedCall.

Typically, the error handler is used to add more debug information to the error message, such as a stack traceback. Such information cannot be gathered after the return of ProtectedCall, since by then, the stack has unwound.

The possible errors are the following:

RuntimeError     a runtime error
ErrMemory        allocating memory, the error handler is not called
ErrErrorHandler  running the error handler

https://www.lua.org/manual/5.5/manual.html#lua_pcall

Example

An error in Lua reaches Go as the error ProtectedCall returns, with the chunk name and line. The message is also left on the stack.

package main

import (
	"fmt"
	"log"

	"github.com/matjam/apogee/lua"
	"github.com/matjam/apogee/stdlib"
)

func main() {
	l := lua.NewState()
	stdlib.Open(l)
	if err := l.LoadBuffer(`
		function update(dt)
		  local speed
		  return speed * dt
		end`, "=game.lua", ""); err != nil {
		log.Fatal(err)
	}
	if err := l.ProtectedCall(0, 0, 0); err != nil {
		log.Fatal(err)
	}

	l.Global("update")
	l.PushNumber(0.016)
	if err := l.ProtectedCall(1, 0, 0); err != nil {
		fmt.Println(err)
		l.Pop(1)
	}
}
Output:
runtime error: game.lua:4: attempt to perform arithmetic on a nil value (local 'speed')

func (*State) ProtectedCallWithContinuation

func (l *State) ProtectedCallWithContinuation(argCount, resultCount, errorFunction, context int, continuation Function) (err error)

ProtectedCallWithContinuation behaves exactly like ProtectedCall, but allows the called function to yield.

https://www.lua.org/manual/5.5/manual.html#lua_pcallk

func (*State) PushBoolean

func (l *State) PushBoolean(b bool)

PushBoolean pushes a boolean value with value b onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pushboolean

func (*State) PushBuffer

func (l *State) PushBuffer[T BufferElement](s []T)

PushBuffer pushes a buffer onto the stack: a userdata through which Lua reads and writes the elements of s, sharing its memory. See buffer.go for how it behaves.

canvas := make([]float64, width*height)
l.PushBuffer(canvas)
l.SetGlobal("canvas") // Lua: canvas[y*width + x] = v

func (*State) PushFString

func (l *State) PushFString(format string, args ...any) string

PushFString pushes onto the stack a formatted string and returns that string. It is similar to fmt.Sprintf, but has some differences: the conversion specifiers are quite restricted. There are no flags, widths, or precisions. The conversion specifiers can only be %% (inserts a % in the string), %s, %f (a Lua number), %p (a pointer as a hexadecimal numeral), %d and %c (an integer as a byte).

https://www.lua.org/manual/5.5/manual.html#lua_pushfstring

func (*State) PushGlobalTable

func (l *State) PushGlobalTable()

PushGlobalTable pushes the global environment onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pushglobaltable

func (*State) PushGoClosure

func (l *State) PushGoClosure(function Function, upValueCount uint8)

PushGoClosure pushes a new Go closure onto the stack.

When a Go function is created, it is possible to associate some values with it, thus creating a Go closure; these values are then accessible to the function whenever it is called. To associate values with a Go function, first these values should be pushed onto the stack (when there are multiple values, the first value is pushed first). Then PushGoClosure is called to create and push the Go function onto the stack, with the argument upValueCount telling how many values should be associated with the function. Calling PushGoClosure also pops these values from the stack.

When upValueCount is 0, this function creates a light Go function, which is just a Go function.

https://www.lua.org/manual/5.5/manual.html#lua_pushcclosure

func (*State) PushGoFunction

func (l *State) PushGoFunction(f Function)

PushGoFunction pushes a Function implemented in Go onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pushcfunction

func (*State) PushInteger

func (l *State) PushInteger[T Integer](n T)

PushInteger pushes n onto the stack as an integer. A uint64 above the largest integer wraps around, as a cast to lua_Integer does in C.

http://www.lua.org/manual/5.5/manual.html#lua_pushinteger

func (*State) PushLightUserData

func (l *State) PushLightUserData(d any)

PushLightUserData pushes a light user data onto the stack. Userdata represents Go values in Lua. A light userdata is any Go value. Its equality matches the Go rules (http://golang.org/ref/spec#Comparison_operators).

https://www.lua.org/manual/5.5/manual.html#lua_pushlightuserdata

func (*State) PushNil

func (l *State) PushNil()

PushNil pushes a nil value onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pushnil

func (*State) PushNumber

func (l *State) PushNumber(n float64)

PushNumber pushes a number onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pushnumber

func (*State) PushNumberFunction

func (l *State) PushNumberFunction[F NumberFunction](f F)

PushNumberFunction pushes f as a Lua function. When a script calls it with exactly its number of arguments, all numbers, and no call or return hook is set, the VM calls f directly without a call frame. Otherwise the arguments convert as with CheckNumber.

func (*State) PushString

func (l *State) PushString(s string)

PushString pushes a string onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pushstring

func (*State) PushThread

func (l *State) PushThread() bool

PushThread pushes the thread l onto the stack. It returns true if l is the main thread of its state.

https://www.lua.org/manual/5.5/manual.html#lua_pushthread

func (*State) PushUserData

func (l *State) PushUserData(d any)

PushUserData is similar to PushLightUserData, but pushes a full userdata onto the stack, with one user value, as lua_newuserdata does.

func (*State) PushUserDataUV

func (l *State) PushUserDataUV(d any, n int)

PushUserDataUV pushes a full userdata holding d, with n user values, each nil to start with.

http://www.lua.org/manual/5.5/manual.html#lua_newuserdatauv

func (*State) PushValue

func (l *State) PushValue(index int)

PushValue pushes a copy of the element at index onto the stack.

https://www.lua.org/manual/5.5/manual.html#lua_pushvalue

func (*State) RawEqual

func (l *State) RawEqual(index1, index2 int) bool

RawEqual verifies that the values at index1 and index2 are primitively equal (that is, without calling their metamethods).

https://www.lua.org/manual/5.5/manual.html#lua_rawequal

func (*State) RawGet

func (l *State) RawGet(index int) Type

RawGet is similar to Table, but does a raw access (without metamethods). It returns the type of the value.

https://www.lua.org/manual/5.5/manual.html#lua_rawget

func (*State) RawGetInt

func (l *State) RawGetInt[T Integer](index int, key T) Type

RawGetInt pushes onto the stack the value table[key] where table is the value at index on the stack. The access is raw, as it doesn't invoke metamethods. It returns the type of the value.

https://www.lua.org/manual/5.5/manual.html#lua_rawgeti

func (*State) RawGetValue

func (l *State) RawGetValue(index int, p any) Type

RawGetValue pushes onto the stack value table[p] where table is the value at index on the stack, and p is a light userdata. The access is raw, as it doesn't invoke metamethods. It returns the type of the value.

https://www.lua.org/manual/5.5/manual.html#lua_rawgetp

func (*State) RawLength

func (l *State) RawLength(index int) int

RawLength returns the length of the value at index. For strings, this is the length. For tables, this is the result of the # operator with no metamethods. For userdata, this is the size of the block of memory allocated for the userdata (not implemented yet). For other values, it is 0.

https://www.lua.org/manual/5.5/manual.html#lua_rawlen

func (*State) RawSet

func (l *State) RawSet(index int)

RawSet is similar to SetTable, but does a raw assignment (without metamethods).

https://www.lua.org/manual/5.5/manual.html#lua_rawset

func (*State) RawSetInt

func (l *State) RawSetInt[T Integer](index int, key T)

RawSetInt does the equivalent of table[n]=v where table is the table at index and v is the value at the top of the stack.

This function pops the value from the stack. The assignment is raw; it doesn't invoke metamethods.

http://www.lua.org/manual/5.5/manual.html#lua_rawseti

func (*State) Register

func (l *State) Register(name string, f Function)

Register sets the Go function f as the new value of global name. If name was already defined, it is overwritten.

https://www.lua.org/manual/5.5/manual.html#lua_register

func (*State) RegisterNumberFunction

func (l *State) RegisterNumberFunction[F NumberFunction](name string, f F)

RegisterNumberFunction sets f as the new value of global name. See PushNumberFunction.

Example

A Go function of numbers is called without a Go call frame when every argument is a number, which suits functions a script calls per pixel.

package main

import (
	"fmt"
	"log"

	"github.com/matjam/apogee/lua"
	"github.com/matjam/apogee/stdlib"
)

func main() {
	const width, height = 4, 2
	var canvas [width * height]float64

	l := lua.NewState()
	stdlib.Open(l)
	l.RegisterNumberFunction("set", func(x, y, v float64) {
		canvas[int(y)*width+int(x)] = v
	})
	if err := l.DoString(`
		for y = 0, 1 do
		  for x = 0, 3 do set(x, y, x + y * 10) end
		end`); err != nil {
		log.Fatal(err)
	}
	fmt.Println(canvas)
}
Output:
[0 1 2 3 10 11 12 13]

func (*State) Remove

func (l *State) Remove(index int)

Remove the element at the given valid index, shifting down the elements above index to fill the gap. This function cannot be called with a pseudo-index, because a pseudo-index is not an actual stack position.

https://www.lua.org/manual/5.5/manual.html#lua_remove

func (*State) Replace

func (l *State) Replace(index int)

Replace moves the top element into the given valid index without shifting any element (therefore replacing the value at the given index), and then pops the top element.

https://www.lua.org/manual/5.5/manual.html#lua_replace

func (*State) Require

func (l *State) Require(name string, f Function, global bool)

Require calls function f with string name as an argument and sets the call result in package.loaded[name], as if that function had been called through require.

If global is true, also stores the result into global name.

Leaves a copy of that result on the stack.

Example

A host can open only the libraries a script should have. Here the script gets the basic functions, string and math, but not io, os or package, and the basic functions that read files are removed.

package main

import (
	"fmt"
	"log"

	"github.com/matjam/apogee/lua"
	"github.com/matjam/apogee/stdlib"
)

func main() {
	l := lua.NewState()
	for _, lib := range []lua.RegistryFunction{
		{Name: "_G", Function: stdlib.OpenBase},
		{Name: "string", Function: stdlib.OpenString},
		{Name: "math", Function: stdlib.OpenMath},
	} {
		l.Require(lib.Name, lib.Function, true)
		l.Pop(1)
	}
	for _, name := range []string{"dofile", "loadfile"} {
		l.PushNil()
		l.SetGlobal(name)
	}

	if err := l.DoString(`print(string.format("%.2f", math.pi))`); err != nil {
		log.Fatal(err)
	}
	if err := l.DoString(`io.open("secrets.txt")`); err != nil {
		fmt.Println(err)
		l.Pop(1)
	}
}
Output:
3.14
runtime error: [string "io.open("secrets.txt")"]:1: attempt to index a nil value (global 'io')

func (*State) Resume

func (l *State) Resume(from *State, argCount int) (yielded bool, err error)

Resume starts or continues the coroutine l. from is the thread resuming it, or nil. To start it, push its function and then argCount arguments onto l's stack; to continue it after a yield, push argCount values for its yield to return.

Resume returns true if the coroutine yielded, with the values it yielded on l's stack; false if it finished, with its results there instead; or an error, with the error value on l's stack. After an error raised in the coroutine, it is dead. An error resuming it at all, such as resuming a dead coroutine, leaves it as it was.

https://www.lua.org/manual/5.5/manual.html#lua_resume

func (*State) SetAllocationLimit

func (l *State) SetAllocationLimit(n int)

SetAllocationLimit limits what the state and its threads may allocate from now on to about n bytes, counting from zero again, and removes the limit for n <= 0. An allocation that would exceed it raises a memory error instead: ProtectedCall returns ErrMemory, pcall returns "not enough memory", and xpcall does not call its message handler, as in C Lua. Allocations that fit what is left still succeed.

A host running untrusted scripts sets a limit before each evaluation, as it arranges an Interrupt, so that no script can exhaust memory:

l.SetAllocationLimit(8 << 20)
err := l.ProtectedCall(0, 1, 0) // errors.Is(err, lua.ErrMemory) when it ran out
Example

A host running untrusted scripts limits what each may allocate. The allocation that would pass the limit fails before it is made.

package main

import (
	"errors"
	"fmt"

	"github.com/matjam/apogee/lua"
	"github.com/matjam/apogee/stdlib"
)

func main() {
	l := lua.NewState()
	stdlib.Open(l)
	l.SetAllocationLimit(8 << 20)
	err := l.DoString(`local s = string.rep("x", 1e9)`)
	message, _ := l.ToString(-1)
	fmt.Println(errors.Is(err, lua.ErrMemory), message)
}
Output:
true not enough memory

func (*State) SetField

func (l *State) SetField(index int, key string)

SetField does the equivalent of table[key]=v where table is the value at index and v is the value on top of the stack.

This function pops the value from the stack. As in Lua, this function may trigger a metamethod for the __newindex event.

https://www.lua.org/manual/5.5/manual.html#lua_setfield

func (*State) SetFieldInt

func (l *State) SetFieldInt[T Integer](index int, i T)

SetFieldInt does t[i] = v, where t is the value at index and v the value on top of the stack, which it pops. As in Lua, this may trigger a metamethod for the "newindex" event.

http://www.lua.org/manual/5.5/manual.html#lua_seti

func (*State) SetFunctions

func (l *State) SetFunctions(functions []RegistryFunction, upValueCount uint8)

func (*State) SetGlobal

func (l *State) SetGlobal(name string)

SetGlobal pops a value from the stack and sets it as the new value of global name.

https://www.lua.org/manual/5.5/manual.html#lua_setglobal

func (*State) SetHook

func (l *State) SetHook(f Hook, mask byte, count int)

SetHook sets the debugging hook function.

f is the hook function. mask specifies on which events the hook will be called: it is formed by a bitwise or of the constants MaskCall, MaskReturn, MaskLine, and MaskCount. The count argument is only meaningful when the mask includes MaskCount. For each event, the hook is called as explained below:

Call hook is called when the interpreter calls a function. The hook is called just after Lua enters the new function, before the function gets its arguments.

Return hook is called when the interpreter returns from a function. The hook is called just before Lua leaves the function. There is no standard way to access the values to be returned by the function.

Line hook is called when the interpreter is about to start the execution of a new line of code, or when it jumps back in the code (even to the same line). (This event only happens while Lua is executing a Lua function.)

Count hook is called after the interpreter executes every count instructions. (This event only happens while Lua is executing a Lua function.)

A hook is disabled by setting mask to zero.

func (*State) SetLocal

func (l *State) SetLocal(frame Frame, n int) (string, bool)

SetLocal sets a local variable of the function running in frame, as Local numbers them, to the value on the top of the stack, and returns its name. It pops the value, and returns false if there is no such variable.

https://www.lua.org/manual/5.5/manual.html#lua_setlocal

func (*State) SetMetaTable

func (l *State) SetMetaTable(index int)

SetMetaTable pops a table from the stack and sets it as the new metatable for the value at index.

https://www.lua.org/manual/5.5/manual.html#lua_setmetatable

func (*State) SetMetaTableNamed

func (l *State) SetMetaTableNamed(name string)

func (*State) SetTable

func (l *State) SetTable(index int)

SetTable does the equivalent of table[key]=v, where table is the value at index, v is the value at the top of the stack and key is the value just below the top.

The function pops both the key and the value from the stack. As in Lua, this function may trigger a metamethod for the __newindex event.

https://www.lua.org/manual/5.5/manual.html#lua_settable

func (*State) SetTop

func (l *State) SetTop(index int)

SetTop accepts any index, or 0, and sets the stack top to index. If the new top is larger than the old one, then the new elements are filled with nil. If index is 0, then all stack elements are removed.

If index is negative, the stack will be decremented by that much. If the decrement is larger than the stack, SetTop will panic().

https://www.lua.org/manual/5.5/manual.html#lua_settop

func (*State) SetUpValue

func (l *State) SetUpValue(function, index int) (name string, ok bool)

SetUpValue sets the value of a closure's upvalue. It assigns the value at the top of the stack to the upvalue and returns its name. It also pops a value from the stack. function and index are as in UpValue.

Returns an empty string and false if the index is greater than the number of upvalues.

https://www.lua.org/manual/5.5/manual.html#lua_setupvalue

func (*State) SetUserValue

func (l *State) SetUserValue(index, n int) bool

SetUserValue pops a value from the stack and sets it as user value n of the full userdata at index. It reports false, popping the value anyway, if the userdata has no such value.

http://www.lua.org/manual/5.5/manual.html#lua_setiuservalue

func (*State) SetWarnFunction

func (l *State) SetWarnFunction(f WarnFunction)

SetWarnFunction sets the function that receives warnings, or nil for none: warnings are then dropped.

https://www.lua.org/manual/5.5/manual.html#lua_setwarnf

func (*State) SortArray

func (l *State) SortArray(index, n, comparator int)

SortArray sorts t[1..n] in place, where t is the table at index, reading and writing its elements raw. If comparator is 0 it orders them with Lua's < operator, metamethods included; otherwise it calls the function at stack index comparator with two elements and treats a true result as "less than". It raises "invalid order function for sorting" when the order it finds is inconsistent. This is table.sort.

func (*State) Status

func (l *State) Status() ThreadStatus

Status returns the status of thread l.

https://www.lua.org/manual/5.5/manual.html#lua_status

func (*State) StringToNumber

func (l *State) StringToNumber(s string) bool

StringToNumber pushes the number the numeral s holds, keeping its type: an integer, or a float. It reports whether s is a numeral, and pushes nothing if it is not.

http://www.lua.org/manual/5.5/manual.html#lua_stringtonumber

func (*State) SubTable

func (l *State) SubTable(index int, name string) bool

func (*State) Table

func (l *State) Table(index int) Type

Table pushes onto the stack the value table[top], where table is the value at index, and top is the value at the top of the stack. This function pops the key from the stack, putting the resulting value in its place. As in Lua, this function may trigger a metamethod for the __index event. It returns the type of the value.

https://www.lua.org/manual/5.5/manual.html#lua_gettable

func (*State) TestUserData

func (l *State) TestUserData(index int, name string) any

func (*State) ToBoolean

func (l *State) ToBoolean(index int) bool

ToBoolean converts the Lua value at index to a Go boolean. Like all tests in Lua, the only false values are false booleans and nil. Otherwise, all other Lua values evaluate to true.

To accept only actual boolean values, use the test IsBoolean.

https://www.lua.org/manual/5.5/manual.html#lua_toboolean

func (*State) ToBuffer

func (l *State) ToBuffer[T BufferElement](index int) ([]T, bool)

ToBuffer returns the slice of the buffer at index, if the value there is a buffer of elements of type T.

func (*State) ToGoFunction

func (l *State) ToGoFunction(index int) Function

ToGoFunction converts a value at index into a Go function. That value must be a Go function, otherwise it returns nil.

https://www.lua.org/manual/5.5/manual.html#lua_tocfunction

func (*State) ToInteger

func (l *State) ToInteger(index int) (int64, bool)

ToInteger converts the Lua value at index into a signed integer. The Lua value must be an integer, a float with an integral value, or a string holding a numeral of either.

If the operation failed, the second return value will be false.

http://www.lua.org/manual/5.5/manual.html#lua_tointegerx

func (*State) ToNumber

func (l *State) ToNumber(index int) (float64, bool)

ToNumber converts the Lua value at index to the Go type for a Lua number (float64). The Lua value must be a number or a string convertible to a number.

If the operation failed, the second return value will be false.

https://www.lua.org/manual/5.5/manual.html#lua_tonumberx

func (*State) ToPointer

func (l *State) ToPointer(index int) uintptr

ToPointer returns the address of the value at index if it is a table, function, userdata, thread or string, and 0 for other values. Different objects give different addresses; it is for debug information and hashing, as string.format's %p uses it.

http://www.lua.org/manual/5.5/manual.html#lua_topointer

func (*State) ToString

func (l *State) ToString(index int) (s string, ok bool)

ToString converts the Lua value at index to a Go string. The Lua value must also be a string or a number; otherwise the function returns false for its second return value.

https://www.lua.org/manual/5.5/manual.html#lua_tolstring

func (*State) ToStringMeta

func (l *State) ToStringMeta(index int) (string, bool)

ToStringMeta converts any Lua value at the given index to a Go string in a reasonable format. The resulting string is pushed onto the stack and also returned by the function.

If the value has a metatable with a "__tostring" field, then ToStringMeta calls the corresponding metamethod with the value as argument, and uses the result of the call as its result.

func (*State) ToThread

func (l *State) ToThread(index int) *State

ToThread converts the value at index to a Lua thread (a State). This value must be a thread, otherwise the return value will be nil.

https://www.lua.org/manual/5.5/manual.html#lua_tothread

func (*State) ToUserData

func (l *State) ToUserData(index int) any

ToUserData returns the Go value held by the userdata at index. Otherwise, it returns nil.

https://www.lua.org/manual/5.5/manual.html#lua_touserdata

func (*State) ToValue

func (l *State) ToValue(index int) any

ToValue converts the value at index into a Go value of type any. The value can be a table, a thread, a function, a Go string, bool or float64, the Go value held by a userdata, or the Go value pushed as light userdata. Otherwise, the function returns nil.

Different objects will give different values. There is no way to convert the value back into its original value.

Typically, this function is used only for debug information.

https://www.lua.org/manual/5.5/manual.html#lua_topointer

func (*State) Top

func (l *State) Top() int

Top returns the index of the top element in the stack. Because Lua indices start at 1, this result is equal to the number of elements in the stack (hence 0 means an empty stack).

https://www.lua.org/manual/5.5/manual.html#lua_gettop

func (*State) Traceback

func (l *State) Traceback(l1 *State, message string, level int)

Traceback creates and pushes a traceback of the stack l1. If message is not nil it is appended at the beginning of the traceback. The level parameter tells at which level to start the traceback.

Past 21 levels it shows the first 10 and the last 11, as Lua 5.5 does.

func (*State) TypeName

func (l *State) TypeName(index int) string

func (*State) TypeOf

func (l *State) TypeOf(index int) Type

TypeOf returns the type of the value at index, or TypeNone for a non-valid (but acceptable) index.

https://www.lua.org/manual/5.5/manual.html#lua_type

func (*State) UpValue

func (l *State) UpValue(function, index int) (name string, ok bool)

UpValue returns the name of the upvalue at index away from function, where index cannot be greater than the number of upvalues.

Returns an empty string and false if the index is greater than the number of upvalues.

func (*State) UpValueID

func (l *State) UpValueID(f, n int) any

UpValueID returns a unique identifier for the upvalue numbered n from the closure at index f. Parameters f and n are as in UpValue (but n cannot be greater than the number of upvalues). It returns nil for an invalid n.

These unique identifiers allow a program to check whether different closures share upvalues. Lua closures that share an upvalue (that is, that access a same external local variable) will return identical ids for those upvalue indices.

func (*State) UpValueJoin

func (l *State) UpValueJoin(f1, n1, f2, n2 int)

UpValueJoin makes the n1-th upvalue of the Lua closure at index f1 refer to the n2-th upvalue of the Lua closure at index f2.

func (*State) UserData

func (l *State) UserData[T any](index int) (T, bool)

UserData returns the Go value held by the userdata at index as a T. It reports false when the value is not a userdata or does not hold a T.

func (*State) UserValue

func (l *State) UserValue(index, n int) Type

UserValue pushes user value n of the full userdata at index and returns its type, or pushes nil and returns TypeNone if the userdata has no such value.

http://www.lua.org/manual/5.5/manual.html#lua_getiuservalue

func (*State) Warning

func (l *State) Warning(message string, toBeContinued bool)

Warning emits a warning, or a piece of one when toBeContinued is set.

https://www.lua.org/manual/5.5/manual.html#lua_warning

func (*State) Where

func (l *State) Where(level int)

Where pushes onto the stack a string identifying the current position of the control at level in the call stack. Typically this string has the following format:

chunkname:currentline:

Level 0 is the running function, level 1 is the function that called the running function, etc.

This function is used to build a prefix for error messages.

func (*State) XMove

func (l *State) XMove(to *State, n int)

XMove pops n values from l's stack and pushes them onto to's. Moving within one state leaves the stack as it is.

https://www.lua.org/manual/5.5/manual.html#lua_xmove

func (*State) Yield

func (l *State) Yield(resultCount int) int

Yield yields the coroutine running l, which must not be the main thread, with resultCount values from the top of the stack, which its Resume returns. A Go function yields with

return l.Yield(n)

Yield does not return, except inside a hook: see YieldWithContinuation.

https://www.lua.org/manual/5.5/manual.html#lua_yield

func (*State) YieldWithContinuation

func (l *State) YieldWithContinuation(resultCount, context int, continuation Function) int

YieldWithContinuation yields as Yield does. When the coroutine resumes, continuation runs in place of the Go function that yielded, if it is not nil, and its results are that function's; Context returns context there. Without a continuation, the values passed to Resume are the function's results.

A hook may yield without results or a continuation. Yield then returns to the hook, which must return at once; the coroutine resumes at the instruction the hook was called for.

https://www.lua.org/manual/5.5/manual.html#lua_yieldk

type ThreadStatus

type ThreadStatus int

A ThreadStatus is a thread's status, as Status reports it.

const (
	ThreadOK    ThreadStatus = iota // running, not started, or finished
	ThreadYield                     // suspended in a yield
	ThreadError                     // stopped by an error, and dead
)

Valid ThreadStatus values.

type Type

type Type int

A Type is a symbolic representation of a Lua VM type.

const (
	TypeNil Type = iota
	TypeBoolean
	TypeLightUserData
	TypeNumber
	TypeString
	TypeTable
	TypeFunction
	TypeUserData
	TypeThread

	TypeNone = TypeNil - 1
)

Valid Type values.

func (Type) String

func (t Type) String() string

String returns the name of Type t.

https://www.lua.org/manual/5.5/manual.html#lua_typename

type WarnFunction

type WarnFunction func(message string, toBeContinued bool)

A WarnFunction receives warnings, as lua_WarnFunction does: a message comes in pieces, each but the last with toBeContinued set.

https://www.lua.org/manual/5.5/manual.html#lua_WarnFunction

func StderrWarnings

func StderrWarnings(w io.Writer) WarnFunction

StderrWarnings returns lauxlib.c's warning function: off at first, "@on" and "@off" messages turn it on and off, and it writes warnings to w, standard error for NewState's states, each on a line of its own after "Lua warning: ".

Jump to

Keyboard shortcuts

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