Lute Runtime

repository·primary·Indexed 43 days ago

https://github.com/luau-lang/lute

A standalone runtime for general-purpose programming in Luau, designed for file I/O, networking, and tooling development. Lute includes a core C++ runtime, a shared Luau standard library (std), and a collection of standalone libraries called batteries. It also features a programmable linter, lute lint, for static analysis of Luau code.

Tokens
42.2K
Snippets
176
Records
226
Agent score
56%

What's inside Lute

  1. What is Lute?

    primary
    Lute is a standalone runtime for the Luau programming language, designed for general-purpose programming outside of sandboxed environments like game engines. It functions similarly to Node.js or Deno, providing the necessary capabilities for Luau to interact with the host system.
  2. Overview of Lute and its libraries

    primary

    Lute is a standalone runtime for general-purpose programming in Luau. It enables tasks like file manipulation, networking, and developing Luau tooling.

    Lute consists of three primary library sets:

    • lute: Core runtime libraries written in C++ that extend Luau with file I/O, networking, and other general-purpose capabilities.
    • std: A Luau standard library that extends the core C++ libraries. It is embedded in Lute and any Lute-compiled executable, providing a shared interface that can be used across different Luau runtimes (including Roblox).
    • batteries: A collection of standalone Luau libraries that do not depend on lute. These are intended to eventually be published as independent packages.
  3. Lute core features and capabilities

    primary

    Lute provides built-in APIs and tooling for general-purpose development, including:

    • System APIs: File system access, HTTP networking, cryptography, and process management.
    • Tooling: A suite of CLI tools including a test runner, a linter, and the Luau type checker.
    • Roblox Compatibility: Ability to run Luau modules that do not depend on the Roblox game engine.
  4. How Lute APIs are organized

    primary

    Lute provides its capabilities through two distinct layers of libraries accessible via Luau's require function using specific aliases:

    1. Low-level libraries: Exposed under the @lute alias. These provide the core system capabilities.
    2. Standard Library (@std): A higher-level library built on top of the @lute libraries. This is the recommended way to perform common tasks.

    For Roblox developers, Lute aims for compatibility by using the same @std API set, allowing code to run in both Lute and Roblox with minimal changes.

  5. Understand the `constant_table_comparison` lint rule

    primary

    The constant_table_comparison lint rule identifies code that attempts to compare a variable to a table literal (e.g., if x == {} then).

    In Luau, tables are compared by reference, not by value. Comparing a variable to a new table literal will always evaluate to false because the literal creates a new, unique table in memory that the variable cannot possibly reference.

    To check if a table is empty, use the next() function instead of comparing to {}.

    -- Violation:
    if x == {} then
        ...
    end
    
    -- Correct approach:
    if next(x) == nil then
        ...
    end
  6. Use the Lute Standard Library (@std)

    primary

    The Lute Standard Library provides a set of high-level, common utilities designed to make Luau useful for general-purpose programming. It is accessible via the reserved alias @std and is categorized into four main areas:

    1. Language Interaction: Parsing Luau, interacting with the compiler, virtual machine, and type checker.
    2. I/O: Interacting with the command line, file system, external processes, and the network.
    3. Platform Abstractions: File system paths, time measurements, and cooperative multitasking.
    4. General Programming Utilities: Table manipulation, string utilities, JSON handling, and testing frameworks.

    To use a module from the standard library, use the require function with the @std/ prefix.

    local _ = require("@std/json")
  7. Understand the difference between @lute and @std libraries

    primary

    Lute provides two distinct sets of libraries:

    1. @std (Standard Library): High-level modules designed for portability. You should prefer these whenever possible, as they are intended to be supported across various Luau runtimes, including Roblox, Lute, and other game engines.

    2. @lute (Runtime Builtins): Low-level, native APIs that provide foundational capabilities like file system access, network access, and access to Luau internals. These are built directly into the Lute runtime.

    Warning: Using @lute libraries will make your code less portable. Code relying on @lute will not function in Roblox or other Luau environments that do not implement these specific native builtins.

  8. Understand the reassigned_parameter lint rule

    primary

    The reassigned_parameter lint rule detects instances where a function parameter is reassigned within the function body. Reassigning parameters is discouraged because it can cause hard-to-spot bugs in downstream code that expects the parameter to maintain its original value.

    local function _(x)
    	x = 2
    	x += 3
    end
  9. Handle command line arguments in Luau

    primary

    In Lute/Luau, command line arguments can be captured at the top of a script using the variadic unpack syntax .... This unpacks the arguments into an array.

    Important: The first element in the resulting array (args[1]) is always the name of the script itself. Subsequent arguments follow from args[2] onwards.

    local args = { ... }
    -- args[1] is the script name
    -- args[2] is the first actual argument
  10. Understand the `no_any` lint rule

    primary

    The no_any lint rule identifies explicit uses of the any type annotation in Luau code. Using any is discouraged because it disables type checking for the associated values, potentially masking bugs and allowing unsafe operations.

    To maintain type safety, follow these patterns:

    1. Use unknown instead of any: The unknown type is type-safe and requires you to perform type narrowing (e.g., using typeof checks) before performing operations on the value.
    2. Use unsound casts for escape hatches: If you must assume a specific type, use the type assertion syntax (value :: T) to narrow the type and explicitly document the assumed runtime contract.
    -- Violation
    local x: any = getValue()
    
    -- Recommended
    local x: unknown = getValue()
    assert(typeof(x) == "table")
    local field = (x :: { field: unknown }).field
  11. Configure and use breakpoints in Lute

    primary

    Breakpoints are identified by a unique ID and a specific line in a source file. They can be set while the Target is paused or before the program launches.

    Breakpoint Types

    • Standard Breakpoints: Trigger the debugbreak callback, stopping execution and scheduling user event coroutines.
    • Conditional Breakpoints: Use Target::evaluateExpression to check if an expression is truthy before stopping.
    • Hit Conditional Breakpoints: Similar to conditional breakpoints, but allow conditions based on the number of times the line has been executed (a "hit").
    • Logpoints: Do not stop execution. Instead, they log a message via onLogpoint. Messages support interpolation of expressions using {} syntax.

    Important Constraints

    • Installation: Breakpoint changes (add/delete) are not reflected in the debuggee until the Target is next paused. This is because modifying breakpoints requires changing Luau bytecode, which is unsafe while running.
    • Scope: Expressions used in conditional breakpoints only evaluate within the variables available at the current stack frame (not parent frames).
    • Availability: Breakpoints are installed via lua_breakpoint once a source becomes available (either the starting file or a file loaded via require).
  12. Use the `lute/debugger` library for programmatic debugging

    primary

    The lute/debugger library allows you to write Luau scripts that can debug other Luau scripts. This is useful for building custom debugging tools or automated testing environments.

    Core Workflow:

    1. Initialize: Construct a Target object using newTarget.
    2. Configure: Before launching the debuggee, use methods like setBreakpoint and removeBreakpoint. You can also configure callbacks such as onBreakpointHit to react to specific events.
    3. Control Execution: Once the code is paused, you can inspect state or move through the code.
    4. Resume: Always call continueProcess to restart the execution of the debuggee after pausing.

    Common Operations when Paused:

    • Thread Inspection: Use getThreads, getMainThread, or getStoppedThread to inspect running coroutines.
    • Stack/Variable Inspection: Use getStackTrace or getVariables to drill into the current state.
    • Expression Evaluation: Use evaluateExpression to evaluate Luau expressions dynamically.
    • Stepping: Use stepOver, stepInto, or stepOut to navigate the code.