It uses a small-step interpreter [1]. Rather than capturing the interpreter's state on the native call stack, small-step interpreters explicitly model said state using stacks of objects - one per active AST node - and environments. Because they're no longer bound to the stack of the implementation language, execution may be cycled, paused and resumed at will.