TLC API Reference

May 17, 2026 ยท View on GitHub

TLC provides two levels of API access: high-level functions that handle the full pipeline, and low-level functions that let you chain individual stages manually.

High-Level API

These functions take Lua source code as a string and handle everything internally.

tlc.run(code)

Compiles and executes Lua code in one step. Returns whatever the code returns.

local tlc = require("tlc")
tlc.run("print('Hello, World!')")
-- Output: Hello, World!

local result = tlc.run("return 2 + 2")
print(result) -- 4

tlc.compile(code)

Compiles Lua source code to a Lua 5.1 bytecode string. The output is binary-compatible with luac and can be loaded with loadstring or saved to a .luac file.

local bytecode = tlc.compile("print('test')")

-- Save to a file:
local f = io.open("output.luac", "wb")
f:write(bytecode)
f:close()

tlc.compileToProto(code)

Compiles Lua source code to a function prototype table (TLC's internal representation). This is useful if you want to inspect the compiled output or execute it with TLC's VM.

local proto = tlc.compileToProto("return 2 + 2")

-- proto.code:         list of bytecode instructions
-- proto.constants:    constant pool (numbers, strings)
-- proto.maxStackSize: register count needed
-- proto.numParams:    number of parameters
-- proto.numUpvals:    number of upvalues
-- proto.isVararg:     whether the function uses ...
-- proto.protos:       nested function prototypes

tlc.parse(code)

Tokenizes and parses Lua source code, returning an Abstract Syntax Tree (AST). See ast.md for the full node specification.

local ast = tlc.parse("local x = 42")
-- Returns:
-- {
--   kind = "Program",
--   body = {
--     kind = "Block",
--     statements = {
--       {
--         kind = "LocalDeclarationStatement",
--         variables = {"x"},
--         initializers = {{kind = "NumericLiteral", value = 42, raw = "42"}}
--       }
--     }
--   }
-- }

tlc.tokenize(code)

Tokenizes Lua source code and returns a list of token tables. Each token has a kind field, an optional value field, and an optional raw field (for numbers).

local tokens = tlc.tokenize("local x = 42")
-- Returns:
-- {
--   {kind = "Keyword",    value = "local"},
--   {kind = "Identifier", value = "x"},
--   {kind = "Equals"},
--   {kind = "Number",     value = 42, raw = "42"},
--   {kind = "EOF"}
-- }

Token kinds: Keyword, Identifier, Number, String, Operator, Vararg, Dot, Equals, Colon, Semicolon, Comma, LeftParen, RightParen, LeftBrace, RightBrace, LeftBracket, RightBracket, EOF.

Low-Level API

These functions let you run individual pipeline stages. Each takes the output of the previous stage as input.

tlc.parseTokens(tokens)

Parses a list of tokens (from tlc.tokenize) into an AST.

local tokens = tlc.tokenize("x = 1")
local ast    = tlc.parseTokens(tokens)

tlc.generate(ast)

Compiles an AST (from tlc.parse or tlc.parseTokens) into a function prototype.

local ast   = tlc.parse("return 1 + 1")
local proto = tlc.generate(ast)

tlc.emit(proto)

Serializes a function prototype into a Lua 5.1 bytecode string.

local proto    = tlc.compileToProto("print('hi')")
local bytecode = tlc.emit(proto)

tlc.execute(proto)

Executes a function prototype in TLC's virtual machine. Returns whatever the prototype returns.

local proto  = tlc.compileToProto("return 42")
local result = tlc.execute(proto)
print(result) -- 42

Class Constructors

For full control, you can instantiate each pipeline stage directly:

local tlc = require("tlc")

-- Tokenize
local tokenizer = tlc.Tokenizer.new("local x = 1 + 2")
local tokens    = tokenizer:tokenize()

-- Parse
local parser = tlc.Parser.new(tokens)
local ast    = parser:parse()

-- Compile
local generator = tlc.CodeGenerator.new(ast)
local proto     = generator:generate()

-- Emit bytecode
local emitter  = tlc.BytecodeEmitter.emit(proto)

-- Run the prototype in TLC's VM
local vm = tlc.VirtualMachine.execute(proto)

Full Pipeline Example

local tlc = require("tlc")

local code = [[
  local function fibonacci(n)
    if n <= 1 then return n end
    return fibonacci(n - 1) + fibonacci(n - 2)
  end

  for i = 0, 10 do
    print(fibonacci(i))
  end
]]

-- One-liner
tlc.run(code)

-- Step-by-step
local tokens = tlc.tokenize(code)
local ast    = tlc.parseTokens(tokens)
local proto  = tlc.generate(ast)
tlc.execute(proto)

-- Compile to bytecode file
local bytecode = tlc.compile(code)
local f = io.open("fibonacci.luac", "wb")
f:write(bytecode)
f:close()