about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--sieve.tlv62
-rw-r--r--src/task.lua11
-rw-r--r--src/teliva.c2
-rw-r--r--template.tlv48
4 files changed, 83 insertions, 40 deletions
diff --git a/sieve.tlv b/sieve.tlv
index ef2c661..92c086a 100644
--- a/sieve.tlv
+++ b/sieve.tlv
@@ -265,18 +265,9 @@
     >
     >You can also override the default big picture screen entirely by creating a buffer called 'doc:main'.
 - __teliva_timestamp:
-    >Sat Feb 26 21:49:00 2022
+    >Sat Feb 26 21:50:11 2022
   main:
     >function main()
-    >  task.spawn(main_task)
-    >  task.scheduler()
-    >  print('out of scheduler')
-    >  Window:getch()
-    >end
-- __teliva_timestamp:
-    >Sat Feb 26 21:50:11 2022
-  main_task:
-    >function main_task()
     >  local c = task.Channel:new()
     >  task.spawn(counter, c)
     >  for i=1,10 do
@@ -308,8 +299,8 @@
     >end
 - __teliva_timestamp:
     >Sat Feb 26 21:55:46 2022
-  main_task:
-    >function main_task()
+  main:
+    >function main()
     >  local primes = task.Channel:new()
     >  task.spawn(sieve, primes)
     >  for i=1,10 do
@@ -346,29 +337,17 @@
     >end
 - __teliva_timestamp:
     >Sat Feb 26 22:09:47 2022
-  main_task:
-    >function main_task(window)
-    >  local primes = task.Channel:new()
-    >  task.spawn(sieve, primes)
-    >  while true do
-    >    window:addstr(primes:recv())
-    >    window:addstr(' ')
-    >    window:refresh()
-    >  end
-    >end
-- __teliva_timestamp:
-    >Sat Feb 26 22:08:52 2022
   __teliva_note:
     >infinite primes
   main:
     >function main()
-    >  Window:nodelay(true)
-    >  Window:clear()
-    >  task.spawn(main_task, Window)
-    >  task.scheduler()
-    >  print('key pressed; done')
-    >  Window:nodelay(false)
-    >  Window:getch()
+    >  local primes = task.Channel:new()
+    >  task.spawn(sieve, primes)
+    >  while true do
+    >    Window:addstr(primes:recv())
+    >    Window:addstr(' ')
+    >    Window:refresh()
+    >  end
     >end
 - __teliva_timestamp:
     >Sat Feb 26 22:09:47 2022
@@ -376,21 +355,26 @@
     >clear screen when it fills up; pause on keypress
     >
     >In Teliva getch() implicitly refreshes the screen.
-  main_task:
-    >function main_task(window)
+  main:
+    >function main()
+    >  Window:nodelay(true)
+    >  Window:clear()
     >  local primes = task.Channel:new()
     >  task.spawn(sieve, primes)
-    >  local h, w = window:getmaxyx()
+    >  local h, w = Window:getmaxyx()
     >  while true do
-    >    window:addstr(primes:recv())
-    >    window:addstr(' ')
-    >    local c = window:getch()
+    >    Window:addstr(primes:recv())
+    >    Window:addstr(' ')
+    >    local c = Window:getch()
     >    if c then break end  -- key pressed
-    >    local y, x = window:getyx()
+    >    local y, x = Window:getyx()
     >    if y > h-1 then
-    >      window:clear()
+    >      Window:clear()
     >    end
     >  end
+    >  print('key pressed; done')
+    >  Window:nodelay(false)
+    >  Window:getch()
     >end
 - __teliva_timestamp:
     >Sat Feb 26 22:27:25 2022
diff --git a/src/task.lua b/src/task.lua
index 8d03316..3b00ef6 100644
--- a/src/task.lua
+++ b/src/task.lua
@@ -380,6 +380,17 @@ _M.RECV      = RECV
 _M.SEND      = SEND
 _M.NOP       = NOP
 
+-- Specific to Teliva
+function spawn_main()
+  task.spawn(main)
+  task.scheduler()
+  assert(false, "Teliva's scheduler ran out of work; this shouldn't happen.\n"..
+                "Either a channel is blocked forever or you're reading past\n"..
+                "the end of a file (after recv() returned nil).\n")
+  curses.nodelay(true)
+  curses.getch()
+end
+
 ----------------------------------------------------------------------------
 ----------------------------------------------------------------------------
 -- Tests
diff --git a/src/teliva.c b/src/teliva.c
index 90da6f1..2e9c9d9 100644
--- a/src/teliva.c
+++ b/src/teliva.c
@@ -1794,7 +1794,7 @@ int handle_image(lua_State* L, char** argv, int n) {
   /* initialize permissions */
   load_permissions_from_user_configuration(L);
   /* call main() */
-  lua_getglobal(L, "main");
+  lua_getglobal(L, "spawn_main");
   status = docall(L, 0, 1);
   if (status != 0) return report_in_developer_mode(L, status);
   return 0;
diff --git a/template.tlv b/template.tlv
index 6721d2b..63210d1 100644
--- a/template.tlv
+++ b/template.tlv
@@ -385,3 +385,51 @@
     >                  '123  ',
     >              'test_check_screen')
     >end
+- __teliva_timestamp: original
+  start_reading:
+    >-- primitive for reading files from a file system (or, later, network)
+    >-- returns a channel or nil on error
+    >-- read lines from the channel using :recv()
+    >-- recv() on the channel will indicate end of file.
+    >function start_reading(fs, filename)
+    >  local result = task.Channel:new()
+    >  local infile = io.open(filename)
+    >  if infile == nil then return nil end
+    >  task.spawn(reading_task, infile, result)
+    >  return result
+    >end
+    >
+    >function reading_task(infile, chanout)
+    >  for line in infile:lines() do
+    >    chanout:send(line)
+    >  end
+    >  chanout:send(nil)  -- eof
+    >end
+- __teliva_timestamp: original
+  start_writing:
+    >-- primitive for writing files to a file system (or, later, network)
+    >-- returns a channel or nil on error
+    >-- write to the channel using :send()
+    >-- indicate you're done writing by calling :close()
+    >-- file will not be externally visible until :close()
+    >function start_writing(fs, filename)
+    >  local result = task.Channel:new()
+    >  local initial_filename = os.tmpname()
+    >  local outfile = io.open(initial_filename, 'w')
+    >  if outfile == nil then return nil end
+    >  result.close = function()
+    >    result:send(nil)  -- end of file
+    >    outfile:close()
+    >    os.rename(initial_filename, filename)
+    >  end
+    >  task.spawn(writing_task, outfile, result)
+    >  return result
+    >end
+    >
+    >function writing_task(outfile, chanin)
+    >  while true do
+    >    local line = chanin:recv()
+    >    if line == nil then break end  -- end of file
+    >    outfile:write(line)
+    >  end
+    >end