Need help designing a "run loop" method

I have a control the emulates a “terminal”.
I also have an “array” the holds a series of instructions (ie. a user entered program)
my “run loop” executes those programs, jumping around as required (goto, gosub etc)
along the way it needs to update the “terminal” with changes in output.

This works fine when the program has no branches or loops
but when it does, the output doesn’t update until the main thread is complete

I think this can be solved with some kind of a timer mechanism that would submit the user instruction in a thread, and the display would be updated each time that subthread completed…

But I cannot seem to figure out how this should be constructed to waste the minimal amout of run time, still be responsive (some instructions require user input, so the GUI must be active at least during that time etc)

Any ideas?

Would it make any sense to model it in the same way a processor does these things ?
In that case it basically just a loop with a “current instruction pointer” and things like gosub just push the current instruction pointer on a stack and then when they return they pop that off the stack and carry on

That way you actually have no recursive loops etc that might block the main thread

1 Like

Well that is part of what I have…
a Pointer that normally gets incremented by one after each instruction, expect for
GOTO, whichs modifies the pointer directly, GOSUB which pushs the current pointer onto a stack, and END (return) which pops the stack and does a GOTO

But even so, I have to have some type of LOOP construct…

Do Next Instruction.... Until
While Pointer < Number of Lines 

any of those block the GUI thread it seems

I thought something with a timer but not sure how it should be constructed

On TimerAction execute next line
or something

The issue is that my “terminal” gets the equivalent of INVALIDATE, which means it doesn’t update until MY run loop completes

Yeah something like that where the timer executes one instruction and that frees up the main loop seems like it would suffice

Well this is not “perfect” yet, but it shows that it overcomes the REFRESH/INVALIDATE issue by “yielding” to the thread … My Break button remains active as well…
Will ultimately need to see how small I can make that time interval (0.1 sec is a long time)

func execute_program(nextLine:Int = -1) {
    codePOINTER = nextLine
    if nextLine<0 { lastErrorCODE=0; codePOINTER = 0 } // init for 1st line
    isRUNNING = (codePOINTER>=0 && codePOINTER<pgmCODE.count && lastErrorCODE==0)
    if !isRUNNING || isPAUSED { return }
    Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
        execute_next_line()
        timer.invalidate()
    }
}
private func execute_next_line() {
    var lineTokens = [String]()
    let ln  = String(format:"%5d",pgmCODE[codePOINTER].lineNum)
    let str = pgmCODE[codePOINTER].code
    print("->\(ln) \(str)  [\(isPAUSED) \(isRUNNING)]")     // trace
    tokenize(str,&lineTokens)   // parse the line into TOKENS
    execute_line(&lineTokens)   // execute the line of TOKENS
    codePOINTER+=1
    execute_program(nextLine: codePOINTER)
}

LOL… I guess just the overhead of the timer statement was enough… setting it to 0.0 and it still works… but remove the Timer completely and it doesnt

The timer may just cause enough of a yield to the main thread/ui thread thats all you need