Добрый день, Аркадий!

Компилятор включает как стадию компиляции — порождение объектного модуля, так и 
стадию компоновки — сборки из этих объектных модулей исполнимого файла 
операционной системы.

Компиляция в узком смысле либо порождает из одного исходника один файл с 
расширением .rasl — он содержит интерпретируемый двоичный код, либо пару файлов 
.rasl+.cpp, если исходный файл содержал нативные вставки или была включена 
оптимизация прямой кодогенерации.

Стадия компоновки по-разному выполняется для случая отсутствия и наличия файлов 
.cpp. Если файлов .cpp нет, то файлы .rasl конкатенируются с интерпретатором и 
получается исполнимый файл операционной системы. Если они есть, то Рефал-5λ 
вызывает компилятор C++ для сборки нового интерпретатора из файлов рантайма и 
файлов .cpp с кодом из нативных вставок. После этого к новому интерпретатору 
конкатенируются файлы .rasl.

А с проблемами в исходном письме я разобрался. Сейчас занят уже динамической 
загрузкой модулей с зависимостями. Исполнимый файл или библиотека могут 
зависеть от других библиотек, их интерпретатор должен находить и подгружать.

Библиотеки могут быть как файлами, целиком состоящими из двоичного 
интерпретируемого кода, так и быть динамическими библиотеками операционной 
системы (.dll/.so) с приклеенным к ним интерпретируемым кодом (как и исполнимые 
файлы). Файлы интерпретируемого кода у меня уже генерируются и загружаются (но 
без зависимостей и с некоторыми недоработками), разделяемые библиотеки 
операционной системы пока в планах.

 

С уважением,
Александр Коновалов 

 

From: Arkady Klimov [mailto:[email protected]] 
Sent: Tuesday, August 7, 2018 7:19 PM
To: [email protected]
Subject: Re: FW: Как мне сделать динамическую загрузку модулей?

 

Добрый день, Александр!

После отпуска разгребаю почту и потихоньку отвечаю, когда чувствую, что надо.

В Вашем письме мне непонятно вот что. Вы пишете:

Компилятор Рефал-5λ создаёт исполнимые файлы операционной системы 

Но почему не "объектные модули"?

Во всех известных мне рефалах компилируется не вся программа, а какая-то ее 
часть, оформленная как файл.

А потом эти "объектные модули" собираются в один исполнимый файл (или грузятся 
как в рефале-6, или конкатенируются)

У вас в рефале-5л есть раздельная компиляция? Если да, то результат компиляции 
одного файла уже не может быть исполнимым, не так ли?

И есть ли у Вас что-то вроде сборки (отдельной от компиляции)?

Возможно, нечеткость в этих вопросах и стала причиной Ваших трудностей?

Аркадий

 

 

27 июля 2018 г., 17:35 пользователь Alexander Konovalov aka Маздайщик 
<[email protected] <mailto:[email protected]> > написал:

Переотправлю письмо через Яндекс, а то с Mail.Ru какие-то проблемы.

Добрый день всем!

Как многие в рассылке знают, я работаю над компилятором Рефала-5λ — точного 
надмножества Рефала-5. Одним из полезных расширений языка являются нативные 
вставки — вставки кода C++ в исходном коде на Рефале. Например,

/* это файл на Рефале */
%%
#include <stdio.h>
%%

$ENTRY Go {
  = <Hello> <Hello>
}

Hello {
%%
  printf("Hello!\n");
  refalrts::splice_to_freelist(arg_begin, arg_end);
  return refalrts::cSuccess;
%%
}

Как это работает. Компилятор Рефал-5λ создаёт исполнимые файлы операционной 
системы (.exe-файлы для Windows, ELF для Linux, какие-то ещё для macOS). 
Скомпилированный файл устроен на манер SFX-архива: он состоит из 
префикса-интерпретатора, исполнимого файла операционной системы, и 
суффикса-интерпретируемого кода — двоичного языка сборки. Как если бы в конец 
интерпретатора refgo приписали бы несколько .rsl-файлов.

Когда компилятор транслирует файлы без нативных вставок, то он берёт уже 
готовый префикс-интерпретатор (скомпилированный ранее) и в конец к нему 
приписывает файлы языка сборки.

Если среди исходных файлов есть файлы с нативными вставками, то компилятор из 
таких файлов создаёт исходники на C++, содержащие текст этих самых нативных 
вставок. Потом вызывает компилятор C++, передавая ему исходники интерпретатора 
языка сборки и эти самые файлы с текстом вставок. Получается исполнимый файл, 
который становится префиксом-интерпретатором. Функции, описанные на C++ (вроде 
функции Hello в примере выше) становятся своего рода встроенными в 
интерпретатор функциями.

Кстати, все библиотечные функции (Prout, Add, Sub, Type) тоже описаны в файле 
на Рефале примерно таким образом: 
https://github.com/bmstu-iu9/simple-refal/blob/master/src/srlib/Library.sref

 

Но уже давно я планирую реализовать динамическую загрузку модулей на манер 
.dll/.so. В этом случае компилятор сможет порождать не-.exe модули, которые 
могут подгружаться как статически (если прописана соответствующая ссылка в 
языке сборки), так и динамически (вызывается соответствующая библиотечная 
функция для загрузки модуля и поиска функции в нём). Если исходные файлы модуля 
не содержат нативных вставок, то создаётся динамически загружаемый модуль 
только с одним языком сборки. Если содержат — вызывается компилятор C++, 
который создаёт .dll/.so операционной системы с нативными функциями, и к нему в 
хвост приписывает язык сборки как раньше.

 

На этом пути много технических проблем, я с ними справлюсь, скорее всего. Но 
вот возникла одна архитектурная, про которую я не вижу красивого гладкого 
решения.

Нужно (как и в случае .dll/.so) обеспечить корректную обработку повторной 
загрузки модуля. Т.е. если некоторый файл был загружен, не грузить его 
повторно, а только увеличивать у него счётчик ссылок.

Но вот как понять, что он уже был загружен? По пути к файлу это сделать сложно. 
На UNIX-системах один и тот же файл может быть доступен как subdir/filename, 
./subdir/./././filename /home/user/subdir/filename, 
/home//user///subdir////filename, 
/home/otheruser/../user/otherdir/../subdir/filename и т.д. На Windows ещё 
веселее: добавляются тонкости с регистром символов в именах, синонимичность / и 
\ и текущие папки на разных дисках. Эмулировать всё это слишком громоздко и тем 
самым некрасиво.

Можно к каждому файлу добавлять хэш, таким образом обнаруживать идентичные 
модули по их содержимому (даже если у них разные имена файлов). Но мне 
почему-то это кажется костылём.

 

С уважением,
Александр Коновалов





 

-- 

_______________

С уважением, 

Аркадий Климов,
с.н.с. ИППМ РАН,
+7(499)135-32-95
+7(916)072-81-48

Ответить