1. Пользуйтесь тегами кода. - [code] ... [/code] 2. Точно указывайте язык, название и версию компилятора (интерпретатора). 3. Название темы должно быть информативным. В описании темы указываем язык!!!
Итак, 14 июня вышла наконец долгожданная версия GNAT GPL 2011.
Много улучшений, новая версия самой IDE (теперь это версия 5.0.1, вместо 4.3.1 из 2009-ой версии, и 4.4.1 из 2010), мне нравится больше, чем прежняя, одна возможность фильтрации результатов компиляции чего стОит (хотя это вроде было и в 2010, но мне сравнивать не с чем, я сразу перешел 2009 -> 2011, поэтому все нововведения будут относительно предпоследней версии).
Что говорит официальная страничка (комментарии - мои):
Улучшенная поддержка А2012 (да, это - главная причина, по которой я обновился. Теперь есть возможность использовать все те фичи, которые на настоящий момент утверждены для нового стандарта, а не просто наблюдать сообщение, что это будет доступно в 2012 году, как было в прежней версии GNAT. Это и "in out" параметры для функций, и условные выражения, и Case-выражения, работают Quantified expressions, дискриминанты для лимитированных тэговых типов, Pre/Post-условия, и многое другое из того, что уже внесено в окончательную редакцию стандарта)
Улучшенные версии (GPS 5.0 - расширенная поддержка С/С++, более мощный редактор, повышенное юзабилити, GtkAda - новые виджеты, интерфейс к граф. библиотеке Cairo). (От себя добавлю, что в редакторе наконец-то сделали выпадающий список Pragma, и список атрибутов типа: )
Более гибкий и эффективный менеджер проектов
Поддержка выгрузки плагинов
Улучшенная поддержка конструкций на .NET-платформе
Более детальные сообщения об исключениях (при использовании ключа -gnateE)
полная поддержка платформы Lego Mindstorms NXT, включая аудио и I2C-сенсоры (об этом есть ролик на youtube, англ.: вот он)
Как видно, много народу хочет попробовать новую среду/новый компилятор - я скачивал пакет размером 140Мб почти 12 часов, скорость иногда падала до 2-3Кб/сек. Но сейчас с этим вроде справились.
В общем, решил я проверить скорость "лямбда-функций". Результаты оказались удручающие. По скорости они оказались ничуть не лучше, чем АСТ-дерево, а "байткоду", сделанному в формате массив данных вида "указатель на операцию, на левый аргумент, на правый аргумент, на результат", они сливают в два раза. Необходимость использовать в случаях, в которых важно время, такой массив очень неприятна - генерация этого массива из АСТ-дерева не так проста, как генерация лямбда-функции, а условные операторы очень геморны.
Самое плохое, на самом деле не это. Самое плохое тут то, что этот код работает только при полной оптимизации, иначе... переполнение стека (ОТКУДА):
Спойлер(Показать/Скрыть)
with Ada.Text_IO; use Ada.Text_IO; with Ada.Real_Time; use Ada.Real_Time;
procedure Test is
type TCommand is record proc: access function (l,r : integer) return integer; arg1, arg2, res: access integer; end record;
function Add (l,r : integer) return integer is begin return l+r; end; function Sub (l,r : integer) return integer is begin return l-r; end; function Mul (l,r : integer) return integer is begin return l*r; end;
Commands : array (1 .. 8) of TCommand;
function Ret_Const (c: integer) return access function return integer is function Inner_Func return integer is begin return c; end; begin return Inner_Func'Unrestricted_Access; end;
function Ret_Add ( l, r: access function return integer ) return access function return integer is function Inner_Func return integer is begin return Add(l.all, r.all); end; begin return Inner_Func'Unrestricted_Access; end;
function Ret_Sub ( l, r: access function return integer ) return access function return integer is function Inner_Func return integer is begin return Sub(l.all, r.all); end; begin return Inner_Func'Unrestricted_Access; end;
function Ret_Mul ( l, r: access function return integer ) return access function return integer is function Inner_Func return integer is begin return Mul(l.all, r.all); end; begin return Inner_Func'Unrestricted_Access; end;
Funcs : array (1 .. 17) of access function return Integer;
type TNodeKind is (nkConst, nkAdd, nkSub, nkMul);
type TNode is record Kind : TNodeKind; Value : integer; L, R : access TNode; end record;
Nodes : array (1 .. 17) of aliased TNode;
function Get_Value (T: TNode) return Integer is begin case T.Kind is when nkConst => return T.Value; when nkAdd => return Add (Get_Value (T.L.all), Get_Value (T.R.all)); when nkSub => return Sub (Get_Value (T.L.all), Get_Value (T.R.all)); when nkMul => return Mul (Get_Value (T.L.all), Get_Value (T.R.all)); end case; end;
T: Time; Times: constant integer := 10_000_000;
begin -- вычисляем непосредственно -- 0.00 сек T := Clock; for j in 1 .. Times loop Data(17) := Sub ( Add (Sub (Add (7, 8), Mul (5,6)), Mul (48,2)), Mul (3, Add (6, 9))); end loop; Put_Line (Duration'Image (To_Duration (Clock - T)));
T := Clock; for j in 1 .. Times loop for i in Commands'Range loop Commands(i).res.all := Commands(i).proc(Commands(i).arg1.all, Commands(i).arg2.all); end loop; end loop; Put_Line (Duration'Image (To_Duration (Clock - T)));
T := Clock; for j in 1 .. Times loop Data(17) := Get_Value(Nodes(17)); end loop; Put_Line (Duration'Image (To_Duration (Clock - T)));
end Test;
Сверху вниз выводится время выполнения простого вычисления (я как мог старался его писать так, чтобы компилятор не сделал замену), выполнения массива указателей на процедуры, выполнения лямбда-функции, выполнения прохода по АСТ-дереву. Выводится примерно так:
Код
0.00ещё нули 1.30 2.60 2.50
Жаль, что генерация таких функций не использует подстановку в на ходу генерирующийся код, скорость бы выросла в разы. Для выполнения пользовательских скриптов это очень важно.
Добавлено через 2 мин. Кстати, мне непонятно ограничение, запрещающее брать указатель от встроенных функций. Компилятор не может сам сделать то, что мы делаем руками - функцию-прокладку?