Я часто фантазировал о попытке создать (еще один) компьютерный язык высокого уровня. Цель состоит в том, чтобы попытаться раздвинуть границы быстроты разработки и результативности. Я попытался бы создать библиотеки вроде минимальных, довольно высокооптимизированных операций, а затем попытаться разработать языковые правила таким образом, чтобы любое выражение или выражение, выражаемое в языке, приводило к оптимальному коду ... если только выражение не было просто по своей сути неоптимальный.
Он будет компилироваться в байт-код, который будет распространяться, а затем в машинный код при установке или при изменении среды процессора. Поэтому, когда исполняемый файл загружен, будет часть загрузчика, которая проверит процессор и несколько байтов управляющих данных в объекте, и если два совпадения, то исполняемая часть объекта может быть загружена сразу, но если нет Затем байт-код для этого объекта должен быть перекомпилирован, а исполняемая часть обновлена. (Таким образом, это не компиляция Just In Time - это при установке программы или компиляции с измененным ЦП.) Часть загрузчика будет очень короткой и приятной, она будет в коде 386, поэтому ее не нужно будет компилировать. Он будет загружать компилятор байт-кода только в случае необходимости, и если это так, он будет загружать объект компилятора, который был маленьким и компактным и оптимизирован для обнаруженной архитектуры. В идеале загрузчик и компилятор должны оставаться резидентными после загрузки, и будет только один экземпляр обоих.
В любом случае, я хотел ответить на мысль, что у вас должно быть как минимум два прохода - я не думаю, что я полностью согласен. Да, я бы использовал второй проход через скомпилированный код, но не через исходный код.
Что вы делаете, когда вы сталкиваетесь с символом, проверяете вашу хеш-таблицу символов, и, если там нет записи, создайте ее и сохраните маркер «прямой ссылки» в скомпилированном коде с указателем на запись таблицы. , Когда вы встретите определения для меток и символов, обновите (или добавьте новые данные) свою таблицу символов.
Отдельные скомпилированные объекты никогда не должны быть такими большими, чтобы они занимали очень много памяти, поэтому, безусловно, весь скомпилированный код должен храниться в памяти до тех пор, пока все это не будет готово для записи. То, как вы сохраняете свой отпечаток памяти небольшим, заключается в простом обращении только с одним объектом за раз, и при этом никогда не храните в памяти более одного небольшого буфера, заполненного исходным кодом. Может быть, 64 КБ или 128 КБ или что-то. (Что-то настолько большое, что накладные расходы, связанные с выполнением вызова для загрузки буфера с диска, невелики по сравнению со временем, которое требуется для чтения данных с диска, чтобы оптимизировать потоковую передачу.)
Итак, один проход через исходный поток для объекта, затем вы объединяете свои кусочки вместе, собирая необходимую информацию о прямой ссылке из хеш-таблицы, а если данных нет, - это ошибка компиляции. Это процесс, который я хотел бы попробовать.