Alexander Herbert
Alexander Herbert

Reputation: 3

how to restart a lua program using the script in the lua script

It's me again

I'm trying to make a Terminal program in Lua since it's my best language I know, I'm making the calculator program in it and I'm trying to make it so if the user types "exit" the program will restart and will go back to the terminal, but I don't know how to reset the program through the code. if anyone can help that be deeply appreciated.

This is the code:

io.write("Terminal is starting up --- done!")
io.write("Making sure everything works --- Done!")
cmd = io.read()
io.write(">")

if cmd == "" then 
    io.write(">\n")
end

if cmd == "cal"then
    io.write("Calculator Terminal Program v1.0")
    io.write("what operation?/n")
    op = io.read()
    
    if op == "exit"then
        io.write("Exiting")
    end
end

Upvotes: 0

Views: 2226

Answers (3)

Amine Kchouk
Amine Kchouk

Reputation: 172

To answer your question directly, I don't think it's possible to "restart the program". However, by taking advantage of loops, you can achieve the same result.

For instance, this code probably does what you want:

print('Terminal is starting up --- done!')
print('Making sure everything works --- Done!')

repeat
    io.write('>')
    cmd = io.read()

    if cmd == 'cal' then
        print('Calculator Terminal Program v1.0')
        repeat
            io.write('Operation: ')
            op = io.read()
        until op == 'exit'
        print('Exiting')
    elseif cmd == 'command' then
        --another command
    else
        print('Unknown command.')
    end

until cmd == 'exit'

Other tips:

  • You should take advantage of elseif instead of writing multiple separate if statements to improve readability.
  • Consider using the print function when you want a new line after writing some text for a better Terminal experience. You could also use io.write('\n').

Upvotes: 0

Foxie Flakey
Foxie Flakey

Reputation: 420

i think this might work through creative use of load() and coroutines this gonna stop restarting itself when 3 total error has occured

if innerProgram == nil then --innerProgram will set to true when it load itself
  local filename = nil
  local errorLimit = 3 --Change this to any value to enable this code to restart itself when error occur until this amount of time set zero or below to exit instantly when error occur
  local errors = 0
  local filename = function()
    local str = debug.getinfo(2, "S").source:sub(2)
    return str:match("^.*/(.*)") or str
  end
  filename = filename()
  local src_h = io.open(filename, "r") --open in read mode
  local src = src_h:read("*a")
  src_h:close()
  local G = _G
  local quit = false --set true when you want to exit instead restart
  local code = nil
  local request = false
  local restart = false --set true when you want restart
  local program
  local yield = coroutine.yield --Incase when coroutine get removed in your calculator code for no reason
  local running = coroutine.running
  local exit = os.exit
  function G.restart()
    restart = true --Always refer to restart variable above
    request = true
    yield() --Always refer to yield above
  end
  function G.os.exit(exitcode) --Replace os.exit with this
    quit = true --Always refer to quit variable above
    reuqest = true
    code = exitcode or nil
    yield() --Always refer to yield above
  end
  function G.coroutine.yield()
    if running() == program and request == false then --Emulating coroutine.yield when it not run inside coroutine
      error("attempt to yield from outside a coroutine")
    end
  end
  G.innerProgram = true --So the inner program not keep loading itself forever
  function copy(obj, seen)
    if type(obj) ~= 'table' then return obj end --got from https://stackoverflow.com/questions/640642/how-do-you-copy-a-lua-table-by-value for us to clone _G variable without reference to original _G thus we can do total restart without using same _G
    if seen and seen[obj] then return seen[obj] end
    local s = seen or {}
    local res = setmetatable({}, getmetatable(obj))
    s[obj] = res
    for k, v in pairs(obj) do res[copy(k, s)] = copy(v, s) end
    return res
  end
  print("Loading "..filename)
  program = coroutine.create(load(src, filename, "bt", copy(G)))
  while errors < errorLimit do
    restart = false
    local status, err = coroutine.resume(program)

    if restart == true then
      print("Restarting...")
      program = coroutine.create(load(src, filename, "bt", copy(G)))
      --Put errors = errors + 1 if you want errors counter to reset every time the program request restart
    end
    
    if status == false and restart ~= true then
      print(filename.." errored with "..err.."\nRestarting...")
      program = coroutine.create(load(src, filename, "bt", copy(G)))
      errors = errors + 1
    elseif restart ~= true then
      print(filename.." done executing.")
      exit()
    end
  end
  return
else
  innerProgram = nil --Nil-ing the variable
end

Features

  1. Auto exit when 3 total errors has occur (configure errorLimit variable)
  2. _G is not shared (same _G as start of the program but not linked with the actual _G)
  3. Emulating yielding outside of coroutine
  4. Replaced os.exit so it yield then the self-loader run the os.exit

How to use

put the code i give above to very first line of your code

Feature Number 1 and 3 test

it error with the a content the value will be different in each error restart

if a == nil then --Only set a when a equal nil so if _G was shared the error value will be same 
  a = math.random() --Set global a to a random value
end
error(a) --Error with number a
os.exit()

Upvotes: 0

DarkWiiPlayer
DarkWiiPlayer

Reputation: 7064

You probably want os.exit(), which terminates the entire program.

Upvotes: 0

Related Questions