Как работают интерпретаторы компилирующего типа?
1) То есть считал строку, скомпилировал - получил двоичный код. Выполнил этот двоичный код. 
НЕТ. Считал — выполнил. Выполняется машинный код интерпретатора, а не программы. 

3) Байт-код понятен среде/виртуальной машине (.NET, Java), которая компилирует байт-код в двоичный код
В ЧИСТОМ СЛУЧАЕ — НЕТ. Считал команду байт-кода — выполнил. Точно так же выполняется машинный код интерпретатора, а не программы. Что-то вроде:
switch (opcode) {
case OP_ADD: {
       auto res = stack.pop() + stack.pop();
       stack.push(res);
   }
.....
}

Байт-код используется по нескольким причинам.
1. 3 быстрее 1.
2. С расширением языка мы меняем только компиляцию в байт-код. Оптимизация байт-кода, интерпретатор — остаются.

А компиляция в машинный код в 1 и 3 — это так называемая JIT-компиляция. Она может выполняться не всегда. Одни команды могут быть в машинном коде, а другие — интерпретироваться.

Кроме того, байт-код часто используется и в классических компиляторах 2-го типа! Это позволяет делать многоплатформенные коллекции компиляторов — все frontend’ы компилируют в байт-код, затем с байт-кодом делаем какую-то магию вроде оптимизации, отдаём его backend’у, и тот готовит OBJ-файл для нужного процессора.
Всё верно?Нет.
"3" Виртуальная машина выполняет байт-код, как подпрограмму, запоминая стек, переменные и пр. окружения. Никакой компиляции.
Разделитель строк — частый разделитель команд языка,  но не единственный.