Разговор о генерации кода для универсального компилятора практически одинаков, независимо от языка, как только вы приступите к нему. Сложности различных языков включают в себя эффективную обработку семантики сред в языке (т. Е. В схеме есть такие вещи, как замыкания и продолжения, а в чем-то вроде BASIC нет).
Но как только вы определились с тем, как такие вещи представлены (а некоторые влияют на эффективность с точки зрения разметки памяти, доступности и т. Д.), Генерация кода становится простой.
Различия, с которыми вы сталкиваетесь, это различия между, скажем, компилятором Scheme, который компилируется в C, а затем передает его компилятору C (который может скомпилировать его для сборки и передать его ассемблеру), против генерирование машинных инструкций непосредственно в ОЗУ вашим компилятором.
Различные этапы дают вам возможность добавить оптимизацию и разделить задачи. Генерация кода C может быть проще, чем генерация сборки или, особенно, машинного кода, потому что компилятор C может сделать для вас тяжелую работу (например, переносимость архитектуры).
Но несколько систем могут использовать C для компиляции кода, который сразу же загружается через процесс динамического связывания и выполняется.
Компиляция на промежуточный язык (а-ля JVM, CLR) также может упростить ситуацию, и тогда вы JIT это. Компиляция байт-кодов JVM не особенно сложна, так как это простой стековый компьютер. Оптимизация этого кода - это другая проблема, но преобразование в машинный код довольно просто. CLR отличается тем, что он захватывает больше семантики компилируемого кода. CLR больше походит на промежуточную фазу компиляции, в отличие от JVM, который является реальным кодом, предназначенным для выполнения как есть.
В конце концов, это где-то массивы данных в ОЗУ, независимо от того, являются ли эти данные машинным кодом или кодом виртуальной машины, и это вопрос деталей. Является ли этот массив собственно ОЗУ или отображается виртуальной машиной из файла - это другая деталь. С виртуальной памятью ваша система, вероятно, не заботится так или иначе.
Так что все сводится к тому, чтобы сосредоточиться на правильной генерации кода. Как только вы освоитесь, перенаправление его на другие компиляторы, в ОЗУ или в файлы является второстепенным шагом.