Давно меня уже мучает отсутствие лямбд во FPC.
Казалось бы все есть - и тип вызова of object и локальные функции. Вроде бы до цели один шаг. По крайней мере в простейшей реализации.
Я попробовал слепить так сказать Proof of concept, для таких себе простейших и довольно быстрых операций. Хотел бы услышать ваши комментарии. Насколько я понимаю, такая же идея трамплинов используется в gcc.
Было бы отлично, если бы Сергей Горелкин и кто-нибудь из разработчиков/хакеров компилятора прокомментировал этот код.
- Код: Выделить всё
program project1;
{$mode objfpc}{$H+}
{$OPTIMIZATION OFF} //с включенной оптимизацией регистр ebp может не хранить кадр стека.
{$ASMMODE INTEL}
type
TTrampolineRec = record
Reg_EBP:Pointer;
LocalProc:Pointer;
Self:Pointer; //будет использоваться в случае локальных функций методов классов
end;
PTrampolineRec = ^TTrampolineRec;
TEvent = procedure (i:integer) of object;
procedure Test(E:TEvent);
var i:integer;
begin
for i:=0 to 9 do //десять раз вызовем локальную функцию через трамплин.
E(i); //заодно и балансировку стека проверим.
end;
procedure Trampoline; //получает неявно self, в нем хранится PTrampolineRec
begin
asm
mov ebx, TTrampolineRec(eax).LocalProc
mov eax, TTrampolineRec(eax).Reg_EBP
call ebx
end;
end;
function TrampRef(T:PTrampolineRec; P:Pointer):TEvent;
begin
T^.LocalProc:=P;
TMethod(Result).Code:=@Trampoline;
TMethod(Result).Data:=T;
end;
procedure T1(T1_i:integer);
var T1_n:Integer;
T1_Event:TEvent;
T1_Tramp:TTrampolineRec; //служебная запись трамплина
procedure T2(i:integer);
begin
WriteLn('Итерация - ', i);
WriteLn(T1_i);
WriteLn(T1_n);
end;
begin
T1_n:=10;
//подготовка трамплина
asm
mov T1_Tramp.Reg_EBP, ebp;
end;
T1_Event:=TrampRef(@T1_Tramp, @T2);
Test(T1_Event);
//в идеале хотелось бы видеть, просто Test(@T2), а подготовкой трамплина занимался бы компилятор
T2(0);
end;
{$R project1.res}
begin
T1(20);
end.
Как будто бы ничего военного, плюс все существующие классы/callback'и/event'ы (с объявлением of object) должны заработать практически бесплатно.
Даже отдельный тип не надо вводить.
Может чего-то я упускаю?