Documentation ¶
Overview ¶
DCLua - A light weight Go Lua VM designed for easy embedding.
The compiler generates correct code in every case I have tested, but the code quality is sometimes poor. If you want better code quality it is possible to compile scripts with luac and load the binaries...
Currently the compiler does not support constant folding, and some special instructions are not used at all (instead preferring simpler sequences of other instructions). For example TESTSET is never generated, TEST is used in all cases (largely because It would greatly complicate the compiler if I tried to use TESTSET where possible). Expressions use a simple "recursive" code generation style, meaning that it wastes registers like crazy in some (rare) cases.
Most (if not all) of the API functions may cause a panic, but only if things go REALLY wrong. If a function does not state that it can panic or "raise an error" it will only do so if a critical internal assumption proves to be wrong (AKA there is a bug in the code somewhere). These errors will have a special prefix prepended onto the error message stating that this error indicates an internal VM bug. If you ever see such an error I want to know about it ASAP.
That said, if an API function *can* "raise an error" it can and will panic if something goes wrong. This is not a problem inside a native function (as the VM is prepared for this), but if you need to call these functions outside of code to be run by the VM you may want to use Protect or Recover to properly catch these errors.
The VM itself does not provide any Lua functions, the standard library is provided entirely by external packages. This means that the standard library never does anything that your own code cannot do (there is no "private API" that is used by the standard library).
Anything to do with the OS or file IO is not provided. Such things do not belong in the core libraries of an embedded scripting language (do you really want scripts to be able to read and write random files without restriction?).
Example ¶
package main import ( "fmt" "strings" "github.com/milochristiansen/lua" "github.com/milochristiansen/lua/lmodbase" "github.com/milochristiansen/lua/lmodmath" "github.com/milochristiansen/lua/lmodpackage" "github.com/milochristiansen/lua/lmodstring" "github.com/milochristiansen/lua/lmodtable" ) func main() { l := lua.NewState() // This is the easiest way to load a core module. // For other modules you probably want to use Preload or Require // This sequence is wrapped in a call to Protect to show how that is done, not because you need to. // These particular functions *should* be 100% safe to call unprotected. Protect is generally used // when you need to do something more complicated and panicking is unacceptable. Code inside native // functions does not need to worry about protection, for them it is up to the caller to worry about // it. It is very rare to need to explicitly call Recover or Protect. err := l.Protect(func() { l.Push(lmodbase.Open) l.Call(0, 0) l.Push(lmodpackage.Open) l.Call(0, 0) l.Push(lmodstring.Open) l.Call(0, 0) l.Push(lmodtable.Open) l.Call(0, 0) l.Push(lmodmath.Open) l.Call(0, 0) // The following standard modules are not provided for one reason or another: // coroutine: No coroutine support, and if I add support later it will not follow the same rules as standard Lua. // utf8: Haven't gotten around to it yet... // io: IO support is not something you want in an extension language. // os: Even worse than IO, untrusted scripts should not have access to this stuff. // debug: Also not good to expose to untrusted scripts (although there is some stuff here that should be part of the base functions). // l.Require("example", loader.Function, false) // l.Pop(1) }) if err != nil { fmt.Println(err) return } err = l.LoadText(strings.NewReader(` print("Hello from github.com/milochristiansen/lua!") `), "", 0) if err != nil { fmt.Println(err) return } err = l.PCall(0, 0) if err != nil { fmt.Println(err) } }
Output: Hello from github.com/milochristiansen/lua!
Index ¶
- Constants
- Variables
- type NativeFunction
- type STypeID
- type State
- func (l *State) AbsIndex(i int) int
- func (l *State) Arith(op opCode)
- func (l *State) Call(args, rtns int)
- func (l *State) Compare(i1, i2 int, op opCode) bool
- func (l *State) CompareRaw(i1, i2 int, op opCode) bool
- func (l *State) ConvertNumber(i int)
- func (l *State) ConvertString(i int)
- func (l *State) DebugValue(i int)
- func (l *State) DumpFunction(i int, strip bool) []byte
- func (l *State) Error()
- func (l *State) ForEach(t int, f func() bool)
- func (l *State) ForEachInTable(t int, f func())deprecated
- func (l *State) ForEachRaw(t int, f func() bool)
- func (l *State) GetIter(i int)
- func (l *State) GetMetaField(i int, name string) TypeID
- func (l *State) GetMetaTable(i int) bool
- func (l *State) GetRaw(i int) interface{}
- func (l *State) GetTable(i int) TypeID
- func (l *State) GetTableRaw(i int) TypeID
- func (l *State) Insert(i int)
- func (l *State) IsNil(i int) bool
- func (l *State) Length(i int) int
- func (l *State) LengthRaw(i int) int
- func (l *State) ListFunc(i int)
- func (l *State) LoadBinary(in io.Reader, name string, env int) error
- func (l *State) LoadText(in io.Reader, name string, env int) error
- func (l *State) LoadTextExternal(in io.Reader, name string, env int) error
- func (l *State) NewTable(as, hs int)
- func (l *State) Next(i int)
- func (l *State) OptFloat(i int, d float64) float64
- func (l *State) OptInt(i int, d int64) int64
- func (l *State) OptString(i int, d string) string
- func (l *State) PCall(args, rtns int) (err error)
- func (l *State) Pop(n int)
- func (l *State) Preload(name string, loader NativeFunction)
- func (l *State) Print(msg ...interface{})
- func (l *State) Printf(format string, msg ...interface{})
- func (l *State) Println(msg ...interface{})
- func (l *State) Protect(f func()) (err error)
- func (l *State) Push(v interface{})
- func (l *State) PushClosure(f NativeFunction, v ...int)
- func (l *State) PushIndex(i int)
- func (l *State) Recover(onStk int, trace bool) func(*error)
- func (l *State) Require(name string, loader NativeFunction, global bool)
- func (l *State) Set(d, s int)
- func (l *State) SetGlobal(name string)
- func (l *State) SetMetaTable(i int)
- func (l *State) SetTable(i int)
- func (l *State) SetTableFunctions(i int, funcs map[string]NativeFunction)
- func (l *State) SetTableRaw(i int)
- func (l *State) SetUpVal(f, i, v int) bool
- func (l *State) SubTypeOf(i int) STypeID
- func (l *State) Test()
- func (l *State) ToBool(i int) bool
- func (l *State) ToFloat(i int) float64
- func (l *State) ToInt(i int) int64
- func (l *State) ToString(i int) string
- func (l *State) ToUser(i int) interface{}
- func (l *State) TryFloat(i int) (float64, bool)
- func (l *State) TryInt(i int) (int64, bool)
- func (l *State) TypeOf(i int) TypeID
- type TypeID
Examples ¶
Constants ¶
const ( // These exported values are used in calls to Arith OpAdd opCode OpSub OpMul OpMod OpPow OpDiv OpIDiv OpBinAND OpBinOR OpBinXOR OpBinShiftL OpBinShiftR OpUMinus OpBinNot OpEqual OpLessThan OpLessOrEqual )
const ( // If you have more than 1000000 items in a single stack frame you probably should think about refactoring... RegistryIndex = -1000000 - iota GlobalsIndex FirstUpVal // To get a specific upvalue use "FirstUpVal-<upvalue index>" )
Variables ¶
var TableIndexOffset = 1
Set to 0 for zero based table indexing. This is only partly tested!
Functions ¶
This section is empty.
Types ¶
type NativeFunction ¶
NativeFunction is the prototype to which native API functions must conform.
type State ¶
type State struct { // Output should be set to whatever writer you want to use for logging. // This is where the standard script functions like print will write their output. // If nil defaults to os.Stdout. Output io.Writer // Add a native stack trace to errors that have attached stack traces. NativeTrace bool // contains filtered or unexported fields }
State is the central arbitrator of all Lua operations.
func (*State) AbsIndex ¶
AbsIndex converts the given index into an absolute index. Use -1 as the index to get the number of items currently on the stack.
func (*State) Arith ¶
func (l *State) Arith(op opCode)
Arith performs the specified the arithmetic operator with the top two items on the stack (or just the top item for OpUMinus and OpBinNot). The result is pushed onto the stack. See "lua_arith" in the Lua 5.3 Reference Manual.
This may raise an error if they values are not appropriate for the given operator.
func (*State) Call ¶
Call runs a function with the given number of arguments and results. The function must be on the stack just before the first argument. If this raises an error the stack is NOT unwound! Call this only from code that is below a call to PCall unless you want your State to be permanently trashed!
func (*State) Compare ¶
Compare performs the specified the comparison operator with the items at the given stack indexes. See "lua_compare" in the Lua 5.3 Reference Manual.
This may raise an error if they values are not appropriate for the given operator.
func (*State) CompareRaw ¶
CompareRaw is exactly like Compare, but without meta-methods.
func (*State) ConvertNumber ¶
ConvertNumber gets the value at the given index and converts it to a number (preferring int over float) and pushes the result. If this is impossible then it pushes nil instead.
func (*State) ConvertString ¶
ConvertString gets the value at the given index and converts it to a string then pushes the result.
func (*State) DebugValue ¶
DebugValue prints internal information about a script value.
func (*State) DumpFunction ¶
DumpFunction converts the Lua function at the given index to a binary chunk. The returned value may be used with LoadBinary to get a function equivalent to the dumped function (but without the original function's up values).
Currently the "strip" argument does nothing.
This (obviously) only works with Lua functions, trying to dump a native function or a non-function value will raise an error.
func (*State) Error ¶
func (l *State) Error()
Error pops a value off the top of the stack, converts it to a string, and raises it as a (general runtime) error.
func (*State) ForEach ¶
ForEach is a fancy version of ForEachRaw that respects metamethods (to be specific, __pairs).
The given function is called once for every item in the table at t. For each call of the function the value is at -1 and the key at -2. You MUST keep the stack balanced inside the function! Do not pop the key and value off the stack before returning!
The value returned by the iteration function determines if ForEach should return early. Return false to break, return true to continue to the next iteration.
Little to no error checking is done, as this is a simple convenience wrapper around a common sequence of public API functions (may raise errors).
func (*State) ForEachInTable
deprecated
func (*State) ForEachRaw ¶
ForEachRaw is a simple wrapper around GetIter and is provided as a convenience.
The given function is called once for every item in the table at t. For each call of the function the value is at -1 and the key at -2. You MUST keep the stack balanced inside the function! Do not pop the key and value off the stack before returning!
The value returned by the iteration function determines if ForEach should return early. Return false to break, return true to continue to the next iteration.
Little to no error checking is done, as this is a simple convenience wrapper around a common sequence of public API functions (may raise errors).
func (*State) GetIter ¶
GetIter pushes a table iterator onto the stack.
This value is type "userdata" and has a "__call" meta method. Calling the iterator will push the next key/value pair onto the stack. The key is not required for the next iteration, so unlike Next you must pop both values.
The end of iteration is signaled by returning a single nil value.
If the given value is not a table this will raise an error.
func (*State) GetMetaField ¶
GetMetaField pushes the meta method with the given name for the item at the given index onto the stack, then returns the type of the pushed item. If the item does not have a meta table or does not have the specified method this does nothing and returns TypNil
func (*State) GetMetaTable ¶
GetMetaTable gets the meta table for the value at the given index and pushes it onto the stack. If the value does not have a meta table then this returns false and pushes nothing.
func (*State) GetRaw ¶
GetRaw gets the raw data for a Lua value. Lua types use the following mapping:
nil -> nil number -> int64 or float64 string -> string bool -> bool table -> string: "table <pointer as hexadecimal>" function -> string: "function <pointer as hexadecimal>" userdata -> The raw user data value
func (*State) GetTable ¶
GetTable reads from the table at the given index, popping the key from the stack and pushing the result. The type of the pushed object is returned. This may raise an error if the value is not a table or is lacking the __index meta method.
func (*State) GetTableRaw ¶
GetTableRaw is like GetTable except it ignores meta methods. This may raise an error if the value is not a table.
func (*State) Insert ¶
Insert takes the item from the TOS and inserts it at the given stack index. Existing items are shifted up as needed, this means that when called with a relative index the item does not end up at the given index, but just *under* that index.
func (*State) IsNil ¶
IsNil check if the value at the given index is nil. Nonexistent values are always nil. Negative indexes are relative to TOS, positive indexes are absolute.
func (*State) Length ¶
Returns the "length" of the item at the given index, exactly like the "#" operator would. If this calls a meta method it may raise an error if the length is not an integer.
func (*State) LengthRaw ¶
Returns the length of the table or string at the given index. This does not call meta methods. If the value is not a table or string this will raise an error.
func (*State) ListFunc ¶
ListFunc prints an assembly listing of the given function's code.
If the value is not a script function this will raise an error.
func (*State) LoadBinary ¶
LoadBinary loads a binary chunk into memory and pushes the result onto the stack. If there is an error it is returned and nothing is pushed. Set env to 0 to use the default environment.
func (*State) LoadText ¶
LoadText loads a text chunk into memory and pushes the result onto the stack. If there is an error it is returned and nothing is pushed. Set env to 0 to use the default environment.
This version uses my own compiler. This compiler does not produce code identical to the standard Lua compiler for all syntax constructs, sometimes it is a little worse, rarely a little better.
func (*State) LoadTextExternal ¶
LoadTextExternal loads a text chunk into memory and pushes the result onto the stack. If there is an error it is returned and nothing is pushed. Set env to 0 to use the default environment.
This version looks for and runs "luac" to compile the chunk. Make sure luac is on your path.
This function is not safe for concurrent use.
func (*State) NewTable ¶
NewTable creates a new table with "as" preallocated array elements and "hs" preallocated hash elements.
func (*State) Next ¶
Next is a basic table iterator.
Pass in the index of a table, Next will pop a key from the stack and push the next key and it's value. This function is not reentrant! Iteration order changes with each iteration, so trying to do two separate iterations of a single table at the same time will result in all kinds of weirdness. If you use this iterator in production code you need your head examined, it is here strictly to power the standard library function `next` (which you also should not use).
If the given value is not a table this will raise an error.
See GetIter.
func (*State) OptFloat ¶
OptFloat is the same as ToFloat, except the given default is returned if the value is nil or non-existent.
func (*State) OptInt ¶
OptInt is the same as ToInt, except the given default is returned if the value is nil or non-existent.
func (*State) OptString ¶
OptString is the same as ToString, except the given default is returned if the value is nil or non-existent.
func (*State) PCall ¶
PCall is exactly like Call, except instead of panicking when it encounters an error the error is cleanly recovered and returned.
On error the stack is reset to the way it was before the call minus the function and it's arguments, the State may then be reused.
func (*State) Preload ¶
func (l *State) Preload(name string, loader NativeFunction)
Preload adds the given loader function to "package.preload" for use with "require".
func (*State) Print ¶
func (l *State) Print(msg ...interface{})
Print writes to the designated output writer (see fmt.Print).
func (*State) Println ¶
func (l *State) Println(msg ...interface{})
Println writes to the designated output writer (see fmt.Println).
func (*State) Protect ¶
Protect calls f inside an error handler. Use when you need to use API functions that may "raise errors" outside of other error handlers (such as PCall).
Protect does the same cleanup PCall does, so it is safe to run code with Call inside a Protected function.
func (*State) Push ¶
func (l *State) Push(v interface{})
Push pushes the given value onto the stack. If the value is not one of nil, float32, float64, int, int32, int64, string, bool, or NativeFunction it is converted to a userdata value before being pushed.
func (*State) PushClosure ¶
func (l *State) PushClosure(f NativeFunction, v ...int)
PushClosure pushes a native function as a closure. All native functions always have at least a single upval, _ENV, but this allows you to set more of them if you wish.
func (*State) Recover ¶
Recover is a simple error handler. Use when you need to use API functions that may "raise errors" outside of other error handlers (such as PCall).
Usage of recover is a little hard to explain, so here is a quick example call:
defer l.Recover(0, false)(&err)
Recover is split into two parts so that it can gather stack data before you potentially mess it up (that way it knows how far to go when unwinding). You should not call Recover before you need it, as if there is an error everything that was added to the stack after it is called will be dropped.
onStk is the number of existing items on the stack that you want to have cleaned if there is an error. 99% of the time you will want to set this to 0! Only set to something other than 0 if your are absolutely sure you know what you are doing!
If trace is false generated errors will not have attached stack traces (which is generally what you want when working with native code).
Recover is the error handler and cleanup function powering PCall and Protect. Those functions simply wrap this one for easier use.
func (*State) Require ¶
func (l *State) Require(name string, loader NativeFunction, global bool)
Require calls the given loader (with name as an argument) if there is no entry for "name" in package.loaded. The result from the call is stored in package.loaded, and if global is true, in a global variable named "name". In any case the module value is pushed onto the stack.
It is possible (albeit, unlikely) that this will raise an error. AFAIK the only way for this to happen is if the loader function errors out.
func (*State) Set ¶
Set sets the value at index d to the value at index s (d = s). Trying to set the registry or an invalid index will do nothing. Setting an absolute index will never fail, the stack will be extended as needed. Be careful not to waste stack space or you could run out of memory! This function is mostly for setting up-values and things like that.
func (*State) SetGlobal ¶
SetGlobal pops a value from the stack and sets it as the new value of global name.
func (*State) SetMetaTable ¶
SetMetaTable pops a table from the stack and sets it as the meta table of the value at the given index. If the value is not a userdata or table then the meta table is set for ALL values of that type!
If you try to set a metatable that is not a table or try to pass an invalid type this will raise an error.
func (*State) SetTable ¶
SetTable writes to the table at the given index, popping the key and value from the stack. This may raise an error if the value is not a table or is lacking the __newindex meta method. The value must be on TOS, the key TOS-1.
func (*State) SetTableFunctions ¶
func (l *State) SetTableFunctions(i int, funcs map[string]NativeFunction)
SetTableFunctions does a raw set for each function in the provided map, using it's map key as the table key. This a simply a loop around calls to SetTableRaw, provided for convenience.
func (*State) SetTableRaw ¶
SetTableRaw is like SetTable except it ignores meta methods. This may raise an error if the value is not a table.
func (*State) SetUpVal ¶
SetUpVal sets upvalue "i" in the function at "f" to the value at "v". If the upvalue index is out of range, "f" is not a function, or the upvalue is not closed, false is returned and nothing is done, else returns true and sets the upvalue.
Any other functions that share this upvalue will also be affected!
func (*State) SubTypeOf ¶
SubTypeOf returns the sub-type of the value at the given index. Negative indexes are relative to TOS, positive indexes are absolute.
func (*State) Test ¶
func (l *State) Test()
Test prints some stack information for sanity checking during test runs.
func (*State) ToBool ¶
ToBool reads a value from the stack at the given index and interprets it as a boolean. Negative indexes are relative to TOS, positive indexes are absolute.
func (*State) ToFloat ¶
ToFloat reads a floating point value from the stack at the given index. Negative indexes are relative to TOS, positive indexes are absolute. If the value is not an float and cannot be converted to one this may panic.
func (*State) ToInt ¶
ToInt reads an integer value from the stack at the given index. Negative indexes are relative to TOS, positive indexes are absolute. If the value is not an integer and cannot be converted to one this may panic.
func (*State) ToString ¶
ToString reads a value from the stack at the given index and formats it as a string. Negative indexes are relative to TOS, positive indexes are absolute. This will call a __tostring metamethod if provided.
This is safe if no metamethods are called, but may panic if the metamethod errors out.
func (*State) ToUser ¶
ToUser reads an userdata value from the stack at the given index. Negative indexes are relative to TOS, positive indexes are absolute. If the value is not an userdata value this may panic.
func (*State) TryFloat ¶
TryFloat attempts to read the value at the given index as a floating point number. Negative indexes are relative to TOS, positive indexes are absolute.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Generic meta-table types and helpers.
|
Generic meta-table types and helpers. |
Helper functions for running scripts snippets in tests.
|
Helper functions for running scripts snippets in tests. |