### Creating and Using a Lua Script Module Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/modules.md This example demonstrates how to create a Lua script that returns a module table, wrap it in a ScriptModule, inject it into another script using `require`, and then execute the main script. Ensure the module script returns a table of functions. ```go moduleScript, err := lua.FromString("module.lua", " local demo_mod = {} function demo_mod.Add(a, b) return a + b end function demo_mod.Mult(a, b) return a * b end return demo_mod ") if err != nil { log.Fatal(err) } module := &lua.ScriptModule{ Script: moduleScript, Name: "demo", Version: "1.0.0", } main, err := lua.FromString("main.lua", " local demo = require(\"demo\") function main() return demo.Mult(5, 5) end ", module) if err != nil { log.Fatal(err) } result, err := main.Run(context.Background()) println(result.String()) // Output: 25 ``` -------------------------------- ### Complete JSON Encoding and Decoding Example in Go Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/json-module.md Demonstrates how to run a Lua script from Go that encodes input data to JSON, decodes it back, creates a JSON array, and returns the results. Requires the 'json' module to be available in the Lua environment. ```go package main import ( "context" "log" "github.com/kelindar/lua" ) func main() { s, err := lua.FromString("json_demo", ` function main(data) local json = require("json") -- Convert input to JSON and back local encoded = json.encode(data) local decoded = json.decode(encoded) -- Create array and encode local arr = json.array("a", "b", "c") local arr_json = json.encode(arr) -- Return both return { original = encoded, decoded_back = decoded, array = arr_json } end `) if err != nil { log.Fatal(err) } // Pass data to script input := map[string]any{ "name": "Alice", "active": true, "scores": []int{100, 95, 87}, } result, err := s.Run(context.Background(), input) if err != nil { log.Fatal(err) } // Process result if result.Type() == lua.TypeTable { tbl := result.(lua.Table) println("Original:", tbl["original"].(lua.String)) println("Array JSON:", tbl["array"].(lua.String)) } } ``` -------------------------------- ### Go: Accessing and Converting Lua Table Data Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Example demonstrating how to run Lua code, check if the result is a table, access fields by key, and convert the table to a native Go map. ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeTable { tbl := result.(lua.Table) // Access fields if nameVal, ok := tbl["name"]; ok { name := nameVal.(lua.String) println(name) } // Convert to native map nativeMap := result.Native().(map[string]any) for k, v := range nativeMap { println(k, v) } } ``` -------------------------------- ### Example Usage of String Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Demonstrates how to retrieve and use a String value from a Lua script execution. It shows checking the type and casting to string. ```go result, _ := s.Run(context.Background(), "world") if result.Type() == lua.TypeString { s := result.(lua.String) println(string(s)) // Output: world } ``` -------------------------------- ### Example Usage of String Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Illustrates creating a Lua String and converting it to a native Go string using the Native() method and a type assertion. ```go s := lua.String("hello") native := s.Native().(string) ``` -------------------------------- ### Example Usage of Bool Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Demonstrates how to retrieve and use a Bool value from a Lua script execution. It shows checking the type and casting to bool. ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeBool { b := result.(lua.Bool) if b { println("Result is true") } } ``` -------------------------------- ### Example Usage of Number Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Demonstrates creating a Lua Number and converting it to a native Go float64 using the Native() method and a type assertion. ```go n := lua.Number(42.5) native := n.Native().(float64) ``` -------------------------------- ### Lua Script with Main Function Source: https://github.com/kelindar/lua/blob/master/_autodocs/errors.md An example of a Lua script that correctly defines a `main()` function, which is required for the script to be considered valid by the library. ```lua function main(arg1, arg2) -- script logic here return result end ``` -------------------------------- ### Example Usage of Bool Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Shows how to create a Lua Bool value and convert it to a native Go boolean using the Native() method and a type assertion. ```go b := lua.Bool(true) native := b.Native().(bool) ``` -------------------------------- ### Example Usage of Bools Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Shows how to create a Lua Bools array and convert it to a native Go slice of booleans using the Native() method and a type assertion. ```go arr := lua.Bools{true, false, true} native := arr.Native().([]bool) ``` -------------------------------- ### Example Usage of Number Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Demonstrates how to retrieve and use a Number value from a Lua script execution. It shows checking the type and casting to float64. ```go result, _ := s.Run(context.Background(), 10) if result.Type() == lua.TypeNumber { n := result.(lua.Number) println(float64(n)) // Output: 10 } // Or use Native() val := result.Native().(float64) println(val) ``` -------------------------------- ### Go: Iterating and Type-Checking Lua Array Elements Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Example showing how to run Lua code, verify the result is an array, and iterate through its elements, checking the type of each element (Number or String) before casting and printing. ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeArray { arr := result.(lua.Array) for i, elem := range arr { switch elem.Type() { case lua.TypeNumber: n := elem.(lua.Number) println(i, "number:", n) case lua.TypeString: s := elem.(lua.String) println(i, "string:", s) } } } ``` -------------------------------- ### Example Usage of Nil Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Demonstrates how to use the Nil type and its String() and Type() methods. The Nil type represents the absence of a value in Lua. ```go var none lua.Nil println(none.String()) // Output: (nil) println(none.Type()) // Output: TypeNil ``` -------------------------------- ### Valid Function Return Signatures for Native Modules Source: https://github.com/kelindar/lua/blob/master/_autodocs/errors.md Provides examples of correct function return signatures for native Lua modules in Go, adhering to the patterns of returning either an error or a Value and an error. ```go // WRONG - returns int instead of Value func badFunc() (int, error) { return 0, nil } // RIGHT - returns only error func funcNoReturn() error { return nil } // RIGHT - returns Value and error func funcWithReturn() (lua.Number, error) { return 0, nil } // RIGHT - returns any Value type func funcReturnsString() (lua.String, error) { return "result", nil } ``` -------------------------------- ### Checking for Nil Value Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Example of how to check if a script execution result is of type Nil. This is typically done after calling Script.Run(). ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeNil { println("Script returned nil") } ``` -------------------------------- ### Get Script Name Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Retrieves the name assigned to the Lua script during its creation. ```go s, _ := lua.FromString("my_script", "function main() return 1 end") println(s.Name()) // Output: my_script ``` -------------------------------- ### Get Script Concurrency Level Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Returns the number of concurrent virtual machines configured for the script's pool. ```go s, _ := lua.New("test", reader, 8) println(s.Concurrency()) // Output: 8 ``` -------------------------------- ### VM Initialization Steps Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Outlines the sequence of operations for initializing a Lua virtual machine (LState), including loading modules and executing the script. ```text 1. Create new LState with custom options 2. Create function from compiled proto 3. Push function to stack 4. Load modules (preload JSON, inject custom modules) 5. PCall the function to execute script body 6. Locate and cache the global main() function 7. Return initialized VM ``` -------------------------------- ### VM Pool Acquire and Release Methods Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Demonstrates how to acquire a VM from the pool, blocking if none are available, and how to release a VM back to the pool, discarding it if the pool is full. This ensures controlled concurrency. ```Go type pool chan *vm func (p pool) Acquire() *vm { return <-p // Block until VM available } func (p pool) Release(vm *vm) { select { case p <- vm: // Return to pool default: // If pool full, discard // VM is discarded; will be recreated on next pool refresh } } ``` -------------------------------- ### Bools Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Represents an array of booleans. Provides methods to get its type, string representation, and native Go slice. ```APIDOC ## Type: Bools ### Description Represents an array of booleans. ### Methods - **Type()** - Returns `TypeBools`. Example: `Bools{true, false}.Type()` - **String()** - Returns a string representation in Go slice syntax. Example: `"[true false]"` - **Native()** - Returns the slice as-is, type `[]bool`. ### Example Usage ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeBools { bools := result.(lua.Bools) for _, b := range bools { println(b) } } ``` ``` -------------------------------- ### Strings Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Represents an array of strings. Provides methods to get its type, string representation, and native Go slice. ```APIDOC ## Type: Strings ### Description Represents an array of strings. ### Methods - **Type()** - Returns `TypeStrings`. Example: `Strings{"a", "b"}.Type()` - **String()** - Returns a string representation in Go slice syntax. Example: `"[a b]"` - **Native()** - Returns the slice as-is, type `[]string`. ### Example Usage ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeStrings { strs := result.(lua.Strings) for _, s := range strs { println(s) } } ``` ``` -------------------------------- ### Script.Run() Execution Flow Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Illustrates the step-by-step process when a client calls Script.Run(), including acquiring a VM, executing Lua code, and returning results. ```text ┌─ Client calls Script.Run(ctx, arg1, arg2) │ ├─ Script.lock.RLock() (acquire read lock) │ ├─ vm := pool.Acquire() (get VM from pool, blocks if empty) │ ├─ lvalue(arg1), lvalue(arg2) (convert Go values to Lua) │ ├─ vm.exec.Push(vm.main) (push function) ├─ vm.exec.Push(lvalues...) (push arguments) ├─ vm.exec.PCall(2, 1, nil) (call main(2 args) → 1 result) │ ├─ result := vm.exec.Get(-1) (get return value from stack) │ ├─ resultOf(result) (convert Lua value to Value) │ ├─ vm.exec.Pop(1) (clean stack) │ ├─ pool.Release(vm) (return VM to pool) │ ├─ Script.lock.RUnlock() (release read lock) │ └─ return Value, error ``` -------------------------------- ### Lua Compilation Process Overview Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Illustrates the steps involved in compiling Lua source code into an Abstract Syntax Tree (AST) and then into bytecode using gopher-lua. ```text Script source code (string or io.Reader) │ ├─ bufio.NewReader() ├─ parse.Parse() (gopher-lua parser) │ └─ Produces *lua.Chunk (AST) │ ├─ lua.Compile() (gopher-lua compiler) │ └─ Produces *lua.FunctionProto (bytecode) │ └─ Store in Script.code for reuse ``` -------------------------------- ### Numbers Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Represents an array of floating-point numbers. Provides methods to get its type, string representation, and native Go slice. ```APIDOC ## Type: Numbers ### Description Represents an array of floating-point numbers. ### Methods - **Type()** - Returns `TypeNumbers`. Example: `Numbers{1, 2, 3}.Type()` - **String()** - Returns a string representation in Go slice syntax. Example: `"[1 2 3]"` - **Native()** - Returns the slice as-is, type `[]float64`. ### Example Usage ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeNumbers { nums := result.(lua.Numbers) for i, n := range nums { println(i, n) } } // Or use Native() slice := result.Native().([]float64) ``` ``` -------------------------------- ### Number Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Represents a 64-bit floating-point number. Provides methods to get its type, string representation, and native float64 value. ```APIDOC ## Type: Number Represents a 64-bit floating-point number. ```go type Number float64 ``` | Method | Returns | Example | |--------|---------|---------| | Type() | `TypeNumber` | `Number(42).Type()` | | String() | String representation | `Number(3.14).String()` → `"3.14"` | | Native() | `float64` | `Number(42).Native()` → `float64(42)` | **Example:** ```go result, _ := s.Run(context.Background(), 10) if result.Type() == lua.TypeNumber { n := result.(lua.Number) println(float64(n)) // Output: 10 } // Or use Native() val := result.Native().(float64) println(val) ``` **Source:** `value.go:99-120` ``` -------------------------------- ### Run Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Executes the `main()` function of the script with the provided arguments. This method is thread-safe and acquires a VM from the pool, executes the script, and releases the VM back. ```APIDOC ## Run ### Description Executes the `main()` function of the script with the provided arguments. This method is thread-safe and acquires a VM from the pool, executes the script, and releases the VM back. ### Method Go Function Signature ### Parameters #### Path Parameters - **ctx** (context.Context) - Required - Context for controlling execution and cancellation #### Query Parameters - **args** (...any) - Optional - Variadic arguments passed to the `main()` function ### Returns - **Value** - The return value from the Lua `main()` function. - **error** - An error if execution fails. ### Errors - `errInvalidScript` if the script has no `main()` function - Lua runtime errors (type mismatches, invalid operations, etc.) - Context cancellation errors if `ctx.Done()` is triggered ### Request Example ```go // Simple scalar arguments result, err := s.Run(context.Background(), 42, "hello") if err != nil { log.Fatal(err) } println(result.String()) // Complex data types input := &MyStruct{Name: "Alice"} result, _ := s.Run(context.Background(), input) // The Lua script can modify input as a side-effect println(input.Name) ``` ``` -------------------------------- ### Bool Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Represents a boolean value. Includes methods for getting the type, string representation ('true' or 'false'), and the native bool value. ```APIDOC ## Type: Bool Represents a boolean value. ```go type Bool bool ``` | Method | Returns | Example | |--------|---------|---------| | Type() | `TypeBool` | `Bool(true).Type()` | | String() | `"true"` or `"false"` | `Bool(true).String()` | | Native() | `bool` | `Bool(true).Native()` → `bool(true)` | **Example:** ```go result, _ := s.Run(context.Background()) if result.Type() == lua.TypeBool { b := result.(lua.Bool) if b { println("Result is true") } } ``` **Source:** `value.go:235-256` ``` -------------------------------- ### Load and Run Lua Script Source: https://github.com/kelindar/lua/blob/master/_autodocs/README.md Demonstrates how to load a Lua script from a string and execute it with arguments. The script calculates the nth Fibonacci number. Ensure the script has a 'main' function for execution. ```go // Load a script s, _ := lua.FromString("fib", ` function main(n) if n < 2 then return 1 end return main(n - 2) + main(n - 1) end `) // Run it with arguments result, _ := s.Run(context.Background(), 10) println(result.String()) // Output: 89 ``` -------------------------------- ### Create Script with New Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Creates a new script from an io.Reader source with a specified number of concurrent VMs. Use this when you need fine-grained control over concurrency. ```Go s, err := lua.New("fibonacci", bytes.NewBufferString(` function main(n) if n < 2 then return 1 end return main(n - 2) + main(n - 1) end `), 4) if err != nil { log.Fatal(err) } deffer s.Close() result, err := s.Run(context.Background(), 10) println(result.String()) // Output: 89 ``` -------------------------------- ### Lua VM Options Configuration Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Configure the initial size, maximum growth, growth increment, call stack size, and memory minimization for the Lua registry and call stack. ```go lua.Options{ RegistrySize: 1024 * 4, // Initial registry RegistryMaxSize: 1024 * 128, // Max growth RegistryGrowStep: 32, // Growth increment CallStackSize: 64, // Max call depth MinimizeStackMemory: true, // Auto-shrink stack } ``` -------------------------------- ### Run VM Execution Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Executes the main function of the VM with provided arguments. Handles context cancellation and returns the result or an error. ```go (v *vm) Run(ctx context.Context, args []any) (Value, error) ``` -------------------------------- ### Create New VM Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Factory function to create a new VM instance for a given script. Ensure proper initialization before execution. ```go func newVM(s *Script) (*vm, error) ``` -------------------------------- ### Script.New() Source: https://github.com/kelindar/lua/blob/master/_autodocs/SUMMARY.md Creates a new Lua script instance with configurable options. This is the primary method for initializing a script environment. ```APIDOC ## Script.New() ### Description Creates a new Lua script instance with options. ### Method (Not specified, likely a constructor or factory method) ### Endpoint (Not applicable for SDK methods) ### Parameters #### Path Parameters (Not applicable) #### Query Parameters (Not applicable) #### Request Body (Not applicable) ### Request Example (Not applicable) ### Response #### Success Response - **Script** (Script) - A new instance of the Script type. #### Response Example (Not applicable) ``` -------------------------------- ### New Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Creates a new script from an io.Reader source with a specified number of concurrent VMs and optional injected modules. It handles Lua compilation and module injection, returning a Script instance or an error. ```APIDOC ## New ### Description Creates a new script from an `io.Reader` source. ### Method `New` ### Parameters #### Path Parameters - **name** (string) - Required - Name identifier for the script (used in error messages) - **source** (io.Reader) - Required - Reader containing the Lua source code - **concurrency** (int) - Optional - Number of concurrent VMs in the pool. If <= 0, uses the default (min of GOMAXPROCS and NumCPU) - **modules** (...Module) - Optional - Variadic list of modules to inject into the script ### Returns `(*Script, error)` — A new Script instance or an error if compilation fails. ### Errors: - Parse errors if the Lua source is invalid - Module injection errors if a module cannot be loaded ### Example: ```go s, err := lua.New("fibonacci", bytes.NewBufferString(` function main(n) if n < 2 then return 1 end return main(n - 2) + main(n - 1) end `), 4) if err != nil { log.Fatal(err) } defer s.Close() result, err := s.Run(context.Background(), 10) println(result.String()) // Output: 89 ``` ``` -------------------------------- ### Registering Native Lua Modules in Go Source: https://github.com/kelindar/lua/blob/master/_autodocs/errors.md This pattern shows how to register a native Go module with a Lua environment. It includes error handling for the registration process, suggesting to check the error message for specific details on failure. ```go module := &lua.NativeModule{Name: "mylib", Version: "1.0"} if err := module.Register("my_func", myFunc); err != nil { log.Fatal("Failed to register function:", err) // Check error message to understand what went wrong } ``` -------------------------------- ### Value Interface Methods Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md The Value interface provides methods to interact with Lua values returned from script execution. It allows checking the type, getting a string representation, accessing the native Go type, and converting to a gopher-lua value. ```APIDOC ## Value Interface The `Value` interface represents a type-safe wrapper around Lua values returned from script execution. Every value returned by `Script.Run()` implements this interface. ### Methods - **Type()** (`Type()`): Returns the type classification of the value. - **String()** (`String()`): Returns the string representation (implements `fmt.Stringer`). - **Native()** (`Native()`): Returns the value as a native Go type (`any`). - **lvalue()** (`lvalue(*lua.LState)`): Converts to a gopher-lua value (internal use). ### Example Usage ```go // Assuming 'result' is a Value interface returned from s.Run() valueType := result.Type() stringValue := result.String() nativeValue := result.Native() ``` ``` -------------------------------- ### Create New VM Pool Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Initializes a new pool of VMs with a specified concurrency level. This controls the maximum number of scripts that can run simultaneously. ```go func newPool(s *Script, concurrency int) (pool, error) ``` -------------------------------- ### Execute Lua Script from String Source: https://github.com/kelindar/lua/blob/master/_autodocs/README.md Run a simple Lua script defined as a string. The script must export a `main` function that accepts arguments and returns a value. Ensure proper error handling during script loading and execution. ```go s, err := lua.FromString("script_name", "\n function main(arg1, arg2) \n return arg1 + arg2 \n end\n") if err != nil { log.Fatal(err) } result, err := s.Run(context.Background(), 10, 20) if err != nil { log.Fatal(err) } println(result.Native().(float64)) // Output: 30 ``` -------------------------------- ### Lua Benchmark Results Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Shows performance metrics for serial Lua benchmarks, including operations per second and nanoseconds per operation for Fibonacci, empty, and update tasks. ```text Benchmark_Serial/fib-8: 5870025 ops, 203 ns/op Benchmark_Serial/empty-8: 8592448 ops, 137 ns/op Benchmark_Serial/update-8: 1000000 ops, 1069 ns/op ``` -------------------------------- ### Create Script with FromReader Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Convenience function to create a script from an io.Reader using default concurrency. Useful for simple script loading from files or network streams. ```Go s, err := lua.FromReader("my_script", file) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Release VM to Pool Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Returns a VM instance back to the pool after its execution is complete. This makes the VM available for subsequent tasks. ```go (p pool) Release(vm *vm) ``` -------------------------------- ### Handling Script Load and Run Errors in Go Source: https://github.com/kelindar/lua/blob/master/_autodocs/errors.md This pattern demonstrates how to load a Lua script and handle potential errors during loading and execution. It includes specific checks for common Lua error messages like 'script is not in a valid state' and 'function not found'. ```go s, err := lua.FromString("script", code) if err != nil { log.Fatal("Script load failed:", err) } result, err := s.Run(context.Background(), args...) if err != nil { switch { case err.Error() == "lua: script is not in a valid state": log.Fatal("Script missing main() function") case strings.Contains(err.Error(), "function not found"): log.Fatal("Undefined Lua function") default: log.Fatal("Script execution failed:", err) } } if result.Type() == lua.TypeNil { log.Println("Script returned nil") } ``` -------------------------------- ### Script Constructors Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Constructors for creating new Lua scripts. ```APIDOC ## Script Constructors ### `New` Creates a new Lua script. - **name** (string) - The name of the script. - **source** (io.Reader) - The source code reader. - **concurrency** (int) - The concurrency level. - **modules** (...Module) - Optional modules to include. Returns a pointer to the Script and an error if creation fails. ``` ```APIDOC ### `FromReader` Creates a new Lua script from an io.Reader. - **name** (string) - The name of the script. - **r** (io.Reader) - The source code reader. - **modules** (...Module) - Optional modules to include. Returns a pointer to the Script and an error if creation fails. ``` ```APIDOC ### `FromString` Creates a new Lua script from a string. - **name** (string) - The name of the script. - **code** (string) - The source code string. - **modules** (...Module) - Optional modules to include. Returns a pointer to the Script and an error if creation fails. ``` -------------------------------- ### Direct Value Conversions in Go Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Demonstrates direct conversions of basic Go types (integer, string, numeric slice) to Lua values using the ValueOf function. ```go // Direct conversions v1 := lua.ValueOf(42) // Number v2 := lua.ValueOf("hello") // String v3 := lua.ValueOf([]int{1,2}) // Numbers ``` -------------------------------- ### Module System Hierarchy Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Illustrates the Module system hierarchy, showing NativeModule and ScriptModule as implementations. Modules are injectable code components used to register Go or Lua functions. ```go Module (interface) ├─ NativeModule │ └─ register Go functions as Lua functions └─ ScriptModule └─ register Lua code as libraries ``` -------------------------------- ### Concurrent Script Execution Source: https://github.com/kelindar/lua/blob/master/_autodocs/README.md Demonstrates safe concurrent execution of scripts using goroutines. The library manages a pool of VMs for parallel processing. ```go // Safe to call from multiple goroutines go s.Run(ctx, arg1) go s.Run(ctx, arg2) go s.Run(ctx, arg3) // All run concurrently with separate VMs from the pool ``` -------------------------------- ### VM Instance Struct Definition Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Defines the VM instance, which wraps a gopher-lua state. It handles executing the main function, value conversions, and managing the Lua state lifecycle. ```go type vm struct { argn int // Number of main() parameters exec *lua.LState // Gopher-lua runtime main *lua.LFunction // Pre-located main function } ``` -------------------------------- ### Acquire VM from Pool Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Retrieves a VM instance from the pool. This operation will block if the pool is currently empty, waiting for a VM to become available. ```go (p pool) Acquire() *vm ``` -------------------------------- ### Create and Load LUA Script Module Source: https://github.com/kelindar/lua/blob/master/README.md Defines a LUA script that acts as a module, exporting functions. This script module is then loaded into another LUA script using `require`. ```lua local demo_mod = {} -- The main table function demo_mod.Mult(a, b) return a * b end return demo_mod ``` ```go // Create a test module which provides hash function module := &ScriptModule{ Script: moduleCode, Name: "demo_mod", Version: "1.0.0", } // Load the script s, err := FromString("test.lua", " local demo = require("demo_mod") function main(input) return demo.Mult(5, 5) end ", module) // <- attach the module out, err := s.Run(context.Background()) println(out) // Output: 25 ``` -------------------------------- ### Go to Lua Type Conversion Logic Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Details the logic for converting Go values into Lua-compatible types, including handling maps, slices, and default types. ```text Go value │ ├─ Check if already a Value type → use directly ├─ Check if map or slice → convert via ValueOf() └─ Default → wrap with gopher-luar ``` -------------------------------- ### Integrate Go Functions as Native Modules Source: https://github.com/kelindar/lua/blob/master/_autodocs/README.md Expose Go functions to Lua scripts by registering them within a `lua.NativeModule`. The Lua script can then `require` this module and call the exposed Go functions. Ensure the Go function signature matches the expected Lua types. ```go // Define a Go function func hash(s lua.String) (lua.Number, error) { h := fnv.New32a() h.Write([]byte(s)) return lua.Number(h.Sum32()), nil } // Create module module := &lua.NativeModule{Name: "crypto", Version: "1.0"} module.Register("hash", hash) // Use in script s, _ := lua.FromString("test", "\n local crypto = require(\"crypto\")\n function main(text) \n return crypto.hash(text)\n end\n", module) result, _ := s.Run(context.Background(), "password") ``` -------------------------------- ### Valid and Invalid Function Signatures for Native Modules Source: https://github.com/kelindar/lua/blob/master/_autodocs/errors.md Illustrates correct and incorrect function signatures for registering native Lua modules in Go, focusing on supported parameter and return types. ```go // WRONG - uses primitive int func badFunc(x int) error { return nil } // RIGHT - uses lua.Number func goodFunc(x lua.Number) error { return nil } // RIGHT - uses lua.Value interface func flexibleFunc(x lua.Value) error { return nil } ``` -------------------------------- ### Run Lua Script from String with Input Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/conversion.md Executes a Lua script defined as a string, passing a Go map as input and retrieving a table as output. Ensure the Lua script correctly handles the input type and expected fields. ```go package main import ( "context" "log" "github.com/kelindar/lua" ) func main() { s, err := lua.FromString("demo", ` function main(input) -- Input can be a struct, map, or Value return { type = type(input), converted = input.value * 2 } end `) if err != nil { log.Fatal(err) } // Pass a map input := map[string]any{ "value": 21, } result, err := s.Run(context.Background(), input) if err != nil { log.Fatal(err) } // Result is a Table if result.Type() == lua.TypeTable { tbl := result.(lua.Table) converted := tbl["converted"] println(converted.Native().(float64)) // Output: 42 } } ``` -------------------------------- ### Create Script with FromString Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Convenience function to create a script directly from a string of Lua code. Ideal for embedding small scripts or testing. ```Go s, err := lua.FromString("test", "\n function main(x) return x * 2 end ") if err != nil { log.Fatal(err) } result, _ := s.Run(context.Background(), 5) println(result.String()) // Output: 10 ``` -------------------------------- ### Script Methods Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Methods available on a Lua script object. ```APIDOC ## Script Methods ### `Name` Returns the name of the script. Returns a string representing the script's name. ``` ```APIDOC ### `Concurrency` Returns the concurrency level of the script. Returns an integer representing the concurrency level. ``` ```APIDOC ### `Run` Executes the Lua script. - **ctx** (context.Context) - The context for the operation. - **args** (...any) - Arguments to pass to the script. Returns the script's return value and an error if execution fails. ``` ```APIDOC ### `Update` Updates the script with new source code from an io.Reader. - **r** (io.Reader) - The new source code reader. Returns an error if the update fails. ``` ```APIDOC ### `Close` Closes the script and releases any resources. Returns an error if closing fails. ``` -------------------------------- ### Custom Struct Conversion via JSON in Go Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/value.md Illustrates converting custom Go structs to Lua tables by leveraging JSON marshaling through the ValueOf function. ```go // Custom structs (JSON marshaled) type Person struct { Name string Age int } v5 := lua.ValueOf(Person{"Bob", 25}) // Table (via JSON) ``` -------------------------------- ### NativeModule.Register() Source: https://github.com/kelindar/lua/blob/master/_autodocs/SUMMARY.md Registers a Go function as a native module, making it callable from within the Lua environment. ```APIDOC ## NativeModule.Register() ### Description Registers a Go function to be exposed as a native module in Lua. ### Method (Not specified, likely an instance method or static method) ### Endpoint (Not applicable for SDK methods) ### Parameters #### Path Parameters (Not applicable) #### Query Parameters (Not applicable) #### Request Body (Not applicable) ### Request Example (Not applicable) ### Response #### Success Response (No specific return value mentioned, likely void or status) #### Response Example (Not applicable) ``` -------------------------------- ### Define VM Type Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Defines the virtual machine structure, holding runtime state and main function. Used for executing Lua scripts. ```go type vm struct { argn int // Number of main() parameters exec *lua.LState // Gopher-lua runtime main *lua.LFunction // main() function } ``` -------------------------------- ### Script.FromString() Source: https://github.com/kelindar/lua/blob/master/_autodocs/SUMMARY.md Provides a convenient way to create and load a Lua script directly from a string containing Lua code. ```APIDOC ## Script.FromString() ### Description Creates a Lua script from a string of Lua code. ### Method (Not specified, likely a constructor or factory method) ### Endpoint (Not applicable for SDK methods) ### Parameters #### Path Parameters (Not applicable) #### Query Parameters (Not applicable) #### Request Body (Not applicable) ### Request Example (Not applicable) ### Response #### Success Response - **Script** (Script) - A new instance of the Script type initialized with the provided code. #### Response Example (Not applicable) ``` -------------------------------- ### Name Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Returns the name of the script. ```APIDOC ## Name ### Description Returns the name of the script. ### Method Go Function Signature ### Returns - **string** - The script name provided at creation. ### Request Example ```go s, _ := lua.FromString("my_script", "function main() return 1 end") println(s.Name()) // Output: my_script ``` ``` -------------------------------- ### Access Module Version in Lua Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/modules.md Demonstrates how to access the 'version' field of a registered NativeModule within a Lua script. ```lua local mylib = require("mylib") print(mylib.version) -- Output: 1.0.0 ``` -------------------------------- ### Lua to Go Type Conversion Logic Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md Outlines the process of converting Lua return values back into Go types, handling numbers, strings, booleans, tables, and other Lua types. ```text Lua return value │ ├─ lua.LNumber → Number ├─ lua.LString → String ├─ lua.LBool → Bool ├─ lua.LTable (numeric keys) │ │ │ ├─ First element is Number → Numbers │ ├─ First element is String → Strings │ ├─ First element is Bool → Bools │ └─ First element is Table → Array ├─ lua.LTable (string keys) → Table ├─ lua.LUserData → extract value, recurse └─ lua.LNil → Nil ``` -------------------------------- ### Convert Lua Table to Go Map Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Demonstrates converting a Lua Table type to a native Go map of any type using the Native() method. ```go tbl := lua.Table{ "name": lua.String("Alice"), "age": lua.Number(30), } native := tbl.Native().(map[string]any) ``` -------------------------------- ### Go Wrapper for Lua Function Source: https://github.com/kelindar/lua/blob/master/_autodocs/architecture.md This Go code demonstrates a wrapper function that handles argument extraction from the Lua stack, calls an original Go function, manages errors, and pushes the return value back to the Lua stack. It's used when registering Go functions with Lua. ```go return func(state *lua.LState) int { // Get argument from stack position 1 s := lua.String(state.CheckString(1)) // Call Go function v, err := originalFunc(s) // Handle error if err != nil { state.RaiseError(err.Error()) return 0 } // Push return value state.Push(lua.LNumber(v)) return 1 // 1 value returned } ``` -------------------------------- ### Convert Lua Strings to Go Slice Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Demonstrates converting a Lua Strings type to a native Go slice of string using the Native() method. ```go arr := lua.Strings{"a", "b", "c"} native := arr.Native().([]string) ``` -------------------------------- ### Run Lua Script with Arguments Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Executes the main function of a Lua script with scalar or complex arguments. The method is thread-safe and manages VM pooling. ```go result, err := s.Run(context.Background(), 42, "hello") if err != nil { log.Fatal(err) } println(result.String()) ``` ```go input := &MyStruct{Name: "Alice"} result, _ := s.Run(context.Background(), input) // The Lua script can modify input as a side-effect println(input.Name) ``` -------------------------------- ### Run Fibonacci Script in LUA Source: https://github.com/kelindar/lua/blob/master/README.md Loads a LUA script from a string and executes its main function with a numerical argument. The script calculates the nth Fibonacci number. ```go // Load the script s, err := FromString("test.lua", " function main(n) if n < 2 then return 1 end return main(n - 2) + main(n - 1) end ") // Run the main() function with 10 as argument result, err := s.Run(context.Background(), 10) println(result.String()) // Output: 89 ``` -------------------------------- ### Integrate Lua Libraries as Script Modules Source: https://github.com/kelindar/lua/blob/master/_autodocs/README.md Package Lua code as a module that can be `require`d by other Lua scripts. This allows for code organization and reuse. The module script must return a table containing its exported functions. ```go // Define a Lua library libScript, _ := lua.FromString("math_lib", "\n local M = {} function M.square(x) return x * x end function M.cube(x) return x * x * x end return M ") // Wrap as module module := &lua.ScriptModule{ Script: libScript, Name: "math_lib", Version: "1.0", } // Use in another script s, _ := lua.FromString("app", "\n local math = require(\"math_lib\")\n function main(n) \n return math.cube(n) \n end\n", module) result, _ := s.Run(context.Background(), 5) // Returns 125 ``` -------------------------------- ### Implement and Register Native LUA Module Source: https://github.com/kelindar/lua/blob/master/README.md Defines a native Go function that can be called from LUA scripts. The function is registered into a `NativeModule` and then loaded by the LUA script using `require`. ```go func hash(s lua.String) (lua.Number, error) { h := fnv.New32a() h.Write([]byte(s)) return lua.Number(h.Sum32()), nil } ``` ```go // Create a test module which provides hash function module := &NativeModule{ Name: "test", Version: "1.0.0", } module.Register("hash", hash) // Load the script s, err := FromString("test.lua", " local api = require("test") function main(input) return api.hash(input) end ", module) // <- attach the module out, err := s.Run(context.Background(), "abcdef") println(out) // Output: 4282878506 ``` -------------------------------- ### Script Source: https://github.com/kelindar/lua/blob/master/_autodocs/types.md Represents a compiled and executable Lua script with a VM pool. It provides methods to run, update, and manage the script's lifecycle. ```APIDOC ## Script Represents a compiled and executable Lua script with a VM pool. ### Constructors - `New(name, source, concurrency, modules...)` — Create with options - `FromReader(name, reader, modules...)` — Create from io.Reader - `FromString(name, code, modules...)` — Create from string ### Methods - `Run(ctx, args...)` — Execute main function - `Update(reader)` — Replace script code - `Name()` — Get script name - `Concurrency()` — Get pool size - `Close()` — Clean up resources ``` -------------------------------- ### Update Script Code Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/script.md Replaces the existing Lua script code with new code provided via an io.Reader. This operation compiles the new code and initializes a fresh VM pool. ```go s, _ := lua.FromString("test", "function main() return 1 end") // Update to new code newCode := "function main() return 2 end" err := s.Update(bytes.NewBufferString(newCode)) if err != nil { log.Fatal(err) } result, _ := s.Run(context.Background()) println(result.String()) // Output: 2 ``` -------------------------------- ### NativeModule.Register Source: https://github.com/kelindar/lua/blob/master/_autodocs/api-reference/modules.md Registers a Go function into the NativeModule, making it callable from Lua scripts. The function signature must adhere to specific input and return type patterns. ```APIDOC ## NativeModule.Register ### Description Registers a Go function into the module. The function signature must conform to library requirements. ### Method `func (m *NativeModule) Register(name string, function any) error` ### Parameters #### Path Parameters - **name** (string) - Required - Function name as exposed to Lua - **function** (any) - Required - Go function following required signature patterns ### Returns - `error` - An error if the function signature is invalid; nil on success. ### Supported Function Signatures: The function must have: - **Input parameters** (0 or 1): Accept `String`, `Number`, `Bool`, or their array variants (`Strings`, `Numbers`, `Bools`), or any Lua `Value` - **Return values**: Either `error` alone or `(Value, error)` | Pattern | Input Args | Return Type | Notes | |---|---|---|---| | `func() error` | None | Error only | Function with no parameters | | `func() (String, error)` | None | Value + error | Return string value | | `func(String) error` | 1 string | Error only | No return value | | `func(String) (Number, error)` | 1 string | Number + error | Transform string to number | | `func(Number) (String, error)` | 1 number | String + error | Convert number to string | | `func(Bool) (Bool, error)` | 1 bool | Bool + error | Accept and return bool | All input/output type combinations of `{String, Number, Bool}` are supported. ### Errors: - `errFuncInput`: Function has invalid input types - `errFuncOutput`: Function has invalid return types ### Example: ```go // Simple function: no input, returns string func getVersion() (lua.String, error) { return lua.String("1.0.0"), nil } // Function with one input and output func hash(s lua.String) (lua.Number, error) { h := fnv.New32a() h.Write([]byte(s)) return lua.Number(h.Sum32()), nil } // Function with error handling func divide(a lua.Number, b lua.Number) (lua.Number, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil } // Create and populate the module module := &lua.NativeModule{ Name: "mylib", Version: "1.0.0", } module.Register("hash", hash) module.Register("version", getVersion) module.Register("divide", divide) // Use in a script s, _ := lua.FromString("test.lua", ` local lib = require("mylib") function main() return lib.hash("test data") end `, module) result, _ := s.Run(context.Background()) println(result.String()) ``` ``` -------------------------------- ### Default VM Pool Concurrency Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Default size for the VM pool, calculated based on system resources (GOMAXPROCS and NumCPU). Ensures optimal concurrency. ```go var defaultConcurrency int ``` -------------------------------- ### NativeModule Structure Source: https://github.com/kelindar/lua/blob/master/_autodocs/INDEX.md Represents a Lua module implemented in Go. It holds registered Go functions and module metadata. ```go type NativeModule struct { lock sync.Mutex funcs map[string]fngen Name string // Module name for require() Version string // Module version string } ```