Using it
SjASMPlus Lua
Native release binaries include Lua 5.4 for SjASMPlus sources. Library users
opt in with the lua Cargo feature. The default library and browser build
recognise LUA, ENDLUA and INCLUDELUA, but report that the feature is absent.
org $8000
LUA ALLPASS
for i = 0, 255 do
sj.add_byte(math.floor(math.sin(math.pi * i / 128) * 15.5))
end
ENDLUA
Use ALLPASS when emitting code: it runs on each of the three assembler passes.
PASS1, PASS2 and PASS3 select one pass; omitting the mode means PASS3.
Lua globals survive between blocks and passes. INCLUDELUA "helpers.lua" loads
through the ordinary source loader on pass 1, sharing the interpreter.
Untaken assembly branches neither run nor load Lua.
The sj interface supports expression evaluation (calc / _c), immediate
assembly (parse_line / _pl, parse_code / _pc), labels and defines,
current_address, byte/word emission, module lookup, diagnostics and
loader-mediated file_exists. get_define(name, true) can read the active
macro’s arguments. Generated source goes through the normal parser and encoder.
With a DEVICE, scripts can select slots/pages and inspect live byte/word
memory on pass 3. Earlier passes return zero for memory reads. Bank selection
and backwards ORG affect these reads just as they affect SAVEBIN.
sj.get_page_at(address) exposes the current mapping; this requested API is
an extension to the pinned 1.21.0 Lua bindings. Custom set_device RAMTOP
values are explicitly refused rather than ignored.
Sandbox and limits
String, table, math, UTF-8 and coroutine libraries are available. load accepts
text, including reader functions, but never bytecode. There is no io, os,
package, require, debug, dofile or loadfile. Process execution and the
zx file writers are refused. sj.exit fails the assembly, not the process;
catching a host error with pcall does not make a failed assembly succeed.
print becomes an assembly note instead of writing directly to stdout.
The interpreter has a 32 MiB memory limit and a ten-million-instruction budget
shared across all passes and coroutines. Generated assembler work is charged
too, with a separate cumulative 32 MiB host-allocation budget. Diagnostics name
the exhausted budget. Randomness starts from a fixed seed, including a call to
math.randomseed() without arguments; explicit seeds remain available.
Lua that emits machine code outside ALLPASS produces a luamc warning.
If that is deliberate, a ; luamc-ok comment on LUA or ENDLUA acknowledges
it, following SjASMPlus.