C'est un programme qui utilise la fonction loadstring de la bibliothèque standard lua pour exécuter un programme lua édité sur la calculatrice.
J'ai complètement réécrit le programme, pour de nombreuses améliorations...
Maintenant chaque nouvelle page contenant un exécuteur va se donner un identifiant différent, et chargera l'ensemble du programme contenu dans une seule variable lua_prgm_[id], ce chargement se faisant à la demande de l'utilisateur, par la modification du contenu de la variable lua_reload_[id].
La compilation et l’exécution du contenu de cette variable est sécurisé, ainsi que l'appel à toutes les fonctions événement, ce qui fait que toute erreur sera gérée et affiché par l’exécuteur et non par l’interpréteur, ce qui aurait pour effet de bloquer l’exécuteur, et donc au mieux de recharger complètement le document, au pire de devoir remettre l’exécuteur sur la calculatrice à partir de l'ordinateur, ce qui est un peu dommage vu l'objectif de ce programme !
Je fais en même temps un éditeur sur la calculatrice, qui fonctionnera en parallèle de ce programme.
Donc tout ça marche très bien, sauf au moment où le document est rechargé... La fonction on.restore n'est pas appelée, les id sont donc remis à jour et le programme utilisateur n'est plus exécuté ...
Voici donc mon code, si vous avez une idée de pourquoi on.restore n'est pas appelée ...
Mes tests on montré que on.save était bien appelée et que on.restore était correctement définie au moment de l'appel à on.create, ce qui n’était pas forcement évident vu les modifications à la table "on."
Si vous avez des questions ou remarques sur l'optimisation de ce programme, n'hésitez pas !
- Code: Select all
EX_s = {id = nil, Loaded = false, Error = nil, isEditor = false, on={}} -- table for global variables
-- error
function EX_s:err(txt)
EX_s.Error = txt
platform.window:invalidate()
end
-- sucurised exec
function EX_s:exec(f, arg)
local s, r
if not f then return nil end
s, r = pcall(f, arg)
if not s then
EX_s:err("(E) ".. r)
else
return r
end
end
-- reload ext prgm
function EX_s:reload()
if EX_s.isEditor then -- clean errors
EX_s.Error = nil
EX_s.isEditor = false
EX_s.editor:setText("")
EX_s.editor:move(0,0)
EX_s.editor:resize(1,1)
end
EX_s.Loaded = false
var.store("lua_reload_"..EX_s.id, 0)
on = {}
local prgm = var.recall("lua_prgm_"..EX_s.id) --get prgm txt
if not prgm then
EX_s:err("Error reading lua_prgm_"..EX_s.id)
elseif type(prgm) ~= "string" then
EX_s:err("lua_prgm_"..EX_s.id .. "should be a string")
else
local cmp, err = loadstring(prgm) -- compile prgm
if not cmp then
EX_s:err("(C) " .. err)
else
local s,r = pcall(cmp) -- exec prgm
if not s then
EX_s:err("(CE) " .. r)
else
for i,f in pairs(on) do -- securize "on." functions, the olny who can be called externally
EX_s.on[i] = f
on[i] = loadstring("return function(arg) return EX_s:exec(EX_s.on["..i.."], arg) end")()
end
EX_s.Loaded = true
end
end
end
EX_s:reinit()
platform.window:invalidate()
end
-- reinitialisation of events endlers
function EX_s:reinit()
function on.paint(gc)
if EX_s.Error then -- error windows
gc:setColorRGB(255,0,0)
gc:drawString("Error", platform.window:width()/2-gc:getStringWidth("Error")/2, 0, "top")
gc:setColorRGB(0,0,0)
if not EX_s.isEditor then
EX_s.editor:move(10,20)
EX_s.editor:resize(platform.window:width()-20, platform.window:height()-30)
EX_s.editor:setText(EX_s.Error)
EX_s.isEditor=true
end
elseif not EX_s.Loaded then --idle window
gc:drawString("Exec ID:"..EX_s.id, platform.window:width()/2-gc:getStringWidth("Exec ID:"..EX_s.id)/2, platform.window:height()/4, "top")
else
EX_s:exec(EX_s.on.paint, gc)
end
end
function on.varChange(varlist)
-- reload event
if not var.recallstr("lua_reload_"..EX_s.id) then return -3 -- never delete this var
elseif var.recall("lua_reload_"..EX_s.id)~=0 then
EX_s:reload()
return 0
elseif Ex_s.Loaded then
return EX_s:exec(EX_s.on.varChange, var)
end
return 0
end
function on.save()
local ret = {}
ret.EX_s = EX_s
if EX_s.Loaded then
ret.u_sv = EX_s:exec(EX_s.on.save)
end
return ret
end
function on.restore(data)
EX_s = data.EX_s
if ret.u_sv then
EX_s:exec(EX_s.on.restore, ret.u_sv)
end
end
function on.create()
if not EX_s.id then
-- initialisation
-- look for curent id
EX_s.id = var.recall("lua_cur_id")
if not EX_s.id then -- create it
EX_s.id = 0
else
EX_s.id = EX_s.id+1 -- or update it
end
math.eval("Unlock lua_cur_id")
var.store("lua_cur_id",EX_s.id) -- and store it
math.eval("Lock lua_cur_id")
-- setting programme update information var
if not var.recallstr("lua_reload_"..EX_s.id) then
var.store("lua_reload_"..EX_s.id, 0)
elseif var.recall("lua_reload_"..EX_s.id)~=0 then
EX_s:reload() -- if the prgm already exist, then try to load it
end
var.monitor("lua_reload_"..EX_s.id)
-- cration of D2 editor for error informations :
if not EX_s.editor then
EX_s.editor = D2Editor.newRichText()
end
EX_s.editor:setReadOnly(true)
end
EX_s:exec(EX_s.on.create)
end
end
EX_s:reinit()