Files
esp32-lua-api/tools/test_gen_api.py
T
evan b9f7c9347c refactor(api)!: declare callbacks as classes an app composes
The runtime has always called fields on the table main.lua returns, but
@lua-global declared them as loose functions, so the stubs type-checked
something that does not exist and read as "define a global".

Callbacks are now @lua-app blocks that generate a class: App for the core
contract, TouchHandlers and ButtonHandlers beside the namespaces they belong
to. An app composes what it implements:

  ---@class PaintApp : App, TouchHandlers

Names follow the rest of the surface: onTouchDown rather than on_touch_down,
with the field names the runtime looks up renamed to match. @lua-field carries
the plain fields (home, data) that were prose in a preamble before.
2026-08-05 10:42:01 -04:00

58 lines
1.7 KiB
Python

#!/usr/bin/env python3
import tempfile
from pathlib import Path
from gen_api import ROOT, parse, render
with tempfile.TemporaryDirectory(dir=ROOT) as directory:
source = Path(directory) / "wrapped.cpp"
source.write_text(
"""// @lua-module fs FsLib
// @lua-const MAX_READ_BYTES integer 65536 Largest portable
// whole-file read.
const luaL_Reg FUNCTIONS[] = {
// --- Reads one complete
// file.
// @param path string Absolute file
// path.
// @return string|nil File
// contents.
{"readFile", readFile},
};
"""
)
module = parse(source)[0]
assert module["consts"][0][3] == "Largest portable whole-file read."
doc = module["functions"][0][1]
assert doc["doc"] == ["Reads one complete file."]
assert doc["params"][0][2] == "Absolute file path."
assert doc["returns"][0][1] == "File contents."
# Callbacks render as fields of a class an app composes, never as global functions.
with tempfile.TemporaryDirectory(dir=ROOT) as directory:
source = Path(directory) / "handlers.cpp"
source.write_text(
"""// @lua-app TouchHandlers
// @lua-field home? string The route back lands on.
// ---Fired when the finger lands.
// @param x integer
// @param y integer
// @lua-fn onTouchDown?
// ---Mounts the route.
// @param route string
// @param arg string|nil
// @lua-fn start
"""
)
output = render(source, parse(source))
assert "---@class TouchHandlers" in output
assert "---@field home? string The route back lands on." in output
assert "---@field onTouchDown? fun(x: integer, y: integer) Fired when the finger lands." in output
assert "---@field start fun(route: string, arg?: string) Mounts the route." in output
assert "function " not in output
print("ok")