Наткнулся на статью C++ всегда быстрее Smalltalk?, в которой в частности утверждается:
«<…> в C++ виртуальные вызовы происходят косвенным образом через таблицу диспетчеризации виртуальных методов. А, как известно, косвенный вызов является очень дорогостоящим на нынешнем поколении процессоров.
В динамических языках, в которых полиморфизм не привязан к иерархии классов/интерфейсов, реализация полиморфного вызова осуществляется совершенно другим образом, намного более эффективным.»
Мне вот теперь интересно, что это за более эффективные реализации, ибо в голову совершенно не приходит никаких идей.
Добро пожаловать!
На текущий момент в блоге затронуты следующие темы: vim, free pascal, lisp, forth, m4
Занимаюсь разработкой своего языка под названием DEmbro, подбробней: wiki и svn
Для постов, не связанных с программированием, у меня есть отдельное жж.
мая 26, 2011
Реализация полиморфизма
мая 19, 2011
Метапаскаль: dquotes
Т.к. программировать на паскале приходится часто, чтобы автоматизировать многие вещи я решил по полной задействовать m4.
Метапаскаль (выдуманный мною термин) — это псевдоязык, компиляция исходников которого происходит в два шага: сначала применяется m4, потом fpc. Причём изначально доступно множество макросов, упрощающих жизнь, и меняющих программирования до неузнаваемости (к примеру, будут макросы для описания классов, методов). Сегодня я занимался «лексической частью» метапаскаля.
Использование m4 с паскалем имеет серьёзную проблему: ограничитель ' (апостроф) используется в m4 для ограничения цитат, и любая строковая константа паскаля сбивает его с толку.
Их можно поменять, но подобрать другие удобные символы для m4 мне не удалось (нужно два различных ограничителя слева и справа, по умолчанию используются ` и '). Кроме того, стандартный (и немаленький) комплект библиотек для m4 написан с использованием ` и '.
Поэтому я решил, что нужно в коде на паскале использовать для строковых констант " вместо ', а перед самой компиляцией конвертировать в исходниках двойную кавычку на одинарную. Собственно, это и делает написанная мною небольшая утилита dquotes.
Она содержит множество параметров на многие случаи жизнь. Например, такой вызов
dquotes -r .\ D*.pasq *.pas
рекурсивно обходит все файлы, начиная с текущей директории, и файлы с названием, начинающимся на D и расширением .pasq сконвертирует и сохранит в файл с таким же названием, но расширением .pas
Можно организовать и обратное преобразование:
dquotes -qq -aq -r .\ D*.pas *.pasq
Из того, что ещё предстоит сделать: обработка стандартных ввода и вывода (для организации цепочки вычислений наподобии «m4 file.pas4 | dquotes -i > file.pas»).
В качестве бонуса, утилитка позволяет задать преобразование любого символа в любой другой, задав их хекс-коды. Поэтому попутно можно решить ещё одну проблему: символ $ (доллар) используется в m4 для получения параметров, и конфликтует с $ из паскаля. Поэтому я решил, что хекс-константы в метапаскале будут записываться начиная с &, а при помощи dquotes конвертироваться в стандартные, начинающиеся с $.
Читать дальше......
мая 05, 2011
DEmbro: разнесение команд по файлам
Вынес команды из центрального файла в тематические. Но кодить теперь, возможно, станет сложнее: если раньше нужную команду я искал в одном файле, то теперь таких файлов 25, и команды распределены весьма условно (не всегда ясно к какой именно категории отнести команду).
Начинаю разбивать монолитную DEmbro-машину на классы.
Читать дальше......
мая 03, 2011
DEmbro: начало глобального рефакторинга
В последнее время изменять ядро DEmbro стало достаточно сложно. Почти каждая правка порождает долгую отладку. Основная причина -- плохо структурированный код, большое число дублирующего кода, неправильно принятые в прошлом решения, которые сразу себя не проявляют, но могут конфликтовать с принятыми позднее решениями. В основном так получилось потому, что раньше я многое не понимал (не мог понять или ленился понять), и потому структурировать код и разбивать его на правильные части было сложно.
Весь код ядра практически находится в одном файле, содержащем 6600+ строк. После раскрытия макросов при помощи m4 получается 12400+ строк чистого паскаля, некоторые из которых напоминают спрессованный мусор:
procedure uint64_divmod (Machine: TForthMachine; Command: PForthCommand); begin with Machine^ do begin TUInt64((Pointer(TUInt(Machine.WP) + (0))^)) := TUInt64((Pointer(TUInt(Machine.WP) + (-2*SizeOf(TUInt64)))^)) mod TUInt64((Pointer(TUInt(Machine.WP) + (-SizeOf(TUInt64)))^));
TUInt64((Pointer(TUInt(Machine.WP) + (-2*SizeOf(TUInt64)))^)) := TUInt64((Pointer(TUInt(Machine.WP) + (-2*SizeOf(TUInt64)))^)) div TUInt64((Pointer(TUInt(Machine.WP) + (-SizeOf(TUInt64)))^));
TUInt64((Pointer(TUInt(Machine.WP) + (- SizeOf(TUInt64)))^)) := TUInt64((Pointer(TUInt(Machine.WP) + (0))^));
end; end;
procedure uint64_shl (Machine: TForthMachine; Command: PForthCommand); begin with Machine^ do begin Dec(WP, SizeOf(TUInt64));
TUInt64((Pointer(TUInt(Machine.WP) + (-SizeOf(TUInt64)))^)) := TUInt64((Pointer(TUInt(Machine.WP) + (-SizeOf(TUInt64)))^)) shl TUInt64((Pointer(TUInt(Machine.WP) + (0))^)) end; end;
Я уже достаточно многое понял, и потому назрел глобальный рефакторинг. Первое, что я сделал, -- вынес из этого файла некоторые реализации команд DEmbro, раскидав их по тематическим файлам (20 получилось пока что). В результате число строк в файле удалось сократить с 6600+ до 3900+. После раскрытия макросов размер не сильно изменился, потому что я выносил команды, слабо использующие макросы.
Впереди я планирую вынести все команды DEmbro из центрального файла в тематические, а потом начну уже разбивать саму DEmbro-машину на части.
Читать дальше......