debug animations

akkartik
Nov 11, 2023, 6:01 PM
UEG224LHBOPWSKOVXTKVAUEL47HET566LJF7ZSWVKMMLBSJWUHFAC

Dependencies

Change contents

  • file addition: 0008-Debug_animation_period (----------)
    [2.2]
    Debug_animation_period = 0.3 -- seconds between animation frames
  • file addition: 0007-save_callstack (----------)
    [2.2]
    -- Internal helper for animate()
    -- Records the stack of function calls that led to any error within a debug animation coroutine.
    -- Lua normally prints out errors with callstacks, but coroutines interrupt the stack unless we do some additional work.
    save_callstack = function(err)
    local callstack = debug.traceback('', --[[stack frame]]2)
    Error_with_callstack = 'Error: ' .. cleaned_up_frame(tostring(err))..'\n'..cleaned_up_callstack(callstack)
    end
  • file addition: 0006-loiter (----------)
    [2.2]
    -- A debugging aid to animate intermediate results in computations.
    -- Can only be called from functions invoked using `animate()`.
    loiter = function()
    coroutine.yield()
    end
  • file addition: 0005-animate (----------)
    [2.2]
    -- A debugging aid to help animate intermediate results within f.
    -- Pause animation in the current frame using loiter().
    -- Try to only have one such call in your program.
    -- You can have multiple, but things might get confusing if one of them indirectly calls the other,
    -- or more generally if a single function ever loiters sometimes under the call tree of one and sometimes under the other.
    animate = function(f, ...)
    local args = {...}
    Error_with_callstack = nil
    local co = coroutine.create(
    function()
    xpcall(function()
    f(unpack(args))
    end,
    save_callstack)
    end)
    coroutine.resume(co, ...)
    if Error_with_callstack then
    error(Error_with_callstack)
    end
    table.insert(Debug_animations_in_progress, {co=co, next_run=Current_time+0.3})
    end
  • file addition: 0004-on.update (----------)
    [2.2]
    on.update = function()
    refresh_debug_animations()
    end
  • file addition: 0003-refresh_debug_animations (----------)
    [2.2]
    -- update any in-progress debug animations
    -- return whether any work remains
    refresh_debug_animations = function()
    local a = Debug_animations_in_progress
    for i=#a,1,-1 do
    if coroutine.status(a[i].co) == 'dead' then
    table.remove(a, i)
    elseif Current_time > a[i].next_run then
    local status, err = coroutine.resume(a[i].co)
    if status == false then error(err) end
    a[i].next_run = Current_time + Debug_animation_period
    end
    end
    return #a > 0
    end
  • file addition: 0002-Debug_animations_in_progress (----------)
    [2.2]
    -- Intermediate state during debug animations.
    Debug_animations_in_progress = {}