From 38ff2ddf11dc686a83be721d705e86c48538c837 Mon Sep 17 00:00:00 2001 From: "Kartik K. Agaram" Date: Sun, 6 Mar 2022 09:13:34 -0800 Subject: [PATCH] move start_reading/start_writing out of template When should code go in the template used by new apps vs the .lua files distributed with Teliva? - from a privilege perspective there's no difference - from a compatibility perspective stuff in .tlv will not get upgraded with Teliva. - for me the maintainer, functions in .lua files are easier to upgrade in a single place. - for the reader of an app, functions in .lua files will not show up to be edited. They can still be overloaded, but the current version isn't as discoverable. Putting something in the app is a slight nudge to readers that they're encouraged to mess with it. - Stuff in .lua files can use local functions and so have more internal complexity. Apps can also hide details within functions, but that'll make them more likely to run into limitations with Teliva's editing environment. I'm not yet sure how to reason about the second point in practice. - Stuff in .tlv files I don't have to worry about compatibility guarantees for. - Stuff in .lua files I _do_ have to worry about compatibility guarantees for. Perhaps this means I'm doing things exactly wrong in this commit? Functions like map/reduce/filter/append seem more timeless, whereas I'm still just feeling my way around with start_reading and start_writing. We'll see. For now I'm ruled by the fourth point. Messing with tasks and the scheduler is much more advanced than anything else in template.tlv; it seems to make sense to add some friction to modifying them. Bottomline: Complex sub-systems go in .lua files. Simple, self-contained definitions go into apps. Both are probably equally burdensome now from a compatibility perspective. --- life.tlv | 48 ------------------------------------------------ src/file.lua | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/lua.c | 2 ++ template.tlv | 48 ------------------------------------------------ zet.tlv | 48 ------------------------------------------------ 5 files changed, 47 insertions(+), 144 deletions(-) create mode 100644 src/file.lua diff --git a/life.tlv b/life.tlv index 7567697..22293ea 100644 --- a/life.tlv +++ b/life.tlv @@ -332,54 +332,6 @@ > '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 - __teliva_timestamp: original grid: >-- main data structure diff --git a/src/file.lua b/src/file.lua new file mode 100644 index 0000000..faac0c3 --- /dev/null +++ b/src/file.lua @@ -0,0 +1,45 @@ +-- 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 + +local function reading_task(infile, chanout) + for line in infile:lines() do + chanout:send(line) + end + chanout:send(nil) -- eof +end + +-- 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 + +local 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 diff --git a/src/lua.c b/src/lua.c index 11a1221..a553315 100644 --- a/src/lua.c +++ b/src/lua.c @@ -236,6 +236,8 @@ static int pmain (lua_State *L) { if (status != 0) return 0; status = dorequire(L, "src/task.lua", "task"); if (status != 0) return 0; + status = dorequire(L, "src/file.lua", "file"); + if (status != 0) return 0; lua_gc(L, LUA_GCRESTART, 0); s->status = handle_luainit(L); if (s->status != 0) return 0; diff --git a/template.tlv b/template.tlv index 4ec78b2..aa78955 100644 --- a/template.tlv +++ b/template.tlv @@ -333,54 +333,6 @@ > '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 - __teliva_timestamp: original render: >function render(window) diff --git a/zet.tlv b/zet.tlv index 6105fda..0977572 100644 --- a/zet.tlv +++ b/zet.tlv @@ -335,54 +335,6 @@ > '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 - __teliva_timestamp: original spaces: >function spaces(n)