Tal (via Lua)

Tal (via Lua)

1. To Provide Some Context

Tal is the assembly language used to construct programs written in Uxn. Uxn is the VM used to sequence gestures in GestVM. GestVM is the gesture synthesizer of choice when building things for Gestlings.

Similar to how sounds are made in LIL via Lua metaprogramming, the goal of this document is to build an interface that generates Tal code from Lua.

Much of this is based off of the code found in simple_path.

2. Tangled Files

<<tal.lua>>=
local tal = {}

<<cmds>>
return tal

3. Commands

3.1. Macro

A TAL macro can be made using tal.macro. Depending on how much manual TAL code will be written, this might not be all that helpful.

<<cmds>>=
function tal.macro(words, name, program)
    table.insert(words, "%" .. name)
    table.insert(words, "{")
    for _,v in pairs(program)
    do
        table.insert(words, v)
    end
    table.insert(words, "}")
end

3.2. Label

Creates an Uxn label.

<<cmds>>=
function tal.label(words, label)
    table.insert(words, "@" .. label)
end

3.3. Num

Helper utility that turns a lua number into an Uxn number (hex value). Number should be an 8-bit unsigned integer.

<<cmds>>=
function tal.num(words, val)
    table.insert(words, "#" .. string.format("%02x", val))
end

3.4. Val

Sets the next value to interpolate towards. This is command 0x26 in gestvm.

<<cmds>>=
function tal.val(words, val)
    tal.num(words, val)
    tal.num(words, 0x26)
    table.insert(words, "DEO")
    table.insert(words, "BRK")
end

3.5. halt

<<cmds>>=
function tal.halt(words)
    table.insert(words, "BRK")
end

3.6. dur

Sets the rate multiplier of the rephasor, expressed as a fractional value.

<<cmds>>=
function tal.dur(words, num, den)
    tal.num(words, num)
    tal.num(words, 0x24)
    table.insert(words, "DEO")
    tal.num(words, den)
    tal.num(words, 0x25)
    table.insert(words, "DEO")
end

3.7. behavior

behavior sets the behavior of the gesture.

TODO: add behavior constants

<<cmds>>=
function tal.behavior(words, id)
    tal.num(words, id)
    tal.num(words, 0x27)
    table.insert(words, "DEO")
end

3.8. jump

jump adds a JMP2 Uxn statement.

<<cmds>>=
function tal.jump(words, label)
    table.insert(words, ";" .. label)
    table.insert(words, "JMP2")
end

3.9. membuf

membuf creates a new memory buffer instance to compile in-memory Tal code.

<<cmds>>=
function tal.membuf(bufname)
    lil(string.format("gmemnew %s", bufname))
end

3.10. start

start sets the absolute location (absolute padding) to 0x100, past the zero-page. Should be called before any other Tal stuff.

<<cmds>>=
function tal.start(words)
    table.insert(words, "|0100")
end

-- I keep wanting to call it begin, not start
function tal.begin(words)
    tal.start(words)
end

3.11. compile_words

The compile_words function takes a set of populated Tal words, and converts it into Uxn bytecode, and copies it over to an instance of gestvm.

words are a table of Tal words and literals. bufname is a string value containing the name of membuf instance in LIL, and gvm is a chunk of LIL code that will push the instance of gvm onto the stack, such as "[grab gvm]".

<<cmds>>=
function tal.compile_words(words, bufname, gvm)
    local program = table.concat(words, " ")
    tal.compile(program, bufname, gvm)
end

3.12. compile

compile will compile a Lua string containing a Tal program into a membuf instance named bufname, and then copy that buffer to an instance of gestvm.

<<cmds>>=
function tal.compile(program, bufname, gvm)
    gestvm_compile(bufname, program)
    lil("gmemcpy [grab " .. 
        bufname .. 
        "] " .. 
        gvm)
end

3.13. enable/disable interpolator

<<cmds>>=
function tal.interpolate(words, state)
    tal.num(words, state)
    tal.num(words, 0x2a)
    table.insert(words, "DEO")
end