По всякому.
Интерпретатор - это когда ваш код поэлементно исполняется (буквально если видим if то парсим проверяем следующее условие, видим оператор print значит выводим и т.п,), на практике чистых интерпретаторов уже давно не осталось.
Следующее развитие интерпретатора - предварительная компиляция во внутренний байткод (точнее парсинг синтаксических лексем в структуры в памяти, с которыми удобнее и главное быстрее работать) - самый популярный способ для непопулярных языков.
Следующее развитие - использование байткода какой-нибудь уже созданной виртуальной машины, которая оптимизирована и вылизано исполнение. В этом случае каждая команда байткода уже не один к одному синтаксические лексемы а буквально как команды к процессору, т.е. одна лексема может быть развернута в несколько команд (.net, java, llvm,...)
Компиляция в нативный код - когда байткод, в который проводится компиляция - это машинный код соответствующий процессор.
Компиляция в другой язык программирования, который имеет компилятор под нужную вам архитектуру, т.е. ваш код преобразуется в промежуточный (truescript например компилируется в javascript а тот исполняется в браузере или на nodejs).
p.s. если вопрос про виртуальные машины в смысле эмуляторы компьютера, то да и там используется jit компиляция, трансляция команд виртуальной машины в реальную на лету, эти технологии так же взяты из мира компиляторов с языков программирования но только как идея а не кодовая база, все же отличается это сильно.