Машина, виртуальная или нет, нуждается в модели вычислений, которая описывает, как вычисления выполняются на ней. По определению, как только он вычисляет, он реализует некоторую модель вычисления. Тогда возникает вопрос: какую модель выбрать для нашей виртуальной машины? Физические машины ограничены тем, что может быть эффективно и действенно сделано аппаратно. Но, как вы заметили, виртуальные машины не имеют таких ограничений, они определяются в программном обеспечении с использованием языков произвольно высокого уровня.
На самом деле, как вы описываете, существуют виртуальные машины высокого уровня. Они называются языками программирования . Например, стандарт C посвящает большую часть своих страниц определению модели для так называемой «абстрактной машины C», которая описывает, как ведут себя программы на C, и в качестве расширения (как правило), как соответствующий компилятор C (или интерпретатор). должен вести себя
Конечно, мы обычно не называем это виртуальной машиной. Под виртуальной машиной обычно понимается нечто более низкое, более близкое к аппаратному, не предназначенное для непосредственного программирования, предназначенное для эффективного выполнения. Это смещение выбора означает, что то, что принимает высокоуровневый составной код (например, то, что вы описываете), не будет считаться виртуальной машиной, поскольку выполняет высокоуровневый код.
Но чтобы перейти к сути, вот несколько причин сделать виртуальную машину (например, что-то, предназначенное для компилятора байт-кода) регистровой или тому подобное. Укладывать и регистрировать машины чрезвычайно просто. Для каждой инструкции есть последовательность инструкций, некоторое состояние и семантика (функция State -> State). Нет сложных сокращений дерева, нет приоритета оператора. Синтаксический анализ, анализ и выполнение очень просты, потому что это минимальный язык (синтаксический сахар компилируется) и предназначен для машинного чтения, а не человеческого чтения.
Напротив, анализ даже самых простых C-подобных языков довольно сложен, и для его выполнения требуются нелокальные анализы, такие как проверка и распространение типов, разрешение перегрузок, поддержка таблицы символов, разрешение строковых идентификаторов, превращение линейного текста в AST на основе приоритетов. , и так далее. Он основан на концепциях, которые естественны для человека, но должны быть тщательно обработаны машинами.
Байт-код JVM, например, излучается javac
. Его практически никогда не нужно читать или писать людям, поэтому естественно ориентировать его на потребление машинами. Если вы оптимизировали его для людей, виртуальная машина будет только при каждом запуске читать код, анализировать его, анализировать это, а затем преобразовать его в промежуточное представление , напоминающее такая модель упрощенной машины в любом случае . С таким же успехом можно вырезать среднего человека.