#! lua
-- task library
local riscos = require "riscos"
local dim, sys, !, $  in riscos
local ipairs = ipairs
local TASK <const> =  0x4b534154

local closedown = \ (self)
        local preclosedown, handle in self
        if preclosedown then preclosedown (self) end -- if
        sys (0x400dd, handle, TASK)
       end

local now = \  (d)
       local t = sys (0x20042) -- OS_ReadMonotonicTime
       => t + ( d or 0 )
       end -- function

local run = \ (self, idle)
     local poll <const> = idle and 0x400e1 or 0x400c7
     local b, handler, preclosedown in self
     local reason, quit, action, err
     local when = ((not idle) and 0) or self.time or 100
     while not (quit or err) do
         reason = sys (poll, self.mask or 0, b, when)
         action = handler[reason]
         quit, err = action and action (self)
         if err then
             self:report (err)
             quit = true
         end -- if
     end -- while
     self:closedown ( )
     end

local respond = \ (self)
      local b, handler in self
      local mesg in handler
      local action = mesg[![b + 16] ]
      if action then => action (self) end -- if
       end

local  handler = {
           [17] = respond, [18] = respond,
           mesg = { [0] = \ (self) => true end, }
           }

local ack = \ (self, react)
       local b in self
       local x, y, fn, ft = ![b + 28], ![b + 32], $[b + 44], ![b + 40]
       ![b + 12], ![b + 16] = ![b + 8], 4   -- DataLoadAck
       sys (0x400e7, 19, b, 0)
       if react then => self:react (fn, ft, x, y) end -- if
      end -- ack

local send = \ (self, target, mesg)
      if target ~= 0 then
       local b in self
       ![b] = 20
       ![b + 12] = 0 -- original
       ![b + 16] = mesg
       assert (sys (0x600e7, 17, b, target, 0), "message failed")
      end -- if
   end -- function

 local msglist = \(t)
      if not t then => 0 end -- if -- no messages important
      local x = dim(4+((#t)<<2))
      for i,y in ipairs(t) do
       ![x-4+((i)<<2)] = y
      end -- for
      ![x+((#t)<<2)] = 0
      => x
    end -- function

local alert = \ (self, err, template)
    -- use your own template maybe
    local m = 'rlua:bin.ME.MultiError -t %s -e "%s"\0'
    -- taskhandle of ancillary task
    =>  sys (0x400de, m:format (template or "rlua:bin.ME.Template", err))
   end -- function

local report = \ (self, s, flag)
         local b, title in self
         $[b] = ("Lua_%s\0"):format (s)
         local r0, r1 = sys (0x400df, b, flag or 17, title)
         => r1 -- 0 no click, 1 OK, 2 Cancel
       end -- report

local spawn = \ (self, name, bsize)
  local wt = {
    b = dim (bsize or 256);
    title = dim (name .. "\0");
    }
    => setmetatable ( wt, { __index = self })
    end

local init = \ (self, mesgs)
     local msglist, title, version in self
     local a = msglist (mesgs)
     local r0, r1 = sys (0x400c0, version or 310, TASK, title, a)
     self.handle = r1
     => r0
      end

local QUIT = \ (self) => true end

=> setmetatable ({
      ack = ack;
      spawn = spawn;
      init = init;
      run = run;
      msglist = msglist;
      alert = alert;
      report = report;
      closedown = closedown;
      now = now;
      handler = handler;
      send = send;
      QUIT = QUIT;
      now = now;
       }, { __index = _G } )


